Vue 3 migration#1036
Draft
Tim020 wants to merge 15 commits into
Draft
Conversation
) * Add Vue 3 migration skeleton (Phase 0) — issue #1033 Creates client-v3/ alongside the existing Vue 2 client/, serving a placeholder Vue 3 app at /ui-new/ via a new RootControllerV3. Both frontends build and serve independently. Backend: RootControllerV3 + /ui-new/assets/ and /ui-new/ handlers in app_server.py (registered before the Vue 2 catch-all route). client-v3 stack: Vue 3.5 / Pinia 3 / Vue Router 5 / Bootstrap-Vue-Next 0.45 / Vite 8 / ESLint 10 / TypeScript strict mode. CI: lint, typecheck, and test jobs added for client-v3 in nodelint.yml and client-test.yml. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Fix formatting --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Client V3 Test Results23 tests 23 ✅ 0s ⏱️ Results for commit 2a89e5b. ♻️ This comment has been updated with latest results. |
* Add Vue 3 core infrastructure (Phase 1) — issue #1033 Pinia stores (user/auth, system/RBAC, websocket), useWebSocket() composable, HTTP interceptor, full router with beforeEach guard, platform/utils/logger ports, API types, constants, full BVN navbar App.vue, and stub views. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Fix BVN component rendering and visual parity with Vue 2 - Switch to BApp wrapper + unplugin-vue-components/BootstrapVueNextResolver for automatic per-component tree-shaken imports (no global plugin needed) - Add bootstrap-vue-next/dist/bootstrap-vue-next.css import in main.ts - Add data-bs-theme="dark" to BNavbar so text renders white on info background (Bootstrap 5 equivalent of Bootstrap 4's type="dark") - Add components.d.ts to tsconfig includes for GlobalComponents type augmentation - Gitignore components.d.ts (auto-generated by unplugin-vue-components on build) - Fix NotFoundView copy and centering to match Vue 2 404View exactly Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Fix npm ci lockfile sync for @emnapi/core and @emnapi/runtime These are transitive deps of @rolldown/binding-wasm32-wasi (cpu: wasm32). npm doesn't install the wasm32 binding on macOS arm64, so their lockfile entries were missing. Added as optionalDependencies to force inclusion. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Fix lockfile: add @emnapi/core and @emnapi/runtime as explicit devDeps These are transitive deps of @rolldown/binding-wasm32-wasi (cpu: wasm32). npm skips that binding on macOS arm64 so its deps never get lockfile entries, causing npm ci to fail on Linux CI. Adding them explicitly to devDependencies forces npm to resolve and record their entries in the lockfile on all platforms. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
- stores/help.ts: Pinia port of Vuex help module with manifest loading, document cache, and Fuse.js full-text search - components/MarkdownRenderer.vue: async marked v18 API via watch+ref; :deep() CSS selectors; import.meta.env.BASE_URL for portable help links across base paths - views/HomeView.vue: reads systemStore.currentShow/settings + userStore.currentUser; currentShowSession stubbed null until Phase 6 - views/AboutView.vue: static content port - views/HelpView.vue: BVN port with sticky sidebar, debounced search, dynamic navbar height offset - views/help/HelpDocView.vue: cache-first doc loading, watch route.params.slug - router: wire /about and /help routes; fix /help child redirect to absolute path; fix catch-all to render NotFoundView in-place (no URL redirect) matching Vue 2 behaviour Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
…Change) (#1039) - Port LoginView and ForcePasswordChangeView to BVN + @vuelidate/core v2 - Add useFormValidation and usePasswordValidation composables - Add changePassword() action to user store - Wire /force-password-change route to real component Bug fixes discovered during verification: - stores/user: authToken was a non-reactive getter reading localStorage, causing Pinia to cache null on first access and never re-evaluate; moved to reactive state field with _setToken/_clearToken actions keeping localStorage in sync - http-interceptor: exclude login endpoint from 401 handling to avoid logout cascade on bad credentials - stores/websocket: websocketHealthy getter incorrectly required authenticated=true; corrected to match Vue 2 behaviour (connection only) - views/LoginView: missing @submit.prevent on BForm caused native form submission - main.ts: import theme-sugar.css and create toast.ts singleton with position top-right; replace scattered useToast() calls with the shared instance Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* Vue 3 migration: Phase 4 — user settings page (/me)
- views/user/SettingsView.vue: 6-tab pill-vertical shell (About, Settings,
Stage Direction Styles, Cue Colour Preferences, Change Password, API Token)
- components/user/settings/AboutUser.vue: titleCase + sorted BTableSimple
- components/user/settings/UserSettingsConfig.vue: 7-field settings form,
PATCH /api/v1/user/settings, vuelidate with notNull/notNullAndGreaterThanZero
- components/user/settings/ChangePassword.vue: 3-field form using
usePasswordValidation, sends old_password for settings context
- components/user/settings/ApiToken.vue: generate/regenerate/revoke with
BModal confirmations, #append slot for copy button
- components/user/settings/CueColourPreferences.vue: cue types fetched
locally (show store not yet available), BModal ref pattern, contrastColor
- components/user/settings/StageDirectionStyles.vue: stage direction styles
fetched locally, v-model:pressed for toggle buttons, no Vue 3 filters
- js/customValidators.ts: notNull, notNullAndGreaterThanZero validators
- stores/user.ts: 8 CRUD actions for overrides, changePassword accepts
oldPassword, logout clears cueColourOverrides
- router/index.ts: /me wired to SettingsView (was PlaceholderView)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Fix BTabs content pane width in user settings page
Add content-class="flex-fill" to BTabs so the tab pane fills the
available horizontal space (BVN doesn't auto-fill unlike BV2). Also
add w-100 to BTableSimple in AboutUser for full-width rendering.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Update migration plan: Phase 4 complete + BVN layout gotchas
Mark Phase 4 as done. Add two BVN-specific notes to the reference
section that will apply to all future phases:
- BTabs vertical requires content-class="flex-fill" to fill width
- BTableSimple requires class="w-100" to be full-width
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Remove plans/VUE3_MIGRATION_PLAN.md from git tracking
File is covered by .gitignore and should not be committed.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Fix V3 user settings visual parity with V2
- dark.scss: override body font to Avenir (matching V2's index.html inline
style) and add .b-form-group margin-bottom (BVN dropped Bootstrap 4's
.form-group built-in 1rem margin)
- AboutUser.vue: wrap rows in <BTbody> so Bootstrap 5's deep child selector
(.table > :not(caption) > * > *) matches and row borders render correctly
- UserSettingsConfig.vue: label-cols="auto" → label-cols="4" for consistent
33% label column across all form rows
- SettingsView.vue: content-class="flex-fill text-start" to fill horizontal
space and reset text-align inherited from #app { text-align: center }
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* Migrate system configuration page to Vue 3 (Phase 5) (#1035) Ports the admin /config section — Shows, System, Settings, Users, Logs, Backups — from Vue 2 Vuex to Vue 3 Pinia with bootstrap-vue-next. Key patterns introduced: - BModal via ref<InstanceType<typeof BModal>> (replaces v-b-modal directive) - #footer slot (replaces #modal-footer in BVN) - window.confirm replaces $bvModal.msgBoxConfirm - SSE log streaming via Web Streams API (response.body.getReader()) - setTimeout-based polling with onBeforeUnmount cleanup - Dynamic Vuelidate rules computed from server-returned setting types - Cross-field date validators using helpers.withMessage Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Add reusable ConfirmDialog composable to replace window.confirm Creates a singleton useConfirm() composable backed by a BModal-based ConfirmDialog component, replacing all window.confirm() calls with a styled, accessible modal dialog that matches the rest of the UI. ConfirmDialog is mounted once in App.vue; all callers share the same instance via module-level reactive state. Supports title, okVariant, okTitle, and cancelTitle options mirroring BV2's msgBoxConfirm API. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Fix ConfigView tab layout to match V2 (horizontal, lazy) V2 used plain horizontal tabs with lazy mounting, not the vertical pill layout carried over from the user settings page. Also restores lazy prop so tab content only mounts on first activation, avoiding all polling timers (sessions, users) starting simultaneously on page load. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Fix Settings accordion animation: use v-model instead of :visible on BCollapse BVN's BCollapse :visible prop sets localNoAnimation=true in useShowHide, bypassing the Bootstrap 5 collapsing transition entirely. Switching to :model-value/@update:model-value keeps animation enabled. Expanded state changed from string[] to Record<string, boolean> to support v-model binding per category key. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Fix Settings form control spacing by removing inline margin-bottom override Bootstrap 5 has no built-in .form-group margin; the global dark.scss adds margin-bottom: 1rem to .b-form-group, but the inline style="margin-bottom: 0" copied from V2 was overriding it, causing rows to appear compacted. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add stores/show.ts: full Pinia port of V2 show Vuex module (cast, characters, character groups, acts, scenes, cue types, sessions, microphones, mic allocations, script modes, session tags, stageManagerMode persisted via pinia-plugin-persistedstate) - Add js/micConflictUtils.ts: mic conflict detection utilities (ported from V2) - Add views/show/ShowConfigView.vue: sticky vertical nav sidebar + RouterView shell - Wire /show-config parent route to ShowConfigView.vue (was PlaceholderView) - Move scriptModes state/action from system.ts to show.ts; update ConfigShows.vue - Fill in GET_CAST_LIST, ELECTED_LEADER, NO_LEADER, SCRIPT_SCROLL WS action handlers Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Ports the four core show config tabs (Show, Acts & Scenes, Cast, Characters) to Vue 3 + BVN, using Pinia, Vuelidate, and vue-multiselect. - Add getShowDetails() + updateShow() actions to systemStore - Add useStatsTable() composable (port of statsTableMixin) - ConfigShow: detail table with titleCase keys + edit modal - ConfigActsAndScenes: Acts CRUD (linked-list order, loop validator) and Scenes CRUD (2-column layout, per-act previous/first scene) - ConfigCast: cast list CRUD + CastLineStats (dynamic act/scene cols) - ConfigCharacters: character CRUD + CharacterGroups (vue-multiselect) + CharacterLineStats - Wire four child routes in router; remaining placeholders unchanged Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* Vue 3 migration: Phase 8 — cue types and session management (#phase8) Port ConfigCues (cue types CRUD + import + counts stats) and ConfigSessions (session list with start/stop + session tag CRUD + import) to Vue 3. Adds useCueDisplay composable, scriptRevisions state + getter + action to show store, and contrast-color type declarations. Cue Configuration tab deferred to Phase 11. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Fix getScriptRevisions API unwrapping and contrastColor strict-ESM crash getScriptRevisions was storing the raw API response object instead of response.revisions. The contrast-color library's standalone function uses `this.namedColors` internally which is undefined in strict ESM — replaced with an inline YIQ formula in utils.ts used by all session + cue components. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Replace explicit WS actionMap with convention-based Pinia store dispatch WS ACTION names (SCREAMING_SNAKE_CASE) are automatically routed to the matching camelCase action on any instantiated Pinia store, so adding a new store action is all that's needed to handle the corresponding WS event — no registration or map entries required. Only four special cases remain for actions that can't follow the naming convention: TOKEN_REFRESH, SHOW_CHANGED, USER_LOGOUT, WS_SETTINGS_CHANGED. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
| const storeMap = (pinia as unknown as { _s: Map<string, Record<string, unknown>> })._s; | ||
| for (const store of storeMap.values()) { | ||
| if (typeof store[camelAction] === 'function') { | ||
| await (store[camelAction] as (d: Record<string, unknown>) => Promise<void>)(data); |
* Add Vue 3 migration Phase 9: Microphone configuration Ports the microphone configuration tab including CRUD, scene×character allocation grid with delta tracking and conflict display, SVG timeline with three view modes (mic/character/cast) and PNG export, scene density heatmap, and resource availability grid. Key fix: add `lazy` to BTabs to prevent BVN's eager tab rendering from causing MicAllocations to mount before parent data is loaded, which would leave internalState empty and break allocation toggling. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Fix ConfigMics tab loading: use v-if="loaded" instead of BTabs lazy BVN renders all tab panels simultaneously; wrapping the BTabs in a v-if="loaded" guard (with a spinner in v-else) prevents MicAllocations from mounting before the parent has fetched microphone data, matching the V2 pattern exactly. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Ports the Stage config tab from V2 to V3, including: - Crew CRUD (CrewList.vue) with first/last name fields - Scenery types + items CRUD (SceneryList.vue) with cascade delete warning - Prop types + items CRUD (PropsList.vue) - Stage Manager (StageManager.vue): scene navigation, allocation cards, SET/STRIKE boundary detection, crew assignments, orphan detection via blockOrphanUtils - SVG props/scenery timeline (StageTimeline.vue) with view mode toggle and PNG export - SVG crew timeline (CrewTimeline.vue) with hard/soft conflict detection - Timeline side panel (TimelineSidePanel.vue) for crew assignment editing - Pinia store (stores/stage.ts) with 8 state arrays, parameterised getters, and 28 actions; POST/PATCH requests use camelCase keys matching the API - blockOrphanUtils.ts + tests copied from V2 (pure TS, no Vue deps) - ConfigStage.vue shell with 5 tabs; router updated to replace PlaceholderView Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* Vue 3 migration: Phase 11 — Script & Revisions configuration Ports the most complex config section of the Vue 2 UI to Vue 3/Pinia: - Stores: script.ts, scriptConfig.ts (with exported computePageStatus) - Composables: useScriptNavigation, useScriptDisplay - Utilities: scriptUtils.ts, mruSortUtils.ts (ported from V2) - Components: RevisionDetailModal, RevisionGraph (D3 hierarchy + zoom), ScriptRevisions (table + branch/load/delete modals), CompiledScripts, StageDirectionStyles (CRUD + import), ScriptLinePart, ScriptLineViewer, ScriptLineEditor, BulkActSceneModal, ScriptEditor (full non-collaborative editor) - Views: ConfigScript (Script + Stage Direction Styles tabs), ConfigScriptRevisions (Revisions + Compiled Scripts tabs) - Router: both show-config-script routes now point to real views Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Fix bugs found during Phase 11 browser testing - Replace structuredClone with JSON round-trip in scriptConfig store and ScriptLineEditor: Vue reactive Proxy objects (Pinia state) cannot be structuredCloned in some environments - Fix canRequestEdit/currentEditor field name mapping (backend returns camelCase, store was reading snake_case) - Reload current page after stopEditing() clears tmpScript so lines remain visible in view mode - Complete StyleForm render function in StageDirectionStyles with all form fields (description, bold/italic/underline toggles, text format select, text colour picker, background colour toggle + picker) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Fix sticky navbar and transparent sticky header in V3 script editor BVN's :sticky="true" generates class sticky-true (not Bootstrap's sticky-top), so the top navbar scrolled away instead of staying fixed. Replace with class="sticky-top" on BNavbar in App.vue. Also define --body-background in dark.scss as an alias for --bs-body-bg, so the script editor sticky header (and timeline components) have a solid background instead of transparent. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Remove redundant hr below script sticky header The sticky header already has border-bottom via CSS, so the separate <hr /> created a double divider with extra gap below the header. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* Add Phase 12: Live Show View (Vue 3 migration)
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>
* Fix three live view bugs: session guard, splitpanes background, v-once 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>
* Wire show session into App.vue: fix navbar state and live redirect
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>
* Fix live redirect to use full path matching WS composable convention
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>
* Revert live redirect path: useRouter() prepends base automatically
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>
* Fix cues not rendering: contrastColor called with object instead of string
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>
* Add variant="success" to add-cue buttons in ScriptLineViewer
Matches V2 styling — compact viewer already had this correctly.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Fix V2 parity issues in live show view
- 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>
* Fix START_SHOW/STOP_SHOW router push paths
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>
* Fix V2 parity gaps found during pre-release audit
- 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>
* Add cue assignment editor to Phase 12 (Cue Configuration tab)
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>
* Fix cue column visual parity: remove border-right, square add button
- 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>
* Use inline plus-square-fill SVG for add-cue button
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>
* Fix add-cue icon colour to match V2 (#06BC8C)
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>
* Restore 15px base font size to match V2 Bootswatch darkly
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>
* Fix navbar padding and font weight to match V2
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>
* Fix visual parity between V3 and V2 UI across all pages
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>
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* Phase 12: Integrate unplugin-icons with Material Design Icons Replaces all inline SVGs and Unicode text-character icon substitutes across the V3 UI with auto-imported MDI components (unplugin-icons + unplugin-vue- components resolver). Removes the bi and ph iconify packages after user chose MDI following a side-by-side preview page comparison. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Replace remaining text-character icon substitutes with MDI components - StageManagerPane: ▼/▶ expand indicators → IMdiChevronDown/IMdiChevronRight; 📌 pin emoji → IMdiPin - TimelineSidePanel: ⚠ Conflicts heading → IMdiAlert - RevisionGraph: +/-/↺ zoom buttons → IMdiMagnifyPlus/IMdiMagnifyMinus/IMdiRefresh (V2 used b-icon-zoom-in, b-icon-zoom-out, b-icon-arrow-clockwise) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- 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.




No description provided.