@page "/tracks/mixes" @inherits CmsMediumBrowserBase @using DeepDrftModels.DTOs @using DeepDrftModels.Enums @attribute [Authorize] @inject ILogger Logger @* Embedded as the MIXES tab content of the Release Archive (Phase 9 §8.A), and still routable at /tracks/mixes 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 waveform affordance (9.5.E) is preserved in both contexts. *@ @if (Embedded) { @GridContent } else { Mixes — DeepDrft CMS Back to Release Archive Mixes @GridContent } @code { /// /// True when rendered as tab content inside the Release Archive; suppresses the standalone page /// chrome (title, container, back button). False (default) renders the full routable page. /// [Parameter] public bool Embedded { get; set; } protected override ReleaseMedium Medium => ReleaseMedium.Mix; protected override string MediumNoun => "mixes"; protected override MixRow ToRow(ReleaseDto release) => new() { Release = release, HasWaveform = !string.IsNullOrEmpty(release.MixMetadata?.WaveformEntryKey) }; // 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 => @ @if (row.HasWaveform) { } else { } @if (row.IsGenerating) { Generating… } else { @(row.HasWaveform ? "Regenerate" : "Generate") } ; private async Task GenerateWaveformAsync(MixRow row) { row.IsGenerating = true; StateHasChanged(); try { var result = await CmsReleaseService.GenerateMixWaveformAsync(row.Release.Id); if (result.Success) { // Optimistic update: the trigger succeeded, so the waveform is stored. Unlike SessionBrowser's // re-fetch (which retrieves the server-generated HeroImageEntryKey), there is nothing to reflect // back here — HasWaveform is derived from WaveformEntryKey being non-null, which we know is now set. row.HasWaveform = true; Snackbar.Add($"Generated waveform for '{row.Release.Title}'.", Severity.Success); } else { var error = result.Messages.FirstOrDefault()?.Message ?? "Unknown error"; Snackbar.Add($"Waveform generation failed for '{row.Release.Title}': {error}", Severity.Error); } } catch (Exception ex) { Logger.LogError(ex, "Waveform generation failed for release {ReleaseId}", row.Release.Id); Snackbar.Add($"Waveform generation failed for '{row.Release.Title}' — please try again.", Severity.Error); } finally { row.IsGenerating = false; StateHasChanged(); } } public sealed class MixRow { public required ReleaseDto Release { get; set; } public bool HasWaveform { get; set; } public bool IsGenerating { get; set; } } }