feat(tui): 30-day uptime timeline in inline detail panel

Statuspage-style colored bar — one █ per day, colored by uptime:
green (>= 99%), yellow (>= 95%), red (< 95%), gray (no data).
30-day percentage shown to the right.

Daily breakdown computed via ComputeDailyBreakdown from state_changes
and loaded alongside detail data in loadDetailCmd. Auto-updates on
cursor move.
This commit is contained in:
2026-06-24 20:16:01 -04:00
parent 6799163cd4
commit a59edf8410
6 changed files with 78 additions and 4 deletions
+50
View File
@@ -0,0 +1,50 @@
package tui
import (
"fmt"
"strings"
"gitea.lerkolabs.com/lerkolabs/uptop/internal/monitor"
)
func (m Model) uptimeTimeline(days []monitor.DayReport, width int) string {
if len(days) == 0 {
return m.st.subtleStyle.Render("No uptime data")
}
maxDays := width - 10
if maxDays < 10 {
maxDays = 10
}
display := days
if len(display) > maxDays {
display = display[len(display)-maxDays:]
}
var sb strings.Builder
for _, d := range display {
ch := "█"
switch {
case d.UptimePct >= 99.0:
sb.WriteString(m.st.specialStyle.Render(ch))
case d.UptimePct >= 95.0:
sb.WriteString(m.st.warnStyle.Render(ch))
case d.UptimePct > 0:
sb.WriteString(m.st.dangerStyle.Render(ch))
default:
sb.WriteString(m.st.subtleStyle.Render("░"))
}
}
pct := days[len(days)-1].UptimePct
pctStyle := m.st.specialStyle
if pct < 99.0 {
pctStyle = m.st.dangerStyle
} else if pct < 99.9 {
pctStyle = m.st.warnStyle
}
sb.WriteString(" " + pctStyle.Render(fmt.Sprintf("%.2f%%", pct)))
return sb.String()
}