feat(realtime): live admin room list (LC-177) #222

Merged
nrupard merged 1 commit from feat/lc-177-live-admin-rooms into main 2026-05-26 19:52:59 +02:00
Owner

Closes LC-177 (split from LC-175). The admin room list (/admin/rooms) was static-on-load: edit / invite / regenerate-invite changed a #room-{id} row only in the acting admin's response, and archive removed it only there. Mechanically symmetric to the LC-175 admin-user surface.

Changes

  • New AdminRoomChanged { room_id, removed } event, broadcast on the admin topic. render_room_row (called by edit / invite / regenerate) fires it with removed = false; post_archive_room fires removed = true.
  • The WS send task renders the matching #room-{id} row OOB (RoomRowFragment gains an oob flag) or an hx-swap-oob="delete" tombstone (room_row_delete.html). build_admin_room_view is factored out of render_room_row and shared with the WS renderer.
  • admin_layout.html already subscribes admin pages to the admin topic (LC-175), so no template-subscribe change. The WS arm + render_admin_room_row are #[cfg(standalone)] (admin routes are standalone-only); in saas the event never fires and falls to render_event (None).
  • admin/rooms.html gets {% let oob = false %} before the row loop so the page-render include resolves the new conditional.

Verification

just test standalone green (106 ok). just test-saas green except the documented routes_uploads nondeterministic flake (its own parallel test threads race on shared upload-dir state) - confirmed 12/12 passing single-threaded in saas; this change touches only the admin room list + ws.rs + events, nothing upload-related. cargo clippy / cargo fmt clean. Regression test (routes_quotas::admin_room_list_is_wired_for_live_row_updates) asserts the OOB-targetable row id and that page-rendered rows are not themselves OOB.

Closes LC-177 (split from LC-175). The admin room list (`/admin/rooms`) was static-on-load: edit / invite / regenerate-invite changed a `#room-{id}` row only in the acting admin's response, and archive removed it only there. Mechanically symmetric to the LC-175 admin-user surface. ## Changes - New `AdminRoomChanged { room_id, removed }` event, broadcast on the `admin` topic. `render_room_row` (called by edit / invite / regenerate) fires it with `removed = false`; `post_archive_room` fires `removed = true`. - The WS send task renders the matching `#room-{id}` row OOB (`RoomRowFragment` gains an `oob` flag) or an `hx-swap-oob="delete"` tombstone (`room_row_delete.html`). `build_admin_room_view` is factored out of `render_room_row` and shared with the WS renderer. - `admin_layout.html` already subscribes admin pages to the `admin` topic (LC-175), so no template-subscribe change. The WS arm + `render_admin_room_row` are `#[cfg(standalone)]` (admin routes are standalone-only); in saas the event never fires and falls to `render_event` (None). - `admin/rooms.html` gets `{% let oob = false %}` before the row loop so the page-render include resolves the new conditional. ## Verification `just test` standalone green (106 ok). `just test-saas` green except the documented `routes_uploads` nondeterministic flake (its own parallel test threads race on shared upload-dir state) - confirmed **12/12 passing single-threaded** in saas; this change touches only the admin room list + ws.rs + events, nothing upload-related. `cargo clippy` / `cargo fmt` clean. Regression test (`routes_quotas::admin_room_list_is_wired_for_live_row_updates`) asserts the OOB-targetable row id and that page-rendered rows are not themselves OOB.
feat(realtime): live admin room list (archive/edit/invite/regenerate) (LC-177)
All checks were successful
check-secrets / Kingfisher (push) Successful in 9s
check-secrets / Nosey parker (push) Successful in 5s
check-secrets / TruffleHog (push) Successful in 6s
check-secrets / Nosey parker (pull_request) Successful in 5s
check-secrets / TruffleHog (pull_request) Successful in 7s
check-secrets / Kingfisher (pull_request) Successful in 10s
Create release / Create release from merged PR (pull_request) Has been skipped
Check / clippy + fmt + tests (pull_request) Successful in 3m19s
e7ece06764
Second admin surface of LC-175, split out. The admin room list (/admin/rooms) was static-on-load: edit / invite / regenerate-invite changed a #room-{id} row only in the acting admin's response, and archive removed it only there. Mechanically symmetric to the LC-175 admin-user surface.

- New AdminRoomChanged { room_id, removed } event, broadcast on the `admin` topic. render_room_row (called by edit / invite / regenerate) fires it with removed=false; post_archive_room fires removed=true.
- The WS send task renders the matching #room-{id} row OOB (RoomRowFragment gains an `oob` flag) or an hx-swap-oob="delete" tombstone (room_row_delete.html). build_admin_room_view is factored out of render_room_row and shared with the WS renderer.
- admin_layout.html already subscribes admin pages to the `admin` topic (LC-175), so no template-subscribe change. The WS arm + render_admin_room_row are #[cfg(standalone)] (admin routes are standalone-only); in saas the event never fires and falls to render_event (None).

admin/rooms.html gets `{% let oob = false %}` before the row loop so the page-render include resolves the new conditional.

Regression test asserts the room list renders the OOB-targetable row id and that page-rendered rows are not themselves OOB.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
nrupard deleted branch feat/lc-177-live-admin-rooms 2026-05-26 19:52:59 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
psa-systems/lets-chat!222
No description provided.