Areas/section view for problems

This commit is contained in:
Magnus Åhall 2024-05-28 12:56:35 +02:00
parent db21b01589
commit e2f888f160
13 changed files with 182 additions and 83 deletions

19
main.go
View File

@ -443,8 +443,25 @@ func pageProblems(w http.ResponseWriter, _ *http.Request, _ *session.T) { // {{{
return return
} }
var found bool
problemsGrouped := make(map[string]map[string][]Problem)
for _, problem := range problems {
if _, found = problemsGrouped[problem.AreaName]; !found {
problemsGrouped[problem.AreaName] = make(map[string][]Problem)
}
if _, found = problemsGrouped[problem.AreaName][problem.SectionName]; !found {
problemsGrouped[problem.AreaName][problem.SectionName] = []Problem{}
}
problemsGrouped[problem.AreaName][problem.SectionName] = append(
problemsGrouped[problem.AreaName][problem.SectionName],
problem,
)
}
page.Data = map[string]any{ page.Data = map[string]any{
"Problems": problems, "Problems": problems,
"ProblemsGrouped": problemsGrouped,
} }
page.Render(w) page.Render(w)
return return

View File

@ -35,12 +35,12 @@ h2:first-child {
h1 { h1 {
font-size: 1.5em; font-size: 1.5em;
color: #fb4934; color: #fb4934;
font-weight: 500; font-weight: 800;
} }
h2 { h2 {
font-size: 1.25em; font-size: 1.25em;
color: #b8bb26; color: #b8bb26;
font-weight: 500; font-weight: 800;
} }
a { a {
color: #3f9da1; color: #3f9da1;
@ -50,7 +50,7 @@ a:hover {
text-decoration: underline; text-decoration: underline;
} }
b { b {
font-weight: 500; font-weight: 800;
} }
input[type="text"], input[type="text"],
textarea, textarea,
@ -80,7 +80,7 @@ button:focus {
} }
span.date { span.date {
color: #d5c4a1; color: #d5c4a1;
font-weight: 500; font-weight: 800;
} }
span.time { span.time {
font-size: 0.9em; font-size: 0.9em;
@ -119,7 +119,7 @@ label {
border-bottom: unset; border-bottom: unset;
} }
#datapoints .header { #datapoints .header {
font-weight: 500; font-weight: 800;
font-size: 0.85em; font-size: 0.85em;
color: #d5c4a1; color: #d5c4a1;
} }

View File

@ -35,12 +35,12 @@ h2:first-child {
h1 { h1 {
font-size: 1.5em; font-size: 1.5em;
color: #fb4934; color: #fb4934;
font-weight: 500; font-weight: 800;
} }
h2 { h2 {
font-size: 1.25em; font-size: 1.25em;
color: #b8bb26; color: #b8bb26;
font-weight: 500; font-weight: 800;
} }
a { a {
color: #3f9da1; color: #3f9da1;
@ -50,7 +50,7 @@ a:hover {
text-decoration: underline; text-decoration: underline;
} }
b { b {
font-weight: 500; font-weight: 800;
} }
input[type="text"], input[type="text"],
textarea, textarea,
@ -80,7 +80,7 @@ button:focus {
} }
span.date { span.date {
color: #d5c4a1; color: #d5c4a1;
font-weight: 500; font-weight: 800;
} }
span.time { span.time {
font-size: 0.9em; font-size: 0.9em;

View File

@ -35,12 +35,12 @@ h2:first-child {
h1 { h1 {
font-size: 1.5em; font-size: 1.5em;
color: #fb4934; color: #fb4934;
font-weight: 500; font-weight: 800;
} }
h2 { h2 {
font-size: 1.25em; font-size: 1.25em;
color: #b8bb26; color: #b8bb26;
font-weight: 500; font-weight: 800;
} }
a { a {
color: #3f9da1; color: #3f9da1;
@ -50,7 +50,7 @@ a:hover {
text-decoration: underline; text-decoration: underline;
} }
b { b {
font-weight: 500; font-weight: 800;
} }
input[type="text"], input[type="text"],
textarea, textarea,
@ -80,7 +80,7 @@ button:focus {
} }
span.date { span.date {
color: #d5c4a1; color: #d5c4a1;
font-weight: 500; font-weight: 800;
} }
span.time { span.time {
font-size: 0.9em; font-size: 0.9em;
@ -152,7 +152,7 @@ label {
margin-bottom: 32px; margin-bottom: 32px;
} }
#page .page-label div { #page .page-label div {
font-weight: 500; font-weight: 800;
font-size: 1.5em; font-size: 1.5em;
color: #fb4934; color: #fb4934;
} }
@ -172,7 +172,7 @@ label {
#areas .area > .name { #areas .area > .name {
background: #fb4934; background: #fb4934;
color: #fff; color: #fff;
font-weight: 500; font-weight: 800;
padding: 4px 16px; padding: 4px 16px;
border-top-left-radius: 4px; border-top-left-radius: 4px;
border-top-right-radius: 4px; border-top-right-radius: 4px;
@ -196,10 +196,10 @@ label {
white-space: nowrap; white-space: nowrap;
} }
#areas .area .section .create .new { #areas .area .section .create .new {
font-weight: 500; font-weight: 800;
} }
#areas .area .section > .name { #areas .area .section > .name {
font-weight: 500; font-weight: 800;
} }
#areas .area .section .triggers .trigger { #areas .area .section .triggers .trigger {
display: grid; display: grid;

View File

@ -35,12 +35,12 @@ h2:first-child {
h1 { h1 {
font-size: 1.5em; font-size: 1.5em;
color: #fb4934; color: #fb4934;
font-weight: 500; font-weight: 800;
} }
h2 { h2 {
font-size: 1.25em; font-size: 1.25em;
color: #b8bb26; color: #b8bb26;
font-weight: 500; font-weight: 800;
} }
a { a {
color: #3f9da1; color: #3f9da1;
@ -50,7 +50,7 @@ a:hover {
text-decoration: underline; text-decoration: underline;
} }
b { b {
font-weight: 500; font-weight: 800;
} }
input[type="text"], input[type="text"],
textarea, textarea,
@ -80,7 +80,7 @@ button:focus {
} }
span.date { span.date {
color: #d5c4a1; color: #d5c4a1;
font-weight: 500; font-weight: 800;
} }
span.time { span.time {
font-size: 0.9em; font-size: 0.9em;
@ -116,12 +116,12 @@ label {
} }
#problems-list .header, #problems-list .header,
#acknowledged-list .header { #acknowledged-list .header {
font-weight: 500; font-weight: 800;
} }
#problems-list .trigger, #problems-list .trigger,
#acknowledged-list .trigger { #acknowledged-list .trigger {
color: #fb4934; color: #fb4934;
font-weight: 500; font-weight: 800;
} }
#problems-list .acknowledge img, #problems-list .acknowledge img,
#acknowledged-list .acknowledge img { #acknowledged-list .acknowledge img {
@ -130,3 +130,26 @@ label {
#acknowledged-list.hidden { #acknowledged-list.hidden {
display: none; display: none;
} }
#areas {
display: flex;
flex-wrap: wrap;
gap: 12px;
margin-top: 16px;
}
#areas .area .section {
display: grid;
grid-template-columns: repeat(2, min-content);
grid-gap: 8px 12px;
}
#areas .area .section .name {
color: #f7edd7;
grid-column: 1 / -1;
font-weight: bold !important;
line-height: 24px;
}
#areas .area .section div {
white-space: nowrap;
}
.hidden {
display: none;
}

View File

@ -35,12 +35,12 @@ h2:first-child {
h1 { h1 {
font-size: 1.5em; font-size: 1.5em;
color: #fb4934; color: #fb4934;
font-weight: 500; font-weight: 800;
} }
h2 { h2 {
font-size: 1.25em; font-size: 1.25em;
color: #b8bb26; color: #b8bb26;
font-weight: 500; font-weight: 800;
} }
a { a {
color: #3f9da1; color: #3f9da1;
@ -50,7 +50,7 @@ a:hover {
text-decoration: underline; text-decoration: underline;
} }
b { b {
font-weight: 500; font-weight: 800;
} }
input[type="text"], input[type="text"],
textarea, textarea,
@ -80,7 +80,7 @@ button:focus {
} }
span.date { span.date {
color: #d5c4a1; color: #d5c4a1;
font-weight: 500; font-weight: 800;
} }
span.time { span.time {
font-size: 0.9em; font-size: 0.9em;

View File

@ -35,12 +35,12 @@ h2:first-child {
h1 { h1 {
font-size: 1.5em; font-size: 1.5em;
color: #fb4934; color: #fb4934;
font-weight: 500; font-weight: 800;
} }
h2 { h2 {
font-size: 1.25em; font-size: 1.25em;
color: #b8bb26; color: #b8bb26;
font-weight: 500; font-weight: 800;
} }
a { a {
color: #3f9da1; color: #3f9da1;
@ -50,7 +50,7 @@ a:hover {
text-decoration: underline; text-decoration: underline;
} }
b { b {
font-weight: 500; font-weight: 800;
} }
input[type="text"], input[type="text"],
textarea, textarea,
@ -80,7 +80,7 @@ button:focus {
} }
span.date { span.date {
color: #d5c4a1; color: #d5c4a1;
font-weight: 500; font-weight: 800;
} }
span.time { span.time {
font-size: 0.9em; font-size: 0.9em;

View File

@ -20,4 +20,13 @@ export class UI {
localStorage.setItem('show_acknowledged', false) localStorage.setItem('show_acknowledged', false)
} }
} }
displayList() {
document.querySelector('.display-list').classList.remove('hidden')
document.querySelector('.display-areas').classList.add('hidden')
}
displayAreas() {
document.querySelector('.display-list').classList.add('hidden')
document.querySelector('.display-areas').classList.remove('hidden')
}
} }

View File

@ -83,7 +83,7 @@
&>.name { &>.name {
background: @color1; background: @color1;
color: #fff; color: #fff;
font-weight: 500; font-weight: @bold;
padding: 4px 16px; padding: 4px 16px;
border-top-left-radius: 4px; border-top-left-radius: 4px;
border-top-right-radius: 4px; border-top-right-radius: 4px;

View File

@ -30,3 +30,33 @@
#acknowledged-list.hidden{ #acknowledged-list.hidden{
display: none; display: none;
} }
#areas {
display: flex;
flex-wrap: wrap;
gap: 12px;
margin-top: 16px;
.area {
.section {
display: grid;
grid-template-columns: repeat(2, min-content);
grid-gap: 8px 12px;
.name {
color: @text2;
grid-column: 1 / -1;
font-weight: bold !important;
line-height: 24px;
}
div {
white-space: nowrap;
}
}
}
}
.hidden {
display: none;
}

View File

@ -12,7 +12,7 @@
@color4: #3f9da1; @color4: #3f9da1;
@color5: #fe8019; @color5: #fe8019;
@bold: 500; @bold: 800;
.lighterOrDarker(@color, @amount) { .lighterOrDarker(@color, @amount) {
@result: lighten(@color, @amount); @result: lighten(@color, @amount);

View File

@ -10,7 +10,7 @@
<h2>{{ .VERSION }}</h2> <h2>{{ .VERSION }}</h2>
<div class="graph"> <div class="graph">
<img src="/images/{{ .VERSION }}/graph.svg"> <img src="/images/{{ .VERSION }}/graph.svg">
</div> </div>
</div> </div>

View File

@ -9,68 +9,88 @@
{{ block "page_label" . }}{{end}} {{ block "page_label" . }}{{end}}
<input type="checkbox" id="show-acked" onclick="_ui.toggleAcknowledged(event)"> <label for="show-acked">Show acknowledged</label> <div>
<input type="radio" name="display" id="display-table" onclick="_ui.displayAreas()" checked> <label for="display-table">Areas</label>
<input type="radio" name="display" id="display-list" onclick="_ui.displayList()"> <label for="display-list">List</label>
</div>
<div id="problems-list"> <div class="display-list hidden">
<div style="grid-column: 1/-1; margin-top: 32px;"><h2>Current</h2></div> <div id="problems-list">
<div style="grid-column: 1/-1; margin-top: 32px;"><h2>Current</h2></div>
<div class="header">Trigger</div> <div class="header">Trigger</div>
<div class="header">Area</div> <div class="header">Area</div>
<div class="header">Section</div> <div class="header">Section</div>
<div class="header">Since</div> <div class="header">Since</div>
{{ range .Data.Problems }} {{ range .Data.Problems }}
{{ if .Acknowledged }} {{ if .Acknowledged }}
{{ continue }} {{ continue }}
{{ end }}
<div class="line"></div>
{{ if eq .TriggerID -1 }}
<div class="trigger">{{ .TriggerName }}</div>
<div class="area">{{ .AreaName }}</div>
<div class="section">{{ .SectionName }}</div>
<div class="start"></div>
<div class="acknowledge"><img src="/images/{{ $version }}/acknowledge.svg"></div>
{{ else }}
<div class="trigger"><a href="/trigger/edit/{{ .TriggerID }}">{{ .TriggerName }}</a></div>
<div class="area">{{ .AreaName }}</div>
<div class="section">{{ .SectionName }}</div>
<div class="start">{{ format_time .Start }}</div>
<div class="acknowledge"><a href="/problem/acknowledge/{{ .ID }}"><img src="/images/{{ $version }}/acknowledge-filled.svg"></a></div>
{{ end }}
{{ end }} {{ end }}
<div class="line"></div> </div>
{{ if eq .TriggerID -1 }} <input type="checkbox" id="show-acked" onclick="_ui.toggleAcknowledged(event)"> <label for="show-acked">Show acknowledged</label>
<div class="trigger">{{ .TriggerName }}</div>
<div class="area">{{ .AreaName }}</div> <div id="acknowledged-list" class="hidden">
<div class="section">{{ .SectionName }}</div> <div style="grid-column: 1/-1; margin-top: 32px;"><h2>Acknowledged</h2></div>
<div class="start"></div> <div class="header">Trigger</div>
<div class="acknowledge"><img src="/images/{{ $version }}/acknowledge.svg"></div> <div class="header">Area</div>
{{ else }} <div class="header">Section</div>
<div class="header">Since</div>
{{ range .Data.Problems }}
{{ if not .Acknowledged }}
{{ continue }}
{{ end }}
<div class="line"></div>
<div class="trigger"><a href="/trigger/edit/{{ .TriggerID }}">{{ .TriggerName }}</a></div> <div class="trigger"><a href="/trigger/edit/{{ .TriggerID }}">{{ .TriggerName }}</a></div>
<div class="area">{{ .AreaName }}</div> <div class="area">{{ .AreaName }}</div>
<div class="section">{{ .SectionName }}</div> <div class="section">{{ .SectionName }}</div>
<div class="start">{{ format_time .Start }}</div> <div class="start">{{ format_time .Start }}</div>
<div class="acknowledge"><a href="/problem/acknowledge/{{ .ID }}"><img src="/images/{{ $version }}/acknowledge-filled.svg"></a></div> <div class="acknowledge"><a href="/problem/unacknowledge/{{ .ID }}"><img src="/images/{{ $version }}/acknowledge-outline.svg"></a></div>
{{ end }} {{ end }}
{{ end }} </div>
</div> </div>
<div id="acknowledged-list" class="hidden"> <div class="display-areas">
<div style="grid-column: 1/-1; margin-top: 32px;"><h2>Acknowledged</h2></div> <div id="areas">
<div class="header">Trigger</div> {{ range $areaName, $sections := .Data.ProblemsGrouped }}
<div class="header">Area</div> <div class="area">
<div class="header">Section</div> <div class="name">{{ $areaName }}</div>
<div class="header">Since</div>
{{ range .Data.Problems }} {{ range $sectionName, $problems := $sections }}
{{ if not .Acknowledged }} <div class="section problems">
{{ continue }} <div class="name">{{ $sectionName }}</div>
{{ end }}
<div class="line"></div>
<div class="trigger"><a href="/trigger/edit/{{ .TriggerID }}">{{ .TriggerName }}</a></div>
<div class="area">{{ .AreaName }}</div>
<div class="section">{{ .SectionName }}</div>
<div class="start">{{ format_time .Start }}</div>
<div class="acknowledge"><a href="/problem/unacknowledge/{{ .ID }}"><img src="/images/{{ $version }}/acknowledge-outline.svg"></a></div>
{{ end }}
</div>
<div id="areas"> {{ range $problems }}
{{ range .Data.Areas }} <div class="trigger">{{ .TriggerName }}</div>
<div class="area">
<div class="name">{{ .Name }}</div> {{ if eq (.Start | html) "0001-01-01 00:00:00 +0000 UTC" }}
{{ range .SortedSections }} <div class="since"></div>
<div class="section"> {{ else }}
<div class="name">{{ .Name }}</div> <div class="since">{{ format_time .Start }}</div>
{{ end }}
{{ end }}
</div>
{{ end }}
</div> </div>
{{ end }} {{ end }}
</div> </div>
{{ end }}
</div> </div>
{{ end }} {{ end }}