[Frontend] Explain gated and blocked states instead of silently hiding or redirecting #382

Closed
opened 2026-08-25 20:42:20 +00:00 by claude-bot · 2 comments
Contributor

Impact: MEDIUM

Found in the August 2026 session lifecycle review (#319).

What the user experiences

Almost every gated or blocked state in the product is handled by hiding the control or silently redirecting, rather than explaining why. A player who follows a shared workbench link gets silently teleported back to the campaign page with no message. A GM sees a "Draft — not yet visible to players" badge on a highlight with no control to approve it and no explanation that approving is a side effect of a completely different button on a different panel. A GM who archives a campaign sees a banner with no restore button and no mention of who (an instance admin, not the GM) can restore it. "Add to shelf" simply vanishes with no explanation when there are no upcoming sessions to add to. A user without edit rights who opens a wiki article's edit URL silently gets the read view rendered at the edit URL, with nothing explaining why their edit didn't take effect.

Evidence

  • webapp/frontend/src/pages/CampaignPlanning.jsx:836-853navigate(..., { replace: true }) on a non-GM with no message shown.
  • webapp/frontend/src/components/SessionHighlights.jsx:265-269 — "Draft — not yet visible to players" badge with no control; only Edit and Delete buttons exist (:281-289), and the state only clears as a side effect of "Approve summary" on SessionDetail.
  • webapp/frontend/src/pages/CampaignDetail.jsx:1268-1292 — the archived-campaign banner names no restore path; canRestoreArchivedCampaign (:1235) requires user?.is_admin, while archiving itself is a GM action (:1365-1373) — a one-way door with no signage of who holds the other key.
  • webapp/frontend/src/components/AddToShelf.jsx:40if (options.length === 0) return null;; the only "keep this" control on every generator vanishes with no explanation.
  • webapp/frontend/src/pages/WikiArticle.jsx:1361isEditMode = mode === "edit" && article?.entry?.can_edit; a user without edit rights opens /wiki/:entryId/edit and silently gets the read view with no message.
  • Contrast: webapp/frontend/src/pages/CampaignNotes.jsx:50-59 and webapp/frontend/src/pages/CampaignHighlights.jsx:74-83 already include a "Back to dashboard" link on their error/blocked states — the pattern for handling this well already exists in the codebase; several wiki pages (WikiProposals.jsx:278-284, WikiNewEntry.jsx:183-189, WikiArticle.jsx:1681-1687, WikiDraftReview.jsx:413-419) just don't follow it, rendering a bare "GM access only." or similar with no navigation at all.

Why it matters for a hosted product

A silent bounce or an unexplained blocked state reads as "the product is broken" rather than "you don't have permission" or "this isn't ready yet" — and a player who can't tell why cannot even ask their GM the right question.

Proposed fix

Replace the silent redirect at CampaignPlanning.jsx:840 with an inline "Prep is GM-only" message. Give SessionHighlights an explicit approve control, or at minimum change the badge text to "Draft — publishes when you approve the session summary". Add a restore hint naming who can restore to the archived-campaign banner. Explain (rather than hide) the empty "Add to shelf" state. Apply the existing "Back to dashboard" pattern from CampaignNotes.jsx/CampaignHighlights.jsx to the four wiki hard-block pages listed above. This is the audit's P13.

Acceptance criteria

  • A non-GM following a workbench link sees an inline explanation instead of a silent redirect.
  • SessionHighlights' draft badge either has an approve control or explains what publishes it.
  • The archived-campaign banner names who can restore the campaign.
  • AddToShelf shows an explanatory empty state instead of disappearing entirely.
  • WikiArticle's edit URL for a non-editor shows a message explaining why the edit view isn't available, instead of silently rendering the read view.
  • WikiProposals, WikiNewEntry, WikiArticle, and WikiDraftReview's hard-block states include navigation back to the dashboard, matching CampaignNotes.jsx/CampaignHighlights.jsx.
**Impact: MEDIUM** Found in the August 2026 session lifecycle review (#319). ## What the user experiences Almost every gated or blocked state in the product is handled by hiding the control or silently redirecting, rather than explaining why. A player who follows a shared workbench link gets silently teleported back to the campaign page with no message. A GM sees a "Draft — not yet visible to players" badge on a highlight with no control to approve it and no explanation that approving is a side effect of a completely different button on a different panel. A GM who archives a campaign sees a banner with no restore button and no mention of who (an instance admin, not the GM) can restore it. "Add to shelf" simply vanishes with no explanation when there are no upcoming sessions to add to. A user without edit rights who opens a wiki article's edit URL silently gets the read view rendered at the edit URL, with nothing explaining why their edit didn't take effect. ## Evidence - `webapp/frontend/src/pages/CampaignPlanning.jsx:836-853` — `navigate(..., { replace: true })` on a non-GM with no message shown. - `webapp/frontend/src/components/SessionHighlights.jsx:265-269` — "Draft — not yet visible to players" badge with no control; only Edit and Delete buttons exist (`:281-289`), and the state only clears as a side effect of "Approve summary" on `SessionDetail`. - `webapp/frontend/src/pages/CampaignDetail.jsx:1268-1292` — the archived-campaign banner names no restore path; `canRestoreArchivedCampaign` (`:1235`) requires `user?.is_admin`, while archiving itself is a GM action (`:1365-1373`) — a one-way door with no signage of who holds the other key. - `webapp/frontend/src/components/AddToShelf.jsx:40` — `if (options.length === 0) return null;`; the only "keep this" control on every generator vanishes with no explanation. - `webapp/frontend/src/pages/WikiArticle.jsx:1361` — `isEditMode = mode === "edit" && article?.entry?.can_edit`; a user without edit rights opens `/wiki/:entryId/edit` and silently gets the read view with no message. - Contrast: `webapp/frontend/src/pages/CampaignNotes.jsx:50-59` and `webapp/frontend/src/pages/CampaignHighlights.jsx:74-83` already include a "Back to dashboard" link on their error/blocked states — the pattern for handling this well already exists in the codebase; several wiki pages (`WikiProposals.jsx:278-284`, `WikiNewEntry.jsx:183-189`, `WikiArticle.jsx:1681-1687`, `WikiDraftReview.jsx:413-419`) just don't follow it, rendering a bare "GM access only." or similar with no navigation at all. ## Why it matters for a hosted product A silent bounce or an unexplained blocked state reads as "the product is broken" rather than "you don't have permission" or "this isn't ready yet" — and a player who can't tell why cannot even ask their GM the right question. ## Proposed fix Replace the silent redirect at `CampaignPlanning.jsx:840` with an inline "Prep is GM-only" message. Give `SessionHighlights` an explicit approve control, or at minimum change the badge text to "Draft — publishes when you approve the session summary". Add a restore hint naming who can restore to the archived-campaign banner. Explain (rather than hide) the empty "Add to shelf" state. Apply the existing "Back to dashboard" pattern from `CampaignNotes.jsx`/`CampaignHighlights.jsx` to the four wiki hard-block pages listed above. This is the audit's P13. ## Acceptance criteria - [ ] A non-GM following a workbench link sees an inline explanation instead of a silent redirect. - [ ] `SessionHighlights`' draft badge either has an approve control or explains what publishes it. - [ ] The archived-campaign banner names who can restore the campaign. - [ ] `AddToShelf` shows an explanatory empty state instead of disappearing entirely. - [ ] `WikiArticle`'s edit URL for a non-editor shows a message explaining why the edit view isn't available, instead of silently rendering the read view. - [ ] `WikiProposals`, `WikiNewEntry`, `WikiArticle`, and `WikiDraftReview`'s hard-block states include navigation back to the dashboard, matching `CampaignNotes.jsx`/`CampaignHighlights.jsx`.
Author
Contributor

Picking this up as v4.3.0 phase 7 (#514), last on the lane. The Prep page explains itself to a non-GM instead of redirecting; the highlights draft badge gets an approve control if a per-highlight endpoint exists and otherwise says what publishes it; the archived banner names that an instance admin restores and, where the count is available, how many scheduled sessions go quiet (#479); "Add to shelf" explains its empty state; the article edit URL tells a reader they cannot edit; and the four wiki hard-block pages get the "Back to dashboard" pattern CampaignHighlights already uses.

Picking this up as v4.3.0 phase 7 (#514), last on the lane. The Prep page explains itself to a non-GM instead of redirecting; the highlights draft badge gets an approve control if a per-highlight endpoint exists and otherwise says what publishes it; the archived banner names that an instance admin restores and, where the count is available, how many scheduled sessions go quiet (#479); "Add to shelf" explains its empty state; the article edit URL tells a reader they cannot edit; and the four wiki hard-block pages get the "Back to dashboard" pattern `CampaignHighlights` already uses.
Author
Contributor

Done in the phase 7b PR (auto-merging on green); ships with v4.3.0. All six.

The four wiki hard-blocks share a new components/BlockedState.jsx rather than four copies (the CampaignHighlights pattern, extracted): what the restriction is, what to do instead, and links back to the article, wiki, campaign or dashboard. WikiArticle's full-page error state gets the same links, since it was the one that could strand a reader with a bare red line.

CampaignPlanning no longer redirects; it says Prep is the GM's workspace and offers the way back (the nav bar already hides Prep from players, so anyone here followed a shared link). WikiArticle's /edit for a non-editor still renders the read view, which is the useful thing to show, with a line saying why. AddToShelf says there is no upcoming session and links to where you schedule one.

Two that needed a decision:

  • Highlights. There is no per-highlight approve endpoint and none was added: POST /sessions/{id}/approve publishes every highlight on the session in a single update. So the badge now reads "Draft — publishes when the session summary is approved", with a count line pointing at that control, which is on the same page, so a link elsewhere would have pointed at the page you are on.
  • Archived banner. silenced_future_sessions (#479) is on the archive response only, not on the campaign, so the count stays with the post-archive confirmation. The banner names the instance admin as the restore path (only to viewers who are not one) and says scheduled sessions stay on the calendar but stop sending reminders.

Tests for each. One collateral fix: GeneratorPanel.test.jsx rendered without a router, which the new link in AddToShelf's empty state needs; its renders are now wrapped. Frontend 787 passed, eslint clean apart from the pre-existing warning, vite build clean; backend 2504 passed / 13 skipped, ruff clean. No migration.

Done in the phase 7b PR (auto-merging on green); ships with v4.3.0. All six. The four wiki hard-blocks share a new `components/BlockedState.jsx` rather than four copies (the `CampaignHighlights` pattern, extracted): what the restriction is, what to do instead, and links back to the article, wiki, campaign or dashboard. `WikiArticle`'s full-page error state gets the same links, since it was the one that could strand a reader with a bare red line. `CampaignPlanning` no longer redirects; it says Prep is the GM's workspace and offers the way back (the nav bar already hides Prep from players, so anyone here followed a shared link). `WikiArticle`'s `/edit` for a non-editor still renders the read view, which is the useful thing to show, with a line saying why. `AddToShelf` says there is no upcoming session and links to where you schedule one. Two that needed a decision: - **Highlights.** There is no per-highlight approve endpoint and none was added: `POST /sessions/{id}/approve` publishes every highlight on the session in a single update. So the badge now reads "Draft — publishes when the session summary is approved", with a count line pointing at that control, which is on the same page, so a link elsewhere would have pointed at the page you are on. - **Archived banner.** `silenced_future_sessions` (#479) is on the archive response only, not on the campaign, so the count stays with the post-archive confirmation. The banner names the instance admin as the restore path (only to viewers who are not one) and says scheduled sessions stay on the calendar but stop sending reminders. Tests for each. One collateral fix: `GeneratorPanel.test.jsx` rendered without a router, which the new link in `AddToShelf`'s empty state needs; its renders are now wrapped. Frontend 787 passed, eslint clean apart from the pre-existing warning, `vite build` clean; backend 2504 passed / 13 skipped, ruff clean. No migration.
Sign in to join this conversation.
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
rbrooks/Quest-Board#382
No description provided.