feat!: stats as a section instead of an overlay
Release / test (push) Failing after 6s
Release / build (amd64, darwin) (push) Has been skipped
Release / build (amd64, linux) (push) Has been skipped
Release / build (arm64, darwin) (push) Has been skipped
Release / build (arm64, linux) (push) Has been skipped
Release / release (push) Has been skipped
Release / test (push) Failing after 6s
Release / build (amd64, darwin) (push) Has been skipped
Release / build (amd64, linux) (push) Has been skipped
Release / build (arm64, darwin) (push) Has been skipped
Release / build (arm64, linux) (push) Has been skipped
Release / release (push) Has been skipped
Stats was the one full-screen view reached by a key of its own rather than by tab, and the interface was less coherent for it. It is now a section sitting third, after Alerts, and behaves like every other one: tab in, tab out, r to refresh. Three things fall out of the move. It auto-refreshes for the first time — the tick handler skips every non-dashboard mode, which is why the overlay never updated while it was open. Its error path no longer forces the queue back into view on a failed fetch, an assumption that only made sense while stats floated above the dashboard. And first-visit loading keys off a statsLoaded flag rather than slice emptiness, because the three empty slices a quiet server returns are a real answer, not a missing one; the loading placeholder is likewise suppressed once something has been drawn, so a background refresh cannot blank the page out from under whoever is reading it. The S key is gone, and with it the ability to peek at statistics from an open incident and land back on it. That round-trip was the only thing statsReturnMode bought, and it was the whole reason stats needed a mode.
This commit is contained in:
+21
-8
@@ -21,11 +21,12 @@ const (
|
||||
// Incidents lead: they are the work. Alerts is the raw feed underneath.
|
||||
sectionIncidents section = iota
|
||||
sectionAlerts
|
||||
sectionStats
|
||||
sectionArchived
|
||||
sectionSchedule
|
||||
sectionUsers
|
||||
|
||||
sectionCount = 5
|
||||
sectionCount = 6
|
||||
)
|
||||
|
||||
type mode int
|
||||
@@ -37,7 +38,6 @@ const (
|
||||
modeNote
|
||||
modeSnooze
|
||||
modeConfirm
|
||||
modeStats
|
||||
modeUserPicker
|
||||
modeUserCreate
|
||||
modeAPIKeyMenu
|
||||
@@ -195,14 +195,14 @@ type Model struct {
|
||||
pendingDeleteEntry *api.ScheduleEntry
|
||||
|
||||
// Stats
|
||||
topAlerts []api.TopAlert
|
||||
hourStats []api.HourStat
|
||||
dayStats []api.DayStat
|
||||
topAlerts []api.TopAlert
|
||||
hourStats []api.HourStat
|
||||
dayStats []api.DayStat
|
||||
// statsLoaded tracks the first fetch separately from emptiness: a server with
|
||||
// no alerts yet legitimately returns three empty slices.
|
||||
statsLoaded bool
|
||||
statsLoading bool
|
||||
statsViewport viewport.Model
|
||||
// statsReturnMode is where esc goes back to, since stats opens from both
|
||||
// the dashboard and an incident.
|
||||
statsReturnMode mode
|
||||
|
||||
// Schedule
|
||||
scheduleWindow time.Time
|
||||
@@ -253,6 +253,10 @@ func NewModel(client *api.Client, serverURL string, refreshInterval time.Duratio
|
||||
manageT := table.New(table.WithFocused(true))
|
||||
manageT.SetStyles(ts)
|
||||
|
||||
// Sized by the first tea.WindowSizeMsg; built here so it carries the default
|
||||
// scroll keymap, which the zero value lacks.
|
||||
statsVP := viewport.New(0, 0)
|
||||
|
||||
noteIn := textinput.New()
|
||||
noteIn.Placeholder = "type your note…"
|
||||
noteIn.CharLimit = 1000
|
||||
@@ -298,6 +302,7 @@ func NewModel(client *api.Client, serverURL string, refreshInterval time.Duratio
|
||||
incidentTable: incidentT,
|
||||
alertTable: alertT,
|
||||
archivedTable: archivedT,
|
||||
statsViewport: statsVP,
|
||||
noteInput: noteIn,
|
||||
snoozeInput: snoozeIn,
|
||||
scheduleWindow: window,
|
||||
@@ -397,6 +402,14 @@ func (m *Model) refreshStatsContent() {
|
||||
buildStatsContent(m.incidentStats, m.topAlerts, m.hourStats, m.dayStats, m.width))
|
||||
}
|
||||
|
||||
func (m Model) statsViewportHeight() int {
|
||||
h := m.height - 5
|
||||
if h < 1 {
|
||||
h = 1
|
||||
}
|
||||
return h
|
||||
}
|
||||
|
||||
func (m Model) detailViewportHeight() int {
|
||||
h := m.height - 5
|
||||
if m.mode == modeNote || m.mode == modeSnooze {
|
||||
|
||||
Reference in New Issue
Block a user