feat: rebuild the guided-tour engine for data-driven, admin-configurable tours (0.6.0)#180
Open
aaronstevenwhite wants to merge 13 commits into
Open
feat: rebuild the guided-tour engine for data-driven, admin-configurable tours (0.6.0)#180aaronstevenwhite wants to merge 13 commits into
aaronstevenwhite wants to merge 13 commits into
Conversation
…e surface and a zod Tour schema that types first-party tours and validates admin-authored tour JSON at load with field-anchored errors.
…tour anchor id and the engine reads the live element for a step through a synchronous subscription.
…t resolves anchors by subscription, declarative state-driver capabilities, a config loader that validates admin tour files, an author-mode anchor inspector, and every component publishing its element through useTourAnchor.
…s data-tour-anchor, seed the catalogue with the first-party tours synchronously so a launch resolves immediately, and point the tour specs at the anchor attribute.
… Alert wrappers so a tour anchor ref attaches to their underlying DOM node.
…t from the card, asserts each step anchor resolves, and drive the ontology tour through it.
…t locates the claims viewer.
…a running tour, implementing the missing world, import, project-assignment, and transcription driver capabilities with their anchor catalog corrections, adding the analytics telemetry, the resume cursor, and the step-card pause control, tolerating a missing tour manifest in the catalogue loader, rewriting every built-in tour onto the engine-walked regression helper, and bumping to 0.6.0 with changelogs.
… so unit tests that mount them in isolation no longer crash, with useTourAnchor and useAnchorElement degrading to a no-op when no registry is present.
…0.6.0 # Conflicts: # CHANGELOG.md # annotation-tool/package.json # docs/docs/project/changelog.md # docs/package.json # model-service/package.json # model-service/pyproject.toml # package.json # server/package.json
20 tasks
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.
Description
Rebuilds the guided-tour engine so a deployment can author and tailor tours from data rather than code. A tour is now a validated data document an administrator ships under
public/tours/, every UI surface a tour points at is a named entry in a typed anchor catalog the build checks, and the runner drives each step's prerequisites declaratively. This is the planned 0.6.0 minor release; the built-in tours and the in-app tour menu are unchanged for end users.The aim throughout was configurability for an admin running a local build who wants to tailor tours to their user base: the anchor catalog is a typed contract, the tour schema validates authored documents loudly, and
public/tours/overrides merge over the built-ins without touching application code.Type of Change
Related Issues
Fixes #
Relates to #
Changes Made
annotation-tool/src/tours/engine/anchorCatalog.ts): every tour-addressable surface declared once;AnchorId = keyof typeof anchorCatalog, so naming an undefined anchor fails to compile. Components publish elements withuseTourAnchor(id)(anchorRegistry.tsx).tourSchema.ts,content/tourLoader.ts):parseTourvalidates and narrows a document; admin tours frompublic/tours/(manifest/tours/index.json) merge over the built-ins (override-by-id, append,enabled: falsedrops).TourRunner.tsx,capabilities.ts,seeders.ts): each step navigates to its route, runs itsdrivercapability, resolves the anchor via the catalogreachedBychain, and simulates its action. Added the previously-missing capabilities (world entity/location/event/time editors, entity/time collection builders, import dialog, project video-assignment, transcription) and corrected theproject-video-assignmentandgroup-management-pagecatalog surfaces.menu/tourTelemetry.ts,TourProvider.tsx,StepCard.tsx): the provider folds the runner's events intostarted/step_viewed(dwell)/completed(totalMs)/abandoned(reason+lastStepIndex); afovea.tour.cursorresumes a reload in place; the step card carries a Pause control.components/ui/dialog.tsx): a dialog goes non-modal and ignores outside-press/focus-out close while a tour runs, so the step card stays reachable; outside a tour, behavior is unchanged (replaces a deployment-mode check).content/tourLoader.ts): an HTML SPA-fallback response for/tours/index.jsonis read as "no manifest" instead of throwing.test/e2e/regression/tours/) plus a comprehensive engine smoke suite; the regression helper asserts completion from the analytics telemetry.0.6.0across all manifests;CHANGELOG.mdanddocs/docs/project/changelog.mdupdated.Testing
Test Environment
Test Cases
Local results (all green):
test/e2e/regression/tours/) against the real backend + the MP4 video corpus — every built-in tour launches through the engine and every step's anchor resolves to completion.test/e2e/smoke/tour-engine.spec.ts,tour-runner.spec.ts) — runner, spotlight, step card, telemetry, the resume cursor, pause/resume, focus, keyboard.tourTelemetry.test.ts7,tourLoader.test.ts8).tour-anchors+critical-pathsmoke (confirms the dialog change leaves normal dialog behavior intact).tsc --noEmit,eslint, andvitest(tours + ui) all clean.How to Test
docker compose -f docker-compose.e2e.yml -f docker-compose.e2e.mp4.yml up -d --buildcd annotation-tool && E2E_BASE_URL=http://localhost:3000 npx playwright test --config=playwright.tours.config.ts --project=regression tours/E2E_BASE_URL=http://localhost:3000 npx playwright test --config=playwright.config.ts --project=smoke test/e2e/smoke/tour-engine.spec.ts test/e2e/smoke/tour-runner.spec.tsScreenshots/Videos
Documentation
Performance Impact
Details: The runner resolves anchors by waking on the registry's change notification rather than polling the DOM, and the spotlight tracks via a single requestAnimationFrame loop while mounted; both are bounded to the active tour's lifetime.
Breaking Changes
Breaking changes:
data-tour-idattribute convention are removed. Tours and anchors are expressed through the catalog, schema, registry, and capabilities.Migration guide:
Tourschema) and place them underpublic/tours/with a/tours/index.jsonmanifest; reference anchors by theirAnchorIdfrom the catalog. Components that exposed a surface to a tour useuseTourAnchor(id)instead of adata-tour-idattribute.Checklist
Additional Notes
The demo-deployment specs under
test/e2e/smoke/tour-demo-*.spec.ts/tour-rigorous-*.spec.ts/tour-live-every-feature.spec.tstarget thedemo.fovea.videodeployment configuration (aVITE_DEMO_PUBLICfrontend with aFOVEA_DEMO_MODEbackend that issues anonymous sessions and a seeded clip corpus). They auto-skip outside that environment. Run locally against the tour-demo stack, the engine itself works in the demo (MSW) context, and the failures are entirely deployment-configuration layers (VITE_DEMO_PUBLICdisables MSW in favor of a real demo-mode backend, which then needs anonymous-auth and a seeded corpus) — none of which this PR changes. These are best validated against the live demo deployment viaLIVE_DEMO_URLat deploy time; the tour engine itself is fully covered by the regression + smoke suites above.Reviewer Guidance
Worth a close look: the analytics-telemetry mapping in
menu/tourTelemetry.tsand its wiring inTourProvider.tsx(thestep_vieweddwell and single-close semantics), and the dialog modal gating incomponents/ui/dialog.tsx(it now reads tour-active state app-wide).