@ -13,405 +13,548 @@
@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">
Hover="true"
<div style="display: flex; flex-direction: row; margin-bottom: auto; margin-top: auto; width: 100%; align-items: center" class="ml-6 mr-6">
Items="_schedule?.Items?.OrderBy(i => i.Index)"
<div class="flex-grow-1">
Dense="true"
@if (_selectedItem is not null)
SelectedItemChanged="@(vm => SelectedItemChanged(vm))"
RowClassFunc="@SelectedRowClassFunc">
<ToolBarContent>
<MudText Typo="Typo.h6">@_schedule.Name Items</MudText>
</ToolBarContent>
<ColGroup>
<col/>
<col/>
<col/>
<col style="width: 60px;"/>
<col style="width: 60px;"/>
<col style="width: 60px;"/>
<col style="width: 60px;"/>
</ColGroup>
<HeaderContent>
<MudTh>Start Time</MudTh>
<MudTh>Collection</MudTh>
<MudTh>Playout Mode</MudTh>
<MudTh/>
<MudTh/>
<MudTh/>
<MudTh/>
</HeaderContent>
<RowTemplate>
<MudTd DataLabel="Start Time">
<MudText Typo="@Typo.body2">
@(context.StartType == StartType.Fixed ? context.StartTime == null ? string.Empty : DateTime.Today.Add(context.StartTime.Value).ToShortTimeString() : "Dynamic")
</MudText>
</MudTd>
<MudTd DataLabel="Collection">
<MudText Typo="@Typo.body2">
@context.CollectionName
</MudText>
</MudTd>
<MudTd DataLabel="Playout Mode">
<MudText Typo="@Typo.body2">
@context.PlayoutMode
@if (context.PlayoutMode == PlayoutMode.Multiple && context.MultipleCount.HasValue)
{
{
@($" ({context.MultipleCount})")
string start = _selectedItem.StartType == StartType.Fixed ? _selectedItem.StartTime == null ? string.Empty : DateTime.Today.Add(_selectedItem.StartTime.Value).ToShortTimeString() : "Dynamic";
}
var mode = _selectedItem.PlayoutMode.ToString();
</MudText>
@if (_selectedItem.PlayoutMode == PlayoutMode.Multiple && _selectedItem.MultipleCount.HasValue)
</MudTd>
<MudTd>
<MudIconButton Icon="@Icons.Material.Filled.ContentCopy"
OnClick="@(_ => CopyItem(context))">
</MudIconButton>
</MudTd>
<MudTd>
@if (!_schedule.ShuffleScheduleItems)
{
<MudIconButton Icon="@Icons.Material.Filled.ArrowUpward"
OnClick="@(_ => MoveItemUp(context))"
Disabled="@(_schedule.ShuffleScheduleItems || _schedule.Items.All(x => x.Index >= context.Index))">
</MudIconButton>
}
</MudTd>
<MudTd>
@if (!_schedule.ShuffleScheduleItems)
{
<MudIconButton Icon="@Icons.Material.Filled.ArrowDownward"
OnClick="@(_ => MoveItemDown(context))"
Disabled="@(_schedule.ShuffleScheduleItems || _schedule.Items.All(x => x.Index <= context.Index))">
</MudIconButton>
}
</MudTd>
<MudTd>
<MudIconButton Icon="@Icons.Material.Filled.Delete"
OnClick="@(_ => RemoveScheduleItem(context))">
</MudIconButton>
</MudTd>
</RowTemplate>
</MudTable>
<MudButton Variant="Variant.Filled" Color="Color.Default" OnClick="@(_ => AddScheduleItem())" Class="mt-4">
Add Schedule Item
</MudButton>
<MudButton Variant="Variant.Filled" Color="Color.Primary" OnClick="@(_ => SaveChanges())" Class="mt-4 ml-4">
Save Changes
</MudButton>
@if (_selectedItem is not null)
{
<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>
@if (!_schedule.ShuffleScheduleItems)
{
{
<MudSelectItem Value="StartType.Fixed">Fixed</MudSelectItem>
mode += $" ({_selectedItem.MultipleCount})";
}
}
</MudSelect>
<MudTimePicker Class="mt-3" Label="Start Time" @bind-Time="@_selectedItem.StartTime" For="@(() => _selectedItem.StartTime)" Disabled="@(_selectedItem.StartType == StartType.Dynamic)" Editable="true"/>
var result = $"{_schedule.Name} ({start} - {_selectedItem.CollectionName} - {mode})";
@if (_selectedItem.StartType == StartType.Fixed)
<MudText>@result</MudText>
}
else
{
{
<MudSelect Class="mt-3" Label="Fixed Start Time Behavior" @bind-Value="_selectedItem.FixedStartTimeBehavior" For="@(() => _selectedItem.FixedStartTimeBehavior)">
<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"
Items="_schedule?.Items?.OrderBy(i => i.Index)"
Dense="true"
SelectedItemChanged="@(vm => SelectedItemChanged(vm))"
RowClassFunc="@SelectedRowClassFunc">
<ColGroup>
<MudHidden Breakpoint="Breakpoint.Xs">
<col/>
<col/>
<col/>
<col style="width: 240px;"/>
</MudHidden>
</ColGroup>
<HeaderContent>
<MudTh>Start Time</MudTh>
<MudTh>Collection</MudTh>
<MudTh>Playout Mode</MudTh>
<MudTh/>
</HeaderContent>
<RowTemplate>
<MudTd DataLabel="Start Time">
<MudText Typo="@Typo.body2">
@(context.StartType == StartType.Fixed ? context.StartTime == null ? string.Empty : DateTime.Today.Add(context.StartTime.Value).ToShortTimeString() : "Dynamic")
</MudText>
</MudTd>
<MudTd DataLabel="Collection">
<MudText Typo="@Typo.body2">
@context.CollectionName
</MudText>
</MudTd>
<MudTd DataLabel="Playout Mode">
<MudText Typo="@Typo.body2">
@context.PlayoutMode
@if (context.PlayoutMode == PlayoutMode.Multiple && context.MultipleCount.HasValue)
{
@($" ({context.MultipleCount})")
}
</MudText>
</MudTd>
<MudTd>
<div class="d-flex">
<MudIconButton Icon="@Icons.Material.Filled.ContentCopy"
OnClick="@(_ => CopyItem(context))">
</MudIconButton>
<MudIconButton Icon="@Icons.Material.Filled.ArrowUpward"
OnClick="@(_ => MoveItemUp(context))"
Disabled="@(_schedule.ShuffleScheduleItems || _schedule.Items.All(x => x.Index >= context.Index))">
</MudIconButton>
<MudIconButton Icon="@Icons.Material.Filled.ArrowDownward"
OnClick="@(_ => MoveItemDown(context))"
Disabled="@(_schedule.ShuffleScheduleItems || _schedule.Items.All(x => x.Index <= context.Index))">
</MudIconButton>
<MudIconButton Icon="@Icons.Material.Filled.Delete"
OnClick="@(_ => RemoveScheduleItem(context))">
</MudIconButton>
</div>
</MudTd>
</RowTemplate>
</MudTable>
@if (_selectedItem is not null)
{
<MudText Typo="Typo.h5" Class="mt-10 mb-2">Schedule Item</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>Start Type</MudText>
</div>
<MudSelect @bind-Value="_selectedItem.StartType" For="@(() => _selectedItem.StartType)">
<MudSelectItem Value="StartType.Dynamic">Dynamic</MudSelectItem>
@if (!_schedule.ShuffleScheduleItems)
{
<MudSelectItem Value="StartType.Fixed">Fixed</MudSelectItem>
}
</MudSelect>
</MudStack>
<MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
<div class="d-flex">
<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">
<MudSelectItem Value="ProgramScheduleItemCollectionType.Collection">Collection</MudSelectItem>
<div class="d-flex">
<MudSelectItem Value="ProgramScheduleItemCollectionType.TelevisionShow">Television Show</MudSelectItem>
<MudText>Collection Type</MudText>
<MudSelectItem Value="ProgramScheduleItemCollectionType.TelevisionSeason">Television Season</MudSelectItem>
</div>
<MudSelectItem Value="ProgramScheduleItemCollectionType.Artist">Artist</MudSelectItem>
<MudSelect @bind-Value="_selectedItem.CollectionType" For="@(() => _selectedItem.CollectionType)">
<MudSelectItem Value="ProgramScheduleItemCollectionType.MultiCollection">Multi Collection</MudSelectItem>
<MudSelectItem Value="ProgramScheduleItemCollectionType.Collection">Collection</MudSelectItem>
<MudSelectItem Value="ProgramScheduleItemCollectionType.SmartCollection">Smart Collection</MudSelectItem>
<MudSelectItem Value="ProgramScheduleItemCollectionType.TelevisionShow">Television Show</MudSelectItem>
<MudSelectItem Value="ProgramScheduleItemCollectionType.Playlist">Playlist</MudSelectItem>
<MudSelectItem Value="ProgramScheduleItemCollectionType.TelevisionSeason">Television Season</MudSelectItem>
</MudSelect>
<MudSelectItem Value="ProgramScheduleItemCollectionType.Artist">Artist</MudSelectItem>
<MudSelectItem Value="ProgramScheduleItemCollectionType.MultiCollection">Multi Collection</MudSelectItem>
<MudSelectItem Value="ProgramScheduleItemCollectionType.SmartCollection">Smart Collection</MudSelectItem>
<MudSelectItem Value="ProgramScheduleItemCollectionType.Playlist">Playlist</MudSelectItem>
</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">
@bind-Value="_selectedItem.Collection" SearchFunc="@SearchCollections"
<div class="d-flex">
ToStringFunc="@(c => c?.Name)" Placeholder="Type to search...">
<MudText>Collection</MudText>
<MoreItemsTemplate>
</div>
<MudText Align="Align.Center" Class="px-4 py-1">
<MudAutocomplete T="MediaCollectionViewModel"
Only the first 10 items are shown
@bind-Value="_selectedItem.Collection" SearchFunc="@SearchCollections"
</MudText>
ToStringFunc="@(c => c?.Name)" Placeholder="Type to search...">
</MoreItemsTemplate>
<MoreItemsTemplate>
</MudAutocomplete>
<MudText Align="Align.Center" Class="px-4 py-1">
Only the first 10 items are shown
</MudText>
</MoreItemsTemplate>
</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">
@bind-Value="_selectedItem.MultiCollection" SearchFunc="@SearchMultiCollections"
<div class="d-flex">
ToStringFunc="@(c => c?.Name)" Placeholder="Type to search...">
<MudText>Multi Collection</MudText>
<MoreItemsTemplate>
</div>
<MudText Align="Align.Center" Class="px-4 py-1">
<MudAutocomplete T="MultiCollectionViewModel"
Only the first 10 items are shown
@bind-Value="_selectedItem.MultiCollection" SearchFunc="@SearchMultiCollections"
</MudText>
ToStringFunc="@(c => c?.Name)" Placeholder="Type to search...">
</MoreItemsTemplate>
<MoreItemsTemplate>
</MudAutocomplete>
<MudText Align="Align.Center" Class="px-4 py-1">
Only the first 10 items are shown
</MudText>
</MoreItemsTemplate>
</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">
@bind-Value="_selectedItem.SmartCollection" SearchFunc="@SearchSmartCollections"
<div class="d-flex">
ToStringFunc="@(c => c?.Name)" Placeholder="Type to search...">
<MudText>Smart Collection</MudText>
<MoreItemsTemplate>
</div>
<MudText Align="Align.Center" Class="px-4 py-1">
<MudAutocomplete T="SmartCollectionViewModel"
Only the first 10 items are shown
@bind-Value="_selectedItem.SmartCollection" SearchFunc="@SearchSmartCollections"
</MudText>
ToStringFunc="@(c => c?.Name)" Placeholder="Type to search...">
</MoreItemsTemplate>
<MoreItemsTemplate>
</MudAutocomplete>
<MudText Align="Align.Center" Class="px-4 py-1">
Only the first 10 items are shown
</MudText>
</MoreItemsTemplate>
</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">
@bind-Value="_selectedItem.MediaItem" SearchFunc="@SearchTelevisionShows"
<div class="d-flex">
ToStringFunc="@(c => c?.Name)" Placeholder="Type to search...">
<MudText>Television Show</MudText>
<MoreItemsTemplate>
</div>
<MudText Align="Align.Center" Class="px-4 py-1">
<MudAutocomplete T="NamedMediaItemViewModel"
Only the first 10 items are shown
@bind-Value="_selectedItem.MediaItem" SearchFunc="@SearchTelevisionShows"
</MudText>
ToStringFunc="@(c => c?.Name)" Placeholder="Type to search...">
</MoreItemsTemplate>
<MoreItemsTemplate>
</MudAutocomplete>
<MudText Align="Align.Center" Class="px-4 py-1">
Only the first 10 items are shown
</MudText>
</MoreItemsTemplate>
</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">
@bind-Value="_selectedItem.MediaItem" SearchFunc="@SearchTelevisionSeasons"
<div class="d-flex">
ToStringFunc="@(c => c?.Name)" Placeholder="Type to search..."
<MudText>Television Season</MudText>
MaxItems="20">
</div>
<MoreItemsTemplate>
<MudAutocomplete T="NamedMediaItemViewModel"
<MudText Align="Align.Center" Class="px-4 py-1">
@bind-Value="_selectedItem.MediaItem" SearchFunc="@SearchTelevisionSeasons"
Only the first 20 items are shown
ToStringFunc="@(c => c?.Name)" Placeholder="Type to search..."
</MudText>
MaxItems="20">
</MoreItemsTemplate>
<MoreItemsTemplate>
</MudAutocomplete>
<MudText Align="Align.Center" Class="px-4 py-1">
Only the first 20 items are shown
</MudText>
</MoreItemsTemplate>
</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">
@bind-Value="_selectedItem.MediaItem" SearchFunc="@SearchArtists"
<div class="d-flex">
ToStringFunc="@(c => c?.Name)" Placeholder="Type to search..."
<MudText>Artist</MudText>
MaxItems="10">
</div>
<MoreItemsTemplate>
<MudAutocomplete T="NamedMediaItemViewModel"
<MudText Align="Align.Center" Class="px-4 py-1">
@bind-Value="_selectedItem.MediaItem" SearchFunc="@SearchArtists"
Only the first 10 items are shown
ToStringFunc="@(c => c?.Name)" Placeholder="Type to search..."
</MudText>
MaxItems="10">
</MoreItemsTemplate>
<MoreItemsTemplate>
</MudAutocomplete>
<MudText Align="Align.Center" Class="px-4 py-1">
Only the first 10 items are shown
</MudText>
</MoreItemsTemplate>
</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">
Value="@_selectedPlaylistGroup"
<MudText>Playlist Group</MudText>
Label="Playlist Group"
</div>
ValueChanged="@(vm => UpdatePlaylistGroupItems(vm))">
<MudSelect T="PlaylistGroupViewModel"
@foreach (PlaylistGroupViewModel playlistGroup in _playlistGroups)
Value="@_selectedPlaylistGroup"
ValueChanged="@(vm => UpdatePlaylistGroupItems(vm))">
@foreach (PlaylistGroupViewModel playlistGroup in _playlistGroups)
{
<MudSelectItem Value="@playlistGroup">@playlistGroup.Name</MudSelectItem>
}
</MudSelect>
</MudStack>
<MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
<div class="d-flex">
<MudText>Playlist</MudText>
</div>
<MudSelect T="PlaylistViewModel" @bind-value="_selectedItem.Playlist">
@foreach (PlaylistViewModel playlist in _playlists)
{
<MudSelectItem Value="@playlist">@playlist.Name</MudSelectItem>
}
</MudSelect>
</MudStack>
}
<MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
<div class="d-flex">
<MudText>Playback Order</MudText>
</div>
<MudSelect @bind-Value="@_selectedItem.PlaybackOrder"
For="@(() => _selectedItem.PlaybackOrder)"
Disabled="@(_selectedItem.CollectionType is ProgramScheduleItemCollectionType.Playlist)">
@switch (_selectedItem.CollectionType)
{
{
<MudSelectItem Value="@playlistGroup">@playlistGroup.Name</MudSelectItem>
case ProgramScheduleItemCollectionType.MultiCollection:
<MudSelectItem Value="PlaybackOrder.Shuffle">Shuffle</MudSelectItem>
<MudSelectItem Value="PlaybackOrder.ShuffleInOrder">Shuffle In Order</MudSelectItem>
break;
case ProgramScheduleItemCollectionType.Collection:
case ProgramScheduleItemCollectionType.SmartCollection:
<MudSelectItem Value="PlaybackOrder.Chronological">Chronological</MudSelectItem>
<MudSelectItem Value="PlaybackOrder.Random">Random</MudSelectItem>
<MudSelectItem Value="PlaybackOrder.Shuffle">Shuffle</MudSelectItem>
<MudSelectItem Value="PlaybackOrder.ShuffleInOrder">Shuffle In Order</MudSelectItem>
break;
case ProgramScheduleItemCollectionType.TelevisionShow:
<MudSelectItem Value="PlaybackOrder.Chronological">Chronological</MudSelectItem>
<MudSelectItem Value="PlaybackOrder.SeasonEpisode">Season, Episode</MudSelectItem>
<MudSelectItem Value="PlaybackOrder.Random">Random</MudSelectItem>
<MudSelectItem Value="PlaybackOrder.Shuffle">Shuffle</MudSelectItem>
<MudSelectItem Value="PlaybackOrder.MultiEpisodeShuffle">Multi-Episode Shuffle</MudSelectItem>
break;
case ProgramScheduleItemCollectionType.Playlist:
break;
default:
<MudSelectItem Value="PlaybackOrder.Chronological">Chronological</MudSelectItem>
<MudSelectItem Value="PlaybackOrder.Random">Random</MudSelectItem>
<MudSelectItem Value="PlaybackOrder.Shuffle">Shuffle</MudSelectItem>
break;
}
}
</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>Playout Mode</MudText>
@foreach (PlaylistViewModel playlist in _playlists)
</div>
<MudSelect @bind-Value="@_selectedItem.PlayoutMode" For="@(() => _selectedItem.PlayoutMode)">
@if (!_schedule.ShuffleScheduleItems)
{
{
<MudSelectItem Value="@playlist">@playlist.Name</MudSelectItem>
<MudSelectItem Value="PlayoutMode.Flood">Flood </MudSelectItem>
}
}
<MudSelectItem Value="PlayoutMode.One">One</MudSelectItem>
<MudSelectItem Value="PlayoutMode.Multiple">Multiple</MudSelectItem>
<MudSelectItem Value="PlayoutMode.Duration">Duration</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>Multiple Count</MudText>
For="@(() => _selectedItem.PlaybackOrder)"
</div>
Disabled="@(_selectedItem.CollectionType is ProgramScheduleItemCollectionType.Playlist)">
<MudTextField @bind-Value="@_selectedItem.MultipleCount"
@switch (_selectedItem.CollectionType)
For="@(() => _selectedItem.MultipleCount)"
{
Disabled="@(_selectedItem.PlayoutMode != PlayoutMode.Multiple)"/>
case ProgramScheduleItemCollectionType.MultiCollection:
</MudStack>
<MudSelectItem Value="PlaybackOrder.Shuffle">Shuffle</MudSelectItem>
<MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
<MudSelectItem Value="PlaybackOrder.ShuffleInOrder">Shuffle In Order</MudSelectItem>
<div class="d-flex">
break;
<MudText>Playout Duration</MudText>
case ProgramScheduleItemCollectionType.Collection:
</div>
case ProgramScheduleItemCollectionType.SmartCollection:
<MudTextField T="int"
<MudSelectItem Value="PlaybackOrder.Chronological">Chronological</MudSelectItem>
@bind-Value="_selectedItem.PlayoutDurationHours"
<MudSelectItem Value="PlaybackOrder.Random">Random</MudSelectItem>
Adornment="Adornment.End"
<MudSelectItem Value="PlaybackOrder.Shuffle">Shuffle</MudSelectItem>
AdornmentText="hours"
<MudSelectItem Value="PlaybackOrder.ShuffleInOrder">Shuffle In Order</MudSelectItem>
Disabled="@(_selectedItem.PlayoutMode != PlayoutMode.Duration)"/>
break;
</MudStack>
case ProgramScheduleItemCollectionType.TelevisionShow:
<MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
<MudSelectItem Value="PlaybackOrder.Chronological">Chronological</MudSelectItem>
<div class="d-flex"></div>
<MudSelectItem Value="PlaybackOrder.SeasonEpisode">Season, Episode</MudSelectItem>
<MudTextField T="int"
<MudSelectItem Value="PlaybackOrder.Random">Random</MudSelectItem>
@bind-Value="_selectedItem.PlayoutDurationMinutes"
<MudSelectItem Value="PlaybackOrder.Shuffle">Shuffle</MudSelectItem>
Adornment="Adornment.End"
<MudSelectItem Value="PlaybackOrder.MultiEpisodeShuffle">Multi-Episode Shuffle</MudSelectItem>
AdornmentText="minutes"
break;
Disabled="@(_selectedItem.PlayoutMode != PlayoutMode.Duration)"/>
case ProgramScheduleItemCollectionType.Playlist:
</MudStack>
break;
<MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
default:
<div class="d-flex">
<MudSelectItem Value="PlaybackOrder.Chronological">Chronological</MudSelectItem>
<MudText>Fill With Group Mode (Show or Artist)</MudText>
<MudSelectItem Value="PlaybackOrder.Random">Random</MudSelectItem>
</div>
<MudSelectItem Value="PlaybackOrder.Shuffle">Shuffle</MudSelectItem>
<MudSelect @bind-Value="@_selectedItem.FillWithGroupMode"
break;
For="@(() => _selectedItem.FillWithGroupMode)"
}
Disabled="@(_selectedItem.CanFillWithGroups == false)">
</MudSelect>
<MudSelectItem Value="FillWithGroupMode.None">(none)</MudSelectItem>
<MudSelect Class="mt-3" Label="Playout Mode" @bind-Value="@_selectedItem.PlayoutMode" For="@(() => _selectedItem.PlayoutMode)">
@if (_selectedItem.CanFillWithGroups)
@if (!_schedule.ShuffleScheduleItems)
{
{
<MudSelectItem Value="FillWithGroupMode.FillWithOrderedGroups">Ordered Groups</MudSelectItem>
<MudSelectItem Value="PlayoutMode.Flood">Flood</MudSelectItem>
<MudSelectItem Value="FillWithGroupMode.FillWithShuffledGroups">Shuffled Groups</MudSelectItem>
}
}
<MudSelectItem Value="PlayoutMode.One">One</MudSelectItem>
else
<MudSelectItem Value="PlayoutMode.Multiple">Multiple</MudSelectItem>
{
<MudSelectItem Value="PlayoutMode.Duration">Duration</MudSelectItem>
_selectedItem.FillWithGroupMode = FillWithGroupMode.None;
</MudSelect>
}
<MudTextField Class="mt-3" Label="Multiple Count" @bind-Value="@_selectedItem.MultipleCount" For="@(() => _selectedItem.MultipleCount)" Disabled="@(_selectedItem.PlayoutMode != PlayoutMode.Multiple)"/>
</MudSelect>
<MudGrid Class="mt-3" Style="align-items: center" Justify="Justify.Center">
</MudStack>
<MudItem xs="6">
<MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
<MudTextField T="int"
<div class="d-flex">
Label="Playout Duration"
<MudText>Tail Mode</MudText>
@bind-Value="_selectedItem.PlayoutDurationHours"
</div>
Adornment="Adornment.End"
<MudSelect @bind-Value="@_selectedItem.TailMode"
AdornmentText="hours"
For="@(() => _selectedItem.TailMode)"
Disabled="@(_selectedItem.PlayoutMode != PlayoutMode.Duration)"/>
Disabled="@(_selectedItem.PlayoutMode != PlayoutMode.Duration)">
</MudItem>
<MudSelectItem Value="@TailMode.None">(none)</MudSelectItem>
<MudItem xs="6">
<MudSelectItem Value="@TailMode.Offline">Offline</MudSelectItem>
<MudTextField T="int"
<MudSelectItem Value="@TailMode.Filler">Filler</MudSelectItem>
@bind-Value="_selectedItem.PlayoutDurationMinutes"
</MudSelect>
Adornment="Adornment.End"
</MudStack>
AdornmentText="minutes"
<MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
Disabled="@(_selectedItem.PlayoutMode != PlayoutMode.Duration)"/>
<div class="d-flex">
</MudItem>
<MudText>Discard To Fill Attempts</MudText>
</MudGrid>
</div>
<MudSelect Class="mt-3" Label="Fill With Group Mode (Show or Artist)" @bind-Value="@_selectedItem.FillWithGroupMode" For="@(() => _selectedItem.FillWithGroupMode)" Disabled="@(_selectedItem.CanFillWithGroups == false)">
<MudTextField @bind-Value="@_selectedItem.DiscardToFillAttempts"
<MudSelectItem Value="FillWithGroupMode.None">(none)</MudSelectItem>
For="@(() => _selectedItem.DiscardToFillAttempts)"
@if (_selectedItem.CanFillWithGroups)
Disabled="@(_selectedItem.PlayoutMode != PlayoutMode.Duration)"/>
{
</MudStack>
<MudSelectItem Value="FillWithGroupMode.FillWithOrderedGroups">Ordered Groups</MudSelectItem>
<MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
<MudSelectItem Value="FillWithGroupMode.FillWithShuffledGroups">Shuffled Groups</MudSelectItem>
<div class="d-flex">
}
<MudText>Custom Title</MudText>
else
</div>
{
<MudTextField @bind-Value="@_selectedItem.CustomTitle" For="@(() => _selectedItem.CustomTitle)"/>
_selectedItem.FillWithGroupMode = FillWithGroupMode.None;
</MudStack>
}
<MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
</MudSelect>
<div class="d-flex">
<MudSelect Class="mt-3" Label="Tail Mode" @bind-Value="@_selectedItem.TailMode" For="@(() => _selectedItem.TailMode)" Disabled="@(_selectedItem.PlayoutMode != PlayoutMode.Duration)">
<MudText>Guide Mode</MudText>
<MudSelectItem Value="@TailMode.None">(none)</MudSelectItem>
</div>
<MudSelectItem Value="@TailMode.Offline">Offline</MudSelectItem>
<MudSelect @bind-Value="@_selectedItem.GuideMode" For="@(() => _selectedItem.GuideMode)">
<MudSelectItem Value="@TailMode.Filler">Filler</MudSelectItem>
<MudSelectItem Value="@GuideMode.Normal">Normal</MudSelectItem>
</MudSelect>
<MudSelectItem Value="@GuideMode.Filler">Filler</MudSelectItem>
<MudTextField Class="mt-3" Label="Discard To Fill Attempts" @bind-Value="@_selectedItem.DiscardToFillAttempts" For="@(() => _selectedItem.DiscardToFillAttempts)" Disabled="@(_selectedItem.PlayoutMode != PlayoutMode.Duration)"/>
</MudSelect>
<MudTextField Class="mt-3" Label="Custom Title" @bind-Value="@_selectedItem.CustomTitle" For="@(() => _selectedItem.CustomTitle)"/>
</MudStack>
<MudSelect Class="mt-3" Label="Guide Mode" @bind-Value="@_selectedItem.GuideMode" For="@(() => _selectedItem.GuideMode)">
<MudText Typo="Typo.h5" Class="mt-10 mb-2">Schedule Item Filler</MudText>
<MudSelectItem Value="@GuideMode.Normal">Normal</MudSelectItem>
<MudDivider Class="mb-6"/>
<MudSelectItem Value="@GuideMode.Filler">Filler</MudSelectItem>
<MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
</MudSelect>
<div class="d-flex">
</MudCardContent>
<MudText>Pre-Roll Filler</MudText>
</MudCard>
</div>
</div>
<MudSelect T="FillerPresetViewModel"
<div style="flex-grow: 1; max-width: 400px;">
@bind-value="_selectedItem.PreRollFiller"
<MudCard>
Clearable="true">
<MudCardContent>
@foreach (FillerPresetViewModel filler in _fillerPresets.Where(f => f.FillerKind == FillerKind.PreRoll))
<MudSelect T="FillerPresetViewModel"
{
Label="Pre-Roll Filler"
<MudSelectItem Value="@filler">@filler.Name</MudSelectItem>
@bind-value="_selectedItem.PreRollFiller"
}
Clearable="true">
</MudSelect>
@foreach (FillerPresetViewModel filler in _fillerPresets.Where(f => f.FillerKind == FillerKind.PreRoll))
</MudStack>
{
<MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
<MudSelectItem Value="@filler">@filler.Name</MudSelectItem>
<div class="d-flex">
}
<MudText>Mid-Roll Filler</MudText>
</MudSelect>
</div>
<MudSelect Class="mt-3"
<MudSelect T="FillerPresetViewModel"
T="FillerPresetViewModel"
@bind-value="_selectedItem.MidRollFiller"
Label="Mid-Roll Filler"
Clearable="true">
@bind-value="_selectedItem.MidRollFiller"
@foreach (FillerPresetViewModel filler in _fillerPresets.Where(f => f.FillerKind == FillerKind.MidRoll))
Clearable="true">
{
@foreach (FillerPresetViewModel filler in _fillerPresets.Where(f => f.FillerKind == FillerKind.MidRoll))
<MudSelectItem Value="@filler">@filler.Name</MudSelectItem>
{
}
<MudSelectItem Value="@filler">@filler.Name</MudSelectItem>
</MudSelect>
}
</MudStack>
</MudSelect>
<MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
<MudSelect Class="mt-3"
<div class="d-flex">
T="FillerPresetViewModel"
<MudText>Post-Roll Filler</MudText>
Label="Post-Roll Filler"
</div>
@bind-value="_selectedItem.PostRollFiller"
<MudSelect T="FillerPresetViewModel"
Clearable="true">
@bind-value="_selectedItem.PostRollFiller"
@foreach (FillerPresetViewModel filler in _fillerPresets.Where(f => f.FillerKind == FillerKind.PostRoll))
Clearable="true">
{
@foreach (FillerPresetViewModel filler in _fillerPresets.Where(f => f.FillerKind == FillerKind.PostRoll))
<MudSelectItem Value="@filler">@filler.Name</MudSelectItem>
{
}
<MudSelectItem Value="@filler">@filler.Name</MudSelectItem>
</MudSelect>
}
<MudSelect Class="mt-3"
</MudSelect>
T="FillerPresetViewModel"
</MudStack>
Label="Tail Filler"
<MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
@bind-value="_selectedItem.TailFiller"
<div class="d-flex">
Clearable="true">
<MudText>Tail Filler</MudText>
@foreach (FillerPresetViewModel filler in _fillerPresets.Where(f => f.FillerKind == FillerKind.Tail))
</div>
{
<MudSelect T="FillerPresetViewModel"
<MudSelectItem Value="@filler">@filler.Name</MudSelectItem>
@bind-value="_selectedItem.TailFiller"
}
Clearable="true">
</MudSelect>
@foreach (FillerPresetViewModel filler in _fillerPresets.Where(f => f.FillerKind == FillerKind.Tail))
<MudSelect Class="mt-3"
{
T="FillerPresetViewModel"
<MudSelectItem Value="@filler">@filler.Name</MudSelectItem>
Label="Fallback Filler"
}
@bind-value="_selectedItem.FallbackFiller"
</MudSelect>
Clearable="true">
</MudStack>
@foreach (FillerPresetViewModel filler in _fillerPresets.Where(f => f.FillerKind == FillerKind.Fallback))
<MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
{
<div class="d-flex">
<MudSelectItem Value="@filler">@filler.Name</MudSelectItem>
<MudText>Fallback Filler</MudText>
}
</div>
</MudSelect>
<MudSelect T="FillerPresetViewModel"
</MudCardContent>
@bind-value="_selectedItem.FallbackFiller"
</MudCard>
Clearable="true">
<MudCard Class="mt-4">
@foreach (FillerPresetViewModel filler in _fillerPresets.Where(f => f.FillerKind == FillerKind.Fallback))
<MudCardContent>
{
<MudSelect Label="Watermark" @bind-Value="@_selectedItem.Watermark" For="@(() => _selectedItem.Watermark)" Clearable="true">
<MudSelectItem Value="@filler">@filler.Name</MudSelectItem>
@foreach (WatermarkViewModel watermark in _watermarks)
}
{
</MudSelect>
<MudSelectItem Value="@watermark">@watermark.Name</MudSelectItem>
</MudStack>
}
<MudText Typo="Typo.h5" Class="mt-10 mb-2">Schedule Item Overrides</MudText>
</MudSelect>
<MudDivider Class="mb-6"/>
<MudSelect Class="mt-3"
<MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
Label="Preferred Audio Language"
<div class="d-flex">
@bind-Value="_selectedItem.PreferredAudioLanguageCode"
<MudText>Watermark</MudText>
For="@(() => _selectedItem.PreferredAudioLanguageCode)"
</div>
Clearable="true">
<MudSelect @bind-Value="@_selectedItem.Watermark" For="@(() => _selectedItem.Watermark)" Clearable="true">
<MudSelectItem Value="@((string)null)">(none)</MudSelectItem>
@foreach (WatermarkViewModel watermark in _watermarks)
@foreach (LanguageCodeViewModel culture in _availableCultures)
{
{
<MudSelectItem Value="@watermark">@watermark.Name</MudSelectItem>
<MudSelectItem Value="@culture.ThreeLetterISOLanguageName">@culture.EnglishName</MudSelectItem>
}
}
</MudSelect>
</MudSelect>
</MudStack>
<MudTextField Class="mt-3" Label="Preferred Audio Title" @bind-Value="@_selectedItem.PreferredAudioTitle" For="@(() => _selectedItem.PreferredAudioTitle)"/>
<MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
<MudSelect Class="mt-3"
<div class="d-flex">
Label="Preferred Subtitle Language"
<MudText>Preferred Audio Language</MudText>
@bind-Value="_selectedItem.PreferredSubtitleLanguageCode"
</div>
For="@(() => _selectedItem.PreferredSubtitleLanguageCode)"
<MudSelect @bind-Value="_selectedItem.PreferredAudioLanguageCode"
Clearable="true">
For="@(() => _selectedItem.PreferredAudioLanguageCode)"
<MudSelectItem Value="@((string)null)">(none)</MudSelectItem>
Clearable="true">
@foreach (LanguageCodeViewModel culture in _availableCultures)
<MudSelectItem Value="@((string)null)">(none)</MudSelectItem>
{
@foreach (LanguageCodeViewModel culture in _availableCultures)
<MudSelectItem Value="@culture.ThreeLetterISOLanguageName">@culture.EnglishName</MudSelectItem>
{
}
<MudSelectItem Value="@culture.ThreeLetterISOLanguageName">@culture.EnglishName</MudSelectItem>
</MudSelect>
}
<MudSelect T="ChannelSubtitleMode?" Class="mt-3" Label="Subtitle Mode" @bind-Value="_selectedItem.SubtitleMode" For="@(() => _selectedItem.SubtitleMode)" Clearable="true">
</MudSelect>
<MudSelectItem T="ChannelSubtitleMode?" Value="@(ChannelSubtitleMode.None)">None</MudSelectItem>
</MudStack>
<MudSelectItem T="ChannelSubtitleMode?" Value="@(ChannelSubtitleMode.Forced)">Forced</MudSelectItem>
<MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
<MudSelectItem T="ChannelSubtitleMode?" Value="@(ChannelSubtitleMode.Default)">Default</MudSelectItem>
<div class="d-flex">
<MudSelectItem T="ChannelSubtitleMode?" Value="@(ChannelSubtitleMode.Any)">Any</MudSelectItem>
<MudText>Preferred Audio Title</MudText>
</MudSelect>
</div>
</MudCardContent>
<MudTextField @bind-Value="@_selectedItem.PreferredAudioTitle" For="@(() => _selectedItem.PreferredAudioTitle)"/>
</MudCard>
</MudStack>
</div>
<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)"
Clearable="true">
<MudSelectItem Value="@((string)null)">(none)</MudSelectItem>
@foreach (LanguageCodeViewModel culture in _availableCultures)
{
<MudSelectItem Value="@culture.ThreeLetterISOLanguageName">@culture.EnglishName</MudSelectItem>
}
</MudSelect>
</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.Forced)">Forced</MudSelectItem>
<MudSelectItem T="ChannelSubtitleMode?" Value="@(ChannelSubtitleMode.Default)">Default</MudSelectItem>
<MudSelectItem T="ChannelSubtitleMode?" Value="@(ChannelSubtitleMode.Any)">Any</MudSelectItem>
</MudSelect>
</MudStack>
}
</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,