[Frontend] Add missing self-service controls: un-reveal a spoiler, delete an XP entry, and .ics calendar export #389
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Impact: MEDIUM
Found in the August 2026 session lifecycle review (#319).
What the user experiences
Three backend capabilities exist with no UI control to reach them. A GM who reveals a spoiler card to the table during a live session has no way to retract it — the backend supports un-revealing, but no button calls it. XP entries appear to be permanently un-deletable from the UI once created. And the calendar-add control only offers Google Calendar; Apple/Outlook users, a substantial share of any hosted audience, have no path to add a session to their calendar at all.
Evidence
webapp/frontend/src/api/shelf.js—revokeSessionRevealis exported and never called anywhere in the frontend.webapp/frontend/src/api/loot.js—fetchXp/deleteXpare exported and never called anywhere in the frontend.webapp/frontend/src/pages/SessionDetail.jsx:1414-1428— "Add to Calendar" offers Google Calendar only, no.icsdownload.Why it matters for a hosted product
Each of these is a real backend capability with zero UI cost to expose, and each closes a specific "I can't undo/manage this" complaint a hosted customer would otherwise have no way to self-serve.
Proposed fix
Add an un-reveal button to the reveal list on
SessionShelf, calling the existingrevokeSessionReveal. Add a delete control to XP entries on the loot ledger, calling the existingdeleteXp. Add an.icsdownload option alongside the existing Google Calendar link onSessionDetail. This is the audit's M4, M5, and thefetchXp/deleteXporphan noted in §2.3.Acceptance criteria
SessionShelfhas an un-reveal control for previously-revealed cards.SessionDetail's calendar control offers an.icsdownload in addition to Google Calendar.Picking this up as v4.3.0 phase 7 (#514). Un-reveal on the shelf's reveal list and delete on XP entries call the endpoints that already exist. For the calendar export the decision is a small server-side
GET /api/sessions/{id}/calendar.ics(members only, one VEVENT in UTC from the same fields the Google link uses) rather than a browser-built file, so times are computed once and tested once; the page links it as a download beside Google Calendar.Done in the phase 7b PR (auto-merging on green); ships with v4.3.0.
Un-reveal is a "Shown to the table" strip on the shelf, not a button on each card:
ShelfRevealOut.shelf_card_idis nullable, so a reveal can outlive its card, and a card-attached control would leave orphans permanently up with no way down. It calls the existingrevokeSessionReveal; the player table picks the change up on its own poll, as it already does for reveals.fetchXpanddeleteXpwere both unused for one underlying reason: the ledger rendered XP totals only, so an individual award was never on screen to act on. Awards are now listed like loot and gold, each with a delete whose confirm names it.On the
.ics: the backend endpoint already existed,GET /api/sessions/{id}/calendar.ics, member-gated,text/calendar, built bycalendar_service.build_single_session_ics, which shares its event, escaping and date code with the subscribable feed and the emailed invites. It had tests and no caller, so this is a download link, not a new endpoint. One change was needed there: eligibility was "status is confirmed", but the "Add to Calendar" section renders onconfirmed_time, so a completed session would have offered a download that answered 400. Widened to "has a scheduled time", which matches both the UI's condition and the feed's statuses. A session with no scheduled time stays 400, not 404: it exists, there is just nothing to put in a calendar yet; documented in the endpoint and asserted in a test.Tests: 5 new backend (member 200, non-member 403, exact DTSTART/DTEND/UID/SUMMARY, past-confirmed still 200 with the right STATUS, unscheduled 400); frontend covers un-reveal, delete-XP-with-confirm, and the
.icslink beside Google Calendar.