Browse Source

rework schedule items editor (#2146)

pull/2147/head
Jason Dove 1 month ago committed by GitHub
parent
commit
833bf3506a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 2
      CHANGELOG.md
  2. 380
      ErsatzTV/Pages/ScheduleItemsEditor.razor

2
CHANGELOG.md

@ -83,7 +83,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Remove some limits on multithreading that are no longer needed with latest ffmpeg - Remove some limits on multithreading that are no longer needed with latest ffmpeg
- Mixed transcoding (software decode, hardware filters/encode) can now use multiple decode threads - Mixed transcoding (software decode, hardware filters/encode) can now use multiple decode threads
- Split main `Settings` page into multiple pages - Split main `Settings` page into multiple pages
- Update UI layout on most pages to be less cramped and to work better on mobile - Update UI layout on all pages to be less cramped and to work better on mobile
### Fixed ### Fixed
- Fix QSV acceleration in docker with older Intel devices - Fix QSV acceleration in docker with older Intel devices

380
ErsatzTV/Pages/ScheduleItemsEditor.razor

@ -13,33 +13,67 @@
@inject ISnackbar Snackbar @inject ISnackbar Snackbar
@inject IMediator Mediator @inject IMediator Mediator
<MudContainer MaxWidth="MaxWidth.ExtraLarge" Class="pt-8"> <MudForm @ref="_form" @bind-IsValid="@_success" Style="max-height: 100%">
<MudTable T="ProgramScheduleItemEditViewModel" <MudPaper Square="true" Style="display: flex; height: 64px; min-height: 64px; width: 100%; z-index: 100; align-items: center">
<div style="display: flex; flex-direction: row; margin-bottom: auto; margin-top: auto; width: 100%; align-items: center" class="ml-6 mr-6">
<div class="flex-grow-1">
@if (_selectedItem is not null)
{
string start = _selectedItem.StartType == StartType.Fixed ? _selectedItem.StartTime == null ? string.Empty : DateTime.Today.Add(_selectedItem.StartTime.Value).ToShortTimeString() : "Dynamic";
var mode = _selectedItem.PlayoutMode.ToString();
@if (_selectedItem.PlayoutMode == PlayoutMode.Multiple && _selectedItem.MultipleCount.HasValue)
{
mode += $" ({_selectedItem.MultipleCount})";
}
var result = $"{_schedule.Name} ({start} - {_selectedItem.CollectionName} - {mode})";
<MudText>@result</MudText>
}
else
{
<MudText>@_schedule.Name</MudText>
}
</div>
<div style="margin-left: auto" class="d-none d-md-flex">
<MudButton Variant="Variant.Filled" Color="Color.Primary" OnClick="SaveChanges" StartIcon="@Icons.Material.Filled.Save">
Save Schedule Items
</MudButton>
<MudButton Class="ml-3" Variant="Variant.Filled" Color="Color.Default" OnClick="AddScheduleItem" StartIcon="@Icons.Material.Filled.PlaylistAdd">
Add Schedule Item
</MudButton>
</div>
<div style="align-items: center; display: flex; margin-left: auto;" class="d-md-none">
<div class="flex-grow-1"></div>
<MudMenu Icon="@Icons.Material.Filled.MoreVert">
<MudMenuItem Icon="@Icons.Material.Filled.Save" Label="Save Schedule Items" OnClick="SaveChanges"/>
<MudMenuItem Icon="@Icons.Material.Filled.PlaylistAdd" Label="Add Schedule Item" OnClick="AddScheduleItem"/>
</MudMenu>
</div>
</div>
</MudPaper>
<div class="d-flex flex-column" style="height: 100vh; overflow-x: auto">
<MudContainer MaxWidth="MaxWidth.ExtraLarge" Class="pt-8">
<MudText Typo="Typo.h5" Class="mb-2">Schedule Items</MudText>
<MudDivider Class="mb-6"/>
<MudTable T="ProgramScheduleItemEditViewModel"
Hover="true" Hover="true"
Items="_schedule?.Items?.OrderBy(i => i.Index)" Items="_schedule?.Items?.OrderBy(i => i.Index)"
Dense="true" Dense="true"
SelectedItemChanged="@(vm => SelectedItemChanged(vm))" SelectedItemChanged="@(vm => SelectedItemChanged(vm))"
RowClassFunc="@SelectedRowClassFunc"> RowClassFunc="@SelectedRowClassFunc">
<ToolBarContent>
<MudText Typo="Typo.h6">@_schedule.Name Items</MudText>
</ToolBarContent>
<ColGroup> <ColGroup>
<MudHidden Breakpoint="Breakpoint.Xs">
<col/> <col/>
<col/> <col/>
<col/> <col/>
<col style="width: 60px;"/> <col style="width: 240px;"/>
<col style="width: 60px;"/> </MudHidden>
<col style="width: 60px;"/>
<col style="width: 60px;"/>
</ColGroup> </ColGroup>
<HeaderContent> <HeaderContent>
<MudTh>Start Time</MudTh> <MudTh>Start Time</MudTh>
<MudTh>Collection</MudTh> <MudTh>Collection</MudTh>
<MudTh>Playout Mode</MudTh> <MudTh>Playout Mode</MudTh>
<MudTh/> <MudTh/>
<MudTh/>
<MudTh/>
<MudTh/>
</HeaderContent> </HeaderContent>
<RowTemplate> <RowTemplate>
<MudTd DataLabel="Start Time"> <MudTd DataLabel="Start Time">
@ -62,67 +96,65 @@
</MudText> </MudText>
</MudTd> </MudTd>
<MudTd> <MudTd>
<div class="d-flex">
<MudIconButton Icon="@Icons.Material.Filled.ContentCopy" <MudIconButton Icon="@Icons.Material.Filled.ContentCopy"
OnClick="@(_ => CopyItem(context))"> OnClick="@(_ => CopyItem(context))">
</MudIconButton> </MudIconButton>
</MudTd>
<MudTd>
@if (!_schedule.ShuffleScheduleItems)
{
<MudIconButton Icon="@Icons.Material.Filled.ArrowUpward" <MudIconButton Icon="@Icons.Material.Filled.ArrowUpward"
OnClick="@(_ => MoveItemUp(context))" OnClick="@(_ => MoveItemUp(context))"
Disabled="@(_schedule.ShuffleScheduleItems || _schedule.Items.All(x => x.Index >= context.Index))"> Disabled="@(_schedule.ShuffleScheduleItems || _schedule.Items.All(x => x.Index >= context.Index))">
</MudIconButton> </MudIconButton>
}
</MudTd>
<MudTd>
@if (!_schedule.ShuffleScheduleItems)
{
<MudIconButton Icon="@Icons.Material.Filled.ArrowDownward" <MudIconButton Icon="@Icons.Material.Filled.ArrowDownward"
OnClick="@(_ => MoveItemDown(context))" OnClick="@(_ => MoveItemDown(context))"
Disabled="@(_schedule.ShuffleScheduleItems || _schedule.Items.All(x => x.Index <= context.Index))"> Disabled="@(_schedule.ShuffleScheduleItems || _schedule.Items.All(x => x.Index <= context.Index))">
</MudIconButton> </MudIconButton>
}
</MudTd>
<MudTd>
<MudIconButton Icon="@Icons.Material.Filled.Delete" <MudIconButton Icon="@Icons.Material.Filled.Delete"
OnClick="@(_ => RemoveScheduleItem(context))"> OnClick="@(_ => RemoveScheduleItem(context))">
</MudIconButton> </MudIconButton>
</div>
</MudTd> </MudTd>
</RowTemplate> </RowTemplate>
</MudTable> </MudTable>
<MudButton Variant="Variant.Filled" Color="Color.Default" OnClick="@(_ => AddScheduleItem())" Class="mt-4"> @if (_selectedItem is not null)
Add Schedule Item {
</MudButton> <MudText Typo="Typo.h5" Class="mt-10 mb-2">Schedule Item</MudText>
<MudButton Variant="Variant.Filled" Color="Color.Primary" OnClick="@(_ => SaveChanges())" Class="mt-4 ml-4"> <MudDivider Class="mb-6"/>
Save Changes <MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
</MudButton> <div class="d-flex">
<MudText>Start Type</MudText>
@if (_selectedItem is not null) </div>
{ <MudSelect @bind-Value="_selectedItem.StartType" For="@(() => _selectedItem.StartType)">
<EditForm Model="_selectedItem">
<FluentValidationValidator/>
<div style="display: flex; flex-direction: row;" class="mt-6">
<div style="flex-grow: 1; max-width: 400px;" class="mr-6">
<MudCard>
<MudCardContent>
<MudSelect Label="Start Type" @bind-Value="_selectedItem.StartType" For="@(() => _selectedItem.StartType)">
<MudSelectItem Value="StartType.Dynamic">Dynamic</MudSelectItem> <MudSelectItem Value="StartType.Dynamic">Dynamic</MudSelectItem>
@if (!_schedule.ShuffleScheduleItems) @if (!_schedule.ShuffleScheduleItems)
{ {
<MudSelectItem Value="StartType.Fixed">Fixed</MudSelectItem> <MudSelectItem Value="StartType.Fixed">Fixed</MudSelectItem>
} }
</MudSelect> </MudSelect>
<MudTimePicker Class="mt-3" Label="Start Time" @bind-Time="@_selectedItem.StartTime" For="@(() => _selectedItem.StartTime)" Disabled="@(_selectedItem.StartType == StartType.Dynamic)" Editable="true"/> </MudStack>
@if (_selectedItem.StartType == StartType.Fixed) <MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
{ <div class="d-flex">
<MudSelect Class="mt-3" Label="Fixed Start Time Behavior" @bind-Value="_selectedItem.FixedStartTimeBehavior" For="@(() => _selectedItem.FixedStartTimeBehavior)"> <MudText>Start Time</MudText>
</div>
<MudTimePicker @bind-Time="@_selectedItem.StartTime"
For="@(() => _selectedItem.StartTime)"
Disabled="@(_selectedItem.StartType == StartType.Dynamic)"
Editable="true"/>
</MudStack>
<MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
<div class="d-flex">
<MudText>Fixed Start Time Behavior</MudText>
</div>
<MudSelect @bind-Value="_selectedItem.FixedStartTimeBehavior" For="@(() => _selectedItem.FixedStartTimeBehavior)" Disabled="@(_selectedItem.StartType is not StartType.Fixed)">
<MudSelectItem Value="@((FixedStartTimeBehavior?)null)">Inherit</MudSelectItem> <MudSelectItem Value="@((FixedStartTimeBehavior?)null)">Inherit</MudSelectItem>
<MudSelectItem T="FixedStartTimeBehavior?" Value="FixedStartTimeBehavior.Strict">Strict - Always Wait For Exact Start Time</MudSelectItem> <MudSelectItem T="FixedStartTimeBehavior?" Value="FixedStartTimeBehavior.Strict">Strict - Always Wait For Exact Start Time</MudSelectItem>
<MudSelectItem T="FixedStartTimeBehavior?" Value="FixedStartTimeBehavior.Flexible">Flexible - Start As Soon As Possible After Start Time</MudSelectItem> <MudSelectItem T="FixedStartTimeBehavior?" Value="FixedStartTimeBehavior.Flexible">Flexible - Start As Soon As Possible After Start Time</MudSelectItem>
</MudSelect> </MudSelect>
} </MudStack>
<MudSelect Class="mt-3" Label="Collection Type" @bind-Value="_selectedItem.CollectionType" For="@(() => _selectedItem.CollectionType)"> <MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
<div class="d-flex">
<MudText>Collection Type</MudText>
</div>
<MudSelect @bind-Value="_selectedItem.CollectionType" For="@(() => _selectedItem.CollectionType)">
<MudSelectItem Value="ProgramScheduleItemCollectionType.Collection">Collection</MudSelectItem> <MudSelectItem Value="ProgramScheduleItemCollectionType.Collection">Collection</MudSelectItem>
<MudSelectItem Value="ProgramScheduleItemCollectionType.TelevisionShow">Television Show</MudSelectItem> <MudSelectItem Value="ProgramScheduleItemCollectionType.TelevisionShow">Television Show</MudSelectItem>
<MudSelectItem Value="ProgramScheduleItemCollectionType.TelevisionSeason">Television Season</MudSelectItem> <MudSelectItem Value="ProgramScheduleItemCollectionType.TelevisionSeason">Television Season</MudSelectItem>
@ -131,9 +163,14 @@
<MudSelectItem Value="ProgramScheduleItemCollectionType.SmartCollection">Smart Collection</MudSelectItem> <MudSelectItem Value="ProgramScheduleItemCollectionType.SmartCollection">Smart Collection</MudSelectItem>
<MudSelectItem Value="ProgramScheduleItemCollectionType.Playlist">Playlist</MudSelectItem> <MudSelectItem Value="ProgramScheduleItemCollectionType.Playlist">Playlist</MudSelectItem>
</MudSelect> </MudSelect>
</MudStack>
@if (_selectedItem.CollectionType == ProgramScheduleItemCollectionType.Collection) @if (_selectedItem.CollectionType == ProgramScheduleItemCollectionType.Collection)
{ {
<MudAutocomplete Class="mt-3" T="MediaCollectionViewModel" Label="Collection" <MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
<div class="d-flex">
<MudText>Collection</MudText>
</div>
<MudAutocomplete T="MediaCollectionViewModel"
@bind-Value="_selectedItem.Collection" SearchFunc="@SearchCollections" @bind-Value="_selectedItem.Collection" SearchFunc="@SearchCollections"
ToStringFunc="@(c => c?.Name)" Placeholder="Type to search..."> ToStringFunc="@(c => c?.Name)" Placeholder="Type to search...">
<MoreItemsTemplate> <MoreItemsTemplate>
@ -142,10 +179,15 @@
</MudText> </MudText>
</MoreItemsTemplate> </MoreItemsTemplate>
</MudAutocomplete> </MudAutocomplete>
</MudStack>
} }
@if (_selectedItem.CollectionType == ProgramScheduleItemCollectionType.MultiCollection) @if (_selectedItem.CollectionType == ProgramScheduleItemCollectionType.MultiCollection)
{ {
<MudAutocomplete Class="mt-3" T="MultiCollectionViewModel" Label="Multi Collection" <MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
<div class="d-flex">
<MudText>Multi Collection</MudText>
</div>
<MudAutocomplete T="MultiCollectionViewModel"
@bind-Value="_selectedItem.MultiCollection" SearchFunc="@SearchMultiCollections" @bind-Value="_selectedItem.MultiCollection" SearchFunc="@SearchMultiCollections"
ToStringFunc="@(c => c?.Name)" Placeholder="Type to search..."> ToStringFunc="@(c => c?.Name)" Placeholder="Type to search...">
<MoreItemsTemplate> <MoreItemsTemplate>
@ -154,10 +196,15 @@
</MudText> </MudText>
</MoreItemsTemplate> </MoreItemsTemplate>
</MudAutocomplete> </MudAutocomplete>
</MudStack>
} }
@if (_selectedItem.CollectionType == ProgramScheduleItemCollectionType.SmartCollection) @if (_selectedItem.CollectionType == ProgramScheduleItemCollectionType.SmartCollection)
{ {
<MudAutocomplete Class="mt-3" T="SmartCollectionViewModel" Label="Smart Collection" <MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
<div class="d-flex">
<MudText>Smart Collection</MudText>
</div>
<MudAutocomplete T="SmartCollectionViewModel"
@bind-Value="_selectedItem.SmartCollection" SearchFunc="@SearchSmartCollections" @bind-Value="_selectedItem.SmartCollection" SearchFunc="@SearchSmartCollections"
ToStringFunc="@(c => c?.Name)" Placeholder="Type to search..."> ToStringFunc="@(c => c?.Name)" Placeholder="Type to search...">
<MoreItemsTemplate> <MoreItemsTemplate>
@ -166,10 +213,15 @@
</MudText> </MudText>
</MoreItemsTemplate> </MoreItemsTemplate>
</MudAutocomplete> </MudAutocomplete>
</MudStack>
} }
@if (_selectedItem.CollectionType == ProgramScheduleItemCollectionType.TelevisionShow) @if (_selectedItem.CollectionType == ProgramScheduleItemCollectionType.TelevisionShow)
{ {
<MudAutocomplete Class="mt-3" T="NamedMediaItemViewModel" Label="Television Show" <MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
<div class="d-flex">
<MudText>Television Show</MudText>
</div>
<MudAutocomplete T="NamedMediaItemViewModel"
@bind-Value="_selectedItem.MediaItem" SearchFunc="@SearchTelevisionShows" @bind-Value="_selectedItem.MediaItem" SearchFunc="@SearchTelevisionShows"
ToStringFunc="@(c => c?.Name)" Placeholder="Type to search..."> ToStringFunc="@(c => c?.Name)" Placeholder="Type to search...">
<MoreItemsTemplate> <MoreItemsTemplate>
@ -178,10 +230,15 @@
</MudText> </MudText>
</MoreItemsTemplate> </MoreItemsTemplate>
</MudAutocomplete> </MudAutocomplete>
</MudStack>
} }
@if (_selectedItem.CollectionType == ProgramScheduleItemCollectionType.TelevisionSeason) @if (_selectedItem.CollectionType == ProgramScheduleItemCollectionType.TelevisionSeason)
{ {
<MudAutocomplete Class="mt-3" T="NamedMediaItemViewModel" Label="Television Season" <MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
<div class="d-flex">
<MudText>Television Season</MudText>
</div>
<MudAutocomplete T="NamedMediaItemViewModel"
@bind-Value="_selectedItem.MediaItem" SearchFunc="@SearchTelevisionSeasons" @bind-Value="_selectedItem.MediaItem" SearchFunc="@SearchTelevisionSeasons"
ToStringFunc="@(c => c?.Name)" Placeholder="Type to search..." ToStringFunc="@(c => c?.Name)" Placeholder="Type to search..."
MaxItems="20"> MaxItems="20">
@ -191,10 +248,15 @@
</MudText> </MudText>
</MoreItemsTemplate> </MoreItemsTemplate>
</MudAutocomplete> </MudAutocomplete>
</MudStack>
} }
@if (_selectedItem.CollectionType == ProgramScheduleItemCollectionType.Artist) @if (_selectedItem.CollectionType == ProgramScheduleItemCollectionType.Artist)
{ {
<MudAutocomplete Class="mt-3" T="NamedMediaItemViewModel" Label="Artist" <MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
<div class="d-flex">
<MudText>Artist</MudText>
</div>
<MudAutocomplete T="NamedMediaItemViewModel"
@bind-Value="_selectedItem.MediaItem" SearchFunc="@SearchArtists" @bind-Value="_selectedItem.MediaItem" SearchFunc="@SearchArtists"
ToStringFunc="@(c => c?.Name)" Placeholder="Type to search..." ToStringFunc="@(c => c?.Name)" Placeholder="Type to search..."
MaxItems="10"> MaxItems="10">
@ -204,32 +266,40 @@
</MudText> </MudText>
</MoreItemsTemplate> </MoreItemsTemplate>
</MudAutocomplete> </MudAutocomplete>
</MudStack>
} }
@if (_selectedItem.CollectionType == ProgramScheduleItemCollectionType.Playlist) @if (_selectedItem.CollectionType == ProgramScheduleItemCollectionType.Playlist)
{ {
<MudSelect Class="mt-3" <MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
T="PlaylistGroupViewModel" <div class="d-flex">
<MudText>Playlist Group</MudText>
</div>
<MudSelect T="PlaylistGroupViewModel"
Value="@_selectedPlaylistGroup" Value="@_selectedPlaylistGroup"
Label="Playlist Group"
ValueChanged="@(vm => UpdatePlaylistGroupItems(vm))"> ValueChanged="@(vm => UpdatePlaylistGroupItems(vm))">
@foreach (PlaylistGroupViewModel playlistGroup in _playlistGroups) @foreach (PlaylistGroupViewModel playlistGroup in _playlistGroups)
{ {
<MudSelectItem Value="@playlistGroup">@playlistGroup.Name</MudSelectItem> <MudSelectItem Value="@playlistGroup">@playlistGroup.Name</MudSelectItem>
} }
</MudSelect> </MudSelect>
<MudSelect Class="mt-3" </MudStack>
T="PlaylistViewModel" <MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
Label="Playlist" <div class="d-flex">
@bind-value="_selectedItem.Playlist"> <MudText>Playlist</MudText>
</div>
<MudSelect T="PlaylistViewModel" @bind-value="_selectedItem.Playlist">
@foreach (PlaylistViewModel playlist in _playlists) @foreach (PlaylistViewModel playlist in _playlists)
{ {
<MudSelectItem Value="@playlist">@playlist.Name</MudSelectItem> <MudSelectItem Value="@playlist">@playlist.Name</MudSelectItem>
} }
</MudSelect> </MudSelect>
</MudStack>
} }
<MudSelect Class="mt-3" <MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
Label="Playback Order" <div class="d-flex">
@bind-Value="@_selectedItem.PlaybackOrder" <MudText>Playback Order</MudText>
</div>
<MudSelect @bind-Value="@_selectedItem.PlaybackOrder"
For="@(() => _selectedItem.PlaybackOrder)" For="@(() => _selectedItem.PlaybackOrder)"
Disabled="@(_selectedItem.CollectionType is ProgramScheduleItemCollectionType.Playlist)"> Disabled="@(_selectedItem.CollectionType is ProgramScheduleItemCollectionType.Playlist)">
@switch (_selectedItem.CollectionType) @switch (_selectedItem.CollectionType)
@ -261,7 +331,12 @@
break; break;
} }
</MudSelect> </MudSelect>
<MudSelect Class="mt-3" Label="Playout Mode" @bind-Value="@_selectedItem.PlayoutMode" For="@(() => _selectedItem.PlayoutMode)"> </MudStack>
<MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
<div class="d-flex">
<MudText>Playout Mode</MudText>
</div>
<MudSelect @bind-Value="@_selectedItem.PlayoutMode" For="@(() => _selectedItem.PlayoutMode)">
@if (!_schedule.ShuffleScheduleItems) @if (!_schedule.ShuffleScheduleItems)
{ {
<MudSelectItem Value="PlayoutMode.Flood">Flood</MudSelectItem> <MudSelectItem Value="PlayoutMode.Flood">Flood</MudSelectItem>
@ -270,25 +345,40 @@
<MudSelectItem Value="PlayoutMode.Multiple">Multiple</MudSelectItem> <MudSelectItem Value="PlayoutMode.Multiple">Multiple</MudSelectItem>
<MudSelectItem Value="PlayoutMode.Duration">Duration</MudSelectItem> <MudSelectItem Value="PlayoutMode.Duration">Duration</MudSelectItem>
</MudSelect> </MudSelect>
<MudTextField Class="mt-3" Label="Multiple Count" @bind-Value="@_selectedItem.MultipleCount" For="@(() => _selectedItem.MultipleCount)" Disabled="@(_selectedItem.PlayoutMode != PlayoutMode.Multiple)"/> </MudStack>
<MudGrid Class="mt-3" Style="align-items: center" Justify="Justify.Center"> <MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
<MudItem xs="6"> <div class="d-flex">
<MudText>Multiple Count</MudText>
</div>
<MudTextField @bind-Value="@_selectedItem.MultipleCount"
For="@(() => _selectedItem.MultipleCount)"
Disabled="@(_selectedItem.PlayoutMode != PlayoutMode.Multiple)"/>
</MudStack>
<MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
<div class="d-flex">
<MudText>Playout Duration</MudText>
</div>
<MudTextField T="int" <MudTextField T="int"
Label="Playout Duration"
@bind-Value="_selectedItem.PlayoutDurationHours" @bind-Value="_selectedItem.PlayoutDurationHours"
Adornment="Adornment.End" Adornment="Adornment.End"
AdornmentText="hours" AdornmentText="hours"
Disabled="@(_selectedItem.PlayoutMode != PlayoutMode.Duration)"/> Disabled="@(_selectedItem.PlayoutMode != PlayoutMode.Duration)"/>
</MudItem> </MudStack>
<MudItem xs="6"> <MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
<div class="d-flex"></div>
<MudTextField T="int" <MudTextField T="int"
@bind-Value="_selectedItem.PlayoutDurationMinutes" @bind-Value="_selectedItem.PlayoutDurationMinutes"
Adornment="Adornment.End" Adornment="Adornment.End"
AdornmentText="minutes" AdornmentText="minutes"
Disabled="@(_selectedItem.PlayoutMode != PlayoutMode.Duration)"/> Disabled="@(_selectedItem.PlayoutMode != PlayoutMode.Duration)"/>
</MudItem> </MudStack>
</MudGrid> <MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
<MudSelect Class="mt-3" Label="Fill With Group Mode (Show or Artist)" @bind-Value="@_selectedItem.FillWithGroupMode" For="@(() => _selectedItem.FillWithGroupMode)" Disabled="@(_selectedItem.CanFillWithGroups == false)"> <div class="d-flex">
<MudText>Fill With Group Mode (Show or Artist)</MudText>
</div>
<MudSelect @bind-Value="@_selectedItem.FillWithGroupMode"
For="@(() => _selectedItem.FillWithGroupMode)"
Disabled="@(_selectedItem.CanFillWithGroups == false)">
<MudSelectItem Value="FillWithGroupMode.None">(none)</MudSelectItem> <MudSelectItem Value="FillWithGroupMode.None">(none)</MudSelectItem>
@if (_selectedItem.CanFillWithGroups) @if (_selectedItem.CanFillWithGroups)
{ {
@ -300,25 +390,49 @@
_selectedItem.FillWithGroupMode = FillWithGroupMode.None; _selectedItem.FillWithGroupMode = FillWithGroupMode.None;
} }
</MudSelect> </MudSelect>
<MudSelect Class="mt-3" Label="Tail Mode" @bind-Value="@_selectedItem.TailMode" For="@(() => _selectedItem.TailMode)" Disabled="@(_selectedItem.PlayoutMode != PlayoutMode.Duration)"> </MudStack>
<MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
<div class="d-flex">
<MudText>Tail Mode</MudText>
</div>
<MudSelect @bind-Value="@_selectedItem.TailMode"
For="@(() => _selectedItem.TailMode)"
Disabled="@(_selectedItem.PlayoutMode != PlayoutMode.Duration)">
<MudSelectItem Value="@TailMode.None">(none)</MudSelectItem> <MudSelectItem Value="@TailMode.None">(none)</MudSelectItem>
<MudSelectItem Value="@TailMode.Offline">Offline</MudSelectItem> <MudSelectItem Value="@TailMode.Offline">Offline</MudSelectItem>
<MudSelectItem Value="@TailMode.Filler">Filler</MudSelectItem> <MudSelectItem Value="@TailMode.Filler">Filler</MudSelectItem>
</MudSelect> </MudSelect>
<MudTextField Class="mt-3" Label="Discard To Fill Attempts" @bind-Value="@_selectedItem.DiscardToFillAttempts" For="@(() => _selectedItem.DiscardToFillAttempts)" Disabled="@(_selectedItem.PlayoutMode != PlayoutMode.Duration)"/> </MudStack>
<MudTextField Class="mt-3" Label="Custom Title" @bind-Value="@_selectedItem.CustomTitle" For="@(() => _selectedItem.CustomTitle)"/> <MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
<MudSelect Class="mt-3" Label="Guide Mode" @bind-Value="@_selectedItem.GuideMode" For="@(() => _selectedItem.GuideMode)"> <div class="d-flex">
<MudText>Discard To Fill Attempts</MudText>
</div>
<MudTextField @bind-Value="@_selectedItem.DiscardToFillAttempts"
For="@(() => _selectedItem.DiscardToFillAttempts)"
Disabled="@(_selectedItem.PlayoutMode != PlayoutMode.Duration)"/>
</MudStack>
<MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
<div class="d-flex">
<MudText>Custom Title</MudText>
</div>
<MudTextField @bind-Value="@_selectedItem.CustomTitle" For="@(() => _selectedItem.CustomTitle)"/>
</MudStack>
<MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
<div class="d-flex">
<MudText>Guide Mode</MudText>
</div>
<MudSelect @bind-Value="@_selectedItem.GuideMode" For="@(() => _selectedItem.GuideMode)">
<MudSelectItem Value="@GuideMode.Normal">Normal</MudSelectItem> <MudSelectItem Value="@GuideMode.Normal">Normal</MudSelectItem>
<MudSelectItem Value="@GuideMode.Filler">Filler</MudSelectItem> <MudSelectItem Value="@GuideMode.Filler">Filler</MudSelectItem>
</MudSelect> </MudSelect>
</MudCardContent> </MudStack>
</MudCard> <MudText Typo="Typo.h5" Class="mt-10 mb-2">Schedule Item Filler</MudText>
<MudDivider Class="mb-6"/>
<MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
<div class="d-flex">
<MudText>Pre-Roll Filler</MudText>
</div> </div>
<div style="flex-grow: 1; max-width: 400px;">
<MudCard>
<MudCardContent>
<MudSelect T="FillerPresetViewModel" <MudSelect T="FillerPresetViewModel"
Label="Pre-Roll Filler"
@bind-value="_selectedItem.PreRollFiller" @bind-value="_selectedItem.PreRollFiller"
Clearable="true"> Clearable="true">
@foreach (FillerPresetViewModel filler in _fillerPresets.Where(f => f.FillerKind == FillerKind.PreRoll)) @foreach (FillerPresetViewModel filler in _fillerPresets.Where(f => f.FillerKind == FillerKind.PreRoll))
@ -326,9 +440,12 @@
<MudSelectItem Value="@filler">@filler.Name</MudSelectItem> <MudSelectItem Value="@filler">@filler.Name</MudSelectItem>
} }
</MudSelect> </MudSelect>
<MudSelect Class="mt-3" </MudStack>
T="FillerPresetViewModel" <MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
Label="Mid-Roll Filler" <div class="d-flex">
<MudText>Mid-Roll Filler</MudText>
</div>
<MudSelect T="FillerPresetViewModel"
@bind-value="_selectedItem.MidRollFiller" @bind-value="_selectedItem.MidRollFiller"
Clearable="true"> Clearable="true">
@foreach (FillerPresetViewModel filler in _fillerPresets.Where(f => f.FillerKind == FillerKind.MidRoll)) @foreach (FillerPresetViewModel filler in _fillerPresets.Where(f => f.FillerKind == FillerKind.MidRoll))
@ -336,9 +453,12 @@
<MudSelectItem Value="@filler">@filler.Name</MudSelectItem> <MudSelectItem Value="@filler">@filler.Name</MudSelectItem>
} }
</MudSelect> </MudSelect>
<MudSelect Class="mt-3" </MudStack>
T="FillerPresetViewModel" <MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
Label="Post-Roll Filler" <div class="d-flex">
<MudText>Post-Roll Filler</MudText>
</div>
<MudSelect T="FillerPresetViewModel"
@bind-value="_selectedItem.PostRollFiller" @bind-value="_selectedItem.PostRollFiller"
Clearable="true"> Clearable="true">
@foreach (FillerPresetViewModel filler in _fillerPresets.Where(f => f.FillerKind == FillerKind.PostRoll)) @foreach (FillerPresetViewModel filler in _fillerPresets.Where(f => f.FillerKind == FillerKind.PostRoll))
@ -346,9 +466,12 @@
<MudSelectItem Value="@filler">@filler.Name</MudSelectItem> <MudSelectItem Value="@filler">@filler.Name</MudSelectItem>
} }
</MudSelect> </MudSelect>
<MudSelect Class="mt-3" </MudStack>
T="FillerPresetViewModel" <MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
Label="Tail Filler" <div class="d-flex">
<MudText>Tail Filler</MudText>
</div>
<MudSelect T="FillerPresetViewModel"
@bind-value="_selectedItem.TailFiller" @bind-value="_selectedItem.TailFiller"
Clearable="true"> Clearable="true">
@foreach (FillerPresetViewModel filler in _fillerPresets.Where(f => f.FillerKind == FillerKind.Tail)) @foreach (FillerPresetViewModel filler in _fillerPresets.Where(f => f.FillerKind == FillerKind.Tail))
@ -356,9 +479,12 @@
<MudSelectItem Value="@filler">@filler.Name</MudSelectItem> <MudSelectItem Value="@filler">@filler.Name</MudSelectItem>
} }
</MudSelect> </MudSelect>
<MudSelect Class="mt-3" </MudStack>
T="FillerPresetViewModel" <MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
Label="Fallback Filler" <div class="d-flex">
<MudText>Fallback Filler</MudText>
</div>
<MudSelect T="FillerPresetViewModel"
@bind-value="_selectedItem.FallbackFiller" @bind-value="_selectedItem.FallbackFiller"
Clearable="true"> Clearable="true">
@foreach (FillerPresetViewModel filler in _fillerPresets.Where(f => f.FillerKind == FillerKind.Fallback)) @foreach (FillerPresetViewModel filler in _fillerPresets.Where(f => f.FillerKind == FillerKind.Fallback))
@ -366,19 +492,25 @@
<MudSelectItem Value="@filler">@filler.Name</MudSelectItem> <MudSelectItem Value="@filler">@filler.Name</MudSelectItem>
} }
</MudSelect> </MudSelect>
</MudCardContent> </MudStack>
</MudCard> <MudText Typo="Typo.h5" Class="mt-10 mb-2">Schedule Item Overrides</MudText>
<MudCard Class="mt-4"> <MudDivider Class="mb-6"/>
<MudCardContent> <MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
<MudSelect Label="Watermark" @bind-Value="@_selectedItem.Watermark" For="@(() => _selectedItem.Watermark)" Clearable="true"> <div class="d-flex">
<MudText>Watermark</MudText>
</div>
<MudSelect @bind-Value="@_selectedItem.Watermark" For="@(() => _selectedItem.Watermark)" Clearable="true">
@foreach (WatermarkViewModel watermark in _watermarks) @foreach (WatermarkViewModel watermark in _watermarks)
{ {
<MudSelectItem Value="@watermark">@watermark.Name</MudSelectItem> <MudSelectItem Value="@watermark">@watermark.Name</MudSelectItem>
} }
</MudSelect> </MudSelect>
<MudSelect Class="mt-3" </MudStack>
Label="Preferred Audio Language" <MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
@bind-Value="_selectedItem.PreferredAudioLanguageCode" <div class="d-flex">
<MudText>Preferred Audio Language</MudText>
</div>
<MudSelect @bind-Value="_selectedItem.PreferredAudioLanguageCode"
For="@(() => _selectedItem.PreferredAudioLanguageCode)" For="@(() => _selectedItem.PreferredAudioLanguageCode)"
Clearable="true"> Clearable="true">
<MudSelectItem Value="@((string)null)">(none)</MudSelectItem> <MudSelectItem Value="@((string)null)">(none)</MudSelectItem>
@ -387,10 +519,18 @@
<MudSelectItem Value="@culture.ThreeLetterISOLanguageName">@culture.EnglishName</MudSelectItem> <MudSelectItem Value="@culture.ThreeLetterISOLanguageName">@culture.EnglishName</MudSelectItem>
} }
</MudSelect> </MudSelect>
<MudTextField Class="mt-3" Label="Preferred Audio Title" @bind-Value="@_selectedItem.PreferredAudioTitle" For="@(() => _selectedItem.PreferredAudioTitle)"/> </MudStack>
<MudSelect Class="mt-3" <MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
Label="Preferred Subtitle Language" <div class="d-flex">
@bind-Value="_selectedItem.PreferredSubtitleLanguageCode" <MudText>Preferred Audio Title</MudText>
</div>
<MudTextField @bind-Value="@_selectedItem.PreferredAudioTitle" For="@(() => _selectedItem.PreferredAudioTitle)"/>
</MudStack>
<MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
<div class="d-flex">
<MudText>Preferred Subtitle Language</MudText>
</div>
<MudSelect @bind-Value="_selectedItem.PreferredSubtitleLanguageCode"
For="@(() => _selectedItem.PreferredSubtitleLanguageCode)" For="@(() => _selectedItem.PreferredSubtitleLanguageCode)"
Clearable="true"> Clearable="true">
<MudSelectItem Value="@((string)null)">(none)</MudSelectItem> <MudSelectItem Value="@((string)null)">(none)</MudSelectItem>
@ -399,19 +539,22 @@
<MudSelectItem Value="@culture.ThreeLetterISOLanguageName">@culture.EnglishName</MudSelectItem> <MudSelectItem Value="@culture.ThreeLetterISOLanguageName">@culture.EnglishName</MudSelectItem>
} }
</MudSelect> </MudSelect>
<MudSelect T="ChannelSubtitleMode?" Class="mt-3" Label="Subtitle Mode" @bind-Value="_selectedItem.SubtitleMode" For="@(() => _selectedItem.SubtitleMode)" Clearable="true"> </MudStack>
<MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
<div class="d-flex">
<MudText>Subtitle Mode</MudText>
</div>
<MudSelect T="ChannelSubtitleMode?" @bind-Value="_selectedItem.SubtitleMode" For="@(() => _selectedItem.SubtitleMode)" Clearable="true">
<MudSelectItem T="ChannelSubtitleMode?" Value="@(ChannelSubtitleMode.None)">None</MudSelectItem> <MudSelectItem T="ChannelSubtitleMode?" Value="@(ChannelSubtitleMode.None)">None</MudSelectItem>
<MudSelectItem T="ChannelSubtitleMode?" Value="@(ChannelSubtitleMode.Forced)">Forced</MudSelectItem> <MudSelectItem T="ChannelSubtitleMode?" Value="@(ChannelSubtitleMode.Forced)">Forced</MudSelectItem>
<MudSelectItem T="ChannelSubtitleMode?" Value="@(ChannelSubtitleMode.Default)">Default</MudSelectItem> <MudSelectItem T="ChannelSubtitleMode?" Value="@(ChannelSubtitleMode.Default)">Default</MudSelectItem>
<MudSelectItem T="ChannelSubtitleMode?" Value="@(ChannelSubtitleMode.Any)">Any</MudSelectItem> <MudSelectItem T="ChannelSubtitleMode?" Value="@(ChannelSubtitleMode.Any)">Any</MudSelectItem>
</MudSelect> </MudSelect>
</MudCardContent> </MudStack>
</MudCard> }
</div> </MudContainer>
</div> </div>
</EditForm> </MudForm>
}
</MudContainer>
@code { @code {
private readonly CancellationTokenSource _cts = new(); private readonly CancellationTokenSource _cts = new();
@ -429,6 +572,9 @@
private PlaylistGroupViewModel _selectedPlaylistGroup; private PlaylistGroupViewModel _selectedPlaylistGroup;
private ProgramScheduleItemEditViewModel _selectedItem; private ProgramScheduleItemEditViewModel _selectedItem;
private MudForm _form;
private bool _success;
public void Dispose() public void Dispose()
{ {
_cts.Cancel(); _cts.Cancel();
@ -675,6 +821,12 @@
private async Task SaveChanges() private async Task SaveChanges()
{ {
await _form.Validate();
if (!_success)
{
return;
}
var items = _schedule.Items.Map(item => new ReplaceProgramScheduleItem( var items = _schedule.Items.Map(item => new ReplaceProgramScheduleItem(
item.Index, item.Index,
item.StartType, item.StartType,

Loading…
Cancel
Save