diff --git a/ErsatzTV.Application/Playouts/Mapper.cs b/ErsatzTV.Application/Playouts/Mapper.cs index da3ebc8b0..7aba77ac4 100644 --- a/ErsatzTV.Application/Playouts/Mapper.cs +++ b/ErsatzTV.Application/Playouts/Mapper.cs @@ -16,7 +16,7 @@ namespace ErsatzTV.Application.Playouts new(GetDisplayTitle(playoutItem.MediaItem), playoutItem.Start, GetDisplayDuration(playoutItem.MediaItem)); private static PlayoutChannelViewModel Project(Channel channel) => - new(channel.Id, channel.Name); + new(channel.Id, channel.Number, channel.Name); private static PlayoutProgramScheduleViewModel Project(ProgramSchedule programSchedule) => new(programSchedule.Id, programSchedule.Name); diff --git a/ErsatzTV.Application/Playouts/PlayoutChannelViewModel.cs b/ErsatzTV.Application/Playouts/PlayoutChannelViewModel.cs index 17baf62d6..73cd0089a 100644 --- a/ErsatzTV.Application/Playouts/PlayoutChannelViewModel.cs +++ b/ErsatzTV.Application/Playouts/PlayoutChannelViewModel.cs @@ -1,4 +1,4 @@ namespace ErsatzTV.Application.Playouts { - public record PlayoutChannelViewModel(int Id, string Name); + public record PlayoutChannelViewModel(int Id, int Number, string Name); } diff --git a/ErsatzTV/Pages/MediaCollectionItemsEditor.razor b/ErsatzTV/Pages/MediaCollectionItemsEditor.razor index eef3671d3..929dd0fa4 100644 --- a/ErsatzTV/Pages/MediaCollectionItemsEditor.razor +++ b/ErsatzTV/Pages/MediaCollectionItemsEditor.razor @@ -87,10 +87,10 @@ return new TableData { TotalItems = _totalItems, Items = _pagedData }; } - private void OnSearch(string text) + private async Task OnSearch(string text) { _searchString = text; - _table.ReloadServerData(); + await _table.ReloadServerData(); } private async Task AddResultsAsync() diff --git a/ErsatzTV/Pages/MediaCollections.razor b/ErsatzTV/Pages/MediaCollections.razor index cadfa9dfd..52dd0fa2d 100644 --- a/ErsatzTV/Pages/MediaCollections.razor +++ b/ErsatzTV/Pages/MediaCollections.razor @@ -79,7 +79,7 @@ if (!result.Cancelled) { await Mediator.Send(new DeleteSimpleMediaCollection(mediaCollection.Id)); - _table.ReloadServerData(); + await _table.ReloadServerData(); } } } @@ -95,10 +95,10 @@ return new TableData { TotalItems = _totalItems, Items = _pagedData }; } - private void OnSearch(string text) + private async Task OnSearch(string text) { _searchString = text; - _table.ReloadServerData(); + await _table.ReloadServerData(); } } \ No newline at end of file diff --git a/ErsatzTV/Pages/PlayoutEditor.razor b/ErsatzTV/Pages/PlayoutEditor.razor new file mode 100644 index 000000000..c7260358a --- /dev/null +++ b/ErsatzTV/Pages/PlayoutEditor.razor @@ -0,0 +1,75 @@ +@page "/playouts/add" +@using ErsatzTV.Application.ProgramSchedules +@using ErsatzTV.Application.ProgramSchedules.Queries +@using ErsatzTV.Application.Channels +@using ErsatzTV.Application.Channels.Queries +@inject NavigationManager NavigationManager +@inject ILogger Logger +@inject ISnackbar Snackbar +@inject IMediator Mediator + +
+ Add Playout + + + + + + + + + + + Add Playout + + + + +
+ +@code { + + private readonly PlayoutEditViewModel _model = new(); + private List _channels; + private List _programSchedules; + + private EditContext _editContext; + private ValidationMessageStore _messageStore; + + protected override async Task OnParametersSetAsync() + { + _channels = await Mediator.Send(new GetAllChannels()); + _programSchedules = await Mediator.Send(new GetAllProgramSchedules()); + } + + protected override void OnInitialized() + { + _editContext = new EditContext(_model); + _messageStore = new ValidationMessageStore(_editContext); + } + + private Task> SearchChannels(string value) => + _channels.Filter(c => $"{c.Number} - {c.Name}".ToLowerInvariant().Contains(value ?? string.Empty)).AsTask(); + + private Task> SearchProgramSchedules(string value) => + _programSchedules.Filter(c => c.Name.ToLowerInvariant().StartsWith(value ?? string.Empty)).AsTask(); + + + private async Task HandleSubmitAsync() + { + _messageStore.Clear(); + if (_editContext.Validate()) + { + Seq errorMessage = (await Mediator.Send(_model.ToCreate())).LeftToSeq(); + + errorMessage.HeadOrNone().Match( + error => + { + Snackbar.Add(error.Value); + Logger.LogError("Unexpected error saving playout: {Error}", error.Value); + }, + () => NavigationManager.NavigateTo("/playouts")); + } + } + +} \ No newline at end of file diff --git a/ErsatzTV/Pages/Playouts.razor b/ErsatzTV/Pages/Playouts.razor index 6e0672423..e815d22c8 100644 --- a/ErsatzTV/Pages/Playouts.razor +++ b/ErsatzTV/Pages/Playouts.razor @@ -1,25 +1,40 @@ @page "/playouts" @using ErsatzTV.Application.Playouts +@using ErsatzTV.Application.Playouts.Commands @using ErsatzTV.Application.Playouts.Queries +@inject IDialogService Dialog @inject IMediator Mediator - + Playouts + + + + + + Id Channel Schedule - Playout Type + @* Playout Type *@ + @context.Id - @context.Channel.Name + @context.Channel.Number - @context.Channel.Name @context.ProgramSchedule.Name - @context.ProgramSchedulePlayoutType + @* @context.ProgramSchedulePlayoutType *@ + + + + + Add Playout + @if (_selectedPlayoutItems != null) { @@ -47,10 +62,28 @@ private List _playouts; private List _selectedPlayoutItems; - protected override async Task OnParametersSetAsync() => - _playouts = await Mediator.Send(new GetAllPlayouts()); + protected override Task OnParametersSetAsync() => + LoadAllPlayouts(); private async Task PlayoutSelected(PlayoutViewModel playout) => _selectedPlayoutItems = await Mediator.Send(new GetPlayoutItemsById(playout.Id)); + + private async Task DeletePlayout(PlayoutViewModel playout) + { + var parameters = new DialogParameters { { "EntityType", "playout" }, { "EntityName", $"{playout.ProgramSchedule.Name} on {playout.Channel.Number} - {playout.Channel.Name}" } }; + var options = new DialogOptions { CloseButton = true, MaxWidth = MaxWidth.ExtraSmall }; + + IDialogReference dialog = Dialog.Show("Delete Media Collection", parameters, options); + DialogResult result = await dialog.Result; + if (!result.Cancelled) + { + await Mediator.Send(new DeletePlayout(playout.Id)); + await LoadAllPlayouts(); + } + } + + private async Task LoadAllPlayouts() => + _playouts = await Mediator.Send(new GetAllPlayouts()); + } \ No newline at end of file diff --git a/ErsatzTV/Pages/ScheduleItemsEditor.razor b/ErsatzTV/Pages/ScheduleItemsEditor.razor index e9ade974b..0eb6a767a 100644 --- a/ErsatzTV/Pages/ScheduleItemsEditor.razor +++ b/ErsatzTV/Pages/ScheduleItemsEditor.razor @@ -5,7 +5,7 @@ @using ErsatzTV.Application.ProgramSchedules.Commands @using ErsatzTV.Application.ProgramSchedules.Queries @inject NavigationManager NavigationManager -@inject ILogger Logger +@inject ILogger Logger @inject ISnackbar Snackbar @inject IMediator Mediator @@ -74,7 +74,7 @@ } - + @foreach (PlayoutMode playoutMode in Enum.GetValues()) { @@ -169,7 +169,8 @@ _schedule.Items.Remove(item); } - private async Task> SearchMediaCollections(string value) => _mediaCollections.Filter(c => c.Name.StartsWith(value)); + private Task> SearchMediaCollections(string value) => + _mediaCollections.Filter(c => c.Name.ToLowerInvariant().StartsWith(value ?? string.Empty)).AsTask(); private async Task SaveChanges() { diff --git a/ErsatzTV/Shared/MediaItemTable.razor b/ErsatzTV/Shared/MediaItemTable.razor index dba0a8778..c1cf83b72 100644 --- a/ErsatzTV/Shared/MediaItemTable.razor +++ b/ErsatzTV/Shared/MediaItemTable.razor @@ -49,10 +49,10 @@ return new TableData { TotalItems = _totalItems, Items = _pagedData }; } - private void OnSearch(string text) + private async Task OnSearch(string text) { _searchString = text; - _table.ReloadServerData(); + await _table.ReloadServerData(); } private class MediaItemAggregate diff --git a/ErsatzTV/Validators/PlayoutEditViewModelValidator.cs b/ErsatzTV/Validators/PlayoutEditViewModelValidator.cs new file mode 100644 index 000000000..607ed375c --- /dev/null +++ b/ErsatzTV/Validators/PlayoutEditViewModelValidator.cs @@ -0,0 +1,14 @@ +using ErsatzTV.ViewModels; +using FluentValidation; + +namespace ErsatzTV.Validators +{ + public class PlayoutEditViewModelValidator : AbstractValidator + { + public PlayoutEditViewModelValidator() + { + RuleFor(p => p.Channel).NotNull(); + RuleFor(p => p.ProgramSchedule).NotNull(); + } + } +} diff --git a/ErsatzTV/ViewModels/PlayoutEditViewModel.cs b/ErsatzTV/ViewModels/PlayoutEditViewModel.cs new file mode 100644 index 000000000..924da2d94 --- /dev/null +++ b/ErsatzTV/ViewModels/PlayoutEditViewModel.cs @@ -0,0 +1,16 @@ +using ErsatzTV.Application.Channels; +using ErsatzTV.Application.Playouts.Commands; +using ErsatzTV.Application.ProgramSchedules; +using ErsatzTV.Core.Domain; + +namespace ErsatzTV.ViewModels +{ + public class PlayoutEditViewModel + { + public ChannelViewModel Channel { get; set; } + public ProgramScheduleViewModel ProgramSchedule { get; set; } + + public CreatePlayout ToCreate() => + new CreatePlayout(Channel.Id, ProgramSchedule.Id, ProgramSchedulePlayoutType.Flood); + } +}