diff options
author | Özgür Kesim <oec@codeblau.de> | 2023-12-30 17:42:58 +0100 |
---|---|---|
committer | Özgür Kesim <oec@codeblau.de> | 2023-12-30 17:42:58 +0100 |
commit | ab4fc1c85cff109d8799da3bd49e210a7fa708b0 (patch) | |
tree | ac583fc049241fdd79f8c4279e6ff8f74c4f5c52 | |
parent | cbc12b958b78d5934fc76a99605f177abb79125c (diff) |
sort by multiple layers; common severity
-rw-r--r-- | data.go | 5 | ||||
-rw-r--r-- | issues.go | 85 | ||||
-rw-r--r-- | list.tmpl | 115 | ||||
-rw-r--r-- | severity.tmpl | 7 | ||||
-rw-r--r-- | table.tmpl | 48 |
5 files changed, 170 insertions, 90 deletions
@@ -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 } @@ -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 +} @@ -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> diff --git a/severity.tmpl b/severity.tmpl new file mode 100644 index 0000000..d8a7230 --- /dev/null +++ b/severity.tmpl @@ -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; } @@ -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 -}} |