diff --git a/DeepDrftCms/DeepDrftCms.csproj b/DeepDrftCms/DeepDrftCms.csproj index 65b0747..c484fdc 100644 --- a/DeepDrftCms/DeepDrftCms.csproj +++ b/DeepDrftCms/DeepDrftCms.csproj @@ -21,6 +21,7 @@ + diff --git a/DeepDrftCms/Pages/Tracks/TrackList.razor b/DeepDrftCms/Pages/Tracks/TrackList.razor new file mode 100644 index 0000000..e63ba33 --- /dev/null +++ b/DeepDrftCms/Pages/Tracks/TrackList.razor @@ -0,0 +1,135 @@ +@page "/cms/tracks" +@rendermode InteractiveServer +@using System.Net +@using AuthBlocksWeb.HierarchicalAuthorize +@using DeepDrftModels.Models +@attribute [HierarchicalRoleAuthorize("Admin")] +@inject ITrackService TrackService +@inject IHttpClientFactory HttpClientFactory +@inject IDialogService DialogService +@inject ISnackbar Snackbar +@inject NavigationManager Navigation + +Tracks — DeepDrft CMS + + + + Tracks + + Add Track + + + + + + No tracks found. + + + Loading tracks… + + + Track Name + Artist + Album + Genre + Release Date + Entry Key + Actions + + + @context.TrackName + @context.Artist + @(context.Album ?? "—") + @(context.Genre ?? "—") + @(context.ReleaseDate?.ToString("yyyy-MM-dd") ?? "—") + @context.EntryKey + + + + + + + + + + + + + + + +@code { + private MudTable? _table; + + private async Task> LoadServerData(TableState state, CancellationToken cancellationToken) + { + var pageNumber = state.Page + 1; // MudTable is 0-based, service is 1-based. + var sortColumn = string.IsNullOrEmpty(state.SortLabel) ? "TrackName" : state.SortLabel; + var sortDescending = state.SortDirection == SortDirection.Descending; + + var result = await TrackService.GetPaged(pageNumber, state.PageSize, sortColumn, sortDescending); + + if (!result.Success || result.Value is null) + { + var errorText = result.Messages.FirstOrDefault()?.Message ?? "Unknown error"; + Snackbar.Add($"Failed to load tracks: {errorText}", Severity.Error); + return new TableData { Items = Array.Empty(), TotalItems = 0 }; + } + + var page = result.Value; + return new TableData + { + Items = page.Items, + TotalItems = page.TotalCount + }; + } + + private async Task ConfirmAndDelete(TrackEntity track) + { + var confirmed = await DialogService.ShowMessageBox( + title: "Delete track", + markupMessage: new MarkupString($"Delete {WebUtility.HtmlEncode(track.TrackName)} by {WebUtility.HtmlEncode(track.Artist)}? This removes both the metadata row and the underlying audio entry."), + yesText: "Delete", + cancelText: "Cancel"); + + if (confirmed != true) return; + + try + { + var client = HttpClientFactory.CreateClient("DeepDrft.API"); + var response = await client.DeleteAsync($"api/cms/track/{track.Id}"); + + if (response.IsSuccessStatusCode) + { + Snackbar.Add($"Deleted '{track.TrackName}'.", Severity.Success); + if (_table is not null) await _table.ReloadServerData(); + } + else + { + Snackbar.Add($"Delete failed ({(int)response.StatusCode} {response.ReasonPhrase}).", Severity.Error); + } + } + catch (Exception ex) + { + Snackbar.Add($"Delete failed: {ex.Message}", Severity.Error); + } + } +} diff --git a/DeepDrftCms/_Imports.razor b/DeepDrftCms/_Imports.razor index cf3d836..d0b266a 100644 --- a/DeepDrftCms/_Imports.razor +++ b/DeepDrftCms/_Imports.razor @@ -8,4 +8,5 @@ @using Microsoft.JSInterop @using DeepDrftCms @using DeepDrftModels.Entities +@using DeepDrftWeb.Services @using MudBlazor