Phase 12: Live Show View (Vue 3 migration)#1058
Merged
Merged
Conversation
Ports the real-time live show execution view to Vue 3 + Pinia: - ShowLiveView.vue: session header, elapsed time, interval overlay with countdown, Splitpanes layout - ScriptViewPane.vue: compiled/page-by-page script loading, keyboard/wheel navigation, script leader mode, lazy page loading via MutationObserver, add-cue and start-interval modals - ScriptLineViewer.vue: normal mode with cue buttons, act/scene labels, interval banners, stage direction styling, cue position left/right support - ScriptLineViewerCompact.vue: compact 2-column mode with cues as rows - StageManagerPane.vue: scene list with setting/striking props/scenery/crew, auto-expand on session follow Adds cues state + loadCues/addNewCue actions to script store. Updates /live route from PlaceholderView to ShowLiveView. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…e collision - router: add proper /live session guard matching V2 — redirect home if no active session or WebSocket is unhealthy (was placeholder comment) - ShowLiveView: override splitpanes v4 pane background with correct specificity (:deep(.default-theme.splitpanes .splitpanes__pane)) so the dark body colour shows instead of the library's default light grey - ScriptViewPane: remove v-once from ScriptLineViewer/Compact in the double-nested v-for — Vue 3 shares _cache[] across all outer iterations so every page rendered page 1's cached VNodes, causing all 1275 line IDs to appear as page_1_* and making cross-page navigation impossible Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
currentShowSession was hardcoded to null (Phase 6 placeholder), causing three bugs: Live nav item always disabled, System/Show Config items never hidden during sessions, and no auto-redirect to /live on initial load. - Import useShowStore and useRouter in App.vue - currentShowSession now reads from showStore.currentSession (reactive) - awaitWSConnect fetches session data after WS connects, then redirects to /live if a session is already active and the user isn't there yet (matches V2 App.vue awaitWSConnect behaviour) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
router.push('/live') with createWebHistory('/ui-new/') navigates to the
V2 app at /live instead of the V3 app at /ui-new/live. The WS composable
already uses the full path explicitly (router.push('/ui-new/live')) and
checks router.currentRoute.value.path against '/ui-new/live'. Apply the
same pattern in awaitWSConnect.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
router.push('/ui-new/live') via useRouter() causes double-base
/ui-new/ui-new/live. The direct module import in useWebSocket.ts bypasses
base handling and needs the full path; useRouter() in components does not.
Revert to router.push('/live') with currentRoute path check against '/live'.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…tring
contrastColor(utils.ts) expects a plain string but the template passed
{ bgColor: '...' }. This threw TypeError inside the v-once BContainer
block; Vue caught the error and cached the failed (empty) render for the
cue column. Fix: call contrastColor(cueBackgroundColour(cue)) directly.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Matches V2 styling — compact viewer already had this correctly. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add Stage Manager toggle to Live Config navbar dropdown - Fix needsIntervalBanner to show at all act boundaries (not just interval_after=true) - Fix cue_position_right default to false (left) matching backend default - Block keyboard/wheel navigation when interval or cue modal is open - Move add-cue "+" button outside BButtonGroup for independent rounded corners - Add variant="success" to "+" button for correct green styling Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Vue Router 4 applies the base path (/ui-new/) internally regardless of whether the router is accessed via useRouter() or direct import. Using full paths like /ui-new/live caused double-prepending to /ui-new/ui-new/live. Also fix the currentRoute.value.path guard comparisons — the path property returns the route without the base prefix. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- HomeView: wire currentShowSession to showStore.currentSession (was null placeholder) - App.vue: add CreateUser component to the no-admin-user setup screen - App.vue: call getRbacRoles() in awaitWSConnect so navbar RBAC is ready before first navigation - Router: /live route now requiresAuth: false (unauthenticated clients can join live view) - Router: already-logged-in redirect returns from.fullPath instead of / unconditionally - Router: /force-password-change gains requiresPasswordChange: true meta - Router: remove unused PlaceholderView import - stores/system: settingsChanged skips re-fetch when show ID unchanged; redirects away from /show-config and /live when no show is loaded (matching V2 behaviour) - stores/show: noLeader toast is now persistent (duration: 0) and dismissed when a leader is elected or getShowSessionData finds an active leader - useWebSocket: re-fetch show session data on reconnect after errors Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Ports the V2 CueEditor/ScriptLineCueEditor/JumpToCueModal trio to V3, completing the Cue Configuration tab previously showing a placeholder. - ScriptLineCueEditor: per-line cue display with add/edit/delete modals, RBAC-filtered cue type options, and duplicate-ident validation - JumpToCueModal: fuzzy cue search with exact/suggestion/no-match states - CueEditor: page navigator with localStorage persistence, Go To Page modal, and adjacent-page pre-fetching for smooth scrolling - script store: adds editCue, deleteCue, and searchCues actions - ConfigCues: replaces PlaceholderView with CueEditor in Cue Configuration tab Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Remove border-right from .cue-column (V2 had no vertical divider line) - Move "+" button inside BButtonGroup (matches V2 behaviour) - Add .add-cue-button CSS to make the "+" button a square icon-sized element, matching V2's plus-square-fill icon appearance Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replaces the variant="success" text "+" button with an inline SVG that faithfully reproduces V2's b-icon-plus-square-fill icon: default button variant (dark background in dark mode) with a 1em × 1em green filled- square icon, exactly matching the original cue column appearance. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
SVG fill was using Bootstrap 5's default success green (#198754). V2's b-icon-plus-square-fill variant="success" resolved to the Bootswatch darkly success colour (#06BC8C), which is the correct value. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Bootstrap 4 Bootswatch darkly sets $font-size-base: 0.9375rem (15px). Bootstrap 5 Bootswatch darkly drops this override, defaulting to 1rem (16px). Every rem-based size — line heights, paddings, margins, button heights — was 6.7% larger, reducing visible content per screen. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Bootstrap 4 defaulted $navbar-padding-x to $spacer (1rem = 16px);
Bootstrap 5 changed it to null → 0px, making navbar content flush to
the viewport edge. Restore with $navbar-padding-x: 1rem.
V2 App.vue had a global `nav a { font-weight: bold }` rule making the
navbar brand and nav-links bold (fontWeight 700). V3 never carried this
over. Add equivalent scoped to .navbar so tab nav-links are unaffected.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Resolves ~15 visual differences identified by page-by-page Playwright comparison to make the V3 migration look identical to V2. Global CSS (dark.scss SCSS variable overrides before Bootstrap imports): - border-radius: .375rem → .25rem (matching Bootstrap 4 default) - table-cell-padding: .5rem → .75rem (matching Bootstrap 4 default) - dropdown-item-padding-x: 1rem → 1.5rem (matching Bootstrap 4 default) - link-decoration: none (Bootstrap 5 Reboot adds underline by default) - Active navbar link: add #nav-collapse a.router-link-active teal colour - Vertical nav-pills: add full-width + centered rule for sidebar pills Per-component fixes: - ConfigActs: interval_after badge → check-square/x-square SVG icons - ScriptRevisions: ✓ span → check-square SVG; add Edit button; remove size="sm" from table buttons; replace text ▼/▲ with chevron SVG icons - CrewList: "Add Crew Member" → "New Crew Member" (match V2 label) - MicList: "Add Microphone" → "New Microphone" (match V2 label) - SessionTagDropdown: ✏️ emoji → inline pencil-fill SVG icon - ConfigCast: add explicit 'First Name'/'Last Name' labels (BVN auto-label only capitalises first word unlike BV2) - AboutUser: add text-center to match V2's centred table alignment Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.




Summary
Live Show View
ShowLiveView.vue: session header bar, elapsed time counter, interval overlay with colour-coded countdown, Splitpanes layout with optional stage manager paneScriptViewPane.vue: compiled-script-first loading with page-by-page fallback, keyboard/wheel navigation (leader only), lazy page loading via MutationObserver, add-cue and start-interval modals (Vuelidate v2), WebSocketSCRIPT_SCROLLdispatchScriptLineViewer.vue: normal mode rendering — cue buttons with colour overrides, act/scene labels, interval banners at all act boundaries, stage direction styling, cue column left/right preferenceScriptLineViewerCompact.vue: compact 2-column mode with cues as prefix/ident rows above contentStageManagerPane.vue: ordered scene list with setting/striking props/scenery/crew per scene, auto-expands current + next scene tracking session follow dataCue Assignment Editor (Cue Configuration tab)
ScriptLineCueEditor.vue: per-line cue display with add/edit/delete modals, RBAC-filtered cue type options (write-permission mask per type), and duplicate-ident validationJumpToCueModal.vue: fuzzy cue search with exact/suggestion/no-match states and similarity % badge; auto-navigates on single exact matchCueEditor.vue: page navigator withlocalStorage('cueEditPage')persistence, Go To Page modal, and adjacent-page pre-fetching; replacesPlaceholderViewin Cue Configuration tabStore changes
stores/script.ts: addscuesstate,cuesForLinegetter,loadCues(),addNewCue(),editCue(),deleteCue(), andsearchCues()actionsrouter/index.ts: replacesPlaceholderViewfor/livewithShowLiveViewVisual parity fixes (Bootstrap 4 → 5)
Global CSS (
dark.scssSCSS variable overrides):.375rem→.25rem(BS4 default).5rem→.75rem(BS4 default)1rem→1.5rem(BS4 default)#00bc8chighlight (V2dark.scssrule)Per-component fixes:
ConfigActs: Interval After badge → check-square/x-square SVG icons (match V2)ScriptRevisions: checkmark span → check-square SVG; add Edit button; removesize="sm"; chevron SVG collapse toggleCrewList: "Add Crew Member" → "New Crew Member"MicList: "Add Microphone" → "New Microphone"SessionTagDropdown: ✏️ emoji → inline pencil-fill Bootstrap icon SVGConfigCast: explicit'First Name'/'Last Name'labels (BVN auto-label only capitalises first word)AboutUser:text-center+scope="row"to match V2's centred tableBug fixes (V2 parity)
currentShowSessioninHomeView.vuewas hardcodednull— now wired toshowStore.currentSessionSTART_SHOW/STOP_SHOWWS handlers corrected for Vue Router 4 base handlingelectedLeader()andgetShowSessionData()v-oncefrom double-nestedv-forcontrastColor()call signature:deepCSS override for dark-mode pane backgroundcue_position_rightdefault: Changed tofalseto match backend column defaultws.onopenre-fetches session data after reconnectTest plan
npm run build— no errorsnpm run typecheck— passesnpm run ci-lint— passesnpm run test:run— 23/23 pass/ui-new/live— script loads, session header renders, cues display🤖 Generated with Claude Code