feat(cms): Release Archive medium tab strip (ALL · CUTS · SESSIONS · MIXES), retire navigate-away cards
Replace the navigate-away ReleaseArchiveBrowser cards and the redundant top-level Releases toggle with an in-page MudTabs strip under the Releases mode: ALL (CmsAllReleasesGrid) plus one enum-driven tab per ReleaseMedium. Sessions/Mixes browsers gain an Embedded flag that suppresses standalone page chrome when hosted as tab content; CmsCutBrowser is the new Cut-filtered grid. /tracks/sessions, /tracks/mixes, /tracks/archive stay reachable by URL.
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
@page "/tracks/genres"
|
||||
@page "/tracks/archive"
|
||||
@using DeepDrftManager.Services
|
||||
@using DeepDrftModels.Enums
|
||||
@inject CmsTrackBrowserViewModel VM
|
||||
@inject ICmsTrackService CmsTrackService
|
||||
@inject ISnackbar Snackbar
|
||||
@@ -36,6 +37,9 @@
|
||||
}
|
||||
</MudStack>
|
||||
|
||||
@* Top-level browse dimension. The former three-way toggle (Tracks / Releases / Release Archive)
|
||||
collapsed to two (§8.A): "Releases" now hosts the in-page medium tab strip below, subsuming both
|
||||
the old Releases grid (as the ALL tab) and the retired Release Archive cards. *@
|
||||
<MudToggleGroup T="BrowseMode"
|
||||
Value="VM.Mode"
|
||||
ValueChanged="OnModeChanged"
|
||||
@@ -45,7 +49,6 @@
|
||||
Class="mb-4">
|
||||
<MudToggleItem Value="BrowseMode.Tracks">Tracks</MudToggleItem>
|
||||
<MudToggleItem Value="BrowseMode.Albums">Releases</MudToggleItem>
|
||||
<MudToggleItem Value="BrowseMode.Archive">Release Archive</MudToggleItem>
|
||||
</MudToggleGroup>
|
||||
|
||||
@if (VM.Mode == BrowseMode.Tracks)
|
||||
@@ -54,15 +57,21 @@
|
||||
}
|
||||
else if (VM.Mode == BrowseMode.Albums)
|
||||
{
|
||||
@* The all-releases grid is now a self-contained component (Phase 9 §8.B): it owns its own load
|
||||
and refresh, so the host renders it with no parameters. The 8.A tab strip hosts this same
|
||||
component as its ALL tab. Genre mode still uses the VM cache below; only album loading moved
|
||||
into the component, so VM.Albums / VM.AlbumsLoading are no longer read here. *@
|
||||
<CmsAllReleasesGrid OnReleasesChanged="OnAlbumsChanged" />
|
||||
}
|
||||
else if (VM.Mode == BrowseMode.Archive)
|
||||
{
|
||||
<ReleaseArchiveBrowser />
|
||||
@* The Release Archive tab strip (§8.A): an ALL tab plus one tab per ReleaseMedium, ALL left-most.
|
||||
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. *@
|
||||
<MudTabs Elevation="0" Rounded="true" ApplyEffectsToContainer="true" PanelClass="pt-4">
|
||||
<MudTabPanel Text="ALL">
|
||||
<CmsAllReleasesGrid OnReleasesChanged="OnAlbumsChanged" />
|
||||
</MudTabPanel>
|
||||
@foreach (var medium in Enum.GetValues<ReleaseMedium>())
|
||||
{
|
||||
<MudTabPanel Text="@MediumTabLabels[medium]">
|
||||
@MediumGrid(medium)
|
||||
</MudTabPanel>
|
||||
}
|
||||
</MudTabs>
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -78,6 +87,29 @@
|
||||
@code {
|
||||
private CmsTrackGrid? _grid;
|
||||
|
||||
// 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).
|
||||
private static readonly IReadOnlyDictionary<ReleaseMedium, string> MediumTabLabels =
|
||||
new Dictionary<ReleaseMedium, string>
|
||||
{
|
||||
[ReleaseMedium.Cut] = "CUTS",
|
||||
[ReleaseMedium.Session] = "SESSIONS",
|
||||
[ReleaseMedium.Mix] = "MIXES",
|
||||
};
|
||||
|
||||
// Medium → embedded grid. Each medium's grid is its own component (Cut has no per-row action; Session
|
||||
// carries hero upload; Mix carries waveform generation), so the content dispatch is a per-medium
|
||||
// mapping by nature — but it is a single switch returning a fragment, not a markup fork. The browsers
|
||||
// render Embedded so their standalone page chrome (container, title, back button) is suppressed here.
|
||||
private RenderFragment MediumGrid(ReleaseMedium medium) => medium switch
|
||||
{
|
||||
ReleaseMedium.Cut => @<CmsCutBrowser />,
|
||||
ReleaseMedium.Session => @<CmsSessionBrowser Embedded="true" />,
|
||||
ReleaseMedium.Mix => @<CmsMixBrowser Embedded="true" />,
|
||||
_ => @<MudText Typo="Typo.body1" Class="mt-4">No grid for this medium.</MudText>
|
||||
};
|
||||
|
||||
// The all-releases grid refreshes its own list after a delete; this notification lets us invalidate
|
||||
// the VM's genre cache so genre counts reflect the deletion on the next switch into Genre mode.
|
||||
private void OnAlbumsChanged()
|
||||
@@ -93,10 +125,12 @@
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
// /tracks/archive and /tracks/albums both land on the Releases view (the tab strip); the old
|
||||
// separate Archive mode is retired (§8.A) but the route stays reachable rather than 404ing.
|
||||
var uri = NavigationManager.Uri;
|
||||
var initial =
|
||||
uri.Contains("/tracks/albums", StringComparison.OrdinalIgnoreCase) ? BrowseMode.Albums
|
||||
: uri.Contains("/tracks/archive", StringComparison.OrdinalIgnoreCase) ? BrowseMode.Archive
|
||||
: uri.Contains("/tracks/archive", StringComparison.OrdinalIgnoreCase) ? BrowseMode.Albums
|
||||
: uri.Contains("/tracks/genres", StringComparison.OrdinalIgnoreCase) ? BrowseMode.Genres
|
||||
: BrowseMode.Tracks;
|
||||
await VM.SwitchModeAsync(initial);
|
||||
@@ -108,7 +142,6 @@
|
||||
var path = mode switch
|
||||
{
|
||||
BrowseMode.Albums => "/tracks/albums",
|
||||
BrowseMode.Archive => "/tracks/archive",
|
||||
BrowseMode.Genres => "/tracks/genres",
|
||||
_ => "/tracks"
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user