aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAleksandr Nogikh <nogikh@google.com>2023-02-22 17:00:10 +0100
committerAleksandr Nogikh <wp32pw@gmail.com>2023-02-22 17:52:26 +0100
commit00f8fc943e4837459d194201c6d5d7f5b95e9f67 (patch)
treee3c09815857ca9049800a9a4d0be0e43a964c529
parent6b9e84f9440313dcd09e408d09d3440f666db8ff (diff)
dashboard: filter by no subsystems
Count the number of bugs without any subsystem and let users filter bugs by this criteria.
-rw-r--r--dashboard/app/cache.go8
-rw-r--r--dashboard/app/main.go18
-rw-r--r--dashboard/app/main_test.go6
-rw-r--r--dashboard/app/subsystems.html6
-rw-r--r--dashboard/app/templates.html3
5 files changed, 37 insertions, 4 deletions
diff --git a/dashboard/app/cache.go b/dashboard/app/cache.go
index 177d4750f..2c8ca6376 100644
--- a/dashboard/app/cache.go
+++ b/dashboard/app/cache.go
@@ -15,8 +15,9 @@ import (
)
type Cached struct {
- Total CachedBugStats
- Subsystems map[string]CachedBugStats
+ Total CachedBugStats
+ Subsystems map[string]CachedBugStats
+ NoSubsystem CachedBugStats
}
type CachedBugStats struct {
@@ -76,6 +77,9 @@ func buildAndStoreCached(c context.Context, bugs []*Bug, ns string, accessLevel
stats.Record(bug)
v.Subsystems[subsystem.Name] = stats
}
+ if len(bug.Tags.Subsystems) == 0 {
+ v.NoSubsystem.Record(bug)
+ }
}
item := &memcache.Item{
Key: cacheKey(ns, accessLevel),
diff --git a/dashboard/app/main.go b/dashboard/app/main.go
index 55574c4c0..ad503c0ef 100644
--- a/dashboard/app/main.go
+++ b/dashboard/app/main.go
@@ -351,11 +351,13 @@ type userBugFilter struct {
Manager string // show bugs that happened on the manager
OnlyManager string // show bugs that happened ONLY on the manager
Subsystem string // only show bugs belonging to the subsystem
+ NoSubsystem bool
}
func MakeBugFilter(r *http.Request) *userBugFilter {
return &userBugFilter{
Subsystem: r.FormValue("subsystem"),
+ NoSubsystem: r.FormValue("no_subsystem") != "",
Manager: r.FormValue("manager"),
OnlyManager: r.FormValue("only_manager"),
}
@@ -386,6 +388,9 @@ func (filter *userBugFilter) MatchBug(bug *Bug) bool {
if filter.Manager != "" && !stringInList(bug.HappenedOn, filter.Manager) {
return false
}
+ if filter.NoSubsystem && len(bug.Tags.Subsystems) > 0 {
+ return false
+ }
if filter.Subsystem != "" && !bug.hasSubsystem(filter.Subsystem) {
return false
}
@@ -396,7 +401,7 @@ func (filter *userBugFilter) Any() bool {
if filter == nil {
return false
}
- return filter.Subsystem != "" || filter.OnlyManager != "" || filter.Manager != ""
+ return filter.Subsystem != "" || filter.OnlyManager != "" || filter.Manager != "" || filter.NoSubsystem
}
// handleMain serves main page.
@@ -862,6 +867,17 @@ func handleSubsystemsList(c context.Context, w http.ResponseWriter, r *http.Requ
}
list = append(list, record)
}
+ list = append(list, &uiSubsystem{
+ Name: "",
+ Open: uiSubsystemStats{
+ Count: cached.NoSubsystem.Open,
+ Link: html.AmendURL("/"+hdr.Namespace, "no_subsystem", "true"),
+ },
+ Fixed: uiSubsystemStats{
+ Count: cached.NoSubsystem.Open,
+ Link: html.AmendURL("/"+hdr.Namespace+"/fixed", "no_subsystem", "true"),
+ },
+ })
sort.Slice(list, func(i, j int) bool { return list[i].Name < list[j].Name })
return serveTemplate(w, "subsystems.html", &uiSubsystemsPage{
Header: hdr,
diff --git a/dashboard/app/main_test.go b/dashboard/app/main_test.go
index fe9410da3..3a07f5040 100644
--- a/dashboard/app/main_test.go
+++ b/dashboard/app/main_test.go
@@ -169,6 +169,7 @@ func TestMainBugFilters(t *testing.T) {
client.UploadBuild(build1)
crash1 := testCrash(build1, 1)
+ crash1.Title = "my-crash-title"
client.ReportCrash(crash1)
client.pollBugs(1)
@@ -182,6 +183,11 @@ func TestMainBugFilters(t *testing.T) {
c.expectOK(err)
assert.NotContains(t, string(reply), build1.Manager) // managers are hidden
assert.Contains(t, string(reply), "Applied filters") // we're seeing a prompt to disable the filter
+ assert.NotContains(t, string(reply), crash1.Title) // the bug does not belong to the subsystem
+
+ reply, err = c.AuthGET(AccessAdmin, "/test1?no_subsystem=true")
+ c.expectOK(err)
+ assert.Contains(t, string(reply), crash1.Title) // the bug has no subsystems
}
func TestSubsystemsList(t *testing.T) {
diff --git a/dashboard/app/subsystems.html b/dashboard/app/subsystems.html
index b6f9bbd71..2b1fe0f57 100644
--- a/dashboard/app/subsystems.html
+++ b/dashboard/app/subsystems.html
@@ -28,7 +28,11 @@ The list of polled trees.
</tr>
{{range $item := .List}}
<tr>
- <td>{{link $item.Open.Link $item.Name}}</td>
+ {{if $item.Name}}
+ <td>{{link $item.Open.Link $item.Name}}</td>
+ {{else}}
+ <td><b>{{link $item.Open.Link "no subsystem"}}</b></td>
+ {{end}}
<td>{{$item.Lists}}</td>
<td>{{link $item.Open.Link (printf "%d" $item.Open.Count)}}</td>
<td>{{link $item.Fixed.Link (printf "%d" $item.Fixed.Count)}}</td>
diff --git a/dashboard/app/templates.html b/dashboard/app/templates.html
index 0a2c9301a..52b8e4ea6 100644
--- a/dashboard/app/templates.html
+++ b/dashboard/app/templates.html
@@ -102,6 +102,9 @@ Use of this source code is governed by Apache 2 LICENSE that can be found in the
{{if .Filter.Subsystem}}
Subsystem={{.Filter.Subsystem}} ({{link (call .DropURL "subsystem") "drop"}})
{{end}}
+ {{if .Filter.NoSubsystem}}
+ NoSubsystem={{.Filter.NoSubsystem}} ({{link (call .DropURL "no_subsystem") "drop"}})
+ {{end}}
<br>
{{end}}
{{end}}