# Catalogsync Task Tree Dashboard Design ## Goal Replace the current Task Center detail tables with a stable tree view: - task - playlist - song The new Task Center must keep task nodes visible across status transitions such as `running -> paused -> completed`, and live refresh must update existing nodes instead of rebuilding the entire task table. ## Problem Statement The current dashboard still feels unstable for two reasons: 1. The expanded task detail is rendered as a large HTML block containing `Summary`, `Stages`, `Workers`, `Running Items`, and `Playlist Progress`. 2. The frontend refresh path still calls `setTaskRows(...)`, which rebuilds the whole Task Center body and then rebinds all event handlers. Even after paused tasks were kept in the query, this full redraw still recreates DOM nodes and causes visible flicker. It also makes the UI feel like a live report view instead of an operator task tree. ## Scope ### In Scope - Rebuild only the `Task Center` section of `/dashboard` - Keep the dashboard top cards for now: - live snapshot - summary - quick actions - create job - playlist coverage - Replace the task detail block with a three-level tree: - task node - playlist child node - song child node - Keep pause/resume/cancel actions on the task node - Preserve expanded task and playlist state across refreshes - Update task status, progress, and counts in place without full Task Center redraw - Keep non-music resource labeling in song rows ### Out of Scope - Redesigning the top dashboard cards - Removing `/jobs`, `/songs`, or other pages - Changing job execution semantics - Changing download logic or retry semantics ## Chosen UI Structure ### Task Center Layout `Task Center` becomes a single tree container instead of a table plus nested detail tables. Each task node shows: - expand/collapse toggle - task display name - task type - task status - scope summary - primary progress text and progress bar - active worker count - lane label - pause/resume button - cancel button When expanded, the task shows only its playlist children. Each playlist node shows: - expand/collapse toggle - playlist name - source label such as `qq #64` - downloaded song count / total song count - progress bar - compact state summary: - running - pending - failed - skipped When expanded, the playlist shows only its song children. Each song node shows: - sequence number - song name - singer summary - platform/source id summary - song status tag - optional `非音乐资源` tag - status note This makes the page behave more like a file explorer tree and removes the distracting intermediate tables. ## Data Model and API Expectations ### Task List `list_task_center_rows()` must return recent tasks for all operator-visible lifecycle states, not just active ones. The intended visible states are: - `queued` - `running` - `pause_requested` - `paused` - `completed` - `completed_with_errors` - `failed` - `canceled` This ensures a task stays in the tree when its state changes; only its displayed status changes. ### Task Detail `/api/jobs/{job_id}` may continue returning its current payload shape, but the dashboard will only consume: - `job` - `playlist_progress` The frontend will ignore `summary`, `stages`, `workers`, and `running_items` for Task Center rendering. ### Playlist Songs `/api/jobs/{job_id}/playlists/{playlist_id}/songs` remains the lazy-loaded source for song child nodes. The existing fields are sufficient: - `position` - `song_name` - `singers` - `platform` - `remote_song_id` - `status` - `status_note` - `is_non_music_resource` ## Rendering Strategy ### Initial Render The server-rendered HTML for `/dashboard` should render a task tree shell directly, not a table with hidden detail rows. ### Live Updates The Task Center refresh path must switch from full `innerHTML` replacement to keyed DOM patching. Rules: 1. Task nodes are keyed by `job_id` 2. Playlist nodes are keyed by `job_id + playlist_id` 3. Song nodes are keyed by `job_id + playlist_id + song_id/position` 4. Existing nodes are updated in place 5. Expanded/collapsed state is preserved in `dashboardState` 6. Status changes never collapse or remove a visible node by themselves ### Removal Policy Nodes may be removed only when they are absent from the latest server payload because they have truly fallen out of the visible result window, not because they changed from active to paused/completed. ## Refresh Model ### Dashboard Summary Refresh The lightweight snapshot refresh may continue updating: - live snapshot text - summary numbers - download stats - playlist coverage These sections can still use simple row replacement because they are small and not interactive. ### Task Tree Refresh Task rows must be refreshed through a dedicated keyed patch function: - update existing task header fields - insert new task nodes - remove missing task nodes only when no longer returned - if a task is expanded, refresh its playlist subtree in place - if a playlist is expanded, refresh its song subtree in place when fresh data arrives The Task Center must no longer call a function that rebuilds the whole container on every poll. ## Error Handling - Failed songs remain visible in the playlist subtree with their note - Non-music resources remain visible and are labeled `非音乐资源` - If playlist song loading fails, show the error message only inside that playlist node - If task detail loading fails, show the error only inside that task node ## Testing Strategy ### Automated - repository test: task list includes completed jobs - API test: dashboard HTML renders the tree shell instead of detail tables - API test: dashboard data continues to expose task rows for live refresh ### Manual - open `/dashboard` - expand one paused task - expand one playlist - wait through multiple refresh cycles - verify: - expanded task stays expanded - expanded playlist stays expanded - no `Summary / Stages / Workers / Running Items` blocks appear under tasks - task status changes update text only, without the whole Task Center flashing ## Assumptions - The operator still wants the top dashboard cards retained for now - Recent finished tasks should remain visible in the Task Center instead of disappearing immediately - The current lazy-load model for song lists is acceptable as long as the node itself stays stable