[Frontend] Fold the Recording Dashboard and SessionDetail's recording panel into one live-session screen #386
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
A GM managing a live session has to juggle three partially-overlapping screens —
SessionDetail,RecordingDashboard, andSessionShelf— with incomplete links between them.AudioStatusSectiononSessionDetailand the standaloneRecordingDashboardshow heavily overlapping recording/attendance state with different labels for the same toggle ("Present"/"Absent" on one, "✓ Here"/"Absent" on the other) and different summary affordances (editable on one, read-only on the other, with nothing telling the user editing lives elsewhere). The Recording Dashboard's own entry link is labelled "Dashboard →" — which in a product that already has a page called "Dashboard" reads as "go home", not "recording controls" — and it only appears once a session leaves theproposedstate, so a GM cannot even reach recording controls to test them before confirming a time.Evidence
webapp/frontend/src/pages/SessionDetail.jsx:110-415(AudioStatusSection) andwebapp/frontend/src/pages/RecordingDashboard.jsx(539 lines) — overlapping state, different labels for the same attendance toggle (SessionDetail.jsx:1385,1404vsRecordingDashboard.jsx:435).webapp/frontend/src/pages/SessionDetail.jsx:317-357(editable summary) vswebapp/frontend/src/pages/RecordingDashboard.jsx:496-506(read-only), with no indication on the read-only copy that editing exists elsewhere.webapp/frontend/src/pages/SessionDetail.jsx:193-199— the sole inbound link to the Recording Dashboard, labelled "Dashboard →", GM-only.webapp/frontend/src/pages/SessionDetail.jsx:121-122—showForGm = isGm && ["confirmed","in_progress","completed"].includes(session.status); a session stillproposedhas no path to the recording dashboard at all.SessionShelf— the surface a GM actually has open during play — to the Recording Dashboard, or from the campaign page or dashboard.Why it matters for a hosted product
Three partial screens for one live-session job means a GM has to remember which screen has which control, and the mislabelled "Dashboard →" entry point actively works against discovery in a product that already overloads the word "Dashboard".
Proposed fix
Fold the Recording Dashboard's live-status panel (its strongest feature — SSE stream, elapsed timer, per-speaker capture, "Present, not captured yet") into
SessionDetail, or foldSessionDetail's recording panel away in favour of the standalone dashboard — either direction is acceptable, but pick one canonical live-session screen rather than maintaining two. Rename the entry link away from "Dashboard →" regardless of which direction is chosen. Make the recording controls reachable from aproposedsession so a GM can test recording ahead of confirming a time. This is the audit's C4.Acceptance criteria
proposedstatus, not onlyconfirmed/in_progress/completed.Picking this up as v4.3.0 phase 8 (#514), the last item. As recorded on #514,
SessionDetailbecomes the canonical live-session screen: the Recording Dashboard's live panel (SSE stream, elapsed timer, per-speaker capture, "present, not captured yet", and the connection-lost state #377 just gave it) moves into the session page's recording section as its own component; the old/sessions/:id/recordingaddress redirects there so bookmarks keep working; the "Recording →" link goes away, the shelf gets a link to the panel, the controls are reachable on a proposed session (with a clear reason if the backend refuses to start one), and the attendance toggle gets one label everywhere.Done in the #386 PR (auto-merging on green); ships with v4.3.0.
SessionDetailis now the one screen. The Recording Dashboard's live half moved into a newcomponents/RecordingPanel.jsx: the SSE stream with its polling fallback and reconnect, the #377 three-state connection machine (last known state kept, "Connection lost, retrying…" with how stale it is, "Unknown" when the server has never answered), the elapsed clock, per-speaker capture, "Present, not captured yet", the #327 capture tripwire, and Start/Stop with "End session when stopping recording". Extracted rather than inlined becauseSessionDetail.jsxwas already 1,800 lines. The editable summary stays where it was and nothing read-only duplicates it any more./sessions/:id/recordingis now a redirect to/sessions/:id#recording, kept alongside the other legacy routes so bookmarks and older Discord embeds still land somewhere useful;RecordingDashboard.jsxand its test file are gone, their behaviour and tests moved. The "Recording →" entry link is gone (the panel is right there), and the shelf, the surface a GM has open during play, gained a Recording link straight to the anchor.On
proposed: no backend change was needed.POST /sessions/{id}/record/startgates onget_session_for_gmand nothing else; there has never been a status rule, so the confirmed-only entry link was hiding a capability that already worked, at exactly the moment a GM wants to check the bot can hear the table. The panel is there fromproposedonwards and says so. Where a recording genuinely cannot start (the campaign is not connected to a Discord server, which is the backend's own 400), the button is disabled with the reason on the page rather than hidden.The attendance toggle now reads "Present" / "Absent" in the one place it appears; the "✓ Here" copy went with the dashboard. The roster is also available from
in_progressrather than onlycompleted, so the mid-session roster the dashboard carried is not lost.One thing the move forced: the live status is per Discord guild, not per session. On a page you opened deliberately that did not matter; on every session page of a campaign it does, or tonight's recording would light up last March's session as "Recording in progress". The payload carries the session id it belongs to, so a recording of another session is reported as exactly that and Start is refused rather than offered.
Also removed the frontend's
approveAudiowrapper: it called the backend's documented deprecated shim for/approve, and the dashboard's "Approve transcript" button was its only caller; the session page's "Approve summary" is the same action against the non-deprecated endpoint. The shim itself is untouched. One thing to revisit if a deployment ever grows: the panel opens the SSE stream (one Redis pubsub connection) on every GM session-page view; gating it by status reintroduced the visibility holes this issue exists to remove, so it is left ungated, GM-only.Frontend suite: 64 files / 799 tests passing, eslint clean apart from the pre-existing
CampaignDetail.jsxwarning,vite buildclean.