From 400d0dd48acc1389747f4a5bed4722b2d126f0db Mon Sep 17 00:00:00 2001 From: Antti Kettunen Date: Sun, 24 May 2026 16:11:25 +0300 Subject: [PATCH] docs(import): align migration docs - describe the implemented nested /import route structure - document the route-local workflow store and stable draft state - update testing, risk, and cleanup notes to match the current code --- webui/docs/migration/import-migration-plan.md | 91 +++++++++++++------ .../docs/migration/page-migration-overview.md | 3 +- 2 files changed, 65 insertions(+), 29 deletions(-) diff --git a/webui/docs/migration/import-migration-plan.md b/webui/docs/migration/import-migration-plan.md index 9a5e4013..1ef64f72 100644 --- a/webui/docs/migration/import-migration-plan.md +++ b/webui/docs/migration/import-migration-plan.md @@ -1,6 +1,6 @@ # WebUI Import Migration Plan -Snapshot date: 2026-05-15 +Snapshot date: 2026-05-24 ## Status @@ -8,8 +8,10 @@ Snapshot date: 2026-05-15 - `import` is now React-owned in the shell route manifest. - The legacy import page DOM has been removed from `webui/index.html`. - Legacy import activation has been removed from `webui/static/init.js`. -- A React route slice now owns import rendering, tab state, album matching, singles matching, auto-import controls, and the client-side processing queue. -- The old import-specific functions still exist at the top of `webui/static/stats-automations.js` as dead code and can be removed in a focused cleanup pass. +- A React route subtree now owns import rendering, nested route state, album matching, singles matching, auto-import controls, and the client-side processing queue. +- The old `tab=` URL contract has been replaced by `/import/album`, `/import/singles`, and `/import/auto`, with `/import` redirecting to `/import/album`. +- Route-local workflow state lives in `webui/src/routes/import/-import.store.ts`, which keeps draft matching, selection, and queue state alive while navigating within the import route. +- The old import-page-specific functions have already been removed from `webui/static/stats-automations.js`; any remaining `import` references there belong to the broader automation feature set, not this page migration. - Backend routes are already grouped around `/api/import/*` and `/api/auto-import/*`. ## Goal @@ -102,30 +104,53 @@ Backend endpoints already available: - `POST /api/auto-import/approve-all` - `POST /api/auto-import/clear-completed` -## Proposed Route Slice +## Implemented Route Slice ```text webui/src/routes/import/ route.tsx + index.tsx + album.tsx + auto.tsx + singles.tsx -import.types.ts -import.api.ts -import.helpers.ts + -import.store.ts -route.test.tsx -ui/ import-page.tsx + album-import-tab.tsx + auto-import-tab.tsx + singles-import-tab.tsx + import-shared.tsx ``` -## Proposed Route Responsibilities +## Implemented Route Responsibilities `route.tsx` - declare `/import` -- validate search params - gate route through `bridge.isPageAllowed('import')` - preload shell context -- ensure the staging-files query +- prefetch the staging-files query without blocking on transient fetch failure + +`index.tsx` + +- redirect `/import` to `/import/album` + +`album.tsx` + - prefetch album staging groups and suggestions -- leave auto-import status/results as tab-specific client queries + +`auto.tsx` + +- validate the `autoFilter` search param +- keep route-driven filter changes in the URL while leaving the rest of the workflow state local + +`singles.tsx` + +- mount the singles import tab without extra route-level loader work `-import.types.ts` @@ -137,32 +162,38 @@ webui/src/routes/import/ - query options for staging, groups, suggestions, auto-import status, auto-import settings, auto-import results, album search, and track search - mutation helpers for album match, album process, singles process, auto-import actions, and settings writes -- a single `invalidateImportQueries(queryClient)` helper for broad route refreshes after processing +- invalidation helpers for broad route refreshes, staging-only refreshes, and auto-import-only refreshes `-import.helpers.ts` - byte-size formatting -- default query param coercion - album and track display labels - confidence class/label mapping - staging match normalization - auto-import result filtering and counters +`-import.store.ts` + +- album search state, selected album, auto-group file paths, and match overrides +- selected single-file state and manual matches +- queue job state and queue entry updates +- single-search draft state +- draft state survival across nested route remounts + `-ui/import-page.tsx` -- route-local match state -- tap-selected file chip state -- singles selection and manual matches -- auto-import polling UI -- client-side processing queue state +- page chrome and nested route navigation +- queue summary and queue-item rendering +- nested route outlet for album, singles, and auto views ## Search Params -Use URL state only for durable, shareable route state: +Use nested route paths for durable, shareable tab state: -- `tab` - - values: `album`, `singles`, `auto` - - default: `album` +- `/import/album` + - default landing route +- `/import/singles` +- `/import/auto` - `autoFilter` - values: `all`, `pending`, `imported`, `failed` - default: `all` @@ -178,7 +209,8 @@ Keep these local to React state: Reasoning: -- The tab and auto-import filter are useful after reloads. +- The tab choice belongs in the path, which keeps deep links simple and avoids an extra `tab=` query param. +- The auto-import filter is still useful after reloads. - The matching workflow is ephemeral and should not create fragile URLs with file indexes or local staging paths. ## Query Model @@ -192,7 +224,7 @@ Useful prefetch data: - `importStagingGroupsQueryOptions()` - `importStagingSuggestionsQueryOptions()` -Tab-specific data: +Nested-route data: - `autoImportStatusQueryOptions()` - `autoImportSettingsQueryOptions()` @@ -239,11 +271,13 @@ Recommended order: This order gives us a visible React page early while delaying the highest-risk file-processing actions until the state model is tested. +The implemented route keeps the same overall migration shape, but the final URL contract uses nested route paths instead of a `tab=` search param. + ## Testing Sketch Unit tests: -- tab and filter search-param defaults +- route path and filter defaults - staging summary formatting - auto-import counters - confidence labels @@ -264,20 +298,21 @@ API tests: Route / component tests: - unauthorized users redirect to profile home -- default route renders the Albums tab -- `?tab=singles` renders the Singles tab -- `?tab=auto&autoFilter=pending` renders pending auto-import results +- default route redirects to `/import/album` +- `/import/singles` renders the Singles tab +- `/import/auto?autoFilter=pending` renders pending auto-import results - refresh invalidates staging queries - album selection opens the match view - drag/drop and tap assignment update track matches - processing queue advances and refreshes staging on completion +- client workflow drafts survive page remounts Playwright can wait until after route ownership flips. ## Risks - The processing queue is client-side and long-running. -- Auto-import polling must stop when leaving the tab or route. +- Auto-import polling must stop when leaving the auto subroute or route. - File indexes can become stale after staging refreshes. - Album matching depends on preserving source, album name, and album artist from search results. - The page currently shares a large legacy module with stats and automations code, so cleanup should be careful and incremental. @@ -293,9 +328,9 @@ Playwright can wait until after route ownership flips. ## Outcome - The route now serves as the first React-owned workflow migration. -- The implementation uses validated search params for `tab` and `autoFilter`. +- The implementation uses nested route paths plus a validated `autoFilter` search param. - The route uses TanStack Query for staging data, suggestions, auto-import polling, mutations, and invalidation. -- Tests cover shell ownership, URL tab state, album match payload preservation, and auto-import rendering. +- Tests cover shell ownership, nested route state, album match payload preservation, and auto-import rendering. ## Recommendation diff --git a/webui/docs/migration/page-migration-overview.md b/webui/docs/migration/page-migration-overview.md index 6016df4b..16808c62 100644 --- a/webui/docs/migration/page-migration-overview.md +++ b/webui/docs/migration/page-migration-overview.md @@ -134,7 +134,8 @@ Rollups: - Primary files: `webui/src/routes/import/*`, `webui/src/platform/shell/route-manifest.ts`. - Main surface: staging files, album and singles matching, suggestion cards, processing queue. - Key coupling: settings-derived staging path assumptions and downstream library state. -- Recommendation: completed as the next migration after `stats`. Follow-up cleanup should remove the dead legacy import functions from `webui/static/stats-automations.js`. +- Recommendation: completed as the next migration after `stats`. The import subtree now uses nested route paths, with `/import` redirecting to `/import/album` and `autoFilter` remaining in the search string; any remaining `import` references in `webui/static/stats-automations.js` belong to the broader automation feature set, not this page migration. +- Route-local workflow state lives in `webui/src/routes/import/-import.store.ts`, which keeps drafts and queue state alive while moving between album, singles, and auto views. - Route plan: `webui/docs/migration/import-migration-plan.md`. ### Wave 2: Search split