- Move import page, tabs, workflow state, and route tests into React-owned route slices - Preserve shell gating, staging queries, album matching, singles matching, auto-import, and queue behavior - Add migration plan snapshot so cleanup/refinement can build on a stable baseline
9.9 KiB
WebUI Import Migration Plan
Snapshot date: 2026-05-15
Status
- Initial implementation completed on 2026-05-15.
importis 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.jsas dead code and can be removed in a focused cleanup pass. - Backend routes are already grouped around
/api/import/*and/api/auto-import/*.
Goal
- Migrate
importinto a React-owned route without changing the user workflow. - Preserve manual album matching, singles matching, auto-import review, and the processing queue.
- Keep staging-folder and import-processing behavior backed by the existing API routes.
- Use the completed
issuesandstatsroutes as the structural reference for route slices, API helpers, shell gating, and tests.
Why import Was The Right Next Route
- It is the safest remaining route after excluding
helpandhydrabase. - It has real workflows, so it gives the migration program more signal than another mostly-static page.
- The backend API boundary is already clearer than the broad dashboard, library, discover, sync, or settings surfaces.
- The page is important enough to validate mutation, polling, and route-local reducer patterns before larger operational pages.
- It does not need a visual redesign or a new shell abstraction to migrate cleanly.
Current Legacy Shape
Page surface in webui/index.html:
- Header
- import folder path
- file count and total size
- refresh action
- Processing queue
- per-job progress
- partial error display
- clear-finished action
- Tabs
- auto-import
- albums
- singles
- Auto-import tab
- enable toggle
- status text
- confidence and interval settings
- scan-now action
- live scan progress
- result filters
- approve, reject, approve-all, and clear-completed actions
- Albums tab
- auto-group suggestions from staging
- album search
- album result cards
- track matching view
- drag/drop and tap-to-assign overrides
- unmatched file pool
- process album action
- Singles tab
- staging file list
- select all / per-file selection
- per-file track search
- manual match selection
- process selected action
Legacy JS responsibilities in webui/static/stats-automations.js:
initializeImportPage- staging fetch and refresh
- tab switching
- auto-import polling
- auto-import mutations
- staging group and suggestion rendering
- album search and match POSTs
- drag/drop assignment state
- singles search and selection state
- client-side processing queue
- sequential album/singles processing requests
Backend endpoints already available:
GET /api/import/staging/filesGET /api/import/staging/groupsGET /api/import/staging/hintsGET /api/import/staging/suggestionsGET /api/import/search/albumsPOST /api/import/album/matchPOST /api/import/album/processGET /api/import/search/tracksPOST /api/import/singles/processGET /api/auto-import/statusPOST /api/auto-import/toggleGET /api/auto-import/settingsPOST /api/auto-import/settingsGET /api/auto-import/resultsPOST /api/auto-import/approve/:idPOST /api/auto-import/reject/:idPOST /api/auto-import/scan-nowPOST /api/auto-import/approve-allPOST /api/auto-import/clear-completed
Proposed Route Slice
webui/src/routes/import/
route.tsx
-import.types.ts
-import.api.ts
-import.helpers.ts
-route.test.tsx
-ui/
import-page.tsx
Proposed Route Responsibilities
route.tsx
- declare
/import - validate search params
- gate route through
bridge.isPageAllowed('import') - preload shell context
- ensure the staging-files query
- prefetch album staging groups and suggestions
- leave auto-import status/results as tab-specific client queries
-import.types.ts
- search param schema
- API response types
- staging file, staging group, album result, track result, match, auto-import result, and queue item types
-import.api.ts
- 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
-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
-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
Search Params
Use URL state only for durable, shareable route state:
tab- values:
album,singles,auto - default:
album
- values:
autoFilter- values:
all,pending,imported,failed - default:
all
- values:
Keep these local to React state:
- album search text
- track search text
- selected album
- match overrides
- selected singles
- processing queue jobs
Reasoning:
- The tab and auto-import filter are useful after reloads.
- The matching workflow is ephemeral and should not create fragile URLs with file indexes or local staging paths.
Query Model
Critical route-loader data:
importStagingFilesQueryOptions()
Useful prefetch data:
importStagingGroupsQueryOptions()importStagingSuggestionsQueryOptions()
Tab-specific data:
autoImportStatusQueryOptions()autoImportSettingsQueryOptions()autoImportResultsQueryOptions(autoFilter)
Lazy search data:
importAlbumSearchQueryOptions(query)importTrackSearchQueryOptions(query)
Mutation-style actions:
- album match draft
- process one album track
- process one single file
- toggle auto-import
- save auto-import settings
- scan now
- approve/reject auto-import result
- approve all
- clear completed
Invalidation rules:
- Processing album or singles files invalidates staging files, staging groups, staging suggestions, auto-import results, and any route-local queue completion summary.
- Auto-import actions invalidate auto-import status and results.
- Auto-import settings writes invalidate settings and status.
- Refresh invalidates staging files, groups, and suggestions.
Incremental Migration Order
Recommended order:
- Add route slice, types, API helpers, reducer, and helper tests.
- Build the React route shell with header, tabs, and staging summary.
- Port the Albums tab search and suggestions, but keep processing disabled until match rendering is covered.
- Port the album matching view, including drag/drop and tap assignment.
- Port the processing queue and album/singles process mutations.
- Port the Singles tab.
- Port the Auto tab and polling behavior.
- Flip
importfromlegacytoreactin the shell route manifest. - Remove the legacy
import-pageDOM fromwebui/index.html. - Remove import-specific legacy functions from
webui/static/stats-automations.js.
This order gives us a visible React page early while delaying the highest-risk file-processing actions until the state model is tested.
Testing Sketch
Unit tests:
- tab and filter search-param defaults
- staging summary formatting
- auto-import counters
- confidence labels
- reducer assignment behavior
- reducer queue transitions
API tests:
- staging files success and error
- staging groups success and error
- album search success and empty result
- track search success and empty result
- album match success and failure
- album process success and partial error
- singles process success and partial error
- auto-import status/results/settings/actions
Route / component tests:
- unauthorized users redirect to profile home
- default route renders the Albums tab
?tab=singlesrenders the Singles tab?tab=auto&autoFilter=pendingrenders 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
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.
- 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.
Decisions To Keep Simple
- Keep the current visual language.
- Keep the existing backend endpoints.
- Keep the processing queue client-side for the first migration.
- Keep file matching state local to the route.
- Do not extract shared workflow primitives until a second migrated route needs them.
Outcome
- The route now serves as the first React-owned workflow migration.
- The implementation uses validated search params for
tabandautoFilter. - 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.
Recommendation
Treat remaining work as cleanup and hardening rather than route selection.
Follow-up work should optimize for:
- shrinking
stats-automations.jsafter cutover - adding E2E coverage around full album and singles processing
- considering route-level code splitting once more large React routes land
It should not optimize for:
- redesign
- backend reshaping
- shared queue abstractions
- migrating
automationsat the same time