@page "/media/playlists" @using ErsatzTV.Application.MediaCollections @using ErsatzTV.Application.Tree @implements IDisposable @inject ILogger Logger @inject ISnackbar Snackbar @inject IMediator Mediator @inject IDialogService Dialog
Playlist Groups
Playlist Group Name
Add Playlist Group
Playlists
Playlist Group
@foreach (PlaylistGroupViewModel playlistGroup in _playlistGroups) { @playlistGroup.Name }
Playlist Name
Add Playlist
@item.Value.Text @if (!string.IsNullOrWhiteSpace(item.Value.EndText)) { @item.Value.EndText }
@foreach (int playlistId in Optional(item.Value.PlaylistId)) { }
@code { private CancellationTokenSource _cts; private readonly List> _treeItems = []; private List _playlistGroups = []; private PlaylistGroupViewModel _selectedPlaylistGroup; private string _playlistGroupName; private string _playlistName; public void Dispose() { _cts?.Cancel(); _cts?.Dispose(); } protected override async Task OnParametersSetAsync() { _cts?.Cancel(); _cts?.Dispose(); _cts = new CancellationTokenSource(); var token = _cts.Token; try { await ReloadPlaylistTree(token); await InvokeAsync(StateHasChanged); } catch (OperationCanceledException) { // do nothing } } private async Task ReloadPlaylistTree(CancellationToken cancellationToken) { _playlistGroups = await Mediator.Send(new GetAllPlaylistGroups(), cancellationToken); _treeItems.Clear(); TreeViewModel tree = await Mediator.Send(new GetPlaylistTree(), cancellationToken); foreach (TreeGroupViewModel group in tree.Groups) { _treeItems.Add(new TreeItemData { Value = new PlaylistTreeItemViewModel(group) }); } } private async Task AddPlaylistGroup() { if (!string.IsNullOrWhiteSpace(_playlistGroupName)) { Either result = await Mediator.Send(new CreatePlaylistGroup(_playlistGroupName), _cts.Token); foreach (BaseError error in result.LeftToSeq()) { Snackbar.Add(error.Value, Severity.Error); Logger.LogError("Unexpected error adding playlist group: {Error}", error.Value); } foreach (PlaylistGroupViewModel _ in result.RightToSeq()) { await ReloadPlaylistTree(_cts.Token); await InvokeAsync(StateHasChanged); } } } private async Task AddPlaylist() { if (_selectedPlaylistGroup is not null && !string.IsNullOrWhiteSpace(_playlistName)) { Either result = await Mediator.Send(new CreatePlaylist(_selectedPlaylistGroup.Id, _playlistName), _cts.Token); foreach (BaseError error in result.LeftToSeq()) { Snackbar.Add(error.Value, Severity.Error); Logger.LogError("Unexpected error adding playlist: {Error}", error.Value); } foreach (PlaylistViewModel playlist in result.RightToSeq()) { foreach (PlaylistTreeItemViewModel item in _treeItems.Map(i => i.Value).Where(item => item.PlaylistGroupId == _selectedPlaylistGroup.Id)) { item.TreeItems.Add(new TreeItemData { Value = new PlaylistTreeItemViewModel(playlist) }); } _playlistName = null; await InvokeAsync(StateHasChanged); } } } private async Task DeleteItem(PlaylistTreeItemViewModel treeItem) { foreach (int playlistGroupId in Optional(treeItem.PlaylistGroupId)) { var parameters = new DialogParameters { { "EntityType", "playlist group" }, { "EntityName", treeItem.Text } }; var options = new DialogOptions { CloseButton = true, MaxWidth = MaxWidth.ExtraSmall }; IDialogReference dialog = await Dialog.ShowAsync("Delete Playlist Group", parameters, options); DialogResult result = await dialog.Result; if (result is not null && !result.Canceled) { Option deleteResult = await Mediator.Send(new DeletePlaylistGroup(playlistGroupId), _cts.Token); foreach (BaseError error in deleteResult) { Snackbar.Add(error.ToString(), Severity.Error); return; } _treeItems.RemoveAll(i => i.Value?.PlaylistGroupId == playlistGroupId); if (_selectedPlaylistGroup?.Id == playlistGroupId) { _selectedPlaylistGroup = null; } _playlistGroups = await Mediator.Send(new GetAllPlaylistGroups(), _cts.Token); await InvokeAsync(StateHasChanged); } } foreach (int playlistId in Optional(treeItem.PlaylistId)) { var parameters = new DialogParameters { { "EntityType", "playlist" }, { "EntityName", treeItem.Text } }; var options = new DialogOptions { CloseButton = true, MaxWidth = MaxWidth.ExtraSmall }; IDialogReference dialog = await Dialog.ShowAsync("Delete Playlist", parameters, options); DialogResult result = await dialog.Result; if (result is not null && !result.Canceled) { Option deleteResult = await Mediator.Send(new DeletePlaylist(playlistId), _cts.Token); foreach (BaseError error in deleteResult) { Snackbar.Add(error.ToString(), Severity.Error); return; } foreach (PlaylistTreeItemViewModel parent in _treeItems.Map(i => i.Value)) { parent.TreeItems.RemoveAll(i => i.Value == treeItem); } await InvokeAsync(StateHasChanged); } } } }