sort by multiple layers; common severity
This commit is contained in:
parent
cbc12b958b
commit
ab4fc1c85c
5
data.go
5
data.go
@ -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
|
||||
}
|
||||
|
83
issues.go
83
issues.go
@ -21,6 +21,7 @@ package main
|
||||
*/
|
||||
|
||||
import (
|
||||
"log"
|
||||
"sort"
|
||||
"strings"
|
||||
"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] }
|
||||
|
||||
|
||||
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
115
list.tmpl
@ -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
7
severity.tmpl
Normal 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; }
|
48
table.tmpl
48
table.tmpl
@ -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 -}}
|
||||
|
Loading…
Reference in New Issue
Block a user