fix
This commit is contained in:
1 parent
49c6c6cc76
commit
6dc2785f71
4 files changed
+117
-24
No files matched your search
+54
-18
@@ -91,6 +91,10 @@ func renderBody(snap snapshot, o snapshotOptions, w, avail int) string {
|
||||
case o.ScanError != nil && len(snap.Issues) == 0:
|
||||
return statusPanel(w, min(avail, 5), colCritical, "SCAN FAILED", o.ScanError.Error(),
|
||||
"no successful scan yet; retrying automatically")
|
||||
case len(snap.Issues) == 0 && len(snap.Resolved) > 0:
|
||||
// Nothing fires any more: keep the last issue on the display,
|
||||
// flipped to resolved, instead of an ALL CLEAR panel.
|
||||
return renderGrid(snap.Resolved, o, w, avail)
|
||||
case len(snap.Issues) == 0:
|
||||
sub := fmt.Sprintf("no issues firing · window %s–%s UTC · scanned %s",
|
||||
snap.WindowStart.Format("15:04"), snap.WindowEnd.Format("15:04"), commas(snap.Events))
|
||||
@@ -99,19 +103,19 @@ func renderBody(snap snapshot, o snapshotOptions, w, avail int) string {
|
||||
}
|
||||
return statusPanel(w, min(avail, 5), colOK, "ALL CLEAR", sub, "")
|
||||
default:
|
||||
return renderGrid(snap, o, w, avail)
|
||||
return renderGrid(snap.Issues, o, w, avail)
|
||||
}
|
||||
}
|
||||
|
||||
// renderGrid lays issues into rows of cards that fill the width; only as many
|
||||
// rows as the height allows are drawn, the rest are counted in the footer.
|
||||
func renderGrid(snap snapshot, o snapshotOptions, w, avail int) string {
|
||||
perRow, _, shown, cardW := gridLayout(len(snap.Issues), w, avail)
|
||||
func renderGrid(views []issueView, o snapshotOptions, w, avail int) string {
|
||||
perRow, _, shown, cardW := gridLayout(len(views), w, avail)
|
||||
var rendered []string
|
||||
for start := 0; start < shown; start += perRow {
|
||||
end := min(start+perRow, shown)
|
||||
var row []string
|
||||
for _, v := range snap.Issues[start:end] {
|
||||
for _, v := range views[start:end] {
|
||||
row = append(row, issueCard(v, cardW, o))
|
||||
}
|
||||
rendered = append(rendered, lipgloss.JoinHorizontal(lipgloss.Top, row...))
|
||||
@@ -145,11 +149,19 @@ func gridLayout(n, width, avail int) (perRow, rows, shown, cardW int) {
|
||||
func issueCard(v issueView, w int, o snapshotOptions) string {
|
||||
a := v.alert
|
||||
fg := priorityColor(a.Priority())
|
||||
resolved := !v.resolvedAt.IsZero()
|
||||
if resolved {
|
||||
// A resolved card keeps its place but reads as recovered: the same
|
||||
// green as the footer's recovered line and the ALL CLEAR panel.
|
||||
fg = colOK
|
||||
}
|
||||
inner := w - 4 // border plus padding on both sides
|
||||
|
||||
// Line 1: HIGH · checkout · for 12m
|
||||
age := ""
|
||||
if !v.firstSeen.IsZero() && !o.Now.IsZero() {
|
||||
if !v.firstSeen.IsZero() && resolved {
|
||||
age = " · for " + shortDur(v.resolvedAt.Sub(v.firstSeen).Round(time.Minute))
|
||||
} else if !v.firstSeen.IsZero() && !o.Now.IsZero() {
|
||||
age = " · for " + shortDur(o.Now.Sub(v.firstSeen).Round(time.Minute))
|
||||
}
|
||||
head := ansi.Truncate(
|
||||
@@ -190,14 +202,20 @@ func issueCard(v issueView, w int, o snapshotOptions) string {
|
||||
}
|
||||
statsLine := ansi.Truncate(strings.Join(segs, " "), inner, "…")
|
||||
|
||||
// Line 4: display state (paged now vs already paged) and the issue link.
|
||||
// Line 4: display state (paged now vs already paged vs resolved) and the
|
||||
// issue link.
|
||||
state := style(colText3, false).Render("ongoing")
|
||||
if v.paged {
|
||||
when := a.Spike.WindowEnd
|
||||
switch {
|
||||
case resolved:
|
||||
state = style(colOK, true).Render("RESOLVED")
|
||||
when = v.resolvedAt
|
||||
case v.paged:
|
||||
state = style(fg, true).Render("PAGED")
|
||||
}
|
||||
var meta []string
|
||||
if !a.Spike.WindowEnd.IsZero() {
|
||||
meta = append(meta, style(colText3, false).Render(fmtTime(a.Spike.WindowEnd)))
|
||||
if !when.IsZero() {
|
||||
meta = append(meta, style(colText3, false).Render(fmtTime(when)))
|
||||
}
|
||||
meta = append(meta, state)
|
||||
if o.BaseURL != "" && len(a.Patterns) > 0 && a.Patterns[0].IssueID != "" {
|
||||
@@ -254,9 +272,12 @@ func renderHeader(snap snapshot, o snapshotOptions) string {
|
||||
}
|
||||
}
|
||||
counts := fmt.Sprintf("%d firing", len(snap.Issues))
|
||||
if paged > 0 {
|
||||
switch {
|
||||
case len(snap.Issues) == 0 && len(snap.Resolved) > 0:
|
||||
left = append(left, style(colOK, true).Render(fmt.Sprintf("%d resolved", len(snap.Resolved))))
|
||||
case paged > 0:
|
||||
left = append(left, style(colCritical, true).Render(fmt.Sprintf("%d PAGED · %s", paged, counts)))
|
||||
} else {
|
||||
default:
|
||||
left = append(left, style(colText2, false).Render(counts))
|
||||
}
|
||||
}
|
||||
@@ -282,7 +303,7 @@ func renderHeader(snap snapshot, o snapshotOptions) string {
|
||||
func renderFooter(snap snapshot, o snapshotOptions) string {
|
||||
var left []string
|
||||
left = append(left, style(colText3, false).Render(footerHint))
|
||||
if hidden := len(snap.Issues) - shownCount(snap, o); hidden > 0 {
|
||||
if hidden := cardCount(snap) - shownCount(snap, o); hidden > 0 {
|
||||
left = append(left, style(colWarn, false).Render(fmt.Sprintf("+%d more not shown (widen or raise the display)", hidden)))
|
||||
}
|
||||
var right []string
|
||||
@@ -299,11 +320,20 @@ func renderFooter(snap snapshot, o snapshotOptions) string {
|
||||
return bar(o.Width-2, strings.Join(left, " "), strings.Join(right, " "))
|
||||
}
|
||||
|
||||
// cardCount is how many cards the body renders: the firing issues, or the
|
||||
// kept resolved ones when nothing fires.
|
||||
func cardCount(snap snapshot) int {
|
||||
if n := len(snap.Issues); n > 0 {
|
||||
return n
|
||||
}
|
||||
return len(snap.Resolved)
|
||||
}
|
||||
|
||||
func shownCount(snap snapshot, o snapshotOptions) int {
|
||||
if o.Height < minUsableHeight {
|
||||
return len(snap.Issues)
|
||||
return cardCount(snap)
|
||||
}
|
||||
_, _, shown, _ := gridLayout(len(snap.Issues), o.Width, o.Height-2)
|
||||
_, _, shown, _ := gridLayout(cardCount(snap), o.Width, o.Height-2)
|
||||
return shown
|
||||
}
|
||||
|
||||
@@ -323,14 +353,20 @@ func renderMinimal(snap snapshot, o snapshotOptions) string {
|
||||
if snap.Err != nil {
|
||||
return "SCAN FAILED: " + snap.Err.Error()
|
||||
}
|
||||
if len(snap.Issues) == 0 {
|
||||
if len(snap.Issues) == 0 && len(snap.Resolved) == 0 {
|
||||
return strings.ToUpper(o.Title) + ": all clear"
|
||||
}
|
||||
lines := make([]string, 0, len(snap.Issues)+1)
|
||||
views := snap.Issues
|
||||
if len(views) == 0 {
|
||||
views = snap.Resolved
|
||||
}
|
||||
lines := make([]string, 0, len(views)+1)
|
||||
lines = append(lines, strings.ToUpper(o.Title)+":")
|
||||
for _, v := range snap.Issues {
|
||||
for _, v := range views {
|
||||
state := "ongoing"
|
||||
if v.paged {
|
||||
if !v.resolvedAt.IsZero() {
|
||||
state = "RESOLVED"
|
||||
} else if v.paged {
|
||||
state = "PAGED"
|
||||
}
|
||||
what := ""
|
||||
|
||||
Reference in new issue
Block a user