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
pull/686/head
Antti Kettunen 2 days ago
parent e2a760bd68
commit 400d0dd48a
No known key found for this signature in database
GPG Key ID: C6B2A3D250359BD7

@ -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

@ -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

Loading…
Cancel
Save