27008086b0fac1b5a32a8d3c9e244e516171b7ac
5 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
27008086b0 |
Follow terdut-server into teams: switch team, per-team schedule
terdut-server v0.12 made everything team-scoped and v0.20 is what this
client now targets. Against it the old client was wrong in three ways:
the schedule moved to /api/teams/{id}/schedule, GET /api/schedule/current
became a list with one entry per team, and users, incidents, alerts and
schedule entries all grew fields the client ignored.
T steps through all teams and then each of yours. The header names what
is showing, and incident and alert rows gain a Team column when more than
one team can appear. team: in config.yaml picks the team to start on, by
name or id; an unknown one is reported and falls back to all teams.
The schedule is one team's rota, so it shows the active team, or with
all teams showing the first one you own. Writes need an owner or an
administrator, and the picker offers only the team's members, since the
server answers 404 for anybody else. Both are checked up front and the
reason goes in the status bar, rather than surfacing as a 403 after the
user has picked somebody. Stats are not team-scoped by the server and
stay that way here.
Users shows an admin/disabled Flags column. Creating and deleting users
is administrators only, and topic, keys and password work on your own
row or on anyone's for an administrator; the server enforces the same
rule, this only explains it before the round trip.
The server has no version endpoint, so an older one is recognised by
GET /api/teams answering 404, and the TUI says it needs v0.20 or later.
Connecting now also loads /api/teams and /api/me with the key, which
means a wrong key fails on start instead of on the first list; /healthz
does not check it. There is no fallback to the pre-team paths.
Rebuilding a table whose column count changes under loaded rows panicked
inside bubbles, because it re-renders the old rows on SetColumns. The
rows are now cleared first and the cursor put back, so a refresh still
does not jump to the top.
Escalation ladders, invites, integrations and the admin settings are
left to the server's web UI. Checked against a real v0.20.1 server with
two teams, an administrator and a plain member.
Breaking: requires terdut-server v0.20.0 or later. Use terdut-tui v0.9.x
with servers before v0.12.
|
||
|
|
e0c5a5cba3 |
Set a user's web UI password from the Users section
terdut-server v0.10.2 serves a web UI you sign in to with a password, and every user starts without one. Until now the only way to give somebody their first password was a curl call with an API key. p in Users sets the selected user's password. The form asks for the current password only in the one case the server checks it: you are changing your own password and already have one. The client has no other way to know who its key belongs to, so opening the form calls GET /api/me first and shows the fields once that answers. Setting someone else's password sends no current_password at all, rather than an empty one. Length (at least 10) and the repeated entry are checked before anything is sent, mirroring the server's rule so a typo costs no round trip. The server stays authoritative: a wrong current password comes back as its own 403 message on the dashboard. The status line says the user's other web sessions were signed out, because the server does that on every password change. API keys are not affected. Older servers have no /api/me. The client now returns a typed StatusError carrying the status code, so a 404 there reads as "needs terdut-server v0.10.2 or later" rather than a bare "server returned 404". Its Error() text is unchanged, so every existing message reads as before. Requires terdut-server v0.10.2 only for this form. Everything else works against the same servers as before. |
||
|
|
e336aeea97 |
feat: reassign on-call days and weeks to another person
Release / test (push) Failing after 4s
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
Assigning over a day somebody else held did nothing but flash a 409 for three seconds. The server holds one person per date and refused any that was taken, all-or-nothing, so pressing W on a week where a single day was already assigned placed none of the other six either. The only way through was d on each day first — seven delete-and-confirm cycles to move one week. The clash is already on screen, so it is found before the request rather than read back out of an error: the picker hands off to a confirmation naming who loses the days and how many there are, and accepting sends the whole selection with replace, which terdut-server v0.8.0 added. One question to move a week, and nobody's shift moves without somebody being asked. A day nobody holds still assigns with no prompt at all. Reassigning somebody to a day they already hold raises no prompt, since it takes nothing from anyone, but it does send replace: the server rejects any date that exists, so without it a harmless no-op would fail. |
||
|
|
85ad2d65ee |
feat: ntfy topics per user, and notifications on the timeline
Release / test (push) Failing after 6s
Release / release (push) Has been skipped
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
terdut-server pages the on-call person through ntfy, but none of it was reachable from here. A user's topic could only be set with curl, so a new user silently got no pages and quietly fell back to the shared fallback topic — which carries no Acknowledge button. And nothing said whether anybody had been paged at all. The Users section grows an Ntfy Topic column and t to edit it, prefilled with the current value. Submitting an empty field clears the topic rather than being rejected as a mistake: clearing is how somebody is taken off their own topic, and it is what the server means by an empty string. Nil and empty arrive as the same thing, because the server stores a blank topic as NULL, so User.Topic flattens the two instead of leaving every caller to. The incident timeline renders the server's notified and notify_failed events. No new fetch — the timeline endpoint already carried them, and unknown types already fell through to a generic label; this is about saying something useful. An event with no user means the fallback topic, not "the server acted", which is the difference between somebody having been paged and the rota having been empty. Both need terdut-server v0.6.0 or later, and the timeline entries a server newer than that. Against an older one the column stays empty and editing a topic reports the server's 404, which is the honest answer. |
||
|
|
8482315651 |
test: cover the API client and the update loop
The repo had no tests at all, which the v0.4.0 rewrite made
uncomfortable: this client speaks terdut-server's REST API directly, and
a wrong path or method is invisible until somebody runs the binary
against a live server. That is exactly how it broke when the server split
alerts from incidents.
The Elm architecture makes most of this cheap to check without a
terminal. Update is (Model, Msg) -> (Model, Cmd), so keypresses can be
synthesised and the resulting model inspected; a nil command is a
readable assertion that the model decided to do nothing.
Three suites:
- client_test.go drives every incident endpoint against an httptest
stub that records method, path, query and body. Also covers the
filter query params, that a server error message survives into the
error the UI shows, that a 404 from the on-call endpoint is not an
error, and that omitted optional fields decode to zero rather than
failing.
- model_test.go covers the pure helpers: filter cycling, the snoozed
pseudo-status, duration formatting, row builders, and the column
width arithmetic that overflowed the terminal once already.
- update_test.go covers the rules worth protecting rather than
coverage for its own sake. Resolve prompts first and cancelling does
not act, since resolution is terminal server-side. A resolved
incident rejects all six workflow keys. Archiving refuses while an
incident is open. The note cursor walks notes only and wraps. Stats
returns to whichever view opened it. Modal states do not auto-refresh
underneath the user.
129 tests, running in about 40ms.
|