@ -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,