From c6ef641ab9cd36b7d698f6e9d8567be16bfaad7c Mon Sep 17 00:00:00 2001 From: daniel-c-harvey Date: Sat, 13 Jun 2026 22:33:33 -0400 Subject: [PATCH] feat(cms): medium-aware Add Track on Release Archive tabs (8.E) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add Track now appears on every Release Archive tab and pre-selects the upload form's medium via ?medium=… (ALL→Cut); the selector stays user-changeable on landing. --- .../Components/Pages/Tracks/BatchUpload.razor | 19 ++++++++++++ .../Components/Pages/Tracks/TrackList.razor | 31 ++++++++++++++++++- 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/DeepDrftManager/Components/Pages/Tracks/BatchUpload.razor b/DeepDrftManager/Components/Pages/Tracks/BatchUpload.razor index 66ee1ea..f1214d5 100644 --- a/DeepDrftManager/Components/Pages/Tracks/BatchUpload.razor +++ b/DeepDrftManager/Components/Pages/Tracks/BatchUpload.razor @@ -130,6 +130,25 @@ private ReleaseType _releaseType = ReleaseType.Single; private ReleaseMedium _medium = ReleaseMedium.Cut; + // Optional pre-select from the Add-Track buttons (§8.E): /tracks/upload?medium=session lands the + // form already in Session mode. A seed only — the medium selector stays user-changeable after load. + // Unrecognised/absent values fall through to the Cut default (same defensive posture as the API's + // TrackController.UploadTrack medium parse). + [SupplyParameterFromQuery(Name = "medium")] public string? MediumParam { get; set; } + + protected override void OnInitialized() + { + // Seed the medium from the query param so a pre-selected upload form (e.g. the Sessions tab's + // Add Track) lands already showing that medium's conditional fields. Goes through OnMediumChanged + // so the single-track collapse runs identically to a user selector change. + if (!string.IsNullOrWhiteSpace(MediumParam) + && Enum.TryParse(MediumParam, ignoreCase: true, out var medium) + && Enum.IsDefined(medium)) + { + OnMediumChanged(medium); + } + } + // Switching to a single-track medium collapses any multi-track selection to the first row so the // single-track invariant holds before submit. The predicate reads the same MediumRules cardinality // declaration the upload service enforces, so the form and the domain cannot drift. diff --git a/DeepDrftManager/Components/Pages/Tracks/TrackList.razor b/DeepDrftManager/Components/Pages/Tracks/TrackList.razor index a962d17..ee3c366 100644 --- a/DeepDrftManager/Components/Pages/Tracks/TrackList.razor +++ b/DeepDrftManager/Components/Pages/Tracks/TrackList.razor @@ -61,7 +61,21 @@ The medium tabs are enum-driven — a fourth medium adds a tab automatically; only a label-lookup entry (MediumTabLabels) and a content arm (MediumGrid) are needed, no markup fork. Selecting a tab swaps the grid below in place; no navigation to a separate page occurs. *@ - + @* Medium-aware Add Track (§8.E): the button lives in the tab-strip chrome (not inside any grid + component — 8.C owns those) and reflects the active tab. It pre-selects the upload form to the + tab's medium via a single query-param (?medium=…); the ALL tab defaults to Cut. The medium is a + seed only — the upload form's selector stays user-changeable after landing. *@ + + + Add Track + + + + @@ -87,6 +101,21 @@ @code { private CmsTrackGrid? _grid; + // Active Release-Archive tab. Panel 0 is ALL; panels 1.. map to Enum.GetValues() in + // order. Drives the medium-aware Add Track button (§8.E). + private int _activeTabIndex; + + // The medium the Add Track button pre-selects for the active tab. ALL (panel 0) defaults to Cut + // (Daniel, 2026-06-13); each medium tab maps to its enum value by position, so a fourth medium tab + // gets a correct Add Track for free — no markup fork. + private ReleaseMedium ActiveMedium => + _activeTabIndex <= 0 ? ReleaseMedium.Cut : Enum.GetValues()[_activeTabIndex - 1]; + + // Single query-param convention: the upload page reads ?medium=… and seeds its selector (which stays + // user-changeable). Always explicit, including ALL→cut, so the link is unambiguous. + private static string AddTrackHref(ReleaseMedium medium) => + $"/tracks/upload?medium={medium.ToString().ToLowerInvariant()}"; + // Medium → tab label. The one place medium display text lives for the tab strip; a future medium adds // one entry here and surfaces a tab automatically. Mirrors the extension discipline the retired // ReleaseArchiveBrowser used for its cards. The ALL tab is rendered separately (it is not a medium).