Skip to content

VPR-59 [3/4] CMS migration: management SPA (frontend)#253

Open
rlorenzo wants to merge 27 commits into
VPR-59-cms-r2-content-nav-backendfrom
VPR-59-cms-r3-frontend
Open

VPR-59 [3/4] CMS migration: management SPA (frontend)#253
rlorenzo wants to merge 27 commits into
VPR-59-cms-r2-content-nav-backendfrom
VPR-59-cms-r3-frontend

Conversation

@rlorenzo

@rlorenzo rlorenzo commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Slice 3 of 4 (stacks on #252; the diff shows only this slice). Built from the CI-verified branch tip — see #251 for why the earlier 6-PR stack (#245-#250) was replaced. Merging this completes the CMS migration as originally scoped; slice 4 (#255) adds delegated block editing on top.

Scope — the CMS management SPA (Vue 3 + Quasar)

  • Files at /CMS/ManageFiles: server-paged list with shareable URL-synced filters, upload/edit dialog with name-conflict and 409 edit-conflict handling, audit trail, import and bulk-encrypt tools.
  • Content blocks: list + QEditor editor with version history, diff viewer, attached files, 409 conflict dialog; cross-block Edit History page with per-version diffs.
  • Left-nav editor with drag/keyboard reorder (shared SortableList + live-region announcements) and independent settings/items save; link collections management.
  • Redesigned CMS hub with permission-scoped cards and a recent-activity rail.
  • Shared composables (use-server-table with stale-response guard, use-url-filtered-table, use-reorder, route-focus a11y), mobile card mode for the five dense list tables, WCAG-focused polish, and the full frontend test suite (1,026 tests).

Deploy notes (whole stack)

  • TEST/PROD config: CMS:LegacyWebrootPath (import tool), viperfiles.txt key file must exist, optional CMS:FileStorageRoot/CMS:ProfilePhotoPath/CMS:EncryptionKeyFile overrides, CMS:DownloadRateLimit limits, Cms:TrashPurgeEnabled stays false until the legacy VIPER 1 purge is retired.
  • Deployment flows through Development → TEST first, per repo convention.

Slice 3/3 of the restacked CMS migration (tip file states). The Vue 3
management UI: files, content blocks with QEditor and version diffs,
left-nav editor, link collections, import and bulk-encrypt tools, the
redesigned hub with the recent-activity rail, shared sortable-list /
server-table / dialog components, mobile card mode, and the full
frontend test suite. Completes the stack; the tree now matches the
development branch tip exactly.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Completes the CMS migration by landing the Vue 3 + Quasar “management SPA” for CMS tools (files, content blocks, left-nav menus), alongside shared SPA infrastructure (router scroll/focus behavior), reusable list/table composables, shared UI components, and an expanded frontend test suite.

Changes:

  • Added CMS management pages/components (hub, files audit, bulk encrypt, content history/diff, left-nav menu management) plus shared CMS composables/types and utilities.
  • Introduced shared frontend building blocks: createSpaRouter (hash + query-aware scroll), useRouteFocus refinements, useReorder + SortableList, and server-paged table composables with URL-synced filters.
  • Updated global styles/tokens/utilities for surfaces, focus rings, and responsive list/table/card layouts; minor Effort audit filter layout adjustments.

Reviewed changes

Copilot reviewed 85 out of 85 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
VueApp/src/styles/colors.css Adds surface/diff/focus tokens and bg utilities for secondary palette colors.
VueApp/src/styles/base.css Adds global a11y/layout helpers (focus, list headers, dialog sizing, card-mode table styling).
VueApp/src/Students/router/index.ts Switches router factory import to create-spa-router.
VueApp/src/shared/createSpaRouter.ts Removes old router factory module (renamed/replaced).
VueApp/src/shared/create-spa-router.ts New router factory with improved base-url normalization and scroll behavior (hash + query-aware).
VueApp/src/shared/tests/create-spa-router.test.ts Tests router scroll behavior and route-focus behavior.
VueApp/src/layouts/ViperLayout.vue Adds “Skip to section menu” skip link when left nav exists.
VueApp/src/layouts/LeftNav.vue Improves left-nav a11y (skip target focusability, roles, landmark labeling).
VueApp/src/Effort/router/index.ts Switches router factory import to create-spa-router.
VueApp/src/Effort/pages/AuditList.vue Reworks search + clear-filters placement to match CMS audit UX.
VueApp/src/Effort/components/EffortLeftNav.vue Makes left nav skip target focusable (tabindex=-1).
VueApp/src/CTS/router/index.ts Switches router factory import to create-spa-router.
VueApp/src/config/colors.ts Extends accessible text-color logic for the new arboretum background color.
VueApp/src/Computing/router/index.ts Switches router factory import to create-spa-router.
VueApp/src/composables/ViperFetch.ts Adds postForm/putForm helpers for multipart uploads; minor object shorthand cleanup.
VueApp/src/composables/use-route-focus.ts Avoids focus-steal on same-path navigations (query-only/hash-only).
VueApp/src/composables/use-reorder.ts New reorder composable (move math + “just moved” highlight state).
VueApp/src/composables/tests/use-reorder.test.ts Unit tests for useReorder.
VueApp/src/components/SortableList.vue New shared sortable list component (drag + buttons + a11y announcements + animations).
VueApp/src/components/BreadcrumbHeading.vue New breadcrumb-style <h1> component for subpages.
VueApp/src/components/tests/sortable-list.test.ts Unit tests for SortableList.
VueApp/src/CMS/types/index.ts Expands CMS TypeScript types for files, blocks, nav, audit/history, and activity rail.
VueApp/src/CMS/router/routes.ts Defines CMS SPA routes and shared home-permission set.
VueApp/src/CMS/router/index.ts Uses new router factory and adds CMS area-root canonicalization to Home.
VueApp/src/CMS/pages/LeftNavMenus.vue New CMS page: list/manage left-nav menus (filters + add dialog + delete).
VueApp/src/CMS/pages/FileAuditLog.vue New CMS page: server-paged file audit trail with URL-synced filters.
VueApp/src/CMS/pages/ContentBlockHistory.vue New CMS page: cross-block edit history with diff viewer.
VueApp/src/CMS/pages/CmsHome.vue Redesigns CMS hub with permission-scoped cards and purge-soon warning.
VueApp/src/CMS/pages/BulkEncrypt.vue New CMS tool page: server-paged list for bulk encryption.
VueApp/src/CMS/file-types.ts Centralizes accepted file extension allow-list for uploads.
VueApp/src/CMS/composables/use-url-filtered-table.ts New composable: URL-synced filters layered over server paging.
VueApp/src/CMS/composables/use-server-table.ts New composable: server-paged QTable core with stale-response guard.
VueApp/src/CMS/composables/use-content-diff-viewer.ts New shared diff-viewer state/helpers for ContentDiffDialog consumers.
VueApp/src/CMS/components/StatusIcon.vue New component: tooltip + sr-only label pattern for status icons.
VueApp/src/CMS/components/RecentActivity.vue New component: CMS hub activity rail + latest-diff helpers.
VueApp/src/CMS/components/PersonSelector.vue New component: server-searched people selector with stale-response guard.
VueApp/src/CMS/components/PermissionSelector.vue New component: lazy-loaded permission selector with client-side filtering.
VueApp/src/CMS/components/PermissionChips.vue New component: compact permission/person-count chip rendering.
VueApp/src/CMS/components/ModifiedStamp.vue New component: shared “MM/DD/YY by user” stamp for table + card modes.
VueApp/src/CMS/components/ListCardField.vue New component: label/value rows for QTable card/grid mode.
VueApp/src/CMS/components/ListCard.vue New component: shared QTable card/grid wrapper for CMS list pages.
VueApp/src/CMS/components/LinkCollections.vue Optimizes grouping/filtering behavior and adjusts filter UX.
VueApp/src/CMS/components/Link.vue Uses StatusBadge for tags and updates tag palette to non-semantic brand roles.
VueApp/src/CMS/components/LeftNavMenuSettingsFields.vue New shared settings form for left-nav menu create/edit.
VueApp/src/CMS/components/LeftNavMenuDialog.vue New create-menu dialog with validation + unsaved-changes guard.
VueApp/src/CMS/components/EditButton.vue New shared edit action button component for tables/cards.
VueApp/src/CMS/components/DeleteRestoreButtons.vue New shared delete/restore action button component.
VueApp/src/CMS/components/DateRangeFilter.vue New shared from/to date filter inputs.
VueApp/src/CMS/components/ContentDiffDialog.vue New diff dialog for content history comparisons.
VueApp/src/CMS/components/ContentBlock.vue Fixes content fetch behavior (avoid duplicate/deep watch) and handles fetch failure.
VueApp/src/CMS/components/ActivityRow.vue New component: recent-activity row layout with safe whole-row click behavior.
VueApp/src/CMS/tests/use-url-filtered-table.test.ts Tests URL-synced server table behavior and equality-guard.
VueApp/src/CMS/tests/use-server-table.test.ts Tests server table behavior and stale-response guard.
VueApp/src/CMS/tests/url.test.ts Tests CMS URL safety helpers (scheme allow/block, malformed handling).
VueApp/src/CMS/tests/test-utils.ts CMS test harness utilities (Quasar/Pinia/router + seeded permissions).
VueApp/src/CMS/tests/router-canonicalization.test.ts Tests CMS /CMS/ → Home canonicalization across permission shapes.
VueApp/src/CMS/tests/person-selector.test.ts Tests PersonSelector min-chars gate and stale-response guard.
VueApp/src/CMS/tests/permission-selector.test.ts Tests PermissionSelector lazy load + filtering + null-clear behavior.
VueApp/src/CMS/tests/modified-stamp.test.ts Tests ModifiedStamp formatting and dual render modes.
VueApp/src/CMS/tests/link.test.ts Tests Link URL safety rendering and tag color cycling behavior.
VueApp/src/CMS/tests/left-nav-menus.test.ts Tests left-nav menu list behavior (filters, deep-link add dialog, delete flow).
VueApp/src/CMS/tests/left-nav-menu-dialog.test.ts Tests create-menu dialog validation and POST success/failure behavior.
VueApp/src/CMS/tests/file-form-dialog-conflict.test.ts Tests file upload name-conflict flows and multipart upload helpers usage.
VueApp/src/CMS/tests/date-range-filter.test.ts Tests DateRangeFilter v-model and change emission.
VueApp/src/CMS/tests/content-diff-dialog.test.ts Tests ContentDiffDialog close/legend/empty behaviors.
VueApp/src/CMS/tests/content-block-history.test.ts Tests history list URL sync + diff viewer behaviors.
VueApp/src/CMS/tests/content-block-edit-diff.test.ts Tests ContentBlockEdit diff-against-current behaviors.
VueApp/src/CMS/tests/cms-home.test.ts Tests CMS hub permission-gated sections and purge warning behavior.
VueApp/src/ClinicalScheduler/router/index.ts Switches router factory import to create-spa-router.
VueApp/src/CAHFS/router/index.ts Switches router factory import to create-spa-router.

Comment thread VueApp/src/styles/base.css Outdated
Comment thread VueApp/src/styles/base.css Outdated
rlorenzo added 2 commits July 2, 2026 19:52
Keyboard-initiated focus on #main-content / #leftNavMenu keeps a
:focus-visible ring; programmatic and mouse focus stay quiet.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 85 out of 85 changed files in this pull request and generated 2 comments.

Comment thread VueApp/src/composables/use-reorder.ts
Comment thread VueApp/src/styles/base.css

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 85 out of 85 changed files in this pull request and generated no new comments.

…p category

A groupByTagCategory that matches no tag category on the collection left
the grouped branch iterating an empty value set, rendering a blank page
on a public-facing component instead of the links.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 89 out of 89 changed files in this pull request and generated 2 comments.

Comment thread VueApp/src/styles/base.css
Comment thread VueApp/src/styles/base.css
Dialog width classes used px, so they ignored the root font-size step
at the 768px breakpoint and user font settings; DESIGN.md mandates rem
sizing throughout.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 89 out of 89 changed files in this pull request and generated no new comments.

rlorenzo added 2 commits July 3, 2026 12:23
Frontend half of the item-save concurrency guard: the items PUT now
carries lastModifiedOn, a 409 opens the Edit Conflict dialog, and the
stamp advances after a successful items save (it bumps the menu
ModifiedOn server-side, so the next save 409ed against the user's own
change).

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 89 out of 89 changed files in this pull request and generated 1 comment.

Comment thread VueApp/src/styles/base.css
rlorenzo added 2 commits July 3, 2026 12:53
The legacy-selector focus rule hard-coded #258cfb while newer rules
use var(--focus-ring-color); one token keeps the rings from drifting.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 89 out of 89 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (1)

VueApp/src/CMS/components/ListCard.vue:24

  • This SFC has a top-level HTML comment after the block. Vue SFC parsers/tooling typically expect only /<script>/<style> (and named custom blocks) at the top level; leaving a stray comment outside those blocks can break compilation or linting in some setups. Move the comment inside the (or into a <script> block comment) to keep the file strictly valid.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 89 out of 89 changed files in this pull request and generated no new comments.

@rlorenzo

rlorenzo commented Jul 3, 2026

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 3, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@VueApp/src/Effort/components/ChangeDetailDiff.vue`:
- Around line 7-19: The ChangeDetailDiff.vue template currently distinguishes
old and new values only with text-negative/text-positive color classes and an
arrow, which lacks non-color meaning. Update the detail rendering in the
ChangeDetailDiff component to add accessible text labels for the old and new
values, preferably visually hidden so the UI stays unchanged, and make sure the
labels are tied to the existing oldValue/newValue spans. Check whether
AuditList.vue already provides announced “Old” and “New” headers before adding
redundant labels.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 8c045652-6a9b-4e40-9b5a-89dac02b1f31

📥 Commits

Reviewing files that changed from the base of the PR and between 27edb0b and 8f439ba.

📒 Files selected for processing (29)
  • VueApp/src/CMS/__tests__/file-form-dialog-conflict.test.ts
  • VueApp/src/CMS/__tests__/inline-file-upload.test.ts
  • VueApp/src/CMS/__tests__/left-nav-edit.test.ts
  • VueApp/src/CMS/__tests__/link-collections.test.ts
  • VueApp/src/CMS/__tests__/test-utils.ts
  • VueApp/src/CMS/components/ActivityRow.vue
  • VueApp/src/CMS/components/ContentBlock.vue
  • VueApp/src/CMS/components/FileFormDialog.vue
  • VueApp/src/CMS/components/InlineFileUpload.vue
  • VueApp/src/CMS/components/LeftNavMenuDialog.vue
  • VueApp/src/CMS/components/LeftNavMenuSettingsFields.vue
  • VueApp/src/CMS/components/LinkCollections.vue
  • VueApp/src/CMS/components/PersonSelector.vue
  • VueApp/src/CMS/pages/ContentBlockEdit.vue
  • VueApp/src/CMS/pages/FileAuditLog.vue
  • VueApp/src/CMS/pages/Files.vue
  • VueApp/src/CMS/pages/LeftNavEdit.vue
  • VueApp/src/CMS/pages/ManageLinkCollections.vue
  • VueApp/src/CMS/types/index.ts
  • VueApp/src/Effort/components/ChangeDetailDiff.vue
  • VueApp/src/Effort/pages/AuditList.vue
  • VueApp/src/components/SortableList.vue
  • VueApp/src/components/__tests__/sortable-list.test.ts
  • VueApp/src/composables/ViperFetch.ts
  • VueApp/src/composables/__tests__/use-audit-colors.test.ts
  • VueApp/src/composables/use-audit-colors.ts
  • VueApp/src/shared/__tests__/create-spa-router.test.ts
  • VueApp/src/shared/create-spa-router.ts
  • VueApp/src/styles/base.css

Comment thread VueApp/src/Effort/components/AuditChangeDetail.vue
feature/clinical-scheduler-audit-log merges to main first and reworked
the same regions of AuditList (filter card, search row, change-detail
markup). Adopt its version wholesale - including AuditChangeDetail,
byte-identical, extended to the desktop layout - and re-apply only the
shared audit palette, so the later main merge resolves cleanly.
ChangeDetailDiff is superseded and removed.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 90 out of 90 changed files in this pull request and generated no new comments.

@rlorenzo rlorenzo changed the title VPR-59 [3/3] CMS migration: management SPA (frontend) VPR-59 [3/4] CMS migration: management SPA (frontend) Jul 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants