sort by multiple layers; common severity

This commit is contained in:
Özgür Kesim 2023-12-30 17:42:58 +01:00
parent cbc12b958b
commit ab4fc1c85c
Signed by: oec
GPG Key ID: F136A7F922D018D7
5 changed files with 170 additions and 90 deletions

View File

@ -61,7 +61,10 @@ func NewData(ctx context.Context, url, token string, num int) *Data {
ctx: ctx, ctx: ctx,
num: num, num: num,
} }
data.tmpl = template.Must(template.New("index").ParseFS(content, "*.tmpl")) funcMap := map[string]any{
"OrderedBy": OrderedBy,
}
data.tmpl = template.Must(template.New("index").Funcs(funcMap).ParseFS(content, "*.tmpl"))
return data return data
} }

View File

@ -21,6 +21,7 @@ package main
*/ */
import ( import (
"log"
"sort" "sort"
"strings" "strings"
"time" "time"
@ -111,7 +112,6 @@ func (b ByAssignment) Less(i, j int) bool {
} }
func (b ByAssignment) Swap(i, j int) { b[i], b[j] = b[j], b[i] } func (b ByAssignment) Swap(i, j int) { b[i], b[j] = b[j], b[i] }
type ById []Issue type ById []Issue
func (b ById) Len() int { return len(b) } func (b ById) Len() int { return len(b) }
@ -213,3 +213,82 @@ func (i Issues) ByCategoryAndTarget(cat, tar string) (issues Issues) {
sort.Sort(sort.Reverse(ByHandlerAndId(issues))) sort.Sort(sort.Reverse(ByHandlerAndId(issues)))
return return
} }
// Follow the example for multiSort in https://pkg.go.dev/sort
type lessFunc func(i1, i2 *Issue) bool
type multiSorter struct {
issues Issues
less []lessFunc
}
func (ms *multiSorter) Len() int {
return len(ms.issues)
}
func (ms *multiSorter) Sort(issues Issues) Issues {
ms.issues = issues
sort.Sort(ms)
return ms.issues
}
func (ms *multiSorter) Swap(i, j int) {
ms.issues[i], ms.issues[j] = ms.issues[j], ms.issues[i]
}
func (ms *multiSorter) Less(i, j int) bool {
p, q := &ms.issues[i], &ms.issues[j]
var k int
for k = 0; k < len(ms.less)-1; k++ {
less := ms.less[k]
switch {
case less(p, q):
return true
case less(q, p):
return false
}
}
return ms.less[k](p, q)
}
var severityOrder = map[string]int{
"block": 0,
"crash": 1,
"major": 2,
"minor": 3,
"text": 4,
"trivial": 5,
"tweak": 6}
var lessFuncs = map[string]lessFunc{
"Category": func(i1, i2 *Issue) bool { return strings.Compare(i1.Category.Name, i2.Category.Name) < 0 },
"Assignment": func(i1, i2 *Issue) bool { return strings.Compare(i1.Handler.Name, i2.Handler.Name) < 0 },
"Handler": func(i1, i2 *Issue) bool { return strings.Compare(i1.Handler.Name, i2.Handler.Name) < 0 },
"Target": func(i1, i2 *Issue) bool { return strings.Compare(i1.TargetVersion.Name, i2.TargetVersion.Name) < 0 },
"Id": func(i1, i2 *Issue) bool { return i1.Id < i2.Id },
"Severity": func(i1, i2 *Issue) bool {
s1, ok := severityOrder[i1.Severity.Name]
if !ok {
return true
}
s2, ok := severityOrder[i2.Severity.Name]
if !ok {
return false
}
return s1 < s2
},
}
func OrderedBy(fields ...string) *multiSorter {
m := &multiSorter{}
for _, field := range fields {
fn, ok := lessFuncs[field]
if !ok {
log.Printf("unknown field to order by: %s\n", field)
return nil
}
m.less = append(m.less, fn)
}
return m
}

View File

@ -21,13 +21,7 @@ pre {
overflow: scroll; overflow: scroll;
text-overflow: wrap,ellipsis; text-overflow: wrap,ellipsis;
} }
.severity-block { color: red; font-style: bold; } {{template "severity.tmpl"}}
.severity-crash { color: red; }
.severity-major { color: brown; }
.severity-minor { color: darkorange; }
.severity-text { color: black; }
.severity-trivial { color: blue; }
.severity-tweak { color: grey; }
</style></head> </style></head>
<body> <body>
<h1>GNU Taler Dashboard</h1> <h1>GNU Taler Dashboard</h1>
@ -38,6 +32,7 @@ pre {
{{- $features := .Features }} {{- $features := .Features }}
{{- $issues := .Issues }} {{- $issues := .Issues }}
{{- $versions := .VersionsByDate }} {{- $versions := .VersionsByDate }}
{{- $sorter := OrderedBy "Severity" "Handler" "Id" -}}
<!-- p> <!-- p>
{{- range $top.Tags }} {{- range $top.Tags }}
<button>{{ . }}</button> <button>{{ . }}</button>
@ -47,7 +42,7 @@ pre {
{{- range $cat := $top.Categories }} {{- range $cat := $top.Categories }}
<h3>{{ . }}</h3> <h3>{{ . }}</h3>
<h4>Features</h4> <h4>Features</h4>
{{- range $features.ByCategory $cat }} {{- range $sorter.Sort ($features.ByCategory $cat) }}
<details> <details>
<summary> <summary>
{{ if .IsHandled }}<span title="assigned to {{.Handler.Name}}">🥷</span>{{else}}<span title="unassigned">❓</span>{{end}} {{ if .IsHandled }}<span title="assigned to {{.Handler.Name}}">🥷</span>{{else}}<span title="unassigned">❓</span>{{end}}
@ -58,12 +53,12 @@ pre {
</details> </details>
{{ end -}} {{ end -}}
<h4>Issues</h4> <h4>Issues</h4>
{{- range $issues.ByCategory $cat }} {{- range $sorter.Sort ($issues.ByCategory $cat) }}
<details> <details>
<summary> <summary>
{{ if .IsHandled }}<span title="assigned to {{.Handler.Name}}">🥷</span>{{else}}<span title="unassigned">❓</span>{{end}} {{ if .IsHandled }}<span title="assigned to {{.Handler.Name}}">🥷</span>{{else}}<span title="unassigned">❓</span>{{end}}
<a href="https://bugs.gnunet.org/view.php?id={{.Id}}" target="_blank">{{.Id}}</a> <a href="https://bugs.gnunet.org/view.php?id={{.Id}}" target="_blank">{{.Id}}</a>
<span class="severity-{{.Severity.Name}}">{{.Summary}}</span><br> <span class="severity-{{.Severity.Name}}" title="severity {{.Severity.Name}}">{{.Summary}}</span><br>
</summary> </summary>
<pre>{{ .Description }}</pre> <pre>{{ .Description }}</pre>
</details> </details>

7
severity.tmpl Normal file
View File

@ -0,0 +1,7 @@
.severity-block { color: red; font-weight: bold; }
.severity-crash { color: deeppink; font-weight: bold; }
.severity-major { color: crimson; }
.severity-minor { color: sienna; }
.severity-text { color: black; }
.severity-trivial { color: grey; }
.severity-tweak { color: steelblue; }

View File

@ -26,21 +26,15 @@ tr:hover {
background: #efefef; background: #efefef;
} }
.feature { .feature {
background: #cdf; background: powderblue;
} }
.issue { .issue {
background: #edc; background: navajowhite;
} }
.minh { .minh {
min-height: 5em; min-height: 5em;
} }
.severity-block { color: red; font-style: bold; } {{template "severity.tmpl"}}
.severity-crash { color: red; }
.severity-major { color: brown; }
.severity-minor { color: darkorange; }
.severity-text { color: black; }
.severity-trivial { color: blue; }
.severity-tweak { color: grey; }
summary { summary {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
@ -74,19 +68,19 @@ details.version {
text-align: justify; text-align: justify;
} }
details[open].feature { details[open].feature {
background: aliceblue; background: ghostwhite;
border: 2px midnightblue solid; border: 4px powderblue solid;
} }
details[open].issue { details[open].issue {
background: lightyellow; background: ghostwhite;
border: 2px brown solid; border: 4px navajowhite solid;
} }
</style></head> </style></head>
<body> <body>
<h1>GNU Taler Dashboard</h1> <h1>GNU Taler Dashboard</h1>
<h2>Table view | <a href="/list">List View</a></h2> <h2>Table view | <a href="/list">List View</a></h2>
Data from {{ .Timestamp.Format "02 Jan 06 15:04 MST"}}, updated every {{ .Freq }} (no auto-refresh). Data from {{ .Timestamp.Format "02 Jan 06 15:04 MST"}}, updated every {{ .Freq }} (no auto-refresh).
{{- with .Lasterror }}, Last error: {{ . }} {{end }} {{- with .Lasterror }} Last error: {{ . }} {{end }}
{{- $top := . -}} {{- $top := . -}}
{{- $features := .Features -}} {{- $features := .Features -}}
{{- $issues := .Issues -}} {{- $issues := .Issues -}}
@ -120,7 +114,8 @@ details[open].issue {
<div>{{ $l := len .}}{{ if lt 1 $l }}{{ $l }} features{{ else }}1 feature{{ end }}</div> <div>{{ $l := len .}}{{ if lt 1 $l }}{{ $l }} features{{ else }}1 feature{{ end }}</div>
<div class="assignment">{{- $unassigned := .Assigned false }}{{if gt $unassigned 0 }}({{ $unassigned}} unassigned){{ end -}}</div> <div class="assignment">{{- $unassigned := .Assigned false }}{{if gt $unassigned 0 }}({{ $unassigned}} unassigned){{ end -}}</div>
</summary> </summary>
{{- range . }} {{- $sorter := OrderedBy "Handler" "Id" -}}
{{- range $sorter.Sort . }}
{{ if .IsHandled }}<span title="assigned to {{.Handler.Name}}">🥷</span>{{else}}<span title="unassigned">❓</span>{{end}} {{ if .IsHandled }}<span title="assigned to {{.Handler.Name}}">🥷</span>{{else}}<span title="unassigned">❓</span>{{end}}
<a href="https://bugs.gnunet.org/view.php?id={{.Id}}" target="_blank">{{.Id}}</a> <a href="https://bugs.gnunet.org/view.php?id={{.Id}}" target="_blank">{{.Id}}</a>
<span class="severity-{{.Severity.Name}}">{{.Summary}}</span><br> <span class="severity-{{.Severity.Name}}">{{.Summary}}</span><br>
@ -133,10 +128,11 @@ details[open].issue {
<div>{{ $l := len .}}{{ if lt 1 $l }}{{ $l }} issues{{ else }}1 issue{{ end }}</div> <div>{{ $l := len .}}{{ if lt 1 $l }}{{ $l }} issues{{ else }}1 issue{{ end }}</div>
<div class="assignment">{{- $unassigned := .Assigned false }}{{if gt $unassigned 0 }} ({{ $unassigned}} unassigned){{ end -}}</div> <div class="assignment">{{- $unassigned := .Assigned false }}{{if gt $unassigned 0 }} ({{ $unassigned}} unassigned){{ end -}}</div>
</summary> </summary>
{{- range . }} {{- $sorter := OrderedBy "Severity" "Handler" "Id" -}}
{{- range $sorter.Sort . }}
{{ if .IsHandled }}<span title="assigned to {{.Handler.Name}}">🥷</span>{{else}}<span title="unassigned">❓</span>{{end}} {{ if .IsHandled }}<span title="assigned to {{.Handler.Name}}">🥷</span>{{else}}<span title="unassigned">❓</span>{{end}}
<a href="https://bugs.gnunet.org/view.php?id={{.Id}}" target="_blank">{{.Id}}</a> <a href="https://bugs.gnunet.org/view.php?id={{.Id}}" target="_blank">{{.Id}}</a>
<span class="severity-{{.Severity.Name}}">{{.Summary}}</span><br> <span class="severity-{{.Severity.Name}}" title="severity {{.Severity.Name}}">{{.Summary}}</span><br>
{{- end}} {{- end}}
</details> </details>
{{ end -}} {{ end -}}