Commit Graph

10 Commits

Author SHA1 Message Date
Niklas Ye e04cfcf433 feat: Last Seen column tracking Alertmanager re-send heartbeat
Release / build (amd64, darwin) (push) Failing after 10s
Release / build (amd64, linux) (push) Failing after 9s
Release / build (arm64, darwin) (push) Failing after 11s
Release / build (arm64, linux) (push) Failing after 9s
Release / release (push) Has been skipped
The alert list showed only Started, which comes from Prometheus and
never changes for the lifetime of an alert instance. A firing alert
that started 12 days ago looked identical whether Alertmanager
refreshed it 30 seconds ago or went silent a week ago.

terdut-server already tracks this: the webhook upsert sets
received_at on every accepted payload, including the periodic
re-sends issued at repeat_interval, and its archiver treats the
field as a liveness heartbeat. The field was already decoded into
api.Alert.ReceivedAt and simply never rendered.

Add a Last Seen column to the alert tables, rendered with the
existing humanAgo helper. The Alerts and Archived tabs share
alertColumns/alertRows, so both pick it up. The width budget is
re-derived for five columns; the slack constant now accounts for
all of bubbles' per-cell padding, so the table lands exactly on
the terminal width instead of overflowing by two columns as it
did with four.

The detail view gains a matching Last Seen line, with the timeline
labels widened to keep values aligned. Since received_at stops
advancing once an alert resolves, also pull through the server's
resolution_source and show it in the status header
(RESOLVED · alertmanager vs RESOLVED · expiry) so a frozen
timestamp is explained.
2026-07-30 08:48:53 +02:00
Niklas Ye 6834302622 feat: Archived alerts tab with archive/unarchive actions
Release / build (amd64, linux) (push) Failing after 6s
Release / release (push) Has been skipped
Release / build (amd64, darwin) (push) Failing after 5s
Release / build (arm64, darwin) (push) Failing after 6s
Release / build (arm64, linux) (push) Failing after 11s
Add a fourth tab (Alerts | Archived | Schedule | Users).
Archived alerts are fetched lazily on first visit using the
archived=true query param on GET /api/alerts.

Press x from the Alerts list or detail to archive an alert;
the non-archived list refreshes immediately. Press x from the
Archived list or detail to unarchive; the archived list
refreshes. Ack/unack are disabled in the Archived detail view.

New API methods: ArchiveAlert (POST), UnarchiveAlert (DELETE).
ArchivedAt field added to the Alert type.
2026-05-22 13:45:30 +02:00
Niklas Ye f8e085e610 feat: one-week schedule view always starting on Monday 2026-05-22 11:56:47 +02:00
Niklas Ye d4839c9f6b fix: guard against negative schedule table cursor in renderUserPicker 2026-05-22 11:51:24 +02:00
Niklas Ye ffacbee429 feat: week numbers in schedule and week-wide assignment
Schedule table now shows ISO week number (W21) on the first
row of each week visible in the 14-day window (first row and
every Monday); other rows get a 4-space indent. Date column
widened from 16→18 to accommodate the prefix.

New W key in Schedule section opens the user picker in
week-assign mode, which assigns the selected user to all 7
days (Mon–Sun) of the ISO week containing the cursor. The +
key retains single-day assignment. The user picker header and
footer reflect which mode is active.
2026-05-22 11:17:17 +02:00
Niklas Ye 9a50770538 feat: Stage 5 — user management and API key lifecycle
Add full user management section (tab to Users):
- User list table with username, email, created date
- n: create user (username + email form)
- d: delete user with confirmation (cascades API keys)
- k: API key management for selected user
  - n: create new key with name input; one-time reveal
    showing key value and integer key ID prominently
  - r: revoke by integer ID (no list endpoint on server)
- c: copy revealed key to clipboard (atotto/clipboard)

API key listing is unavailable server-side, so the reveal
screen displays the key ID prominently for future revocation.
2026-05-21 14:14:07 +02:00
Niklas Ye ba7a862789 feat: Stage 4 — on-call schedule calendar view
Adds a 14-day schedule list accessible via the Schedule tab.

Keybindings in schedule section:
  ←/→ (or h/l)  shift the 2-week window back/forward by one week
  j/k            navigate rows
  +              open user picker — select a user to assign to the date
  d              delete the selected day's assignment (y/N confirmation)
  r              refresh schedule from server

The user picker fetches the user list from the server on first open
(cached for the session). Selecting a user assigns them to the
highlighted date (POST /api/schedule all-or-nothing; 409 conflicts
surface as a status bar error).

The on-call header shows today's scheduled person and the current
window date range. On-call data refreshes on schedule actions.

API additions: GetSchedule, GetCurrentOnCall, AssignSchedule,
DeleteScheduleEntry, ListUsers. ScheduleEntry and User types added.
2026-05-21 13:56:57 +02:00
Niklas Ye b5ee62f145 feat: Stage 3 — alert detail, acknowledge, comments, stats charts
Press enter on any alert to open a full-screen detail pane (viewport).
Keybindings in detail mode:
  a/A   acknowledge / unacknowledge (updates immediately)
  c     compose a comment (text input at bottom)
  [/]   cycle comment cursor up/down
  d     delete selected comment (y/N confirmation)
  s     assign placeholder — shows "not yet supported by server"
  S     open stats view: top alerts + by-hour/by-day ASCII bar charts
  esc   back to dashboard

API additions: GetAlert, AcknowledgeAlert, UnacknowledgeAlert,
GetComments, AddComment, DeleteComment, GetTopAlerts,
GetStatsByHour, GetStatsByDay.
2026-05-21 13:48:01 +02:00
Niklas Ye e29cff21ae feat: Stage 2 — alert dashboard with live table and stats
Adds a bubbles/table alert list showing Name, Status, Started (relative
time), and Ack By columns. Stats bar shows total/firing/resolved counts.
Filter cycles firing → resolved → all with [f]. Auto-refresh fires on
the configured interval via tea.Tick. Table scrolls with j/k.
2026-05-21 13:37:05 +02:00
Niklas Ye 55ee64530b feat: Stage 1 scaffold — config, API client, placeholder TUI
Sets up the full project structure following the hactl/gokapi-tui
architecture: strict Elm-pattern Bubbletea TUI, YAML config at
~/.config/terdut-tui/config.yaml, REST API client with Bearer auth,
self-update via GitHub Releases, and a three-section tab placeholder
(Alerts / Schedule / Users) that verifies server connectivity on startup.
2026-05-21 13:28:13 +02:00