feat(room): split About vs Manage IA + polish both pages (LC-454) #442

Merged
longjacksonle merged 1 commit from feat/room-info-settings-redesign into main 2026-06-24 21:12:54 +02:00

What

Rethinks the room admin information architecture and polishes both pages. Closes LC-454 (subtasks LC-455..459). IA was proposed and approved before building.

Information architecture (approved)

  • Info -> "About" (/room/{id}/info, any member): read-oriented. The "Docs" tab is renamed About (Description + Wiki); Pinned and Files unchanged; a new Preferences tab holds the personal per-room nickname. The delete-room Danger zone leaves this page.
  • Moderators -> "Manage" (/room/{id}/manage, admin/mod): GET /room/{id}/moderators now 302-redirects to /manage for back-compat. The mutating action routes (POST grant, DELETE revoke, posting-policy, retention) keep their original URLs. Sections become standardized cards: Posting policy, Integrations (webhooks/email/feeds grouped), Roles & overrides, Message retention (caution card), and the Danger zone (delete room, moved here).

Gating preserved (not loosened)

  • Manage page stays room_can_manage_overrides, which is enclave_can_manage (perms.rs) - so moving Delete here changes who can do it for nobody.
  • Integration routes stay is_room_moderator (unchanged, not folded into the stricter page gate).
  • post_delete_room is untouched; the type-to-confirm is client-side only (button disabled until the phrase matches + native confirm()). Save feedback is additive (new SettingsFeedback status + toast OOB to the global #lc-toast-region); no existing hx-swap-oob target changed.

Polish

Shared .lc-set-* cards + .btn/.input everywhere; one shared empty-state partial (icon + muted text) across description/wiki/pinned/files/overrides; posting-policy + nickname Saves return the settings status + toast (were silent); retention is a caution card with a state pill and a "preview only" note; unified headers; light/dark via tokens.

How to test

  • Delete-room confirm: Manage page (as enclave owner/admin) -> Danger zone: Delete is disabled until you type delete this room; then it enables and submits (native confirm as a second guard). post_delete_room unchanged.
  • Role-gated visibility: plain member sees no "Manage" header action; GET /room/{id}/manage 403s and /moderators 302s to it; the About page shows no Danger zone. Enclave owner/admin/site-admin see both. A room moderator who is not enclave-admin still reaches webhooks/email/feeds by their own routes (gate unchanged).
  • Save feedback: change posting policy / nickname -> inline status + toast.

Verification

just build-css, just check (clippy + fmt clean), just test, just test-saas all green (updated one contract assertion: the tab label "Docs" -> "About"). just verify built the release binary clean, but its server-up harness does not supply the mandatory LETS_CHAT_BUNYIP_SSO_* startup vars, so the standalone server cannot boot to serve /login in this sandbox (environmental, not a regression).

Flagged separately (not in this PR)

Per the request: in the chat view, thread/reply rendering looks muddled - inline quoted-reply stubs and the "1 reply" pill don't clearly convey parent-reply-thread relationships. Left untouched here for a focused follow-up.

🤖 Generated with Claude Code

## What Rethinks the room admin information architecture and polishes both pages. Closes LC-454 (subtasks LC-455..459). IA was proposed and approved before building. ## Information architecture (approved) - **Info -> "About"** (`/room/{id}/info`, any member): read-oriented. The "Docs" tab is renamed **About** (Description + Wiki); **Pinned** and **Files** unchanged; a new **Preferences** tab holds the personal per-room nickname. The delete-room Danger zone leaves this page. - **Moderators -> "Manage"** (`/room/{id}/manage`, admin/mod): `GET /room/{id}/moderators` now **302-redirects** to `/manage` for back-compat. The mutating action routes (POST grant, DELETE revoke, posting-policy, retention) keep their original URLs. Sections become standardized cards: **Posting policy**, **Integrations** (webhooks/email/feeds grouped), **Roles & overrides**, **Message retention** (caution card), and the **Danger zone** (delete room, moved here). ## Gating preserved (not loosened) - Manage page stays `room_can_manage_overrides`, which **is** `enclave_can_manage` (perms.rs) - so moving Delete here changes who can do it for nobody. - Integration routes stay `is_room_moderator` (unchanged, not folded into the stricter page gate). - `post_delete_room` is untouched; the type-to-confirm is **client-side only** (button disabled until the phrase matches + native confirm()). Save feedback is **additive** (new SettingsFeedback status + toast OOB to the global `#lc-toast-region`); no existing `hx-swap-oob` target changed. ## Polish Shared `.lc-set-*` cards + `.btn`/`.input` everywhere; one shared empty-state partial (icon + muted text) across description/wiki/pinned/files/overrides; posting-policy + nickname Saves return the settings status + toast (were silent); retention is a caution card with a state pill and a "preview only" note; unified headers; light/dark via tokens. ## How to test - **Delete-room confirm:** Manage page (as enclave owner/admin) -> Danger zone: Delete is disabled until you type `delete this room`; then it enables and submits (native confirm as a second guard). `post_delete_room` unchanged. - **Role-gated visibility:** plain member sees no "Manage" header action; `GET /room/{id}/manage` 403s and `/moderators` 302s to it; the About page shows no Danger zone. Enclave owner/admin/site-admin see both. A room moderator who is not enclave-admin still reaches webhooks/email/feeds by their own routes (gate unchanged). - **Save feedback:** change posting policy / nickname -> inline status + toast. ## Verification `just build-css`, `just check` (clippy + fmt clean), `just test`, `just test-saas` all green (updated one contract assertion: the tab label "Docs" -> "About"). `just verify` built the release binary clean, but its `server-up` harness does not supply the mandatory `LETS_CHAT_BUNYIP_SSO_*` startup vars, so the standalone server cannot boot to serve `/login` in this sandbox (environmental, not a regression). ## Flagged separately (not in this PR) Per the request: in the chat view, thread/reply rendering looks muddled - inline quoted-reply stubs and the "1 reply" pill don't clearly convey parent-reply-thread relationships. Left untouched here for a focused follow-up. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
feat(room): split About vs Manage information architecture + polish (LC-454)
All checks were successful
check-secrets / Nosey parker (pull_request) Successful in 5s
check-secrets / TruffleHog (pull_request) Successful in 5s
check-secrets / Nosey parker (push) Successful in 14s
check-secrets / Kingfisher (pull_request) Successful in 16s
check-secrets / Kingfisher (push) Successful in 17s
check-secrets / TruffleHog (push) Successful in 18s
Check / clippy + fmt + tests (pull_request) Successful in 3m24s
Create release / Create release from merged PR (pull_request) Has been skipped
72693b6cff
Room config was scattered across two chat-header pages with no clear model: "Info" mixed read content, a personal nickname setting, room metadata, and a destructive delete action; "Moderators" was really a room-admin settings page whose name undersold it.

Reorganized to a read-vs-admin split (approved IA):

- Info becomes read-oriented "About" (Description, Wiki on the renamed About tab; Pinned; Files) plus a new personal "Preferences" tab holding the per-room nickname. The Danger zone (delete room) leaves this page.
- Moderators becomes "Manage" at /room/{id}/manage; GET /room/{id}/moderators 302-redirects there for back-compat. The mutating action routes (POST grant, DELETE revoke, posting-policy, retention) keep their original URLs. Sections become standardized cards: Posting policy, Integrations (webhooks/email/feeds grouped), Roles & overrides, Message retention (caution card), and the Danger zone (delete room) moved here.

Gating preserved exactly: the Manage page stays room_can_manage_overrides (== enclave_can_manage, so moving Delete here changes who can do it for nobody); the integration routes stay is_room_moderator; post_delete_room is untouched.

Polish: every section uses the .lc-set-* card vocabulary + .btn/.input; one shared empty-state partial (icon + muted text) across description/wiki/pinned/files/overrides; posting-policy and nickname Saves now return the shared SettingsFeedback status + toast (additive - no existing hx-swap-oob target changed); retention is a caution card with a state pill and a "preview only" note; the delete-room Danger zone reuses the Settings delete-account type-to-confirm friction (client-side gate in roominfo.js, button disabled until the phrase matches, native confirm() as second guard); headers unified with Settings/Transcripts; light/dark via tokens.

Verified: just build-css, just check (clippy+fmt clean), just test, just test-saas all green. just verify built the release binary clean but its server-up harness does not supply the mandatory LETS_CHAT_BUNYIP_SSO_* startup vars, so the standalone server cannot boot to serve /login in this sandbox (environmental, not a regression).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
longjacksonle scheduled this pull request to auto merge when all checks succeed 2026-06-24 21:09:42 +02:00
longjacksonle deleted branch feat/room-info-settings-redesign 2026-06-24 21:12:54 +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!442
No description provided.