feat(cms): bring per-medium tab grids to ALL-tab parity (§8.C)
Render the rich CmsAlbumBrowser filtered per medium in the CUTS/SESSIONS/MIXES tabs via an optional RowActions slot; retire the thin CmsMediumTable. Session hero and Mix waveform actions preserved; ALL tab and TrackList unchanged.
This commit is contained in:
@@ -7,10 +7,11 @@
|
||||
@inject ILogger<CmsSessionBrowser> Logger
|
||||
|
||||
@* Embedded as the SESSIONS tab content of the Release Archive (Phase 9 §8.A), and still routable at
|
||||
/tracks/sessions for direct-URL access. When embedded, the page chrome (title, container, the now-
|
||||
meaningless "Back to Release Archive" button) is suppressed — the host tab strip owns that frame; only
|
||||
the grid renders. The standalone route keeps the full page chrome. The per-row hero affordance (9.5.E)
|
||||
is preserved in both contexts. *@
|
||||
/tracks/sessions for direct-URL access. The grid is the rich CmsAlbumBrowser filtered to Sessions
|
||||
(§8.C parity: expand-tracks, delete, Type chip, per-row edit), with the Session hero upload supplied
|
||||
as its medium-specific RowActions slot so that affordance survives the move off the thin table. When
|
||||
embedded, the page chrome (title, container, the now-meaningless "Back to Release Archive" button) is
|
||||
suppressed; the standalone route keeps it. The hero affordance (9.5.E) is preserved in both contexts. *@
|
||||
@if (Embedded)
|
||||
{
|
||||
@GridContent
|
||||
@@ -49,47 +50,51 @@ else
|
||||
HeroImageEntryKey = release.SessionMetadata?.HeroImageEntryKey
|
||||
};
|
||||
|
||||
protected override ReleaseDto ReleaseOf(SessionRow row) => row.Release;
|
||||
|
||||
// The grid itself — identical in the embedded and standalone contexts. Defined once as a fragment so
|
||||
// both branches above render the same markup without duplication.
|
||||
private RenderFragment GridContent => @<CmsMediumTable TRow="SessionRow"
|
||||
Rows="Rows"
|
||||
Loading="Loading"
|
||||
ReleaseAccessor="@(row => row.Release)"
|
||||
ThumbUrl="@(key => ThumbUrl(key))"
|
||||
TitleHeader="Session"
|
||||
EmptyMessage="No sessions found.">
|
||||
<ActionContent Context="row">
|
||||
@if (row.HeroImageEntryKey is { Length: > 0 } heroKey)
|
||||
// both branches above render the same markup without duplication. The hero upload is the Session's
|
||||
// medium-specific RowActions content; the grid hands it each release, and RowFor recovers the
|
||||
// matching SessionRow's upload state.
|
||||
private RenderFragment GridContent => @<CmsAlbumBrowser Releases="Releases"
|
||||
IsLoading="Loading"
|
||||
OnReleasesChanged="ReloadAsync">
|
||||
<RowActions Context="release">
|
||||
@{ var row = RowFor(release); }
|
||||
@if (row is not null)
|
||||
{
|
||||
<div class="cms-album-thumb" style="background-image: url('@ThumbUrl(heroKey)');"></div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="cms-album-thumb cms-album-thumb--fallback"></div>
|
||||
}
|
||||
<MudFileUpload T="IBrowserFile"
|
||||
Accept="image/*"
|
||||
FilesChanged="@(file => UploadHeroAsync(row, file))"
|
||||
Disabled="@row.IsUploading">
|
||||
<ActivatorContent>
|
||||
<MudButton Variant="Variant.Outlined"
|
||||
Size="Size.Small"
|
||||
StartIcon="@Icons.Material.Filled.Image"
|
||||
@if (row.HeroImageEntryKey is { Length: > 0 } heroKey)
|
||||
{
|
||||
<div class="cms-album-thumb" style="background-image: url('@ThumbUrl(heroKey)');"></div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="cms-album-thumb cms-album-thumb--fallback"></div>
|
||||
}
|
||||
<MudFileUpload T="IBrowserFile"
|
||||
Accept="image/*"
|
||||
FilesChanged="@(file => UploadHeroAsync(row, file))"
|
||||
Disabled="@row.IsUploading">
|
||||
@if (row.IsUploading)
|
||||
{
|
||||
<MudProgressCircular Class="mr-2" Size="Size.Small" Indeterminate="true" />
|
||||
<span>Uploading…</span>
|
||||
}
|
||||
else
|
||||
{
|
||||
<span>@(row.HeroImageEntryKey is { Length: > 0 } ? "Replace hero" : "Set hero")</span>
|
||||
}
|
||||
</MudButton>
|
||||
</ActivatorContent>
|
||||
</MudFileUpload>
|
||||
</ActionContent>
|
||||
</CmsMediumTable>;
|
||||
<ActivatorContent>
|
||||
<MudButton Variant="Variant.Outlined"
|
||||
Size="Size.Small"
|
||||
StartIcon="@Icons.Material.Filled.Image"
|
||||
Disabled="@row.IsUploading">
|
||||
@if (row.IsUploading)
|
||||
{
|
||||
<MudProgressCircular Class="mr-2" Size="Size.Small" Indeterminate="true" />
|
||||
<span>Uploading…</span>
|
||||
}
|
||||
else
|
||||
{
|
||||
<span>@(row.HeroImageEntryKey is { Length: > 0 } ? "Replace hero" : "Set hero")</span>
|
||||
}
|
||||
</MudButton>
|
||||
</ActivatorContent>
|
||||
</MudFileUpload>
|
||||
}
|
||||
</RowActions>
|
||||
</CmsAlbumBrowser>;
|
||||
|
||||
private async Task UploadHeroAsync(SessionRow row, IBrowserFile? file)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user