From 00f8fc943e4837459d194201c6d5d7f5b95e9f67 Mon Sep 17 00:00:00 2001 From: Aleksandr Nogikh Date: Wed, 22 Feb 2023 17:00:10 +0100 Subject: dashboard: filter by no subsystems Count the number of bugs without any subsystem and let users filter bugs by this criteria. --- dashboard/app/cache.go | 8 ++++++-- dashboard/app/main.go | 18 +++++++++++++++++- dashboard/app/main_test.go | 6 ++++++ dashboard/app/subsystems.html | 6 +++++- dashboard/app/templates.html | 3 +++ 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. {{range $item := .List}} - {{link $item.Open.Link $item.Name}} + {{if $item.Name}} + {{link $item.Open.Link $item.Name}} + {{else}} + {{link $item.Open.Link "no subsystem"}} + {{end}} {{$item.Lists}} {{link $item.Open.Link (printf "%d" $item.Open.Count)}} {{link $item.Fixed.Link (printf "%d" $item.Fixed.Count)}} 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}}
{{end}} {{end}} -- cgit mrf-deployment