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,
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
}

View File

@ -21,6 +21,7 @@ package main
*/
import (
"log"
"sort"
"strings"
"time"
@ -103,7 +104,7 @@ func (b ByCategory) Less(i, j int) bool {
}
func (b ByCategory) Swap(i, j int) { b[i], b[j] = b[j], b[i] }
type ByAssignment []Issue
type ByAssignment []Issue
func (b ByAssignment) Len() int { return len(b) }
func (b ByAssignment) Less(i, j int) bool {
@ -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] }
type ById []Issue
func (b ById) Len() int { return len(b) }
@ -199,7 +199,7 @@ func (i Issues) ByCategory(cat string) (issues Issues) {
issues = append(issues, issue)
}
}
sort.Sort(sort.Reverse(ByHandlerAndId(issues)))
sort.Sort(sort.Reverse(ByHandlerAndId(issues)))
return issues
}
@ -213,3 +213,82 @@ func (i Issues) ByCategoryAndTarget(cat, tar string) (issues Issues) {
sort.Sort(sort.Reverse(ByHandlerAndId(issues)))
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
}

115
list.tmpl
View File

@ -1,75 +1,70 @@
<!DOCTYPE html>
<head><title>GNU Taler Dashboard</title>
<head><title>GNU Taler Dashboard</title>
<style>
body {
margin-left:1%;
margin-right:1%;
font-family:sans-serif;
margin-left:1%;
margin-right:1%;
font-family:sans-serif;
}
h3 {
color: brown;
color: brown;
}
h4 {
margin-left: 5%;
margin-left: 5%;
}
details {
margin-left: 5%;
margin-right: 5%;
margin-left: 5%;
margin-right: 5%;
}
pre {
max-width: 100%;
overflow: scroll;
text-overflow: wrap,ellipsis;
max-width: 100%;
overflow: scroll;
text-overflow: wrap,ellipsis;
}
.severity-block { color: red; font-style: bold; }
.severity-crash { color: red; }
.severity-major { color: brown; }
.severity-minor { color: darkorange; }
.severity-text { color: black; }
.severity-trivial { color: blue; }
.severity-tweak { color: grey; }
{{template "severity.tmpl"}}
</style></head>
<body>
<h1>GNU Taler Dashboard</h1>
<h2><a href="/">Table view</a> | List View </h2>
Data from {{ .Timestamp.Format "02 Jan 06 15:04 MST"}}, updateting every {{ .Freq }} (no auto-refresh)
{{ with .Lasterror }}, Last error: {{ . }} {{end}}
{{- $top := . }}
{{- $features := .Features }}
{{- $issues := .Issues }}
{{- $versions := .VersionsByDate }}
<!-- p>
{{- range $top.Tags }}
<button>{{ . }}</button>
{{ end -}}
</p -->
<body>
<h1>GNU Taler Dashboard</h1>
<h2><a href="/">Table view</a> | List View </h2>
Data from {{ .Timestamp.Format "02 Jan 06 15:04 MST"}}, updateting every {{ .Freq }} (no auto-refresh)
{{ with .Lasterror }}, Last error: {{ . }} {{end}}
{{- $top := . }}
{{- $features := .Features }}
{{- $issues := .Issues }}
{{- $versions := .VersionsByDate }}
{{- $sorter := OrderedBy "Severity" "Handler" "Id" -}}
<!-- p>
{{- range $top.Tags }}
<button>{{ . }}</button>
{{ end -}}
</p -->
{{- range $cat := $top.Categories }}
<h3>{{ . }}</h3>
<h4>Features</h4>
{{- range $features.ByCategory $cat }}
<details>
<summary>
{{ 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>
<span class="severity-{{.Severity.Name}}">{{.Summary}}</span><br>
</summary>
<pre>{{ .Description }}</pre>
</details>
{{ end -}}
<h4>Issues</h4>
{{- range $issues.ByCategory $cat }}
<details>
<summary>
{{ 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>
<span class="severity-{{.Severity.Name}}">{{.Summary}}</span><br>
</summary>
<pre>{{ .Description }}</pre>
</details>
{{ end -}}
{{ end -}}
<p>
<i>taler-dashboard - version: {{.Commit}} - <a href="https://git.kesim.org/taler/taler-dashboard">https://git.kesim.org/taler/taler-dashboard</a> </i>
</body>
{{- range $cat := $top.Categories }}
<h3>{{ . }}</h3>
<h4>Features</h4>
{{- range $sorter.Sort ($features.ByCategory $cat) }}
<details>
<summary>
{{ 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>
<span class="severity-{{.Severity.Name}}">{{.Summary}}</span><br>
</summary>
<pre>{{ .Description }}</pre>
</details>
{{ end -}}
<h4>Issues</h4>
{{- range $sorter.Sort ($issues.ByCategory $cat) }}
<details>
<summary>
{{ 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>
<span class="severity-{{.Severity.Name}}" title="severity {{.Severity.Name}}">{{.Summary}}</span><br>
</summary>
<pre>{{ .Description }}</pre>
</details>
{{ end -}}
{{ end -}}
<p>
<i>taler-dashboard - version: {{.Commit}} - <a href="https://git.kesim.org/taler/taler-dashboard">https://git.kesim.org/taler/taler-dashboard</a> </i>
</body>
</html>

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;
}
.feature {
background: #cdf;
background: powderblue;
}
.issue {
background: #edc;
background: navajowhite;
}
.minh {
min-height: 5em;
}
.severity-block { color: red; font-style: bold; }
.severity-crash { color: red; }
.severity-major { color: brown; }
.severity-minor { color: darkorange; }
.severity-text { color: black; }
.severity-trivial { color: blue; }
.severity-tweak { color: grey; }
{{template "severity.tmpl"}}
summary {
display: flex;
justify-content: space-between;
@ -74,19 +68,19 @@ details.version {
text-align: justify;
}
details[open].feature {
background: aliceblue;
border: 2px midnightblue solid;
background: ghostwhite;
border: 4px powderblue solid;
}
details[open].issue {
background: lightyellow;
border: 2px brown solid;
background: ghostwhite;
border: 4px navajowhite solid;
}
</style></head>
<body>
<h1>GNU Taler Dashboard</h1>
<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).
{{- with .Lasterror }}, Last error: {{ . }} {{end }}
{{- with .Lasterror }} Last error: {{ . }} {{end }}
{{- $top := . -}}
{{- $features := .Features -}}
{{- $issues := .Issues -}}
@ -116,27 +110,29 @@ details[open].issue {
{{- with $version := $versions.Get . }}
<td><div class="minh">{{ with $features.ByCategoryAndTarget $cat $tar }}
<details class="feature">
<summary>
<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>
</summary>
{{- range . }}
<summary>
<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>
</summary>
{{- $sorter := OrderedBy "Handler" "Id" -}}
{{- range $sorter.Sort . }}
{{ 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>
<span class="severity-{{.Severity.Name}}">{{.Summary}}</span><br>
<span class="severity-{{.Severity.Name}}">{{.Summary}}</span><br>
{{- end}}
</details>
{{- end }}
{{- with $issues.ByCategoryAndTarget $cat $tar }}
<details class="issue">
<summary>
<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>
</summary>
{{- range . }}
<summary>
<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>
</summary>
{{- $sorter := OrderedBy "Severity" "Handler" "Id" -}}
{{- range $sorter.Sort . }}
{{ 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>
<span class="severity-{{.Severity.Name}}">{{.Summary}}</span><br>
<span class="severity-{{.Severity.Name}}" title="severity {{.Severity.Name}}">{{.Summary}}</span><br>
{{- end}}
</details>
{{ end -}}