fix: refresh stale browse cache on track edits and allow deleting empty releases

- Add CmsTrackBrowserViewModel.Invalidate(); called from TrackEdit/BatchEdit on save or delete so album/genre cache is invalidated and re-fetches on next mode switch
- CmsAlbumBrowser now handles 0-track releases: confirm dialog + DeleteReleaseAsync instead of early return; partial-failure path also fires OnReleasesChanged to trigger cache invalidation
- TrackList.OnAlbumsChanged now calls VM.Invalidate() so genres stay fresh after any album delete
- UnifiedTrackService.DeleteAsync cascades release soft-delete when last live track is removed (non-fatal; logs on failure)
- New DELETE api/track/release/{id} endpoint (ApiKeyAuthorize) for direct release soft-delete
- EF migration SoftDeleteOrphanedReleases backfills existing orphaned release rows via raw SQL (data-only, no schema change)
This commit is contained in:
daniel-c-harvey
2026-06-11 17:56:18 -04:00
parent fd8c0e389f
commit f02974b3c2
14 changed files with 430 additions and 4 deletions
@@ -4,6 +4,7 @@
@using Microsoft.AspNetCore.Components.Forms
@attribute [Authorize]
@inject ICmsTrackService CmsTrackService
@inject CmsTrackBrowserViewModel VM
@inject IHttpClientFactory HttpClientFactory
@inject ISnackbar Snackbar
@inject IDialogService DialogService
@@ -227,6 +228,9 @@
_form.TrackNumber);
if (updated.Success)
{
// Album/genre browse lists derive from this track's metadata; drop their cache so
// the /tracks browser re-fetches fresh data on next mode switch.
VM.Invalidate();
Snackbar.Add("Track updated.", Severity.Success);
await LoadAsync();
}
@@ -276,6 +280,9 @@
var result = await CmsTrackService.DeleteTrackAsync(Id);
if (result.Success)
{
// Deleting a track can empty or alter a release; drop the browse cache so the
// /tracks album and genre lists re-fetch fresh counts on next mode switch.
VM.Invalidate();
Snackbar.Add("Track deleted.", Severity.Success);
Nav.NavigateTo("/tracks");
}