docs: move Phase 8 §8.0 to COMPLETED; unblock §8.1-§8.5 in PLAN
This commit is contained in:
@@ -134,39 +134,33 @@ Reusable presentational components in `DeepDrftShared.Client` (the RCL consumed
|
||||
|
||||
Three browse modes for the CMS `/tracks` page — **Track**, **Album**, **Genre** — selected by a toggle, each deep-linkable so the public home page can link straight into a mode. One view-model (DI-scoped, matching the `TracksViewModel` pattern) feeds all three views; the divergence is in rendering, not data paths (per the standing "same data, different uses" preference). This supersedes the deferred §6.2 — Album and Genre modes *are* the intermediate browse surface that item was waiting on. Full spec: `product-notes/phase-8-cms-track-browser.md` (normalization gate, component decomposition, VM design, URL scheme, data contracts, open questions).
|
||||
|
||||
**§8.0 is a hard pre-requisite gate** — a breaking `TrackEntity` normalization that must land before any UI work in §8.1–§8.5. It also dissolves the largest UI open question (the old `AlbumSummaryDto` widening — the new Release table supplies those fields directly). The Waveform Pre-Processing tab is **removed**, folded into an in-grid status column + per-row/page-level generate actions (see §8.2). Review decisions folded in 2026-06-11; §8.0's own open questions (nullable release FK, upload upsert flow, public `TrackDto` read shape) still need Daniel sign-off before that migration is cut.
|
||||
**§8.0 landed on 2026-06-11** — a breaking `TrackEntity` normalization has been completed and is stable on dev. §8.1–§8.5 are now unblocked. The Waveform Pre-Processing tab is **removed**, folded into an in-grid status column + per-row/page-level generate actions (see §8.2).
|
||||
|
||||
### 8.0 `TrackEntity` normalization (pre-requisite — must land before §8.1–§8.5)
|
||||
|
||||
- **What:** Split the flat `TrackEntity` into two normalized tables. New **`ReleaseEntity`** holds release-cardinal data (`Title`, `Artist`, `Genre?`, `ReleaseDate?`, `ImagePath?`, `ReleaseType`, `CreatedByUserId?`). Slimmed **`TrackEntity`** holds track-cardinal data only (`Id`, `ReleaseId` FK, `Release` nav, `EntryKey`, `TrackName`, `TrackNumber`, `OriginalFileName?`) — the release fields are removed from it. New `ReleaseDto`; `TrackDto` slims and gains `ReleaseId` + a **nested `Release` (`ReleaseDto`)** (resolved 2026-06-11: nested, not a flat read model — flat fields are removed and every consumer is updated, not denormalized back); `AlbumSummaryDto` is retired in favour of `ReleaseDto`.
|
||||
- **Why:** The flat schema duplicates release-level metadata on every track row — updating an album's cover art or artist means rewriting every track. Phase 8 introduces album-as-a-unit editing (Batch Edit, album-scoped delete), so the model should match the domain: a Release is first-class; Tracks belong to a Release. This collapses several §8 UI open questions (Album-mode parent rows become Release rows directly; no `GROUP BY`-derived summary).
|
||||
- **Shape:** Sequenced as **five mergeable waves** (notes §0.6): (1) data model — `ReleaseEntity`/config/migration in `DeepDrftData`; (2) DTOs/services/repositories/API — `ReleaseDto`, slimmed `TrackDto`, JOIN-projecting repository, upload find-or-create Release; **Waves 1 + 2 are a single deployment unit** (removing the entity fields breaks compile until the DTO/service layer lands — never merge Wave 1 alone); (3) public-client consumers (`TrackCard`, `TrackDetail`, `TrackMetaLabel`, `NowPlayingCard`) re-point to `track.Release.*`; (4) existing CMS surfaces (`TrackEdit`, `TrackNew`, `BatchUpload`, `TrackList`) minimally updated to compile on the normalized model — Waves 3 + 4 run in parallel; (5) the Phase 8 UI (§8.1–§8.5) begins only after 1–4 are stable. The breaking migration: create `releases`, populate from distinct `(album, artist)` groups, add + populate `release_id` FK, drop redundant track columns. Remaining open questions for Daniel: nullable release FK for album-less tracks (recommend yes), upload auto-create-or-find Release (recommend yes — committed in Wave 2 shape). Full spec, wave breakdown, and per-file consumer list: notes §0 / §0.6.
|
||||
|
||||
### 8.1 URL scheme + mode toggle *(depends on §8.0)*
|
||||
### 8.1 URL scheme + mode toggle
|
||||
|
||||
- **What:** `/tracks` (Track mode, default), `/tracks/albums`, `/tracks/genres` as route segments; a toggle inside the existing "Tracks" tab switches mode and pushes the matching URL. The Waveform Pre-Processing tab is untouched.
|
||||
- **Why:** The public home page hard-codes these as cross-host deep-links; a route segment reads as a stable address and matches the app's existing segment-based routing (`/tracks/upload`, `/tracks/{id}`). Query-param mode (`?mode=`) was the alternative — rejected as transient-looking view state, optionally tolerated as an alias.
|
||||
- **Shape:** One `TrackList` component carrying three `@page` directives (or three thin wrappers passing an `InitialMode`); the toggle drives `Mode` + `NavigationManager.NavigateTo`. See notes §3, §9.
|
||||
|
||||
### 8.2 `CmsTrackGrid` — the reusable flat track table (DRY core) *(depends on §8.0)*
|
||||
### 8.2 `CmsTrackGrid` — the reusable flat track table (DRY core)
|
||||
|
||||
- **What:** Extract today's `MudTable<TrackDto>` into a standalone `CmsTrackGrid.razor` taking `AlbumFilter`/`GenreFilter` params. Apply the new column layout: Track # → 40×40 art thumb → Track Name → Artist → Album → Genre → Release Date (`d MMMM, yyyy`) → **Waveform Status** → Actions. Entry Key + File Name move out of the grid into an Info-icon tooltip (monospace). Art thumb reuses the public `TrackCard` fallback pattern, defined locally CMS-side.
|
||||
- **Why:** Single source of truth for the track-table layout — consumed by both Track mode (no filter) and Genre mode (genre filter), so no duplicated table markup. Decluttering Entry Key / File Name into a tooltip keeps the grid scannable while the data stays reachable. The Waveform column replaces the removed Waveform Pre-Processing tab (status visible inline; per-row Generate when no profile; page-level "Generate All Missing" in the Track-mode header).
|
||||
- **Shape:** Owns its own `MudTable` + `LoadServerData` + delete-confirm (lifted from `TrackList`). `GetPagedAsync` gains optional `album`/`genre` filter params — the one filter data-contract change (the endpoint already supports the filters); post-§0 the filter joins through `releases`. Waveform status comes from a new `HasWaveformProfile` bool on `TrackDto` (recommended over a second per-page lookup; fold into the §8.0 DTO pass). Display date format is presentation-only; sort key stays the raw `DateOnly`. See notes §8, §9, §11.
|
||||
|
||||
### 8.3 Album mode *(depends on §8.0)*
|
||||
### 8.3 Album mode
|
||||
|
||||
- **What:** `CmsAlbumBrowser` — parent release rows (art, title, artist, track count, genre, release date, release-type chip, Edit + Delete) that expand to child track rows (track # + name only). Edit → Batch Edit page (§8.5); Delete → album-scoped delete of every track.
|
||||
- **Why:** A scannable release catalogue is the CMS analogue of the public `AlbumsView`, and the natural place to manage a release as a unit.
|
||||
- **Shape:** Post-§0, parent rows are `ReleaseEntity`/`ReleaseDto` rows — `GetReleasesAsync` (eager, once) supplies title/artist/genre/date/type directly, no derivation. Child tracks lazy via `GetPagedAsync(album:)` (joins through `releases`) on first expand, cached per row — no new endpoint. Expandable `MudTable` over `MudTreeView` (parent rows are multi-column, not tree-shaped). **The old `AlbumSummaryDto` widening question is dissolved by §8.0 normalization** — the Release table has all the fields, so the parent row is fully populated at rest with no DTO widening and no lazy derivation. See notes §6, §10, §0.5.
|
||||
|
||||
### 8.4 Genre mode *(depends on §8.0)*
|
||||
### 8.4 Genre mode
|
||||
|
||||
- **What:** `CmsGenreBrowser` — a responsive `MudCard` grid (one card per genre: name + track count); clicking a card expands it (accordion, one open at a time) to reveal a `CmsTrackGrid` filtered to that genre.
|
||||
- **Why:** CMS analogue of the public `GenresView`; the card-to-grid expand is the cheapest second mode because the grid is already built (§8.2).
|
||||
- **Shape:** `GetGenreSummariesAsync` once; the expanded panel renders `CmsTrackGrid` with `GenreFilter` set and the Add button suppressed — zero duplicated table markup. The embedded grid gets the waveform status column + per-row generate for free. See notes §7, §9.
|
||||
|
||||
### 8.5 Batch Edit page *(depends on §8.0)*
|
||||
### 8.5 Batch Edit page
|
||||
|
||||
- **What:** New page `/tracks/album/{albumName}/edit`, reached from an Album-mode row's Edit action. `BatchUpload`'s master-detail mechanics with the release's data preloaded; submit swaps per-row `UploadTrackAsync` for `UpdateAsync` on existing tracks (new tracks still upload). Distinct from the existing single-track edit at `/tracks/{id}`.
|
||||
- **Why:** Editing a release as a unit (rename tracks, reorder, swap cover, add tracks) without round-tripping the single-track editor per track.
|
||||
|
||||
Reference in New Issue
Block a user