Commit Graph

331 Commits

Author SHA1 Message Date
lerko 835844314e fix(tui): show context-aware Enter hint in hotbar
CI / test (pull_request) Successful in 1m49s
CI / lint (pull_request) Successful in 1m12s
CI / vulncheck (pull_request) Successful in 50s
When cursor is on a group row, hotbar now shows [Enter]Expand or
[Enter]Collapse instead of [Enter]Detail, matching actual behavior.
2026-06-30 17:09:58 -04:00
lerko dc79e2baaa refactor(tui): remove full-page detail, SLA, and history views
CI / test (pull_request) Successful in 1m49s
CI / lint (pull_request) Successful in 1m16s
CI / vulncheck (pull_request) Successful in 56s
All monitor detail content now lives in the sidebar panel.
Delete the full-page viewDetailPanel, viewSLAPanel, viewHistoryPanel,
handleDetailKey, handleSLAKey, handleHistoryKey, openSLAView, and
related dead code (histogram, sparkline tooltip, detailViewport).

Remove stateDetail, stateSLA, stateHistory session states.
Update tests to use detailOpen/detailMode instead of removed states.
2026-06-30 09:28:12 -04:00
lerko 3e02833df4 feat(tui): enter opens detail sidebar, logs as bottom strip
Enter on a site now opens the detail sidebar instead of a
full-page takeover. Enter on a group expands/collapses children
(same as space). Logs panel moves to a toggleable bottom strip
via the l key with j/k scrolling when focused.
2026-06-30 09:12:13 -04:00
lerko 8581662237 feat(tui): SLA and history as sidebar detail modes
SLA and History views now render inside the detail sidebar panel
instead of taking over the full screen. Press s/h to switch modes,
Esc to return to default detail view. Cursor movement resets to
default mode.

- Add detailMode state (detailDefault/detailSLA/detailHistory)
- SLA sidebar: period selector, uptime bars, daily breakdown
- History sidebar: sparkline density, transition list, stats
- Panel title shows "SLA · name" or "History · name" in sub-modes
- Period keys [1]-[4] work in SLA mode from dashboard state
2026-06-30 09:09:04 -04:00
lerko 2779f9f532 feat(tui): tall-narrow detail sidebar for master-detail layout
Replace the old two-column/single-column inline detail with a
vertically stacked layout optimized for the right-side panel.

Content stack: status line, type details, uptime, error, latency
chart (3-row), 30d timeline, sparkline, min/avg/max stats, and
up to 5 state changes — all flowing top-to-bottom within the
~55% width detail panel.
2026-06-30 09:03:30 -04:00
lerko 4321e094a3 feat(tui): move detail panel from bottom overlay to right side
Restructure dashboard from [Monitors 70% | Logs 30%] to
[Monitors 45% | Detail 55%] master-detail layout. Detail panel
now sits beside the monitor list instead of below it, keeping
dashboard context visible during inspection.

- Detail panel renders in horizontal split (right of monitors)
- Logs sidebar removed; `l` key opens fullscreen logs directly
- recalcLayout no longer subtracts detail height from table rows
- Remove unused renderCompactLogLine/viewLogsSidebar (Phase 4 recreates)
2026-06-30 08:59:17 -04:00
lerko 1856820c3e feat(tui): single-dashboard layout with sidebar and overlay
CI / test (pull_request) Successful in 1m44s
CI / lint (pull_request) Successful in 1m16s
CI / vulncheck (pull_request) Successful in 50s
Replace 3-tab navigation with a single monitoring dashboard.

- Replace tab bar with minimal status line (pulse + counts + version)
- Maintenance becomes a toggleable left sidebar (m key)
  - Compact list: active (●) and scheduled (○) windows
  - Enter opens full-screen detail with end/delete actions
- Settings becomes a centered floating overlay (S key)
  - Alerts/Nodes/Users sub-sections with left/right navigation
  - Full CRUD support inside overlay with returnState tracking
- Remove currentTab, switchTab, tab constants, tab click zones
- Replace deleteTab with deleteKind string for cleaner dispatch
- Separate settingsCursor/settingsOffset from main cursor
- Panel focus: maint → monitors → logs → detail
- Context-sensitive footer key hints per focused panel
2026-06-29 16:12:53 -04:00
lerko aeee2cd0ce fix(tui): cohesion polish across all views
CI / test (pull_request) Successful in 1m44s
CI / lint (pull_request) Successful in 1m16s
CI / vulncheck (pull_request) Successful in 56s
- Hide nonsense latency/histogram data for group monitors in detail view
- Add missing status colors to fmtStatusWord (LATE, STALE, PENDING, etc)
- Wrap Maint and Settings tabs in titled panels to match Monitors tab
- Standardize headers: breadcrumb style (History > Name, SLA > Name)
- Standardize footer key order: actions first, [q/Esc] Back last
- Add # column to Nodes table for consistency with all other tables
- Use titleStyle for section headers (CONFIGURATION, DAILY BREAKDOWN)
- Fix panel focus not switching when clicking monitor rows from logs panel
2026-06-29 11:06:58 -04:00
lerko 7ce5af5bf6 fix(tui): correct delete confirm labels, normalize help text
CI / test (pull_request) Successful in 1m52s
CI / lint (pull_request) Successful in 1m11s
CI / vulncheck (pull_request) Successful in 56s
Delete confirmation dialog used wrong magic numbers for entity kind
mapping — maintenance windows showed as "alert", settings deletions
showed as "monitor". Now uses tab/section constants to match correctly.

Also: consistent [q/Esc] Back across all views (detail inline, logs,
SLA, history headers), extract detailKeys(), remove dead maxSections
variable, add nodes empty state hint, use models.Status constants in
siteOrder, delete orphaned theme.png.
2026-06-29 09:44:51 -04:00
lerko 18e2d60210 feat(tui): mouse click for settings sections, column sort, logs panel
CI / test (pull_request) Successful in 1m44s
CI / lint (pull_request) Successful in 1m17s
CI / vulncheck (pull_request) Successful in 56s
- Click Alerts/Nodes/Users sub-tabs in settings to switch sections
- Click STATUS/NAME/LATENCY column headers to sort (click again
  to reverse direction)
- Logs panel show/hide: [l] toggles sidebar visibility, click
  focused panel to hide. Monitors expand to full width when hidden.
- Logs full-screen: Enter when focused on logs opens scrollable
  full-screen log view with severity tags, filter toggle [f],
  and live updates
2026-06-28 12:24:52 -04:00
lerko ab1194f74d fix(monitor): refresh maintenance cache after loading sites
CI / test (pull_request) Successful in 1m49s
CI / lint (pull_request) Successful in 1m17s
CI / vulncheck (pull_request) Successful in 56s
Move refreshMaintenanceCache() to after sites are loaded into
liveState. Previously it ran before the site loading loop, so on
the first iteration liveState was empty and the cache resolved
to nothing. This caused groups to briefly show DOWN on startup
for children that were in maintenance, until the next poll cycle
repopulated the cache.
2026-06-28 11:15:35 -04:00
lerko 25f4b20b87 feat(monitor): save state changes for group monitors
CI / test (pull_request) Successful in 1m57s
CI / lint (pull_request) Successful in 1m11s
CI / vulncheck (pull_request) Successful in 56s
checkGroup() now detects status transitions and persists them as
state change records, same as individual monitors. Groups also
get StatusChangedAt updates and log entries for down/recovery
events. This enables history and SLA views for group monitors.
2026-06-28 11:00:25 -04:00
lerko 7171dcd6f8 feat(tui): expand selected alert config below table
CI / test (pull_request) Successful in 1m51s
CI / lint (pull_request) Successful in 1m22s
CI / vulncheck (pull_request) Successful in 56s
Show a detail line below the alert table for the selected row
with untruncated config, health status, last sent time, and
send/fail counts. Solves the CONFIG column truncation issue
without requiring the full-screen detail view.
2026-06-28 10:41:25 -04:00
lerko 822eda4dfd feat(tui): two-column detail panel with type-specific enrichment
CI / test (pull_request) Successful in 1m52s
CI / lint (pull_request) Successful in 1m17s
CI / vulncheck (pull_request) Successful in 51s
Redesign the inline detail panel from a single left-aligned column
to a two-column layout that uses the full panel width.

Left column (55%): latency chart, min/avg/max stats, 30-day
uptime timeline.

Right column (45%): status/latency/last-check summary, type-
specific metadata (HTTP response code + SSL expiry, ping hostname,
port target, push interval/last heartbeat, DNS resolver), uptime
percentage + retry count, and up to 5 state changes listed
vertically with error reasons.

Narrow terminals (<80 cols) fall back to the original stacked
single-column layout.
2026-06-28 10:23:45 -04:00
lerko a5fd3aec90 refactor: propagate context.Context through call chains
CI / test (pull_request) Successful in 1m56s
CI / lint (pull_request) Successful in 1m17s
CI / vulncheck (pull_request) Successful in 56s
Thread context.Context from callers instead of creating
context.Background() at every call site. Engine stores its
lifecycle ctx for use by triggerAlert goroutines. TUI Model
carries ctx for store operations in Cmd closures. CLI commands
create a root ctx and thread it through openStore, seed
functions, and init methods.

Only two intentional context.Background() remain in non-root
positions: engine constructor default (overridden by Start)
and drainWrites (parent already cancelled at shutdown).
2026-06-27 19:43:44 -04:00
lerko 8f16a09da1 refactor: decompose monitor.go and sqlstore.go into focused files
CI / test (pull_request) Successful in 1m44s
CI / lint (pull_request) Successful in 1m11s
CI / vulncheck (pull_request) Successful in 56s
Split monitor.go (1131→350 lines) into alerts.go, checks.go,
sites.go, and maintenance.go by concern. Split sqlstore.go
(833→470 lines) into sqlstore_alerts.go, sqlstore_history.go,
and sqlstore_maintenance.go by domain. Tests move with their
implementation. Pure reorganization — no behavioral changes.
2026-06-27 19:23:34 -04:00
lerko 50f77da131 refactor: extract magic numbers to named constants
CI / test (pull_request) Successful in 1m43s
CI / lint (pull_request) Successful in 1m17s
CI / vulncheck (pull_request) Successful in 51s
Replace inline numeric literals with named constants across 14 files:
server timeouts/rate limits, cluster thresholds/intervals, DB pool
sizes, alert/dial timeouts, TUI uptime thresholds, node status
thresholds, and state history limits.
2026-06-27 15:44:03 -04:00
lerko edbc2beddd fix(test): check errors instead of discarding with bare _
CI / test (pull_request) Successful in 1m53s
CI / lint (pull_request) Successful in 1m16s
CI / vulncheck (pull_request) Successful in 56s
Replace bare _ error discards with t.Fatalf checks across
sqlstore_test, crypto_test, server_test, and checker_test.
2026-06-27 11:53:10 -04:00
lerko 3a089e7c1d feat(store): detect overlapping maintenance windows
CI / test (pull_request) Successful in 1m46s
CI / lint (pull_request) Successful in 1m16s
CI / vulncheck (pull_request) Successful in 56s
Warn via log when creating a maintenance window that overlaps with an
existing one for the same monitor, parent group, or global scope.
Handles both timed and indefinite windows.
2026-06-27 10:58:43 -04:00
lerko 5cc1a005ea feat(assets): full screenshot refresh for new multi-panel layout
CI / test (pull_request) Successful in 1m50s
CI / lint (pull_request) Successful in 1m17s
CI / vulncheck (pull_request) Successful in 46s
Recaptured all screenshots and demo GIF reflecting the complete TUI
overhaul: 3-tab layout, titled panel borders, log sidebar, inline
detail with latency chart + uptime timeline, full-screen detail with
two-column layout + response histogram.

New screenshots: fulldetail.png, settings.png, maint.png.
Removed: alerts.png, logs.png (now Settings sub-sections and sidebar).
Updated README screenshot grid to match new layout.
2026-06-26 15:57:36 -04:00
lerko 11344b4ae6 feat(tui): two-column bottom layout, endpoint/status split, clean labels
CI / test (pull_request) Successful in 2m4s
CI / lint (pull_request) Successful in 1m11s
CI / vulncheck (pull_request) Successful in 56s
Bottom section: graphs (latency + histogram) 70% left, state changes
30% right. Top section rearranged: endpoint details left, status +
timing + HTTP right. Bottom section labels use bold accent without
trailing rules. Spacing between top and bottom halves.

Removed unused renderSparkTooltip (zone marks not wired in column
layout — can restore later).
2026-06-24 21:11:04 -04:00
lerko 11b647b952 fix(tui): add spacing between latency graph and histogram 2026-06-24 20:58:44 -04:00
lerko 1268d99f5c feat(tui): styled section headers with trailing rules in detail panel
Section labels (STATE CHANGES, LATENCY, RESPONSE TIME DISTRIBUTION,
PROBE RESULTS) now render in bold accent color with a trailing ───
rule that fills the width. Two-column info block separated by a full
divider below. Creates clear visual boundaries between sections.
2026-06-24 20:56:21 -04:00
lerko fb50184f37 feat(tui): two-column detail layout with viewport scrolling
Refactored full-screen detail panel: status+endpoint on left column,
timing+config on right column. Halves vertical height of the info
section. Content wraps in a viewport when it exceeds terminal height
— scroll with j/k/arrows/pgup/pgdn.

Restored renderSparkTooltip lost in rewrite. Fixed lint warnings.
2026-06-24 20:48:15 -04:00
lerko 99121d07d8 feat(tui): response time distribution histogram in full-screen detail
Horizontal bar chart showing latency distribution across 5 buckets:
0-50ms, 50-100ms, 100-200ms, 200-500ms, 500ms+. Color-coded green
(fast), yellow (medium), red (slow). Shows count per bucket.

Appears in the full-screen detail panel (Enter) after the sparkline
stats. Skipped for push monitors (no latency data).
2026-06-24 20:23:22 -04:00
lerko a59edf8410 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.
2026-06-24 20:16:01 -04:00
lerko 6799163cd4 fix(tui): apply sort to group children, not just ungrouped monitors
CI / test (pull_request) Successful in 2m4s
CI / lint (pull_request) Successful in 1m17s
CI / vulncheck (pull_request) Successful in 56s
2026-06-24 19:44:50 -04:00
lerko 28fb6c8889 feat(tui): alert failure badge on Settings tab
Settings tab warn count now includes failed alert channels — alerts
where the last send failed (LastSendOK=false, LastSendAt not zero).
Shows as a red badge number alongside offline node count. Surfaces
broken alert channels without navigating to Settings.
2026-06-21 19:10:18 -04:00
lerko d982359f25 feat(tui): column sort with indicator on monitors table
Press < / > to cycle sort column (Status, Name, Latency). Press r to
reverse direction. Sorted column shows ▲/▼ arrow in the header.

Groups always float to top. Sort applies to ungrouped monitors and
group children independently. Default: Status descending (DOWN first).
2026-06-21 19:09:42 -04:00
lerko 4af800a359 feat(tui): multi-row color-coded sparkline chart with Y-axis
CI / test (pull_request) Successful in 1m48s
CI / lint (pull_request) Successful in 1m17s
CI / vulncheck (pull_request) Successful in 56s
Replace ntcharts with custom multi-row sparkline. Each bar is color-
coded by latency threshold (green < 200ms, yellow < 500ms, red > 500ms)
and DOWN checks render in red. 3 rows tall with 24 discrete levels.

Y-axis labels (max/min ms) on the left, Min/Avg/Max stats below.
Zero external dependencies — removed ntcharts.
2026-06-21 17:43:50 -04:00
lerko a8c43bdb8e feat(tui): ntcharts sparkline with Y-axis labels and stats
Replaced streamline chart with ntcharts sparkline (block elements,
auto-scaling). Height=2, Y-axis labels (max/min ms) on the left,
Min/Avg/Max stats below. Denser and more readable than the line chart.
2026-06-21 17:12:25 -04:00
lerko d0805f61c6 fix(tui): size chart width to data point count 2026-06-21 13:41:05 -04:00
lerko ad469c86eb feat(tui): ntcharts latency line chart in inline detail panel
Replace block-element sparkline with ntcharts streamline chart in the
inline detail panel. Renders a 4-row line chart with thin line style
using the theme accent color. Auto-scales Y axis to latency range.

Added github.com/NimbleMarkets/ntcharts v0.5.1 dependency (lipgloss v1
compatible). Min/Avg/Max stats rendered below the chart.
2026-06-21 13:05:02 -04:00
lerko 01dd53241a refactor: separate log timestamp from message as structured LogEntry
CI / test (pull_request) Successful in 2m4s
CI / lint (pull_request) Successful in 1m12s
CI / vulncheck (pull_request) Successful in 56s
Introduced models.LogEntry{Message, CreatedAt} to replace raw strings
in the log pipeline. Timestamps are now formatted at render time, not
baked into stored messages.

- Engine: appendLog stores LogEntry with time.Now()
- Store: LoadLogs returns []LogEntry, selects created_at from DB
- Store: strips legacy [HH:MM] prefix from pre-refactor DB entries
- TUI: sidebar shows "MM/DD HH:MM" from CreatedAt
- TUI: full log view shows "MM/DD HH:MM" from CreatedAt
- SaveLog still receives plain message string (DB handles timestamp)
2026-06-20 20:04:08 -04:00
lerko 81f8c71b6f feat(tui): persist detail panel state as user preference
Detail open/closed state saved via SetPreference on toggle and
restored on session start. Same pattern as theme persistence —
survives restarts and works per-user over SSH.
2026-06-20 19:50:13 -04:00
lerko 7109b6fa1c feat(tui): panel focus with click, scroll, and keyboard
Click any panel (Monitors, Logs, Detail) to focus it — accent border
follows focus. Mouse wheel scrolls the focused panel.

Keyboard: l toggles log panel focus. Arrow keys scroll logs when
focused, navigate monitors when not. Esc returns focus to monitors.

Log sidebar now supports scroll offset — tracks position across
renders without a viewport. Mouse wheel scrolls 3 lines, keyboard
scrolls 1.
2026-06-20 19:44:35 -04:00
lerko e5ac4a1fec feat(tui): lazygit-style titled panel borders
All panels wrapped in titled rounded borders (╭─ Title ──╮). Focused
panel gets accent-colored border, unfocused panels get muted border.

- Monitors panel: titled "Monitors", focused when detail is closed
- Logs panel: titled "Logs", always unfocused (passive display)
- Detail panel: titled with monitor name, focused when open

Table's own RoundedBorder replaced with HiddenBorder — the titled
panel border provides the visual frame, table uses space-separated
columns internally. Consistent chrome across all panels.
2026-06-20 19:30:59 -04:00
lerko 065d5d74bb fix(tui): remove leading newline from bordered sidebar 2026-06-20 19:24:14 -04:00
lerko 08f14f3af8 feat(tui): bordered log sidebar, Enter for full-screen detail
Log sidebar wrapped in rounded border (no left/bottom edge — shared
with monitors table). Creates visual separation between panels.

Enter on a monitor opens the full-screen detail view (existing
stateDetail) for deep dive — history, SLA, probe results, connection
chain. i stays as inline detail toggle.

Footer key hints now context-sensitive: show h/s/Enter when detail
is open, show full keybindings when closed.
2026-06-20 19:18:57 -04:00
lerko 5720fabdbc fix(tui): limit sidebar height to match table, fix detail clipping
Log sidebar was rendering all lines regardless of table height. When
detail panel was open and table shrank, the sidebar stayed tall, pushing
the detail panel past MaxHeight (clipped to empty). Now sidebar accepts
a maxLines parameter capped to table row count.
2026-06-20 19:13:37 -04:00
lerko 54299583d6 debug: make detail title visible with danger style 2026-06-20 19:08:21 -04:00
lerko c9bd9a5a2e fix(tui): shrink table rows when detail panel is open 2026-06-20 19:02:18 -04:00
lerko 66b0681a76 feat(tui): inline detail panel below monitors table
Press i to toggle a compact detail panel below the monitors+logs
split. Shows status, latency, uptime, state changes, sparkline, and
key hints in ~6 lines. Auto-updates when cursor moves between
monitors. h/s/e keys work from the inline detail for history, SLA,
and edit. Escape closes the panel.

No more full-screen detail takeover for the common case. The old
stateDetail path remains for h/s sub-views which still go full-screen.
2026-06-20 18:58:49 -04:00
lerko 060cd24de2 fix(tui): align log sidebar with monitor table top edge
CI / test (pull_request) Successful in 1m42s
CI / lint (pull_request) Successful in 1m16s
CI / vulncheck (pull_request) Successful in 51s
2026-06-20 18:23:52 -04:00
lerko 5c40629987 fix(tui): clamp log sidebar width, strip redundant prefixes
Log lines now hard-clamped to panel width via lipgloss MaxWidth.
Stripped "Monitor " and "Push " prefixes from sidebar messages —
redundant in a monitoring app, saves 8 chars per line. Improved
prefix width calculation to prevent line wrapping at narrow widths.
2026-06-20 18:17:08 -04:00
lerko e12f42fe16 fix(tui): use panel width for table layout in split-pane mode
Table columns were computed from terminal width, causing row wrapping
when the monitors panel only gets 70% of the space. Introduced
contentWidth field set per-tab in viewDashboard. computeLayout,
isWide, and renderTable now use contentWidth for column visibility,
available space, and max table width calculations.

Columns gracefully hide (SSL, RETRIES, TYPE, UPTIME) when the panel
is narrower, matching the existing responsive breakpoint behavior.
2026-06-20 18:14:01 -04:00
lerko 8323d27e7d feat(tui): compact log sidebar with severity icons
Replace full viewLogsTab with compact sidebar renderer for the 70/30
monitors split. Single-char severity icons (▼▲◆●·), truncated messages,
no header chrome. Renders directly from engine logs without viewport.
2026-06-20 18:06:07 -04:00
lerko 047bb237e0 feat(tui): consolidate 6 tabs to 3, add log sidebar
Tab bar: Monitors | Maint | Settings (was 6 tabs).

Settings tab merges Alerts, Nodes, Users as sub-sections with
left/right arrow navigation. Each section keeps its own cursor,
keybindings, and CRUD operations.

Monitors tab now shows a log sidebar at >= 120 cols (70/30 split).
Under 120 cols, monitors render full-width without logs.

- Introduced tab constants (tabMonitors, tabMaint, tabSettings)
- Introduced section constants (sectionAlerts, sectionNodes, sectionUsers)
- Removed stateLogs and stateUsers states
- All magic tab numbers replaced with named constants
2026-06-20 17:59:47 -04:00
lerko 5398cccd44 feat(tui): add divider lines framing the content area
CI / test (pull_request) Successful in 1m47s
CI / lint (pull_request) Successful in 1m12s
CI / vulncheck (pull_request) Successful in 51s
Full-width horizontal rules above and below the content area. Tab bar
sits above the top divider, status/keys bar sits below the bottom
divider. Creates three clear visual zones: navigation, content, status.
2026-06-20 17:09:40 -04:00
lerko 4bf64c3841 chore(assets): recapture with summary stats bars
CI / test (pull_request) Successful in 1m45s
CI / lint (pull_request) Successful in 1m11s
CI / vulncheck (pull_request) Successful in 56s
2026-06-20 16:48:37 -04:00