CMS Phase 9 Wave 3: Release Archive tab, medium selector, Session/Mix browsers

Renames Genre tab to Release Archive with switch-free medium card group
(Enum.GetValues-driven). Adds MediumFields single dispatch + CutFields/SessionFields/
MixFields per-medium sections embedded by all five upload/edit forms. BatchUpload
enforces single-track invariant for Session/Mix. Adds CmsSessionBrowser (hero-image
upload) and CmsMixBrowser (waveform status + per-row Generate trigger).
ICmsReleaseService/CmsReleaseService wraps api/release endpoints.
Note: medium selector is forward-compat only — API write path pending.
This commit is contained in:
daniel-c-harvey
2026-06-12 23:07:15 -04:00
parent 5f7eaed112
commit 2f47efeb46
22 changed files with 970 additions and 45 deletions
@@ -22,15 +22,6 @@
T="string" Label="Release Date (YYYY-MM-DD)" Placeholder="2024-01-15"
Variant="Variant.Outlined" Disabled="Disabled" />
</MudItem>
<MudItem xs="12" sm="6">
<MudSelect T="ReleaseType" Value="ReleaseType" ValueChanged="@((ReleaseType v) => ReleaseTypeChanged.InvokeAsync(v))"
Label="Release Type" Variant="Variant.Outlined" Disabled="Disabled">
@foreach (var rt in Enum.GetValues<ReleaseType>())
{
<MudSelectItem T="ReleaseType" Value="rt">@rt</MudSelectItem>
}
</MudSelect>
</MudItem>
<MudItem xs="12" sm="6">
<MudField Label="Cover Art" Variant="Variant.Outlined" InnerPadding="false">
<MudStack Spacing="3">
@@ -70,6 +61,12 @@
</MudField>
</MudItem>
</MudGrid>
<MudDivider Class="my-4" />
<MediumFields @bind-Medium="MediumBinding"
@bind-ReleaseType="ReleaseTypeBinding"
Disabled="Disabled" />
</MudPaper>
@code {
@@ -83,6 +80,8 @@
[Parameter] public EventCallback<string> ReleaseDateChanged { get; set; }
[Parameter] public ReleaseType ReleaseType { get; set; } = ReleaseType.Single;
[Parameter] public EventCallback<ReleaseType> ReleaseTypeChanged { get; set; }
[Parameter] public ReleaseMedium Medium { get; set; } = ReleaseMedium.Cut;
[Parameter] public EventCallback<ReleaseMedium> MediumChanged { get; set; }
[Parameter] public IBrowserFile? SelectedImageFile { get; set; }
[Parameter] public EventCallback<IBrowserFile?> SelectedImageFileChanged { get; set; }
@@ -98,6 +97,20 @@
? null
: $"/api/image/{Uri.EscapeDataString(ExistingImagePath)}";
// MediumFields uses two-way @bind; bridge its bindings to this component's own
// parameter/EventCallback pairs so the parent form stays the single owner of the values.
private ReleaseMedium MediumBinding
{
get => Medium;
set => MediumChanged.InvokeAsync(value);
}
private ReleaseType ReleaseTypeBinding
{
get => ReleaseType;
set => ReleaseTypeChanged.InvokeAsync(value);
}
private Task HandleImageFileSelected(InputFileChangeEventArgs e) =>
SelectedImageFileChanged.InvokeAsync(e.File);