more layout updates for mobile (#2137)
* update trakt, filler, filler editor ui * update schedules and playouts * update playout editor * update dependencies * update yaml playout editor * update path replacement editor
This commit is contained in:
@@ -25,11 +25,11 @@
|
||||
<PackageReference Include="LanguageExt.Core" Version="4.4.9" />
|
||||
<PackageReference Include="Markdig" Version="0.41.3" />
|
||||
<PackageReference Include="MediatR.Courier.DependencyInjection" Version="5.0.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="9.0.6" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="9.0.6" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="9.0.6" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.SpaServices.Extensions" Version="9.0.6" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="9.0.6">
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="9.0.7" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="9.0.7" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="9.0.7" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.SpaServices.Extensions" Version="9.0.7" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="9.0.7">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
|
||||
+219
-219
@@ -19,241 +19,241 @@
|
||||
@inject IMediator Mediator
|
||||
|
||||
<MudForm Model="@_model" @ref="@_form" Validation="@(_validator.ValidateValue)" ValidationDelay="0" Style="max-height: 100%">
|
||||
<MudPaper Square="true" Style="display: flex; height: 64px; min-height: 64px; width: 100%; z-index: 100; align-items: center">
|
||||
<MudButton Variant="Variant.Filled" Color="Color.Primary" Class="ml-8" OnClick="HandleSubmitAsync" StartIcon="@(IsEdit ? Icons.Material.Filled.Save : Icons.Material.Filled.Add)">@(IsEdit ? "Save Channel" : "Add Channel")</MudButton>
|
||||
</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">Channel</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>Number</MudText>
|
||||
</div>
|
||||
<MudTextField @bind-Value="_model.Number" For="@(() => _model.Number)" Immediate="true"/>
|
||||
</MudStack>
|
||||
<MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
|
||||
<div class="d-flex">
|
||||
<MudText>Name</MudText>
|
||||
</div>
|
||||
<MudTextField @bind-Value="_model.Name" For="@(() => _model.Name)"/>
|
||||
</MudStack>
|
||||
<MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
|
||||
<div class="d-flex">
|
||||
<MudText>Group</MudText>
|
||||
</div>
|
||||
<MudTextField @bind-Value="_model.Group" For="@(() => _model.Group)"/>
|
||||
</MudStack>
|
||||
<MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
|
||||
<div class="d-flex">
|
||||
<MudText>Categories</MudText>
|
||||
</div>
|
||||
<MudTextField @bind-Value="_model.Categories" For="@(() => _model.Categories)" HelperText="Comma-separated list of categories"/>
|
||||
</MudStack>
|
||||
<MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
|
||||
<div class="d-flex">
|
||||
<MudText>Active Mode</MudText>
|
||||
</div>
|
||||
<MudSelect @bind-Value="_model.ActiveMode" For="@(() => _model.ActiveMode)">
|
||||
<MudSelectItem Value="@(ChannelActiveMode.Active)">Active</MudSelectItem>
|
||||
<MudSelectItem Value="@(ChannelActiveMode.Hidden)">Hidden</MudSelectItem>
|
||||
<MudSelectItem Value="@(ChannelActiveMode.Inactive)">Inactive</MudSelectItem>
|
||||
</MudSelect>
|
||||
</MudStack>
|
||||
<MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
|
||||
<div class="d-flex">
|
||||
<MudText>Progress Mode</MudText>
|
||||
</div>
|
||||
<MudSelect @bind-Value="_model.ProgressMode" For="@(() => _model.ProgressMode)">
|
||||
<MudSelectItem Value="@(ChannelProgressMode.Always)">Always</MudSelectItem>
|
||||
<MudSelectItem Value="@(ChannelProgressMode.OnDemand)">On Demand</MudSelectItem>
|
||||
</MudSelect>
|
||||
</MudStack>
|
||||
<MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
|
||||
<div class="d-flex">
|
||||
<MudText>Streaming Mode</MudText>
|
||||
</div>
|
||||
<MudSelect @bind-Value="_model.StreamingMode" For="@(() => _model.StreamingMode)">
|
||||
<MudSelectItem Value="@(StreamingMode.TransportStreamHybrid)">MPEG-TS</MudSelectItem>
|
||||
<MudSelectItem Value="@(StreamingMode.TransportStream)">MPEG-TS (Legacy)</MudSelectItem>
|
||||
<MudSelectItem Value="@(StreamingMode.HttpLiveStreamingDirect)">HLS Direct</MudSelectItem>
|
||||
<MudSelectItem Value="@(StreamingMode.HttpLiveStreamingSegmenter)">HLS Segmenter</MudSelectItem>
|
||||
<MudSelectItem Value="@(StreamingMode.HttpLiveStreamingSegmenterV2)">HLS Segmenter V2</MudSelectItem>
|
||||
</MudSelect>
|
||||
</MudStack>
|
||||
<MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
|
||||
<div class="d-flex">
|
||||
<MudText>FFmpeg Profile</MudText>
|
||||
</div>
|
||||
<MudSelect @bind-Value="_model.FFmpegProfileId" For="@(() => _model.FFmpegProfileId)"
|
||||
Disabled="@(_model.StreamingMode == StreamingMode.HttpLiveStreamingDirect)">
|
||||
@foreach (FFmpegProfileViewModel profile in _ffmpegProfiles)
|
||||
{
|
||||
<MudSelectItem Value="@profile.Id">@profile.Name</MudSelectItem>
|
||||
}
|
||||
</MudSelect>
|
||||
</MudStack>
|
||||
<MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
|
||||
<div class="d-flex">
|
||||
<MudText>Stream Selector Mode</MudText>
|
||||
</div>
|
||||
<MudSelect @bind-Value="_model.StreamSelectorMode" For="@(() => _model.StreamSelectorMode)">
|
||||
<MudSelectItem Value="@(ChannelStreamSelectorMode.Default)">Default</MudSelectItem>
|
||||
<MudSelectItem Value="@(ChannelStreamSelectorMode.Custom)">Custom</MudSelectItem>
|
||||
</MudSelect>
|
||||
</MudStack>
|
||||
@if (_model.StreamSelectorMode is ChannelStreamSelectorMode.Default)
|
||||
{
|
||||
<MudPaper Square="true" Style="display: flex; height: 64px; min-height: 64px; width: 100%; z-index: 100; align-items: center">
|
||||
<MudButton Variant="Variant.Filled" Color="Color.Primary" Class="ml-8" OnClick="HandleSubmitAsync" StartIcon="@(IsEdit ? Icons.Material.Filled.Save : Icons.Material.Filled.Add)">@(IsEdit ? "Save Channel" : "Add Channel")</MudButton>
|
||||
</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">Channel</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>Preferred Audio Language</MudText>
|
||||
<MudText>Number</MudText>
|
||||
</div>
|
||||
<MudSelect @bind-Value="_model.PreferredAudioLanguageCode"
|
||||
For="@(() => _model.PreferredAudioLanguageCode)"
|
||||
Clearable="true">
|
||||
<MudSelectItem Value="@((string)null)">(none)</MudSelectItem>
|
||||
@foreach (LanguageCodeViewModel culture in _availableCultures)
|
||||
<MudTextField @bind-Value="_model.Number" For="@(() => _model.Number)" Immediate="true"/>
|
||||
</MudStack>
|
||||
<MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
|
||||
<div class="d-flex">
|
||||
<MudText>Name</MudText>
|
||||
</div>
|
||||
<MudTextField @bind-Value="_model.Name" For="@(() => _model.Name)"/>
|
||||
</MudStack>
|
||||
<MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
|
||||
<div class="d-flex">
|
||||
<MudText>Group</MudText>
|
||||
</div>
|
||||
<MudTextField @bind-Value="_model.Group" For="@(() => _model.Group)"/>
|
||||
</MudStack>
|
||||
<MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
|
||||
<div class="d-flex">
|
||||
<MudText>Categories</MudText>
|
||||
</div>
|
||||
<MudTextField @bind-Value="_model.Categories" For="@(() => _model.Categories)" HelperText="Comma-separated list of categories"/>
|
||||
</MudStack>
|
||||
<MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
|
||||
<div class="d-flex">
|
||||
<MudText>Active Mode</MudText>
|
||||
</div>
|
||||
<MudSelect @bind-Value="_model.ActiveMode" For="@(() => _model.ActiveMode)">
|
||||
<MudSelectItem Value="@(ChannelActiveMode.Active)">Active</MudSelectItem>
|
||||
<MudSelectItem Value="@(ChannelActiveMode.Hidden)">Hidden</MudSelectItem>
|
||||
<MudSelectItem Value="@(ChannelActiveMode.Inactive)">Inactive</MudSelectItem>
|
||||
</MudSelect>
|
||||
</MudStack>
|
||||
<MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
|
||||
<div class="d-flex">
|
||||
<MudText>Progress Mode</MudText>
|
||||
</div>
|
||||
<MudSelect @bind-Value="_model.ProgressMode" For="@(() => _model.ProgressMode)">
|
||||
<MudSelectItem Value="@(ChannelProgressMode.Always)">Always</MudSelectItem>
|
||||
<MudSelectItem Value="@(ChannelProgressMode.OnDemand)">On Demand</MudSelectItem>
|
||||
</MudSelect>
|
||||
</MudStack>
|
||||
<MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
|
||||
<div class="d-flex">
|
||||
<MudText>Streaming Mode</MudText>
|
||||
</div>
|
||||
<MudSelect @bind-Value="_model.StreamingMode" For="@(() => _model.StreamingMode)">
|
||||
<MudSelectItem Value="@(StreamingMode.TransportStreamHybrid)">MPEG-TS</MudSelectItem>
|
||||
<MudSelectItem Value="@(StreamingMode.TransportStream)">MPEG-TS (Legacy)</MudSelectItem>
|
||||
<MudSelectItem Value="@(StreamingMode.HttpLiveStreamingDirect)">HLS Direct</MudSelectItem>
|
||||
<MudSelectItem Value="@(StreamingMode.HttpLiveStreamingSegmenter)">HLS Segmenter</MudSelectItem>
|
||||
<MudSelectItem Value="@(StreamingMode.HttpLiveStreamingSegmenterV2)">HLS Segmenter V2</MudSelectItem>
|
||||
</MudSelect>
|
||||
</MudStack>
|
||||
<MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
|
||||
<div class="d-flex">
|
||||
<MudText>FFmpeg Profile</MudText>
|
||||
</div>
|
||||
<MudSelect @bind-Value="_model.FFmpegProfileId" For="@(() => _model.FFmpegProfileId)"
|
||||
Disabled="@(_model.StreamingMode == StreamingMode.HttpLiveStreamingDirect)">
|
||||
@foreach (FFmpegProfileViewModel profile in _ffmpegProfiles)
|
||||
{
|
||||
<MudSelectItem Value="@culture.ThreeLetterISOLanguageName">@culture.EnglishName</MudSelectItem>
|
||||
<MudSelectItem Value="@profile.Id">@profile.Name</MudSelectItem>
|
||||
}
|
||||
</MudSelect>
|
||||
</MudStack>
|
||||
<MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
|
||||
<div class="d-flex">
|
||||
<MudText>Preferred Audio Title</MudText>
|
||||
<MudText>Stream Selector Mode</MudText>
|
||||
</div>
|
||||
<MudTextField @bind-Value="_model.PreferredAudioTitle" For="@(() => _model.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="_model.PreferredSubtitleLanguageCode"
|
||||
For="@(() => _model.PreferredSubtitleLanguageCode)"
|
||||
Clearable="true">
|
||||
<MudSelectItem Value="@((string)null)">(none)</MudSelectItem>
|
||||
@foreach (LanguageCodeViewModel culture in _availableCultures)
|
||||
{
|
||||
<MudSelectItem Value="@culture.ThreeLetterISOLanguageName">@culture.EnglishName</MudSelectItem>
|
||||
}
|
||||
<MudSelect @bind-Value="_model.StreamSelectorMode" For="@(() => _model.StreamSelectorMode)">
|
||||
<MudSelectItem Value="@(ChannelStreamSelectorMode.Default)">Default</MudSelectItem>
|
||||
<MudSelectItem Value="@(ChannelStreamSelectorMode.Custom)">Custom</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 @bind-Value="_model.SubtitleMode" For="@(() => _model.SubtitleMode)">
|
||||
<MudSelectItem Value="@(ChannelSubtitleMode.None)">None</MudSelectItem>
|
||||
<MudSelectItem Value="@(ChannelSubtitleMode.Forced)">Forced</MudSelectItem>
|
||||
<MudSelectItem Value="@(ChannelSubtitleMode.Default)">Default</MudSelectItem>
|
||||
<MudSelectItem Value="@(ChannelSubtitleMode.Any)">Any</MudSelectItem>
|
||||
</MudSelect>
|
||||
</MudStack>
|
||||
}
|
||||
else
|
||||
{
|
||||
<MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
|
||||
<div class="d-flex">
|
||||
<MudText>Stream Selector</MudText>
|
||||
</div>
|
||||
<MudSelect @bind-Value="_model.StreamSelector"
|
||||
For="@(() => _model.StreamSelector)">
|
||||
<MudSelectItem T="string" Value="@((string)null)">(none)</MudSelectItem>
|
||||
@foreach (string selector in _streamSelectors)
|
||||
{
|
||||
<MudSelectItem T="string" Value="@selector">@selector</MudSelectItem>
|
||||
}
|
||||
</MudSelect>
|
||||
</MudStack>
|
||||
}
|
||||
<MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
|
||||
<div class="d-flex">
|
||||
<MudText>Music Video Credits Mode</MudText>
|
||||
</div>
|
||||
<MudSelect @bind-Value="_model.MusicVideoCreditsMode" For="@(() => _model.MusicVideoCreditsMode)">
|
||||
<MudSelectItem Value="@(ChannelMusicVideoCreditsMode.None)">None</MudSelectItem>
|
||||
<MudSelectItem Value="@(ChannelMusicVideoCreditsMode.GenerateSubtitles)">Generate Subtitles</MudSelectItem>
|
||||
</MudSelect>
|
||||
</MudStack>
|
||||
<MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
|
||||
<div class="d-flex">
|
||||
<MudText>Music Video Credits Template</MudText>
|
||||
</div>
|
||||
<MudSelect @bind-Value="_model.MusicVideoCreditsTemplate"
|
||||
For="@(() => _model.MusicVideoCreditsTemplate)"
|
||||
Disabled="@(_model.MusicVideoCreditsMode != ChannelMusicVideoCreditsMode.GenerateSubtitles)">
|
||||
<MudSelectItem T="string" Value="@((string)null)">(none)</MudSelectItem>
|
||||
@foreach (string template in _musicVideoCreditsTemplates)
|
||||
{
|
||||
<MudSelectItem T="string" Value="@template">@template</MudSelectItem>
|
||||
}
|
||||
</MudSelect>
|
||||
</MudStack>
|
||||
<MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
|
||||
<div class="d-flex">
|
||||
<MudText>Song Video Mode</MudText>
|
||||
</div>
|
||||
<MudSelect @bind-Value="_model.SongVideoMode" For="@(() => _model.SongVideoMode)">
|
||||
<MudSelectItem Value="@(ChannelSongVideoMode.Default)">Default</MudSelectItem>
|
||||
<MudSelectItem Value="@(ChannelSongVideoMode.WithProgress)">With Progress</MudSelectItem>
|
||||
</MudSelect>
|
||||
</MudStack>
|
||||
<MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
|
||||
<div class="d-flex">
|
||||
<MudText>Logo</MudText>
|
||||
</div>
|
||||
<InputFile id="fileInput" OnChange="UploadLogo" style="display: none;"/>
|
||||
<MudButton HtmlTag="label"
|
||||
Variant="Variant.Filled"
|
||||
Color="Color.Primary"
|
||||
StartIcon="@Icons.Material.Filled.CloudUpload"
|
||||
for="fileInput">
|
||||
Upload Logo
|
||||
</MudButton>
|
||||
</MudStack>
|
||||
<MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
|
||||
<div class="d-flex">
|
||||
<MudText>External Logo URL</MudText>
|
||||
</div>
|
||||
<MudTextField @bind-Value="_model.ExternalLogoUrl" For="@(() => _model.ExternalLogoUrl)"/>
|
||||
</MudStack>
|
||||
<MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
|
||||
<div class="d-flex">
|
||||
<MudText>Logo Preview</MudText>
|
||||
</div>
|
||||
@if (!string.IsNullOrWhiteSpace(_model.Logo?.Path) || !string.IsNullOrWhiteSpace(_model.ExternalLogoUrl))
|
||||
@if (_model.StreamSelectorMode is ChannelStreamSelectorMode.Default)
|
||||
{
|
||||
<MudElement HtmlTag="img" src="@(string.IsNullOrWhiteSpace(_model.ExternalLogoUrl) ? _model.Logo.UrlWithContentType : _model.ExternalLogoUrl)" Style="max-height: 50px"/>
|
||||
<MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
|
||||
<div class="d-flex">
|
||||
<MudText>Preferred Audio Language</MudText>
|
||||
</div>
|
||||
<MudSelect @bind-Value="_model.PreferredAudioLanguageCode"
|
||||
For="@(() => _model.PreferredAudioLanguageCode)"
|
||||
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>Preferred Audio Title</MudText>
|
||||
</div>
|
||||
<MudTextField @bind-Value="_model.PreferredAudioTitle" For="@(() => _model.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="_model.PreferredSubtitleLanguageCode"
|
||||
For="@(() => _model.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 @bind-Value="_model.SubtitleMode" For="@(() => _model.SubtitleMode)">
|
||||
<MudSelectItem Value="@(ChannelSubtitleMode.None)">None</MudSelectItem>
|
||||
<MudSelectItem Value="@(ChannelSubtitleMode.Forced)">Forced</MudSelectItem>
|
||||
<MudSelectItem Value="@(ChannelSubtitleMode.Default)">Default</MudSelectItem>
|
||||
<MudSelectItem Value="@(ChannelSubtitleMode.Any)">Any</MudSelectItem>
|
||||
</MudSelect>
|
||||
</MudStack>
|
||||
}
|
||||
</MudStack>
|
||||
<MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
|
||||
<div class="d-flex">
|
||||
<MudText>Watermark</MudText>
|
||||
</div>
|
||||
<MudSelect @bind-Value="_model.WatermarkId" For="@(() => _model.WatermarkId)"
|
||||
Disabled="@(_model.StreamingMode == StreamingMode.HttpLiveStreamingDirect)"
|
||||
Clearable="true">
|
||||
<MudSelectItem T="int?" Value="@((int?)null)">(none)</MudSelectItem>
|
||||
@foreach (WatermarkViewModel watermark in _watermarks)
|
||||
else
|
||||
{
|
||||
<MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
|
||||
<div class="d-flex">
|
||||
<MudText>Stream Selector</MudText>
|
||||
</div>
|
||||
<MudSelect @bind-Value="_model.StreamSelector"
|
||||
For="@(() => _model.StreamSelector)">
|
||||
<MudSelectItem T="string" Value="@((string)null)">(none)</MudSelectItem>
|
||||
@foreach (string selector in _streamSelectors)
|
||||
{
|
||||
<MudSelectItem T="string" Value="@selector">@selector</MudSelectItem>
|
||||
}
|
||||
</MudSelect>
|
||||
</MudStack>
|
||||
}
|
||||
<MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
|
||||
<div class="d-flex">
|
||||
<MudText>Music Video Credits Mode</MudText>
|
||||
</div>
|
||||
<MudSelect @bind-Value="_model.MusicVideoCreditsMode" For="@(() => _model.MusicVideoCreditsMode)">
|
||||
<MudSelectItem Value="@(ChannelMusicVideoCreditsMode.None)">None</MudSelectItem>
|
||||
<MudSelectItem Value="@(ChannelMusicVideoCreditsMode.GenerateSubtitles)">Generate Subtitles</MudSelectItem>
|
||||
</MudSelect>
|
||||
</MudStack>
|
||||
<MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
|
||||
<div class="d-flex">
|
||||
<MudText>Music Video Credits Template</MudText>
|
||||
</div>
|
||||
<MudSelect @bind-Value="_model.MusicVideoCreditsTemplate"
|
||||
For="@(() => _model.MusicVideoCreditsTemplate)"
|
||||
Disabled="@(_model.MusicVideoCreditsMode != ChannelMusicVideoCreditsMode.GenerateSubtitles)">
|
||||
<MudSelectItem T="string" Value="@((string)null)">(none)</MudSelectItem>
|
||||
@foreach (string template in _musicVideoCreditsTemplates)
|
||||
{
|
||||
<MudSelectItem T="string" Value="@template">@template</MudSelectItem>
|
||||
}
|
||||
</MudSelect>
|
||||
</MudStack>
|
||||
<MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
|
||||
<div class="d-flex">
|
||||
<MudText>Song Video Mode</MudText>
|
||||
</div>
|
||||
<MudSelect @bind-Value="_model.SongVideoMode" For="@(() => _model.SongVideoMode)">
|
||||
<MudSelectItem Value="@(ChannelSongVideoMode.Default)">Default</MudSelectItem>
|
||||
<MudSelectItem Value="@(ChannelSongVideoMode.WithProgress)">With Progress</MudSelectItem>
|
||||
</MudSelect>
|
||||
</MudStack>
|
||||
<MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
|
||||
<div class="d-flex">
|
||||
<MudText>Logo</MudText>
|
||||
</div>
|
||||
<InputFile id="fileInput" OnChange="UploadLogo" style="display: none;"/>
|
||||
<MudButton HtmlTag="label"
|
||||
Variant="Variant.Filled"
|
||||
Color="Color.Primary"
|
||||
StartIcon="@Icons.Material.Filled.CloudUpload"
|
||||
for="fileInput">
|
||||
Upload Logo
|
||||
</MudButton>
|
||||
</MudStack>
|
||||
<MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
|
||||
<div class="d-flex">
|
||||
<MudText>External Logo URL</MudText>
|
||||
</div>
|
||||
<MudTextField @bind-Value="_model.ExternalLogoUrl" For="@(() => _model.ExternalLogoUrl)"/>
|
||||
</MudStack>
|
||||
<MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
|
||||
<div class="d-flex">
|
||||
<MudText>Logo Preview</MudText>
|
||||
</div>
|
||||
@if (!string.IsNullOrWhiteSpace(_model.Logo?.Path) || !string.IsNullOrWhiteSpace(_model.ExternalLogoUrl))
|
||||
{
|
||||
<MudSelectItem T="int?" Value="@watermark.Id">@watermark.Name</MudSelectItem>
|
||||
<MudElement HtmlTag="img" src="@(string.IsNullOrWhiteSpace(_model.ExternalLogoUrl) ? _model.Logo.UrlWithContentType : _model.ExternalLogoUrl)" Style="max-height: 50px"/>
|
||||
}
|
||||
</MudSelect>
|
||||
</MudStack>
|
||||
<MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
|
||||
<div class="d-flex">
|
||||
<MudText>Fallback Filler</MudText>
|
||||
</div>
|
||||
<MudSelect @bind-Value="_model.FallbackFillerId" For="@(() => _model.FallbackFillerId)" Clearable="true">
|
||||
<MudSelectItem T="int?" Value="@((int?)null)">(none)</MudSelectItem>
|
||||
@foreach (FillerPresetViewModel fillerPreset in _fillerPresets)
|
||||
{
|
||||
<MudSelectItem T="int?" Value="@fillerPreset.Id">@fillerPreset.Name</MudSelectItem>
|
||||
}
|
||||
</MudSelect>
|
||||
</MudStack>
|
||||
</MudContainer>
|
||||
</div>
|
||||
</MudStack>
|
||||
<MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
|
||||
<div class="d-flex">
|
||||
<MudText>Watermark</MudText>
|
||||
</div>
|
||||
<MudSelect @bind-Value="_model.WatermarkId" For="@(() => _model.WatermarkId)"
|
||||
Disabled="@(_model.StreamingMode == StreamingMode.HttpLiveStreamingDirect)"
|
||||
Clearable="true">
|
||||
<MudSelectItem T="int?" Value="@((int?)null)">(none)</MudSelectItem>
|
||||
@foreach (WatermarkViewModel watermark in _watermarks)
|
||||
{
|
||||
<MudSelectItem T="int?" Value="@watermark.Id">@watermark.Name</MudSelectItem>
|
||||
}
|
||||
</MudSelect>
|
||||
</MudStack>
|
||||
<MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
|
||||
<div class="d-flex">
|
||||
<MudText>Fallback Filler</MudText>
|
||||
</div>
|
||||
<MudSelect @bind-Value="_model.FallbackFillerId" For="@(() => _model.FallbackFillerId)" Clearable="true">
|
||||
<MudSelectItem T="int?" Value="@((int?)null)">(none)</MudSelectItem>
|
||||
@foreach (FillerPresetViewModel fillerPreset in _fillerPresets)
|
||||
{
|
||||
<MudSelectItem T="int?" Value="@fillerPreset.Id">@fillerPreset.Name</MudSelectItem>
|
||||
}
|
||||
</MudSelect>
|
||||
</MudStack>
|
||||
</MudContainer>
|
||||
</div>
|
||||
</MudForm>
|
||||
|
||||
@code {
|
||||
|
||||
@@ -6,137 +6,181 @@
|
||||
@using ErsatzTV.Application.MediaItems
|
||||
@using ErsatzTV.Application.Television
|
||||
@using ErsatzTV.Core.Domain.Filler
|
||||
@using ErsatzTV.Validators
|
||||
@using FluentValidation.Results
|
||||
@implements IDisposable
|
||||
@inject NavigationManager NavigationManager
|
||||
@inject ILogger<FillerPresetEditor> Logger
|
||||
@inject ISnackbar Snackbar
|
||||
@inject IMediator Mediator
|
||||
|
||||
<MudContainer MaxWidth="MaxWidth.ExtraLarge" Class="pt-8">
|
||||
<div style="max-width: 400px;">
|
||||
<MudText Typo="Typo.h4" Class="mb-4">@(IsEdit ? "Edit Filler Preset" : "Add Filler Preset")</MudText>
|
||||
|
||||
@if (_editContext is not null)
|
||||
{
|
||||
<EditForm EditContext="_editContext" OnSubmit="@HandleSubmitAsync">
|
||||
<FluentValidationValidator/>
|
||||
<MudCard>
|
||||
<MudCardContent>
|
||||
<MudTextField Class="mt-3" Label="Name" @bind-Value="_model.Name" For="@(() => _model.Name)"/>
|
||||
<MudSelect Class="mt-3" Label="Filler Kind" @bind-Value="_model.FillerKind" For="@(() => _model.FillerKind)" Disabled="@IsEdit">
|
||||
<MudSelectItem Value="@(FillerKind.PreRoll)">Pre-Roll</MudSelectItem>
|
||||
<MudSelectItem Value="@(FillerKind.MidRoll)">Mid-Roll</MudSelectItem>
|
||||
<MudSelectItem Value="@(FillerKind.PostRoll)">Post-Roll</MudSelectItem>
|
||||
<MudSelectItem Value="@(FillerKind.Tail)">Tail</MudSelectItem>
|
||||
<MudSelectItem Value="@(FillerKind.Fallback)">Fallback</MudSelectItem>
|
||||
</MudSelect>
|
||||
<MudSelect Class="mt-3" Label="Filler Mode" @bind-Value="_model.FillerMode" For="@(() => _model.FillerMode)"
|
||||
Disabled="@(_model.FillerKind is FillerKind.Fallback or FillerKind.Tail)">
|
||||
<MudSelectItem Value="@(FillerMode.Duration)">Duration</MudSelectItem>
|
||||
<MudSelectItem Value="@(FillerMode.Count)">Count</MudSelectItem>
|
||||
<MudSelectItem Value="@(FillerMode.Pad)">Pad</MudSelectItem>
|
||||
<MudSelectItem Value="@(FillerMode.RandomCount)">Random Count</MudSelectItem>
|
||||
</MudSelect>
|
||||
<MudTimePicker Class="mt-3" Label="Filler Duration" @bind-Time="@_model.Duration" For="@(() => _model.Duration)" Disabled="@(_model.FillerMode != FillerMode.Duration)"/>
|
||||
<MudTextField Class="mt-3" Label="Filler Count" @bind-Value="@_model.Count" For="@(() => _model.Count)" Disabled="@(_model.FillerMode != FillerMode.Count && _model.FillerMode != FillerMode.RandomCount)"/>
|
||||
<MudSelect Class="mt-3" Label="Filler Pad To Nearest Minute" @bind-Value="_model.PadToNearestMinute" For="@(() => _model.PadToNearestMinute)" Disabled="@(_model.FillerMode != FillerMode.Pad)">
|
||||
<MudSelectItem T="int?" Value="5">5 (:00, :05, :10, :15, :20, etc)</MudSelectItem>
|
||||
<MudSelectItem T="int?" Value="10">10 (:00, :10, :20, :30, :40, :50)</MudSelectItem>
|
||||
<MudSelectItem T="int?" Value="15">15 (:00, :15, :30, :45)</MudSelectItem>
|
||||
<MudSelectItem T="int?" Value="30">30 (:00, :30)</MudSelectItem>
|
||||
</MudSelect>
|
||||
<MudCheckBox Class="mt-3" Label="Allow Watermarks" @bind-Value="@_model.AllowWatermarks" For="@(() => _model.AllowWatermarks)"/>
|
||||
<MudSelect Class="mt-3" Label="Filler Collection Type" @bind-Value="_model.CollectionType" For="@(() => _model.CollectionType)">
|
||||
<MudSelectItem Value="ProgramScheduleItemCollectionType.Collection">Collection</MudSelectItem>
|
||||
<MudSelectItem Value="ProgramScheduleItemCollectionType.TelevisionShow">Television Show</MudSelectItem>
|
||||
<MudSelectItem Value="ProgramScheduleItemCollectionType.TelevisionSeason">Television Season</MudSelectItem>
|
||||
<MudSelectItem Value="ProgramScheduleItemCollectionType.Artist">Artist</MudSelectItem>
|
||||
<MudSelectItem Value="ProgramScheduleItemCollectionType.MultiCollection">Multi Collection</MudSelectItem>
|
||||
<MudSelectItem Value="ProgramScheduleItemCollectionType.SmartCollection">Smart Collection</MudSelectItem>
|
||||
</MudSelect>
|
||||
@if (_model.CollectionType == ProgramScheduleItemCollectionType.Collection)
|
||||
<MudForm Model="@_model" @ref="@_form" Validation="@(_validator.ValidateValue)" ValidationDelay="0" Style="max-height: 100%">
|
||||
<MudPaper Square="true" Style="display: flex; height: 64px; min-height: 64px; width: 100%; z-index: 100; align-items: center">
|
||||
<MudButton Variant="Variant.Filled" Color="Color.Primary" Class="ml-8" OnClick="HandleSubmitAsync" StartIcon="@(IsEdit ? Icons.Material.Filled.Save : Icons.Material.Filled.Add)">@(IsEdit ? "Save Filler Preset" : "Add Filler Preset")</MudButton>
|
||||
</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">Filler Preset</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>Name</MudText>
|
||||
</div>
|
||||
<MudTextField @bind-Value="_model.Name" For="@(() => _model.Name)"/>
|
||||
</MudStack>
|
||||
<MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
|
||||
<div class="d-flex">
|
||||
<MudText>Kind</MudText>
|
||||
</div>
|
||||
<MudSelect @bind-Value="_model.FillerKind" For="@(() => _model.FillerKind)" Disabled="@IsEdit">
|
||||
<MudSelectItem Value="@(FillerKind.PreRoll)">Pre-Roll</MudSelectItem>
|
||||
<MudSelectItem Value="@(FillerKind.MidRoll)">Mid-Roll</MudSelectItem>
|
||||
<MudSelectItem Value="@(FillerKind.PostRoll)">Post-Roll</MudSelectItem>
|
||||
<MudSelectItem Value="@(FillerKind.Tail)">Tail</MudSelectItem>
|
||||
<MudSelectItem Value="@(FillerKind.Fallback)">Fallback</MudSelectItem>
|
||||
</MudSelect>
|
||||
</MudStack>
|
||||
<MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
|
||||
<div class="d-flex">
|
||||
<MudText>Mode</MudText>
|
||||
</div>
|
||||
<MudSelect @bind-Value="_model.FillerMode" For="@(() => _model.FillerMode)"
|
||||
Disabled="@(_model.FillerKind is FillerKind.Fallback or FillerKind.Tail)">
|
||||
<MudSelectItem Value="@(FillerMode.Duration)">Duration</MudSelectItem>
|
||||
<MudSelectItem Value="@(FillerMode.Count)">Count</MudSelectItem>
|
||||
<MudSelectItem Value="@(FillerMode.Pad)">Pad</MudSelectItem>
|
||||
<MudSelectItem Value="@(FillerMode.RandomCount)">Random Count</MudSelectItem>
|
||||
</MudSelect>
|
||||
</MudStack>
|
||||
<MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
|
||||
<div class="d-flex">
|
||||
<MudText>Duration</MudText>
|
||||
</div>
|
||||
<MudTimePicker @bind-Time="@_model.Duration" For="@(() => _model.Duration)" Disabled="@(_model.FillerMode != FillerMode.Duration)"/>
|
||||
</MudStack>
|
||||
<MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
|
||||
<div class="d-flex">
|
||||
<MudText>Count</MudText>
|
||||
</div>
|
||||
<MudTextField @bind-Value="@_model.Count" For="@(() => _model.Count)" Disabled="@(_model.FillerMode != FillerMode.Count && _model.FillerMode != FillerMode.RandomCount)"/>
|
||||
</MudStack>
|
||||
<MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
|
||||
<div class="d-flex">
|
||||
<MudText>Pad To Nearest Minute</MudText>
|
||||
</div>
|
||||
<MudSelect @bind-Value="_model.PadToNearestMinute" For="@(() => _model.PadToNearestMinute)" Disabled="@(_model.FillerMode != FillerMode.Pad)">
|
||||
<MudSelectItem T="int?" Value="5">5 (:00, :05, :10, :15, :20, etc)</MudSelectItem>
|
||||
<MudSelectItem T="int?" Value="10">10 (:00, :10, :20, :30, :40, :50)</MudSelectItem>
|
||||
<MudSelectItem T="int?" Value="15">15 (:00, :15, :30, :45)</MudSelectItem>
|
||||
<MudSelectItem T="int?" Value="30">30 (:00, :30)</MudSelectItem>
|
||||
</MudSelect>
|
||||
</MudStack>
|
||||
<MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
|
||||
<div class="d-flex">
|
||||
<MudText>Allow Watermarks</MudText>
|
||||
</div>
|
||||
<MudCheckBox @bind-Value="@_model.AllowWatermarks" For="@(() => _model.AllowWatermarks)" Dense="true"/>
|
||||
</MudStack>
|
||||
<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="_model.CollectionType" For="@(() => _model.CollectionType)">
|
||||
<MudSelectItem Value="ProgramScheduleItemCollectionType.Collection">Collection</MudSelectItem>
|
||||
<MudSelectItem Value="ProgramScheduleItemCollectionType.TelevisionShow">Television Show</MudSelectItem>
|
||||
<MudSelectItem Value="ProgramScheduleItemCollectionType.TelevisionSeason">Television Season</MudSelectItem>
|
||||
<MudSelectItem Value="ProgramScheduleItemCollectionType.Artist">Artist</MudSelectItem>
|
||||
<MudSelectItem Value="ProgramScheduleItemCollectionType.MultiCollection">Multi Collection</MudSelectItem>
|
||||
<MudSelectItem Value="ProgramScheduleItemCollectionType.SmartCollection">Smart Collection</MudSelectItem>
|
||||
</MudSelect>
|
||||
</MudStack>
|
||||
@if (_model.CollectionType == ProgramScheduleItemCollectionType.Collection)
|
||||
{
|
||||
<MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
|
||||
<div class="d-flex">
|
||||
<MudText>Collection</MudText>
|
||||
</div>
|
||||
<MudSelect T="MediaCollectionViewModel" @bind-value="_model.Collection">
|
||||
@foreach (MediaCollectionViewModel collection in _mediaCollections)
|
||||
{
|
||||
<MudSelect Class="mt-3"
|
||||
T="MediaCollectionViewModel"
|
||||
Label="Collection"
|
||||
@bind-value="_model.Collection">
|
||||
@foreach (MediaCollectionViewModel collection in _mediaCollections)
|
||||
{
|
||||
<MudSelectItem Value="@collection">@collection.Name</MudSelectItem>
|
||||
}
|
||||
</MudSelect>
|
||||
<MudSelectItem Value="@collection">@collection.Name</MudSelectItem>
|
||||
}
|
||||
@if (_model.CollectionType == ProgramScheduleItemCollectionType.MultiCollection)
|
||||
</MudSelect>
|
||||
</MudStack>
|
||||
}
|
||||
@if (_model.CollectionType == ProgramScheduleItemCollectionType.MultiCollection)
|
||||
{
|
||||
<MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
|
||||
<div class="d-flex">
|
||||
<MudText>Multi Collection</MudText>
|
||||
</div>
|
||||
<MudSelect T="MultiCollectionViewModel" @bind-value="_model.MultiCollection">
|
||||
@foreach (MultiCollectionViewModel collection in _multiCollections)
|
||||
{
|
||||
<MudSelect Class="mt-3"
|
||||
T="MultiCollectionViewModel"
|
||||
Label="Multi Collection"
|
||||
@bind-value="_model.MultiCollection">
|
||||
@foreach (MultiCollectionViewModel collection in _multiCollections)
|
||||
{
|
||||
<MudSelectItem Value="@collection">@collection.Name</MudSelectItem>
|
||||
}
|
||||
</MudSelect>
|
||||
<MudSelectItem Value="@collection">@collection.Name</MudSelectItem>
|
||||
}
|
||||
@if (_model.CollectionType == ProgramScheduleItemCollectionType.SmartCollection)
|
||||
</MudSelect>
|
||||
</MudStack>
|
||||
}
|
||||
@if (_model.CollectionType == ProgramScheduleItemCollectionType.SmartCollection)
|
||||
{
|
||||
<MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
|
||||
<div class="d-flex">
|
||||
<MudText>Smart Collection</MudText>
|
||||
</div>
|
||||
<MudSelect T="SmartCollectionViewModel" @bind-value="_model.SmartCollection">
|
||||
@foreach (SmartCollectionViewModel collection in _smartCollections)
|
||||
{
|
||||
<MudSelect Class="mt-3"
|
||||
T="SmartCollectionViewModel"
|
||||
Label="Smart Collection"
|
||||
@bind-value="_model.SmartCollection">
|
||||
@foreach (SmartCollectionViewModel collection in _smartCollections)
|
||||
{
|
||||
<MudSelectItem Value="@collection">@collection.Name</MudSelectItem>
|
||||
}
|
||||
</MudSelect>
|
||||
<MudSelectItem Value="@collection">@collection.Name</MudSelectItem>
|
||||
}
|
||||
@if (_model.CollectionType == ProgramScheduleItemCollectionType.TelevisionShow)
|
||||
</MudSelect>
|
||||
</MudStack>
|
||||
}
|
||||
@if (_model.CollectionType == ProgramScheduleItemCollectionType.TelevisionShow)
|
||||
{
|
||||
<MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
|
||||
<div class="d-flex">
|
||||
<MudText>Television Show</MudText>
|
||||
</div>
|
||||
<MudSelect T="NamedMediaItemViewModel" @bind-value="_model.MediaItem">
|
||||
@foreach (NamedMediaItemViewModel show in _televisionShows)
|
||||
{
|
||||
<MudSelect Class="mt-3"
|
||||
T="NamedMediaItemViewModel"
|
||||
Label="Television Show"
|
||||
@bind-value="_model.MediaItem">
|
||||
@foreach (NamedMediaItemViewModel show in _televisionShows)
|
||||
{
|
||||
<MudSelectItem Value="@show">@show.Name</MudSelectItem>
|
||||
}
|
||||
</MudSelect>
|
||||
<MudSelectItem Value="@show">@show.Name</MudSelectItem>
|
||||
}
|
||||
@if (_model.CollectionType == ProgramScheduleItemCollectionType.TelevisionSeason)
|
||||
</MudSelect>
|
||||
</MudStack>
|
||||
}
|
||||
@if (_model.CollectionType == ProgramScheduleItemCollectionType.TelevisionSeason)
|
||||
{
|
||||
<MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
|
||||
<div class="d-flex">
|
||||
<MudText>Television Season</MudText>
|
||||
</div>
|
||||
<MudSelect T="NamedMediaItemViewModel" @bind-value="_model.MediaItem">
|
||||
@foreach (NamedMediaItemViewModel season in _televisionSeasons)
|
||||
{
|
||||
<MudSelect Class="mt-3"
|
||||
T="NamedMediaItemViewModel"
|
||||
Label="Television Season"
|
||||
@bind-value="_model.MediaItem">
|
||||
@foreach (NamedMediaItemViewModel season in _televisionSeasons)
|
||||
{
|
||||
<MudSelectItem Value="@season">@season.Name</MudSelectItem>
|
||||
}
|
||||
</MudSelect>
|
||||
<MudSelectItem Value="@season">@season.Name</MudSelectItem>
|
||||
}
|
||||
@if (_model.CollectionType == ProgramScheduleItemCollectionType.Artist)
|
||||
</MudSelect>
|
||||
</MudStack>
|
||||
}
|
||||
@if (_model.CollectionType == ProgramScheduleItemCollectionType.Artist)
|
||||
{
|
||||
<MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
|
||||
<div class="d-flex">
|
||||
<MudText>Artist</MudText>
|
||||
</div>
|
||||
<MudSelect T="NamedMediaItemViewModel" @bind-value="_model.MediaItem">
|
||||
@foreach (NamedMediaItemViewModel artist in _artists)
|
||||
{
|
||||
<MudSelect Class="mt-3"
|
||||
T="NamedMediaItemViewModel"
|
||||
Label="Artist"
|
||||
@bind-value="_model.MediaItem">
|
||||
@foreach (NamedMediaItemViewModel artist in _artists)
|
||||
{
|
||||
<MudSelectItem Value="@artist">@artist.Name</MudSelectItem>
|
||||
}
|
||||
</MudSelect>
|
||||
<MudSelectItem Value="@artist">@artist.Name</MudSelectItem>
|
||||
}
|
||||
</MudCardContent>
|
||||
<MudCardActions>
|
||||
<MudButton ButtonType="ButtonType.Submit" Variant="Variant.Filled" Color="Color.Primary" Class="ml-auto">
|
||||
@(IsEdit ? "Save Changes" : "Add Filler Preset")
|
||||
</MudButton>
|
||||
</MudCardActions>
|
||||
</MudCard>
|
||||
</EditForm>
|
||||
}
|
||||
</MudSelect>
|
||||
</MudStack>
|
||||
}
|
||||
</MudContainer>
|
||||
</div>
|
||||
</MudContainer>
|
||||
</MudForm>
|
||||
|
||||
@code {
|
||||
private readonly CancellationTokenSource _cts = new();
|
||||
@@ -145,15 +189,15 @@
|
||||
public int Id { get; set; }
|
||||
|
||||
private readonly FillerPresetEditViewModel _model = new();
|
||||
private EditContext _editContext;
|
||||
private ValidationMessageStore _messageStore;
|
||||
private readonly FillerPresetEditViewModelValidator _validator = new();
|
||||
private MudForm _form;
|
||||
|
||||
private List<MediaCollectionViewModel> _mediaCollections = new();
|
||||
private List<MultiCollectionViewModel> _multiCollections = new();
|
||||
private List<SmartCollectionViewModel> _smartCollections = new();
|
||||
private List<NamedMediaItemViewModel> _televisionShows = new();
|
||||
private List<NamedMediaItemViewModel> _televisionSeasons = new();
|
||||
private List<NamedMediaItemViewModel> _artists = new();
|
||||
private List<MediaCollectionViewModel> _mediaCollections = [];
|
||||
private List<MultiCollectionViewModel> _multiCollections = [];
|
||||
private List<SmartCollectionViewModel> _smartCollections = [];
|
||||
private List<NamedMediaItemViewModel> _televisionShows = [];
|
||||
private List<NamedMediaItemViewModel> _televisionSeasons = [];
|
||||
private List<NamedMediaItemViewModel> _artists = [];
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
@@ -212,23 +256,17 @@
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
_editContext = new EditContext(_model);
|
||||
_messageStore = new ValidationMessageStore(_editContext);
|
||||
}
|
||||
|
||||
private bool IsEdit => Id != 0;
|
||||
|
||||
private async Task HandleSubmitAsync()
|
||||
{
|
||||
_messageStore.Clear();
|
||||
if (_editContext.Validate())
|
||||
await _form.Validate();
|
||||
ValidationResult result = await _validator.ValidateAsync(_model, _cts.Token);
|
||||
if (result.IsValid)
|
||||
{
|
||||
IRequest<Either<BaseError, Unit>> request = IsEdit ? _model.ToEdit() : _model.ToUpdate();
|
||||
|
||||
Seq<BaseError> errorMessage = await Mediator.Send(request, _cts.Token)
|
||||
.Map(result => result.LeftToSeq());
|
||||
Seq<BaseError> errorMessage = (await Mediator.Send(request, _cts.Token)).LeftToSeq();
|
||||
|
||||
errorMessage.HeadOrNone().Match(
|
||||
error =>
|
||||
|
||||
@@ -6,66 +6,70 @@
|
||||
@inject IDialogService Dialog
|
||||
@inject IMediator Mediator
|
||||
|
||||
<MudContainer MaxWidth="MaxWidth.ExtraLarge" Class="pt-8">
|
||||
<div>
|
||||
<MudButton Variant="Variant.Filled" Color="Color.Primary" Href="media/filler/presets/add">
|
||||
<MudForm Style="max-height: 100%">
|
||||
<MudPaper Square="true" Style="display: flex; height: 64px; min-height: 64px; width: 100%; z-index: 100; align-items: center">
|
||||
<MudButton Variant="Variant.Filled" Color="Color.Primary" Class="ml-8" StartIcon="@Icons.Material.Filled.Add" Href="media/filler/presets/add">
|
||||
Add Filler Preset
|
||||
</MudButton>
|
||||
</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">Filler Presets</MudText>
|
||||
<MudDivider Class="mb-6"/>
|
||||
<MudTable Hover="true"
|
||||
@bind-RowsPerPage="@_fillerPresetsRowsPerPage"
|
||||
ServerData="@(new Func<TableState, CancellationToken, Task<TableData<FillerPresetViewModel>>>(ServerReloadFillerPresets))"
|
||||
Dense="true"
|
||||
@ref="_fillerPresetsTable">
|
||||
<ColGroup>
|
||||
<MudHidden Breakpoint="Breakpoint.Xs">
|
||||
<col/>
|
||||
<col/>
|
||||
<col style="width: 120px;"/>
|
||||
</MudHidden>
|
||||
</ColGroup>
|
||||
<HeaderContent>
|
||||
<MudTh>Name</MudTh>
|
||||
<MudTh>Filler Kind</MudTh>
|
||||
<MudTh/>
|
||||
</HeaderContent>
|
||||
<RowTemplate>
|
||||
<MudTd DataLabel="Name">@context.Name</MudTd>
|
||||
<MudTd DataLabel="Filler Kind">
|
||||
@(
|
||||
context.FillerKind switch
|
||||
{
|
||||
FillerKind.PreRoll => "Pre-Roll",
|
||||
FillerKind.MidRoll => "Mid-Roll",
|
||||
FillerKind.PostRoll => "Post-Roll",
|
||||
FillerKind.Fallback => "Fallback",
|
||||
FillerKind.Tail => "Tail",
|
||||
_ => "None"
|
||||
}
|
||||
)
|
||||
</MudTd>
|
||||
<MudTd>
|
||||
<div style="align-items: center; display: flex;">
|
||||
<MudTooltip Text="Edit Filler Preset">
|
||||
<MudIconButton Icon="@Icons.Material.Filled.Edit"
|
||||
Href="@($"media/filler/presets/{context.Id}/edit")">
|
||||
</MudIconButton>
|
||||
</MudTooltip>
|
||||
<MudTooltip Text="Delete Filler Preset">
|
||||
<MudIconButton Icon="@Icons.Material.Filled.Delete"
|
||||
OnClick="@(_ => DeleteFillerPreset(context))">
|
||||
</MudIconButton>
|
||||
</MudTooltip>
|
||||
</div>
|
||||
</MudTd>
|
||||
</RowTemplate>
|
||||
<PagerContent>
|
||||
<MudTablePager/>
|
||||
</PagerContent>
|
||||
</MudTable>
|
||||
</MudContainer>
|
||||
</div>
|
||||
<MudTable Class="mt-4"
|
||||
Hover="true"
|
||||
@bind-RowsPerPage="@_fillerPresetsRowsPerPage"
|
||||
ServerData="@(new Func<TableState, CancellationToken, Task<TableData<FillerPresetViewModel>>>(ServerReloadFillerPresets))"
|
||||
Dense="true"
|
||||
@ref="_fillerPresetsTable">
|
||||
<ToolBarContent>
|
||||
<MudText Typo="Typo.h6">Filler Presets</MudText>
|
||||
</ToolBarContent>
|
||||
<ColGroup>
|
||||
<col/>
|
||||
<col/>
|
||||
<col style="width: 120px;"/>
|
||||
</ColGroup>
|
||||
<HeaderContent>
|
||||
<MudTh>Name</MudTh>
|
||||
<MudTh>Filler Kind</MudTh>
|
||||
<MudTh/>
|
||||
</HeaderContent>
|
||||
<RowTemplate>
|
||||
<MudTd DataLabel="Name">@context.Name</MudTd>
|
||||
<MudTd DataLabel="Filler Kind">
|
||||
@(
|
||||
context.FillerKind switch
|
||||
{
|
||||
FillerKind.PreRoll => "Pre-Roll",
|
||||
FillerKind.MidRoll => "Mid-Roll",
|
||||
FillerKind.PostRoll => "Post-Roll",
|
||||
FillerKind.Fallback => "Fallback",
|
||||
FillerKind.Tail => "Tail",
|
||||
_ => "None"
|
||||
}
|
||||
)
|
||||
</MudTd>
|
||||
<MudTd>
|
||||
<div style="align-items: center; display: flex;">
|
||||
<MudTooltip Text="Edit Filler Preset">
|
||||
<MudIconButton Icon="@Icons.Material.Filled.Edit"
|
||||
Href="@($"media/filler/presets/{context.Id}/edit")">
|
||||
</MudIconButton>
|
||||
</MudTooltip>
|
||||
<MudTooltip Text="Delete Filler Preset">
|
||||
<MudIconButton Icon="@Icons.Material.Filled.Delete"
|
||||
OnClick="@(_ => DeleteFillerPreset(context))">
|
||||
</MudIconButton>
|
||||
</MudTooltip>
|
||||
</div>
|
||||
</MudTd>
|
||||
</RowTemplate>
|
||||
<PagerContent>
|
||||
<MudTablePager/>
|
||||
</PagerContent>
|
||||
</MudTable>
|
||||
</MudContainer>
|
||||
</MudForm>
|
||||
|
||||
@code {
|
||||
private readonly CancellationTokenSource _cts = new();
|
||||
@@ -90,7 +94,7 @@
|
||||
|
||||
IDialogReference dialog = await Dialog.ShowAsync<DeleteDialog>("Delete Filler Preset", parameters, options);
|
||||
DialogResult result = await dialog.Result;
|
||||
if (!result.Canceled)
|
||||
if (result is { Canceled: false })
|
||||
{
|
||||
await Mediator.Send(new DeleteFillerPreset(fillerPreset.Id), _cts.Token);
|
||||
if (_fillerPresetsTable != null)
|
||||
|
||||
@@ -3,89 +3,99 @@
|
||||
@using System.Globalization
|
||||
@using ErsatzTV.Application.Channels
|
||||
@using ErsatzTV.Application.ProgramSchedules
|
||||
@using ErsatzTV.Validators
|
||||
@using FluentValidation.Results
|
||||
@implements IDisposable
|
||||
@inject NavigationManager NavigationManager
|
||||
@inject ILogger<PlayoutEditor> Logger
|
||||
@inject ISnackbar Snackbar
|
||||
@inject IMediator Mediator
|
||||
|
||||
<MudContainer MaxWidth="MaxWidth.ExtraLarge" Class="pt-8">
|
||||
<MudText Typo="Typo.h4" Class="mb-4">
|
||||
@switch (Kind)
|
||||
{
|
||||
case PlayoutKind.ExternalJson:
|
||||
<span>Add External Json Playout</span>
|
||||
break;
|
||||
case PlayoutKind.Yaml:
|
||||
<span>Add YAML Playout</span>
|
||||
break;
|
||||
case PlayoutKind.Block:
|
||||
<span>Add Block Playout</span>
|
||||
break;
|
||||
default:
|
||||
<span>Add Playout</span>
|
||||
break;
|
||||
}
|
||||
</MudText>
|
||||
<div style="max-width: 400px;">
|
||||
<EditForm EditContext="_editContext" OnSubmit="@HandleSubmitAsync">
|
||||
<FluentValidationValidator/>
|
||||
<MudCard>
|
||||
<MudCardContent>
|
||||
<MudSelect T="ChannelViewModel"
|
||||
Label="Channel"
|
||||
@bind-value="_model.Channel"
|
||||
HelperText="Disabled channels already have a playout">
|
||||
@foreach (ChannelViewModel channel in _channels)
|
||||
{
|
||||
<MudSelectItem Disabled="@(channel.PlayoutCount > 0)" Value="@channel">
|
||||
@($"{channel.Number} - {channel.Name}")
|
||||
</MudSelectItem>
|
||||
}
|
||||
</MudSelect>
|
||||
@switch (Kind)
|
||||
<MudForm @ref="_form" Validation="@(_validator.ValidateValue)" ValidationDelay="0" Style="max-height: 100%">
|
||||
<MudPaper Square="true" Style="display: flex; height: 64px; min-height: 64px; width: 100%; z-index: 100; align-items: center">
|
||||
<MudButton Class="ml-8" OnClick="HandleSubmitAsync" Variant="Variant.Filled" Color="Color.Primary" StartIcon="@Icons.Material.Filled.Add">
|
||||
@switch (Kind)
|
||||
{
|
||||
case PlayoutKind.ExternalJson:
|
||||
@:Add External Json Playout
|
||||
break;
|
||||
case PlayoutKind.Yaml:
|
||||
@:Add YAML Playout
|
||||
break;
|
||||
case PlayoutKind.Block:
|
||||
@:Add Block Playout
|
||||
break;
|
||||
default:
|
||||
@:Add Playout
|
||||
break;
|
||||
}
|
||||
</MudButton>
|
||||
</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">Playout</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>Channel</MudText>
|
||||
</div>
|
||||
<MudSelect T="ChannelViewModel" @bind-value="_model.Channel" HelperText="Disabled channels already have a playout">
|
||||
@foreach (ChannelViewModel channel in _channels)
|
||||
{
|
||||
case PlayoutKind.ExternalJson:
|
||||
<MudTextField Label="External Json File" @bind-Value="_model.ExternalJsonFile" For="@(() => _model.ExternalJsonFile)"/>
|
||||
break;
|
||||
case PlayoutKind.Yaml:
|
||||
<MudTextField Label="YAML File" @bind-Value="_model.YamlFile" For="@(() => _model.YamlFile)"/>
|
||||
break;
|
||||
case PlayoutKind.Block:
|
||||
break;
|
||||
default:
|
||||
<MudSelect Class="mt-3"
|
||||
T="ProgramScheduleViewModel"
|
||||
Label="Schedule"
|
||||
@bind-value="_model.ProgramSchedule">
|
||||
@foreach (ProgramScheduleViewModel schedule in _programSchedules)
|
||||
{
|
||||
<MudSelectItem Value="@schedule">@schedule.Name</MudSelectItem>
|
||||
}
|
||||
</MudSelect>
|
||||
break;
|
||||
<MudSelectItem Disabled="@(channel.PlayoutCount > 0)" Value="@channel">
|
||||
@($"{channel.Number} - {channel.Name}")
|
||||
</MudSelectItem>
|
||||
}
|
||||
</MudCardContent>
|
||||
<MudCardActions>
|
||||
<MudButton ButtonType="ButtonType.Submit" Variant="Variant.Filled" Color="Color.Primary">
|
||||
Add Playout
|
||||
</MudButton>
|
||||
</MudCardActions>
|
||||
</MudCard>
|
||||
</EditForm>
|
||||
</MudSelect>
|
||||
</MudStack>
|
||||
@switch (Kind)
|
||||
{
|
||||
case PlayoutKind.ExternalJson:
|
||||
<MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
|
||||
<div class="d-flex">
|
||||
<MudText>External Json File</MudText>
|
||||
</div>
|
||||
<MudTextField @bind-Value="_model.ExternalJsonFile" For="@(() => _model.ExternalJsonFile)"/>
|
||||
</MudStack>
|
||||
break;
|
||||
case PlayoutKind.Yaml:
|
||||
<MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
|
||||
<div class="d-flex">
|
||||
<MudText>YAML File</MudText>
|
||||
</div>
|
||||
<MudTextField @bind-Value="_model.YamlFile" For="@(() => _model.YamlFile)"/>
|
||||
</MudStack>
|
||||
break;
|
||||
case PlayoutKind.Block:
|
||||
break;
|
||||
default:
|
||||
<MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
|
||||
<div class="d-flex">
|
||||
<MudText>Schedule</MudText>
|
||||
</div>
|
||||
<MudSelect T="ProgramScheduleViewModel" @bind-value="_model.ProgramSchedule">
|
||||
@foreach (ProgramScheduleViewModel schedule in _programSchedules)
|
||||
{
|
||||
<MudSelectItem Value="@schedule">@schedule.Name</MudSelectItem>
|
||||
}
|
||||
</MudSelect>
|
||||
</MudStack>
|
||||
break;
|
||||
}
|
||||
</MudContainer>
|
||||
</div>
|
||||
</MudContainer>
|
||||
</MudForm>
|
||||
|
||||
@code {
|
||||
private readonly CancellationTokenSource _cts = new();
|
||||
|
||||
private readonly PlayoutEditViewModel _model = new();
|
||||
private readonly PlayoutEditViewModelValidator _validator = new();
|
||||
private MudForm _form;
|
||||
|
||||
private List<ChannelViewModel> _channels = [];
|
||||
private List<ProgramScheduleViewModel> _programSchedules = [];
|
||||
|
||||
private EditContext _editContext;
|
||||
private ValidationMessageStore _messageStore;
|
||||
|
||||
[Parameter]
|
||||
public string Kind { get; set; }
|
||||
|
||||
@@ -109,16 +119,11 @@
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
_editContext = new EditContext(_model);
|
||||
_messageStore = new ValidationMessageStore(_editContext);
|
||||
}
|
||||
|
||||
private async Task HandleSubmitAsync()
|
||||
{
|
||||
_messageStore.Clear();
|
||||
if (_editContext.Validate())
|
||||
await _form.Validate();
|
||||
ValidationResult result = await _validator.ValidateAsync(_model, _cts.Token);
|
||||
if (result.IsValid)
|
||||
{
|
||||
Seq<BaseError> errorMessage = (await Mediator.Send(_model.ToCreate(), _cts.Token)).LeftToSeq();
|
||||
|
||||
|
||||
+215
-197
@@ -12,208 +12,226 @@
|
||||
@inject IEntityLocker EntityLocker;
|
||||
@inject ICourier Courier;
|
||||
|
||||
<MudContainer MaxWidth="MaxWidth.ExtraLarge" Class="pt-8">
|
||||
<div>
|
||||
<MudButton Variant="Variant.Filled" Color="Color.Primary" Href="playouts/add">
|
||||
Add Playout
|
||||
</MudButton>
|
||||
<MudTooltip Text="This feature is experimental">
|
||||
<MudButton Class="ml-3" Variant="Variant.Filled" Color="Color.Primary" StartIcon="@Icons.Material.Filled.Warning" Href="@($"playouts/add/{PlayoutKind.Block}")">
|
||||
Add Block Playout
|
||||
</MudButton>
|
||||
</MudTooltip>
|
||||
<MudTooltip Text="This feature is experimental">
|
||||
<MudButton Class="ml-3" Variant="Variant.Filled" Color="Color.Primary" StartIcon="@Icons.Material.Filled.Warning" Href="@($"playouts/add/{PlayoutKind.Yaml}")">
|
||||
Add YAML Playout
|
||||
</MudButton>
|
||||
</MudTooltip>
|
||||
<MudTooltip Text="This feature is experimental">
|
||||
<MudButton Class="ml-3" Variant="Variant.Filled" Color="Color.Primary" StartIcon="@Icons.Material.Filled.Warning" Href="@($"playouts/add/{PlayoutKind.ExternalJson}")">
|
||||
Add External Json Playout
|
||||
</MudButton>
|
||||
</MudTooltip>
|
||||
<MudButton Class="ml-3" Variant="Variant.Filled" Color="Color.Warning" StartIcon="@Icons.Material.Filled.Refresh" OnClick="@ResetAllPlayouts">
|
||||
Reset All Playouts
|
||||
</MudButton>
|
||||
</div>
|
||||
<MudTable Hover="true"
|
||||
Dense="true"
|
||||
Class="mt-4"
|
||||
SelectedItemChanged="@(async (PlayoutNameViewModel x) => await PlayoutSelected(x))"
|
||||
@bind-RowsPerPage="@_rowsPerPage"
|
||||
ServerData="@(new Func<TableState, CancellationToken, Task<TableData<PlayoutNameViewModel>>>(ServerReload))"
|
||||
@ref="_table">
|
||||
<ToolBarContent>
|
||||
<MudText Typo="Typo.h6">Playouts</MudText>
|
||||
</ToolBarContent>
|
||||
<ColGroup>
|
||||
<col/>
|
||||
<col/>
|
||||
<col/>
|
||||
<col style="width: 225px;"/>
|
||||
</ColGroup>
|
||||
<HeaderContent>
|
||||
<MudTh>
|
||||
<MudTableSortLabel SortBy="new Func<PlayoutViewModel, object>(x => decimal.Parse(x.Channel.Number, CultureInfo.InvariantCulture))">
|
||||
Channel
|
||||
</MudTableSortLabel>
|
||||
</MudTh>
|
||||
<MudTh>
|
||||
<MudTableSortLabel SortBy="new Func<PlayoutViewModel, object>(x => x.ProgramSchedule.Name)">
|
||||
Default Schedule
|
||||
</MudTableSortLabel>
|
||||
</MudTh>
|
||||
<MudTh>Playout Type</MudTh>
|
||||
<MudTh/>
|
||||
</HeaderContent>
|
||||
<RowTemplate>
|
||||
<MudTd DataLabel="Channel">@context.ChannelNumber - @context.ChannelName</MudTd>
|
||||
<MudTd DataLabel="Schedule">@context.ScheduleName</MudTd>
|
||||
<MudTd DataLabel="Playout Type">
|
||||
@switch (context.PlayoutType)
|
||||
{
|
||||
case ProgramSchedulePlayoutType.Block:
|
||||
<span>Block</span>
|
||||
break;
|
||||
case ProgramSchedulePlayoutType.Yaml:
|
||||
<span>YAML</span>
|
||||
break;
|
||||
case ProgramSchedulePlayoutType.ExternalJson:
|
||||
<span>External Json</span>
|
||||
break;
|
||||
default:
|
||||
<span></span>
|
||||
break;
|
||||
}
|
||||
</MudTd>
|
||||
<MudTd>
|
||||
<div style="align-items: center; display: flex;">
|
||||
<div style="align-items: center; display: flex; height: 48px; justify-content: center; width: 48px;">
|
||||
@if (EntityLocker.IsPlayoutLocked(context.PlayoutId))
|
||||
<MudForm Style="max-height: 100%">
|
||||
<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"></div>
|
||||
<div style="margin-left: auto" class="d-none d-md-flex">
|
||||
<MudButton Variant="Variant.Filled" Color="Color.Primary" StartIcon="@Icons.Material.Filled.Add" Href="playouts/add">
|
||||
Add Playout
|
||||
</MudButton>
|
||||
<MudTooltip Text="This feature is experimental">
|
||||
<MudButton Class="ml-3" Variant="Variant.Filled" Color="Color.Primary" StartIcon="@Icons.Material.Filled.Warning" Href="@($"playouts/add/{PlayoutKind.Block}")">
|
||||
Add Block Playout
|
||||
</MudButton>
|
||||
</MudTooltip>
|
||||
<MudTooltip Text="This feature is experimental">
|
||||
<MudButton Class="ml-3" Variant="Variant.Filled" Color="Color.Primary" StartIcon="@Icons.Material.Filled.Warning" Href="@($"playouts/add/{PlayoutKind.Yaml}")">
|
||||
Add YAML Playout
|
||||
</MudButton>
|
||||
</MudTooltip>
|
||||
<MudTooltip Text="This feature is experimental">
|
||||
<MudButton Class="ml-3" Variant="Variant.Filled" Color="Color.Primary" StartIcon="@Icons.Material.Filled.Warning" Href="@($"playouts/add/{PlayoutKind.ExternalJson}")">
|
||||
Add External Json Playout
|
||||
</MudButton>
|
||||
</MudTooltip>
|
||||
<MudButton Class="ml-3" Variant="Variant.Filled" Color="Color.Warning" StartIcon="@Icons.Material.Filled.Refresh" OnClick="@ResetAllPlayouts">
|
||||
Reset All Playouts
|
||||
</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.Add" Label="Add Playout" Href="playouts/add"/>
|
||||
<MudMenuItem Icon="@Icons.Material.Filled.Warning" Label="Add Block Playout" Href="@($"playouts/add/{PlayoutKind.Block}")"/>
|
||||
<MudMenuItem Icon="@Icons.Material.Filled.Warning" Label="Add YAML Playout" Href="@($"playouts/add/{PlayoutKind.Yaml}")"/>
|
||||
<MudMenuItem Icon="@Icons.Material.Filled.Warning" Label="Add External Json Playout" Href="@($"playouts/add/{PlayoutKind.ExternalJson}")"/>
|
||||
<MudMenuItem Icon="@Icons.Material.Filled.Refresh" Label="Reset All Playouts" OnClick="ResetAllPlayouts"/>
|
||||
</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">Playouts</MudText>
|
||||
<MudDivider Class="mb-6"/>
|
||||
<MudTable Hover="true"
|
||||
Dense="true"
|
||||
SelectedItemChanged="@(async (PlayoutNameViewModel x) => await PlayoutSelected(x))"
|
||||
@bind-RowsPerPage="@_rowsPerPage"
|
||||
ServerData="@(new Func<TableState, CancellationToken, Task<TableData<PlayoutNameViewModel>>>(ServerReload))"
|
||||
@ref="_table">
|
||||
<ColGroup>
|
||||
<MudHidden Breakpoint="Breakpoint.Xs">
|
||||
<col/>
|
||||
<col/>
|
||||
<col/>
|
||||
<col style="width: 225px;"/>
|
||||
</MudHidden>
|
||||
</ColGroup>
|
||||
<HeaderContent>
|
||||
<MudTh>
|
||||
<MudTableSortLabel SortBy="new Func<PlayoutViewModel, object>(x => decimal.Parse(x.Channel.Number, CultureInfo.InvariantCulture))">
|
||||
Channel
|
||||
</MudTableSortLabel>
|
||||
</MudTh>
|
||||
<MudTh Class="d-none d-md-table-cell">
|
||||
<MudTableSortLabel SortBy="new Func<PlayoutViewModel, object>(x => x.ProgramSchedule.Name)">
|
||||
Default Schedule
|
||||
</MudTableSortLabel>
|
||||
</MudTh>
|
||||
<MudTh Class="d-none d-md-table-cell">Playout Type</MudTh>
|
||||
<MudTh/>
|
||||
</HeaderContent>
|
||||
<RowTemplate>
|
||||
<MudTd>@context.ChannelNumber - @context.ChannelName</MudTd>
|
||||
<MudTd Class="d-none d-md-table-cell">@context.ScheduleName</MudTd>
|
||||
<MudTd Class="d-none d-md-table-cell">
|
||||
@switch (context.PlayoutType)
|
||||
{
|
||||
<MudProgressCircular Color="Color.Primary" Size="Size.Small" Indeterminate="true"/>
|
||||
case ProgramSchedulePlayoutType.Block:
|
||||
<span>Block</span>
|
||||
break;
|
||||
case ProgramSchedulePlayoutType.Yaml:
|
||||
<span>YAML</span>
|
||||
break;
|
||||
case ProgramSchedulePlayoutType.ExternalJson:
|
||||
<span>External Json</span>
|
||||
break;
|
||||
default:
|
||||
<span></span>
|
||||
break;
|
||||
}
|
||||
</div>
|
||||
@if (context.PlayoutType == ProgramSchedulePlayoutType.Flood)
|
||||
{
|
||||
if (context.ProgressMode is ChannelProgressMode.OnDemand)
|
||||
{
|
||||
<MudTooltip Text="Alternate Schedules are not supported with On Demand progress">
|
||||
<MudIconButton Icon="@Icons.Material.Filled.EditCalendar"
|
||||
Disabled="true">
|
||||
</MudIconButton>
|
||||
</MudTooltip>
|
||||
}
|
||||
else
|
||||
{
|
||||
<MudTooltip Text="Edit Alternate Schedules">
|
||||
<MudIconButton Icon="@Icons.Material.Filled.EditCalendar"
|
||||
</MudTd>
|
||||
<MudTd>
|
||||
<div style="align-items: center; display: flex;">
|
||||
<div style="align-items: center; display: flex; height: 48px; justify-content: center; width: 48px;">
|
||||
@if (EntityLocker.IsPlayoutLocked(context.PlayoutId))
|
||||
{
|
||||
<MudProgressCircular Color="Color.Primary" Size="Size.Small" Indeterminate="true"/>
|
||||
}
|
||||
</div>
|
||||
@if (context.PlayoutType == ProgramSchedulePlayoutType.Flood)
|
||||
{
|
||||
if (context.ProgressMode is ChannelProgressMode.OnDemand)
|
||||
{
|
||||
<MudTooltip Text="Alternate Schedules are not supported with On Demand progress">
|
||||
<MudIconButton Icon="@Icons.Material.Filled.EditCalendar"
|
||||
Disabled="true">
|
||||
</MudIconButton>
|
||||
</MudTooltip>
|
||||
}
|
||||
else
|
||||
{
|
||||
<MudTooltip Text="Edit Alternate Schedules">
|
||||
<MudIconButton Icon="@Icons.Material.Filled.EditCalendar"
|
||||
Disabled="@EntityLocker.IsPlayoutLocked(context.PlayoutId)"
|
||||
Href="@($"playouts/{context.PlayoutId}/alternate-schedules")">
|
||||
</MudIconButton>
|
||||
</MudTooltip>
|
||||
}
|
||||
|
||||
<MudTooltip Text="Reset Playout">
|
||||
<MudIconButton Icon="@Icons.Material.Filled.Refresh"
|
||||
Disabled="@EntityLocker.IsPlayoutLocked(context.PlayoutId)"
|
||||
OnClick="@(_ => ResetPlayout(context))">
|
||||
</MudIconButton>
|
||||
</MudTooltip>
|
||||
<MudTooltip Text="Schedule Reset">
|
||||
<MudIconButton Icon="@Icons.Material.Filled.Update"
|
||||
Disabled="@EntityLocker.IsPlayoutLocked(context.PlayoutId)"
|
||||
OnClick="@(_ => ScheduleReset(context))">
|
||||
</MudIconButton>
|
||||
</MudTooltip>
|
||||
}
|
||||
else if (context.PlayoutType == ProgramSchedulePlayoutType.ExternalJson)
|
||||
{
|
||||
<MudTooltip Text="Edit External Json File">
|
||||
<MudIconButton Icon="@Icons.Material.Filled.Edit"
|
||||
Disabled="@EntityLocker.IsPlayoutLocked(context.PlayoutId)"
|
||||
OnClick="@(_ => EditExternalJsonFile(context))">
|
||||
</MudIconButton>
|
||||
</MudTooltip>
|
||||
<div style="width: 48px"></div>
|
||||
<div style="width: 48px"></div>
|
||||
}
|
||||
else if (context.PlayoutType == ProgramSchedulePlayoutType.Yaml)
|
||||
{
|
||||
<MudTooltip Text="Edit Playout">
|
||||
<MudIconButton Icon="@Icons.Material.Filled.Edit"
|
||||
Disabled="@EntityLocker.IsPlayoutLocked(context.PlayoutId)"
|
||||
Href="@($"playouts/yaml/{context.PlayoutId}")">
|
||||
</MudIconButton>
|
||||
</MudTooltip>
|
||||
<MudTooltip Text="Reset Playout">
|
||||
<MudIconButton Icon="@Icons.Material.Filled.Refresh"
|
||||
Disabled="@EntityLocker.IsPlayoutLocked(context.PlayoutId)"
|
||||
OnClick="@(_ => ResetPlayout(context))">
|
||||
</MudIconButton>
|
||||
</MudTooltip>
|
||||
<div style="width: 48px"></div>
|
||||
}
|
||||
else if (context.PlayoutType == ProgramSchedulePlayoutType.Block)
|
||||
{
|
||||
<MudTooltip Text="Edit Playout">
|
||||
<MudIconButton Icon="@Icons.Material.Filled.Edit"
|
||||
Disabled="@EntityLocker.IsPlayoutLocked(context.PlayoutId)"
|
||||
Href="@($"playouts/block/{context.PlayoutId}")">
|
||||
</MudIconButton>
|
||||
</MudTooltip>
|
||||
<MudTooltip Text="Reset Playout">
|
||||
<MudIconButton Icon="@Icons.Material.Filled.Refresh"
|
||||
Disabled="@EntityLocker.IsPlayoutLocked(context.PlayoutId)"
|
||||
OnClick="@(_ => ResetPlayout(context))">
|
||||
</MudIconButton>
|
||||
</MudTooltip>
|
||||
<div style="width: 48px"></div>
|
||||
}
|
||||
<MudTooltip Text="Delete Playout">
|
||||
<MudIconButton Icon="@Icons.Material.Filled.Delete"
|
||||
Disabled="@EntityLocker.IsPlayoutLocked(context.PlayoutId)"
|
||||
Href="@($"playouts/{context.PlayoutId}/alternate-schedules")">
|
||||
OnClick="@(_ => DeletePlayout(context))">
|
||||
</MudIconButton>
|
||||
</MudTooltip>
|
||||
}
|
||||
|
||||
<MudTooltip Text="Reset Playout">
|
||||
<MudIconButton Icon="@Icons.Material.Filled.Refresh"
|
||||
Disabled="@EntityLocker.IsPlayoutLocked(context.PlayoutId)"
|
||||
OnClick="@(_ => ResetPlayout(context))">
|
||||
</MudIconButton>
|
||||
</MudTooltip>
|
||||
<MudTooltip Text="Schedule Reset">
|
||||
<MudIconButton Icon="@Icons.Material.Filled.Update"
|
||||
Disabled="@EntityLocker.IsPlayoutLocked(context.PlayoutId)"
|
||||
OnClick="@(_ => ScheduleReset(context))">
|
||||
</MudIconButton>
|
||||
</MudTooltip>
|
||||
}
|
||||
else if (context.PlayoutType == ProgramSchedulePlayoutType.ExternalJson)
|
||||
{
|
||||
<MudTooltip Text="Edit External Json File">
|
||||
<MudIconButton Icon="@Icons.Material.Filled.Edit"
|
||||
Disabled="@EntityLocker.IsPlayoutLocked(context.PlayoutId)"
|
||||
OnClick="@(_ => EditExternalJsonFile(context))">
|
||||
</MudIconButton>
|
||||
</MudTooltip>
|
||||
<div style="width: 48px"></div>
|
||||
<div style="width: 48px"></div>
|
||||
}
|
||||
else if (context.PlayoutType == ProgramSchedulePlayoutType.Yaml)
|
||||
{
|
||||
<MudTooltip Text="Edit Playout">
|
||||
<MudIconButton Icon="@Icons.Material.Filled.Edit"
|
||||
Disabled="@EntityLocker.IsPlayoutLocked(context.PlayoutId)"
|
||||
Href="@($"playouts/yaml/{context.PlayoutId}")">
|
||||
</MudIconButton>
|
||||
</MudTooltip>
|
||||
<MudTooltip Text="Reset Playout">
|
||||
<MudIconButton Icon="@Icons.Material.Filled.Refresh"
|
||||
Disabled="@EntityLocker.IsPlayoutLocked(context.PlayoutId)"
|
||||
OnClick="@(_ => ResetPlayout(context))">
|
||||
</MudIconButton>
|
||||
</MudTooltip>
|
||||
<div style="width: 48px"></div>
|
||||
}
|
||||
else if (context.PlayoutType == ProgramSchedulePlayoutType.Block)
|
||||
{
|
||||
<MudTooltip Text="Edit Playout">
|
||||
<MudIconButton Icon="@Icons.Material.Filled.Edit"
|
||||
Disabled="@EntityLocker.IsPlayoutLocked(context.PlayoutId)"
|
||||
Href="@($"playouts/block/{context.PlayoutId}")">
|
||||
</MudIconButton>
|
||||
</MudTooltip>
|
||||
<MudTooltip Text="Reset Playout">
|
||||
<MudIconButton Icon="@Icons.Material.Filled.Refresh"
|
||||
Disabled="@EntityLocker.IsPlayoutLocked(context.PlayoutId)"
|
||||
OnClick="@(_ => ResetPlayout(context))">
|
||||
</MudIconButton>
|
||||
</MudTooltip>
|
||||
<div style="width: 48px"></div>
|
||||
}
|
||||
<MudTooltip Text="Delete Playout">
|
||||
<MudIconButton Icon="@Icons.Material.Filled.Delete"
|
||||
Disabled="@EntityLocker.IsPlayoutLocked(context.PlayoutId)"
|
||||
OnClick="@(_ => DeletePlayout(context))">
|
||||
</MudIconButton>
|
||||
</MudTooltip>
|
||||
</div>
|
||||
</MudTd>
|
||||
</RowTemplate>
|
||||
<PagerContent>
|
||||
<MudTablePager/>
|
||||
</PagerContent>
|
||||
</MudTable>
|
||||
|
||||
@if (_selectedPlayoutId != null)
|
||||
{
|
||||
<MudTable Class="mt-8"
|
||||
Hover="true"
|
||||
Dense="true"
|
||||
@bind-RowsPerPage="@_detailRowsPerPage"
|
||||
ServerData="@(new Func<TableState, CancellationToken, Task<TableData<PlayoutItemViewModel>>>(DetailServerReload))"
|
||||
@ref="_detailTable">
|
||||
<ToolBarContent>
|
||||
<MudText Typo="Typo.h6">Playout Detail</MudText>
|
||||
<MudSwitch T="bool" Class="ml-6" @bind-Value="@ShowFiller" Color="Color.Secondary" Label="Show Filler"/>
|
||||
</ToolBarContent>
|
||||
<HeaderContent>
|
||||
<MudTh>Start</MudTh>
|
||||
<MudTh>Finish</MudTh>
|
||||
<MudTh>Media Item</MudTh>
|
||||
<MudTh>Duration</MudTh>
|
||||
</HeaderContent>
|
||||
<RowTemplate>
|
||||
<MudTd DataLabel="Start">@context.Start.ToString("G", _dtf)</MudTd>
|
||||
<MudTd DataLabel="Finish">@context.Finish.ToString("G", _dtf)</MudTd>
|
||||
<MudTd DataLabel="Media Item">@context.Title</MudTd>
|
||||
<MudTd DataLabel="Duration">@context.Duration</MudTd>
|
||||
</RowTemplate>
|
||||
<PagerContent>
|
||||
<MudTablePager/>
|
||||
</PagerContent>
|
||||
</MudTable>
|
||||
}
|
||||
</MudContainer>
|
||||
</div>
|
||||
</MudTd>
|
||||
</RowTemplate>
|
||||
<PagerContent>
|
||||
<MudTablePager/>
|
||||
</PagerContent>
|
||||
</MudTable>
|
||||
@if (_selectedPlayoutId != null)
|
||||
{
|
||||
<MudText Typo="Typo.h5" Class="mt-6 mb-2">Playout Detail</MudText>
|
||||
<MudDivider Class="mb-6"/>
|
||||
<MudTable Hover="true"
|
||||
Dense="true"
|
||||
@bind-RowsPerPage="@_detailRowsPerPage"
|
||||
ServerData="@(new Func<TableState, CancellationToken, Task<TableData<PlayoutItemViewModel>>>(DetailServerReload))"
|
||||
@ref="_detailTable">
|
||||
<ToolBarContent>
|
||||
<MudSwitch T="bool" Class="ml-6" @bind-Value="@ShowFiller" Color="Color.Secondary" Label="Show Filler"/>
|
||||
</ToolBarContent>
|
||||
<HeaderContent>
|
||||
<MudTh>Start</MudTh>
|
||||
<MudTh>Finish</MudTh>
|
||||
<MudTh>Media Item</MudTh>
|
||||
<MudTh>Duration</MudTh>
|
||||
</HeaderContent>
|
||||
<RowTemplate>
|
||||
<MudTd DataLabel="Start">@context.Start.ToString("G", _dtf)</MudTd>
|
||||
<MudTd DataLabel="Finish">@context.Finish.ToString("G", _dtf)</MudTd>
|
||||
<MudTd DataLabel="Media Item">@context.Title</MudTd>
|
||||
<MudTd DataLabel="Duration">@context.Duration</MudTd>
|
||||
</RowTemplate>
|
||||
<PagerContent>
|
||||
<MudTablePager/>
|
||||
</PagerContent>
|
||||
</MudTable>
|
||||
}
|
||||
</MudContainer>
|
||||
</div>
|
||||
</MudForm>
|
||||
|
||||
@code {
|
||||
private readonly CancellationTokenSource _cts = new();
|
||||
|
||||
@@ -7,91 +7,100 @@
|
||||
@inject IMediator Mediator
|
||||
@inject NavigationManager NavigationManager
|
||||
|
||||
<MudContainer MaxWidth="MaxWidth.ExtraLarge" Class="pt-8">
|
||||
<MudTable Hover="true"
|
||||
Dense="true"
|
||||
SelectedItemChanged="@(async (ProgramScheduleViewModel x) => await ScheduleSelected(x))"
|
||||
@bind-RowsPerPage="@_rowsPerPage"
|
||||
ServerData="@(new Func<TableState, CancellationToken, Task<TableData<ProgramScheduleViewModel>>>(ServerReload))"
|
||||
@ref="_table">
|
||||
<ToolBarContent>
|
||||
<MudText Typo="Typo.h6">Schedules</MudText>
|
||||
</ToolBarContent>
|
||||
<ColGroup>
|
||||
<col/>
|
||||
<col style="width: 240px;"/>
|
||||
</ColGroup>
|
||||
<HeaderContent>
|
||||
<MudTh>
|
||||
<MudTableSortLabel SortBy="new Func<ProgramScheduleViewModel, object>(x => x.Name)">
|
||||
Name
|
||||
</MudTableSortLabel>
|
||||
</MudTh>
|
||||
<MudTh/>
|
||||
</HeaderContent>
|
||||
<RowTemplate>
|
||||
<MudTd DataLabel="Name">@context.Name</MudTd>
|
||||
<MudTd>
|
||||
<div style="align-items: center; display: flex;">
|
||||
<MudTooltip Text="Edit Properties">
|
||||
<MudIconButton Icon="@Icons.Material.Filled.Edit"
|
||||
Href="@($"schedules/{context.Id}")">
|
||||
</MudIconButton>
|
||||
</MudTooltip>
|
||||
<MudTooltip Text="Edit Schedule Items">
|
||||
<MudIconButton Icon="@Icons.Material.Filled.FormatListNumbered"
|
||||
Href="@($"schedules/{context.Id}/items")">
|
||||
</MudIconButton>
|
||||
</MudTooltip>
|
||||
<MudTooltip Text="Copy Schedule">
|
||||
<MudIconButton Icon="@Icons.Material.Filled.ContentCopy"
|
||||
OnClick="@(_ => CopySchedule(context))">
|
||||
</MudIconButton>
|
||||
</MudTooltip>
|
||||
<MudTooltip Text="Delete Schedule">
|
||||
<MudIconButton Icon="@Icons.Material.Filled.Delete"
|
||||
OnClick="@(_ => DeleteSchedule(context))">
|
||||
</MudIconButton>
|
||||
</MudTooltip>
|
||||
</div>
|
||||
</MudTd>
|
||||
</RowTemplate>
|
||||
<PagerContent>
|
||||
<MudTablePager/>
|
||||
</PagerContent>
|
||||
</MudTable>
|
||||
<MudButton Variant="Variant.Filled" Color="Color.Primary" Href="schedules/add" Class="mt-4">
|
||||
Add Schedule
|
||||
</MudButton>
|
||||
|
||||
@if (_selectedSchedule != null)
|
||||
{
|
||||
<MudTable Hover="true"
|
||||
Class="mt-8"
|
||||
@bind-RowsPerPage="@_detailRowsPerPage"
|
||||
ServerData="@(new Func<TableState, CancellationToken, Task<TableData<ProgramScheduleItemViewModel>>>(DetailServerReload))"
|
||||
@ref="_detailTable">
|
||||
<ToolBarContent>
|
||||
<MudText Typo="Typo.h6">@_selectedSchedule.Name Items</MudText>
|
||||
</ToolBarContent>
|
||||
<HeaderContent>
|
||||
<MudTh>Start Time</MudTh>
|
||||
<MudTh>Collection</MudTh>
|
||||
<MudTh>Playout Mode</MudTh>
|
||||
</HeaderContent>
|
||||
<RowTemplate>
|
||||
<MudTd DataLabel="Start Time">
|
||||
@(context.StartType == StartType.Fixed ? context.StartTime == null ? string.Empty : DateTime.Today.Add(context.StartTime.Value).ToShortTimeString() : "Dynamic")
|
||||
</MudTd>
|
||||
<MudTd DataLabel="Collection">@context.Name</MudTd>
|
||||
<MudTd DataLabel="Playout Mode">@context.PlayoutMode</MudTd>
|
||||
</RowTemplate>
|
||||
<PagerContent>
|
||||
<MudTablePager/>
|
||||
</PagerContent>
|
||||
</MudTable>
|
||||
}
|
||||
</MudContainer>
|
||||
<MudForm Style="max-height: 100%">
|
||||
<MudPaper Square="true" Style="display: flex; height: 64px; min-height: 64px; width: 100%; z-index: 100; align-items: center">
|
||||
<MudButton Variant="Variant.Filled" Color="Color.Primary" Class="ml-8" StartIcon="@Icons.Material.Filled.Add" Href="schedules/add">
|
||||
Add Schedule
|
||||
</MudButton>
|
||||
</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">Schedules</MudText>
|
||||
<MudDivider Class="mb-6"/>
|
||||
<MudTable Hover="true"
|
||||
Dense="true"
|
||||
Breakpoint="Breakpoint.None"
|
||||
SelectedItemChanged="@(async (ProgramScheduleViewModel x) => await ScheduleSelected(x))"
|
||||
@bind-RowsPerPage="@_rowsPerPage"
|
||||
ServerData="@(new Func<TableState, CancellationToken, Task<TableData<ProgramScheduleViewModel>>>(ServerReload))"
|
||||
@ref="_table">
|
||||
<ColGroup>
|
||||
<MudHidden Breakpoint="Breakpoint.Xs">
|
||||
<col/>
|
||||
<col style="width: 240px;"/>
|
||||
</MudHidden>
|
||||
</ColGroup>
|
||||
<HeaderContent>
|
||||
<MudTh>
|
||||
<MudTableSortLabel SortBy="new Func<ProgramScheduleViewModel, object>(x => x.Name)">
|
||||
Name
|
||||
</MudTableSortLabel>
|
||||
</MudTh>
|
||||
<MudTh/>
|
||||
</HeaderContent>
|
||||
<RowTemplate>
|
||||
<MudTd>@context.Name</MudTd>
|
||||
<MudTd>
|
||||
<div style="align-items: center; display: flex;">
|
||||
<MudTooltip Text="Edit Properties">
|
||||
<MudIconButton Icon="@Icons.Material.Filled.Edit"
|
||||
Href="@($"schedules/{context.Id}")">
|
||||
</MudIconButton>
|
||||
</MudTooltip>
|
||||
<MudTooltip Text="Edit Schedule Items">
|
||||
<MudIconButton Icon="@Icons.Material.Filled.FormatListNumbered"
|
||||
Href="@($"schedules/{context.Id}/items")">
|
||||
</MudIconButton>
|
||||
</MudTooltip>
|
||||
<MudTooltip Text="Copy Schedule">
|
||||
<MudIconButton Icon="@Icons.Material.Filled.ContentCopy"
|
||||
OnClick="@(_ => CopySchedule(context))">
|
||||
</MudIconButton>
|
||||
</MudTooltip>
|
||||
<MudTooltip Text="Delete Schedule">
|
||||
<MudIconButton Icon="@Icons.Material.Filled.Delete"
|
||||
OnClick="@(_ => DeleteSchedule(context))">
|
||||
</MudIconButton>
|
||||
</MudTooltip>
|
||||
</div>
|
||||
</MudTd>
|
||||
</RowTemplate>
|
||||
<PagerContent>
|
||||
<MudTablePager/>
|
||||
</PagerContent>
|
||||
</MudTable>
|
||||
@if (_selectedSchedule != null)
|
||||
{
|
||||
<MudHidden Breakpoint="Breakpoint.SmAndDown">
|
||||
<MudTable Hover="true"
|
||||
Class="mt-8"
|
||||
@bind-RowsPerPage="@_detailRowsPerPage"
|
||||
ServerData="@(new Func<TableState, CancellationToken, Task<TableData<ProgramScheduleItemViewModel>>>(DetailServerReload))"
|
||||
@ref="_detailTable">
|
||||
<ToolBarContent>
|
||||
<MudText Typo="Typo.h6">@_selectedSchedule.Name Items</MudText>
|
||||
</ToolBarContent>
|
||||
<HeaderContent>
|
||||
<MudTh>Start Time</MudTh>
|
||||
<MudTh>Collection</MudTh>
|
||||
<MudTh>Playout Mode</MudTh>
|
||||
</HeaderContent>
|
||||
<RowTemplate>
|
||||
<MudTd DataLabel="Start Time">
|
||||
@(context.StartType == StartType.Fixed ? context.StartTime == null ? string.Empty : DateTime.Today.Add(context.StartTime.Value).ToShortTimeString() : "Dynamic")
|
||||
</MudTd>
|
||||
<MudTd DataLabel="Collection">@context.Name</MudTd>
|
||||
<MudTd DataLabel="Playout Mode">@context.PlayoutMode</MudTd>
|
||||
</RowTemplate>
|
||||
<PagerContent>
|
||||
<MudTablePager/>
|
||||
</PagerContent>
|
||||
</MudTable>
|
||||
</MudHidden>
|
||||
}
|
||||
</MudContainer>
|
||||
</div>
|
||||
</MudForm>
|
||||
|
||||
@code {
|
||||
private readonly CancellationTokenSource _cts = new();
|
||||
@@ -132,7 +141,7 @@
|
||||
|
||||
IDialogReference dialog = await Dialog.ShowAsync<DeleteDialog>("Delete Schedule", parameters, options);
|
||||
DialogResult result = await dialog.Result;
|
||||
if (!result.Canceled)
|
||||
if (result is { Canceled: false })
|
||||
{
|
||||
await Mediator.Send(new DeleteProgramSchedule(programSchedule.Id), _cts.Token);
|
||||
if (_table != null)
|
||||
@@ -154,7 +163,7 @@
|
||||
|
||||
IDialogReference dialog = await Dialog.ShowAsync<CopyScheduleDialog>("Copy Schedule", parameters, options);
|
||||
DialogResult dialogResult = await dialog.Result;
|
||||
if (!dialogResult.Canceled && dialogResult.Data is ProgramScheduleViewModel data)
|
||||
if (dialogResult is { Canceled: false, Data: ProgramScheduleViewModel data })
|
||||
{
|
||||
NavigationManager.NavigateTo($"schedules/{data.Id}/items");
|
||||
}
|
||||
|
||||
@@ -7,68 +7,74 @@
|
||||
@inject IEntityLocker Locker
|
||||
@inject ChannelWriter<IBackgroundServiceRequest> WorkerChannel
|
||||
|
||||
<MudContainer MaxWidth="MaxWidth.ExtraLarge" Class="pt-8">
|
||||
<div>
|
||||
<MudButton Variant="Variant.Filled"
|
||||
<MudForm Style="max-height: 100%">
|
||||
<MudPaper Square="true" Style="display: flex; height: 64px; min-height: 64px; width: 100%; z-index: 100; align-items: center">
|
||||
<MudButton Class="ml-8"
|
||||
StartIcon="@Icons.Material.Filled.Add"
|
||||
Variant="Variant.Filled"
|
||||
Color="Color.Primary"
|
||||
Disabled="@Locker.IsTraktLocked()"
|
||||
OnClick="@(_ => AddTraktList())">
|
||||
Add Trakt List
|
||||
</MudButton>
|
||||
</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">Trakt Lists</MudText>
|
||||
<MudDivider Class="mb-6"/>
|
||||
<MudTable Hover="true"
|
||||
@bind-RowsPerPage="@_traktListsRowsPerPage"
|
||||
ServerData="@(new Func<TableState, CancellationToken, Task<TableData<TraktListViewModel>>>(ServerReloadTraktLists))"
|
||||
Dense="true"
|
||||
@ref="_traktListsTable">
|
||||
<ColGroup>
|
||||
<MudHidden Breakpoint="Breakpoint.Xs">
|
||||
<col/>
|
||||
<col/>
|
||||
<col/>
|
||||
<col style="width: 180px;"/>
|
||||
</MudHidden>
|
||||
</ColGroup>
|
||||
<HeaderContent>
|
||||
<MudTh>Id</MudTh>
|
||||
<MudTh>Name</MudTh>
|
||||
<MudTh>Match Status</MudTh>
|
||||
<MudTh/>
|
||||
</HeaderContent>
|
||||
<RowTemplate>
|
||||
<MudTd>@context.Slug</MudTd>
|
||||
<MudTd>@context.Name</MudTd>
|
||||
<MudTd>@context.MatchCount of @context.ItemCount</MudTd>
|
||||
<MudTd>
|
||||
<div style="align-items: center; display: flex;">
|
||||
<MudTooltip Text="Search Trakt List">
|
||||
<MudIconButton Icon="@Icons.Material.Filled.Search"
|
||||
Disabled="@Locker.IsTraktLocked()"
|
||||
Href="@($"search?query=trakt_list%3a{context.TraktId}")">
|
||||
</MudIconButton>
|
||||
</MudTooltip>
|
||||
<MudTooltip Text="Match Trakt List Items">
|
||||
<MudIconButton Icon="@Icons.Material.Filled.Refresh"
|
||||
Disabled="@Locker.IsTraktLocked()"
|
||||
OnClick="@(_ => MatchListItems(context))">
|
||||
</MudIconButton>
|
||||
</MudTooltip>
|
||||
<MudTooltip Text="Delete Trakt List">
|
||||
<MudIconButton Icon="@Icons.Material.Filled.Delete"
|
||||
Disabled="@Locker.IsTraktLocked()"
|
||||
OnClick="@(_ => DeleteTraktList(context))">
|
||||
</MudIconButton>
|
||||
</MudTooltip>
|
||||
</div>
|
||||
</MudTd>
|
||||
</RowTemplate>
|
||||
<PagerContent>
|
||||
<MudTablePager/>
|
||||
</PagerContent>
|
||||
</MudTable>
|
||||
</MudContainer>
|
||||
</div>
|
||||
<MudTable Class="mt-4"
|
||||
Hover="true"
|
||||
@bind-RowsPerPage="@_traktListsRowsPerPage"
|
||||
ServerData="@(new Func<TableState, CancellationToken, Task<TableData<TraktListViewModel>>>(ServerReloadTraktLists))"
|
||||
Dense="true"
|
||||
@ref="_traktListsTable">
|
||||
<ToolBarContent>
|
||||
<MudText Typo="Typo.h6">Trakt Lists</MudText>
|
||||
</ToolBarContent>
|
||||
<ColGroup>
|
||||
<col/>
|
||||
<col/>
|
||||
<col/>
|
||||
<col style="width: 180px;"/>
|
||||
</ColGroup>
|
||||
<HeaderContent>
|
||||
<MudTh>Id</MudTh>
|
||||
<MudTh>Name</MudTh>
|
||||
<MudTh>Match Status</MudTh>
|
||||
<MudTh/>
|
||||
</HeaderContent>
|
||||
<RowTemplate>
|
||||
<MudTd DataLabel="Id">@context.Slug</MudTd>
|
||||
<MudTd DataLabel="Name">@context.Name</MudTd>
|
||||
<MudTd DataLabel="Match Status">@context.MatchCount of @context.ItemCount</MudTd>
|
||||
<MudTd>
|
||||
<div style="align-items: center; display: flex;">
|
||||
<MudTooltip Text="Search Trakt List">
|
||||
<MudIconButton Icon="@Icons.Material.Filled.Search"
|
||||
Disabled="@Locker.IsTraktLocked()"
|
||||
Href="@($"search?query=trakt_list%3a{context.TraktId}")">
|
||||
</MudIconButton>
|
||||
</MudTooltip>
|
||||
<MudTooltip Text="Match Trakt List Items">
|
||||
<MudIconButton Icon="@Icons.Material.Filled.Refresh"
|
||||
Disabled="@Locker.IsTraktLocked()"
|
||||
OnClick="@(_ => MatchListItems(context))">
|
||||
</MudIconButton>
|
||||
</MudTooltip>
|
||||
<MudTooltip Text="Delete Trakt List">
|
||||
<MudIconButton Icon="@Icons.Material.Filled.Delete"
|
||||
Disabled="@Locker.IsTraktLocked()"
|
||||
OnClick="@(_ => DeleteTraktList(context))">
|
||||
</MudIconButton>
|
||||
</MudTooltip>
|
||||
</div>
|
||||
</MudTd>
|
||||
</RowTemplate>
|
||||
<PagerContent>
|
||||
<MudTablePager/>
|
||||
</PagerContent>
|
||||
</MudTable>
|
||||
</MudContainer>
|
||||
</MudForm>
|
||||
|
||||
@code {
|
||||
private readonly CancellationTokenSource _cts = new();
|
||||
@@ -115,7 +121,7 @@
|
||||
|
||||
IDialogReference dialog = await Dialog.ShowAsync<DeleteDialog>("Delete Trakt List", parameters, options);
|
||||
DialogResult result = await dialog.Result;
|
||||
if (!result.Canceled)
|
||||
if (result is { Canceled: false })
|
||||
{
|
||||
await WorkerChannel.WriteAsync(new DeleteTraktList(traktList.Id), _cts.Token);
|
||||
}
|
||||
|
||||
@@ -623,7 +623,7 @@
|
||||
|
||||
IDialogReference dialog = await Dialog.ShowAsync<DeleteFromDatabaseDialog>("Delete From Database", parameters, options);
|
||||
DialogResult result = await dialog.Result;
|
||||
if (!result.Canceled)
|
||||
if (result is { Canceled: false })
|
||||
{
|
||||
var request = new DeleteItemsFromDatabase(
|
||||
movieIds.Append(showIds)
|
||||
|
||||
@@ -9,53 +9,25 @@
|
||||
@inject IMediator Mediator
|
||||
@inject IEntityLocker EntityLocker;
|
||||
|
||||
<MudContainer MaxWidth="MaxWidth.ExtraLarge" Class="pt-8">
|
||||
<MudText Typo="Typo.h4" Class="mb-4">Edit YAML Playout - @_channelName</MudText>
|
||||
<MudGrid>
|
||||
<MudItem xs="4">
|
||||
<div style="max-width: 400px;" class="mr-4">
|
||||
<MudCard>
|
||||
<MudCardHeader>
|
||||
<CardHeaderContent>
|
||||
<MudText Typo="Typo.h5">YAML File</MudText>
|
||||
</CardHeaderContent>
|
||||
</MudCardHeader>
|
||||
<MudCardContent>
|
||||
<MudButton Disabled="@EntityLocker.IsPlayoutLocked(Id)" Variant="Variant.Filled" Color="Color.Primary" OnClick="@(_ => EditYamlFile())" Class="mt-4">
|
||||
Edit YAML File
|
||||
</MudButton>
|
||||
</MudCardContent>
|
||||
</MudCard>
|
||||
</div>
|
||||
</MudItem>
|
||||
<MudItem xs="4">
|
||||
<div style="max-width: 400px;" class="mb-6">
|
||||
<MudCard>
|
||||
<MudCardHeader>
|
||||
<CardHeaderContent>
|
||||
<MudText Typo="Typo.h5">Playout Items and History</MudText>
|
||||
</CardHeaderContent>
|
||||
</MudCardHeader>
|
||||
<MudCardContent>
|
||||
<!-- reset will erase all items -->
|
||||
<!--
|
||||
<div>
|
||||
<MudButton Disabled="@EntityLocker.IsPlayoutLocked(Id)" Variant="Variant.Filled" Color="Color.Warning" OnClick="@(_ => EraseItems(eraseHistory: false))" Class="mt-4">
|
||||
Erase Items
|
||||
</MudButton>
|
||||
</div>
|
||||
-->
|
||||
<div>
|
||||
<MudButton Disabled="@EntityLocker.IsPlayoutLocked(Id)" Variant="Variant.Filled" Color="Color.Error" OnClick="@(_ => EraseItems(eraseHistory: true))" Class="mt-4">
|
||||
Erase Items and History
|
||||
</MudButton>
|
||||
</div>
|
||||
</MudCardContent>
|
||||
</MudCard>
|
||||
</div>
|
||||
</MudItem>
|
||||
</MudGrid>
|
||||
</MudContainer>
|
||||
<MudForm Style="max-height: 100%">
|
||||
<MudPaper Square="true" Style="display: flex; height: 64px; min-height: 64px; width: 100%; z-index: 100; align-items: center">
|
||||
<MudText Class="ml-8" >Edit YAML Playout - @_channelName</MudText>
|
||||
</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">YAML File</MudText>
|
||||
<MudDivider Class="mb-6"/>
|
||||
<MudButton Disabled="@EntityLocker.IsPlayoutLocked(Id)" Variant="Variant.Filled" Color="Color.Primary" OnClick="@(_ => EditYamlFile())">
|
||||
Edit YAML File
|
||||
</MudButton>
|
||||
<MudText Typo="Typo.h5" Class="mt-6 mb-2">Playout Items and History</MudText>
|
||||
<MudDivider Class="mb-6"/>
|
||||
<MudButton Disabled="@EntityLocker.IsPlayoutLocked(Id)" Variant="Variant.Filled" Color="Color.Error" OnClick="@(_ => EraseItems(eraseHistory: true))">
|
||||
Erase Items and History
|
||||
</MudButton>
|
||||
</MudContainer>
|
||||
</div>
|
||||
</MudForm>
|
||||
|
||||
@code {
|
||||
private readonly CancellationTokenSource _cts = new();
|
||||
|
||||
@@ -5,68 +5,78 @@
|
||||
@inject ISnackbar Snackbar
|
||||
@inject IMediator Mediator
|
||||
|
||||
<MudContainer MaxWidth="MaxWidth.ExtraLarge" Class="pt-8">
|
||||
<MudTable Hover="true" Items="_pathReplacements.OrderBy(r => r.Id)" Dense="true" @bind-SelectedItem="_selectedItem">
|
||||
<ToolBarContent>
|
||||
<MudText Typo="Typo.h6"><b>@_source?.Name</b> Path Replacements</MudText>
|
||||
</ToolBarContent>
|
||||
<ColGroup>
|
||||
<col/>
|
||||
<col/>
|
||||
<col style="width: 60px;"/>
|
||||
</ColGroup>
|
||||
<HeaderContent>
|
||||
<MudTh>@Name Path</MudTh>
|
||||
<MudTh>Local Path</MudTh>
|
||||
<MudTh/>
|
||||
</HeaderContent>
|
||||
<RowTemplate>
|
||||
<MudTd DataLabel="@($"{Name} Path")">
|
||||
<MudText Typo="@(context == _selectedItem ? Typo.subtitle2 : Typo.body2)">
|
||||
@context.RemotePath
|
||||
</MudText>
|
||||
</MudTd>
|
||||
<MudTd DataLabel="Local Path">
|
||||
<MudText Typo="@(context == _selectedItem ? Typo.subtitle2 : Typo.body2)">
|
||||
@context.LocalPath
|
||||
</MudText>
|
||||
</MudTd>
|
||||
<MudTd>
|
||||
<MudTooltip Text="Delete Path Replacement">
|
||||
<MudIconButton Icon="@Icons.Material.Filled.Delete"
|
||||
OnClick="@(_ => RemovePathReplacement(context))">
|
||||
</MudIconButton>
|
||||
</MudTooltip>
|
||||
</MudTd>
|
||||
</RowTemplate>
|
||||
</MudTable>
|
||||
<MudButton Variant="Variant.Filled" Color="Color.Default" OnClick="@(_ => AddPathReplacement())" Class="mt-4">
|
||||
Add Path Replacement
|
||||
</MudButton>
|
||||
<MudButton Variant="Variant.Filled" Color="Color.Primary" OnClick="@(_ => SaveChanges())" Class="mt-4 ml-4">
|
||||
Save Changes
|
||||
</MudButton>
|
||||
|
||||
@if (_selectedItem is not null)
|
||||
{
|
||||
<div style="max-width: 400px;">
|
||||
<EditForm Model="_selectedItem">
|
||||
<FluentValidationValidator/>
|
||||
<MudCard Class="mt-6">
|
||||
<MudCardContent>
|
||||
<MudTextField Label="@($"{Name} Path")"
|
||||
@bind-Value="@_selectedItem.RemotePath"
|
||||
For="@(() => _selectedItem.RemotePath)"/>
|
||||
<MudTextField Class="mt-3"
|
||||
Label="Local Path"
|
||||
@bind-Value="@_selectedItem.LocalPath"
|
||||
For="@(() => _selectedItem.LocalPath)"/>
|
||||
</MudCardContent>
|
||||
</MudCard>
|
||||
</EditForm>
|
||||
</div>
|
||||
}
|
||||
</MudContainer>
|
||||
<MudForm Style="max-height: 100%">
|
||||
<MudPaper Square="true" Style="display: flex; height: 64px; min-height: 64px; width: 100%; z-index: 100; align-items: center">
|
||||
<MudButton Variant="Variant.Filled" Color="Color.Primary" OnClick="@(_ => SaveChanges())" StartIcon="@Icons.Material.Filled.Save" Class="ml-8">
|
||||
Save Path Replacements
|
||||
</MudButton>
|
||||
</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">@_source?.Name</MudText>
|
||||
<MudDivider Class="mb-6"/>
|
||||
<MudTable Hover="true" Items="_pathReplacements.OrderBy(r => r.Id)" Dense="true" @bind-SelectedItem="_selectedItem">
|
||||
<ColGroup>
|
||||
<MudHidden Breakpoint="Breakpoint.Xs">
|
||||
<col/>
|
||||
<col/>
|
||||
<col style="width: 60px;"/>
|
||||
</MudHidden>
|
||||
</ColGroup>
|
||||
<HeaderContent>
|
||||
<MudTh>@Name Path</MudTh>
|
||||
<MudTh>Local Path</MudTh>
|
||||
<MudTh/>
|
||||
</HeaderContent>
|
||||
<RowTemplate>
|
||||
<MudTd DataLabel="@($"{Name} Path")">
|
||||
<MudText Typo="@(context == _selectedItem ? Typo.subtitle2 : Typo.body2)">
|
||||
@context.RemotePath
|
||||
</MudText>
|
||||
</MudTd>
|
||||
<MudTd DataLabel="Local Path">
|
||||
<MudText Typo="@(context == _selectedItem ? Typo.subtitle2 : Typo.body2)">
|
||||
@context.LocalPath
|
||||
</MudText>
|
||||
</MudTd>
|
||||
<MudTd>
|
||||
<MudTooltip Text="Delete Path Replacement">
|
||||
<MudIconButton Icon="@Icons.Material.Filled.Delete"
|
||||
OnClick="@(_ => RemovePathReplacement(context))">
|
||||
</MudIconButton>
|
||||
</MudTooltip>
|
||||
</MudTd>
|
||||
</RowTemplate>
|
||||
</MudTable>
|
||||
<MudButton Variant="Variant.Filled" Color="Color.Default" OnClick="@(_ => AddPathReplacement())" Class="mt-4">
|
||||
Add Path Replacement
|
||||
</MudButton>
|
||||
<MudText Typo="Typo.h5" Class="mt-6 mb-2">Path Replacement</MudText>
|
||||
<MudDivider Class="mb-6"/>
|
||||
@if (_selectedItem is not null)
|
||||
{
|
||||
<MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
|
||||
<div class="d-flex">
|
||||
<MudText>@($"{Name} Path")</MudText>
|
||||
</div>
|
||||
<MudTextField @bind-Value="@_selectedItem.RemotePath"
|
||||
For="@(() => _selectedItem.RemotePath)"
|
||||
Required="true"
|
||||
RequiredError="Remote path is required!"/>
|
||||
</MudStack>
|
||||
<MudStack Row="true" Breakpoint="Breakpoint.SmAndDown" Class="form-field-stack gap-md-8 mb-5">
|
||||
<div class="d-flex">
|
||||
<MudText>Local Path</MudText>
|
||||
</div>
|
||||
<MudTextField @bind-Value="@_selectedItem.LocalPath"
|
||||
For="@(() => _selectedItem.LocalPath)"
|
||||
Required="true"
|
||||
RequiredError="Local path is required!"/>
|
||||
</MudStack>
|
||||
}
|
||||
</MudContainer>
|
||||
</div>
|
||||
</MudForm>
|
||||
|
||||
@code {
|
||||
private readonly CancellationTokenSource _cts = new();
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using ErsatzTV.Core.Domain.Filler;
|
||||
using ErsatzTV.ViewModels;
|
||||
using FluentValidation;
|
||||
using FluentValidation.Results;
|
||||
|
||||
namespace ErsatzTV.Validators;
|
||||
|
||||
@@ -39,4 +40,18 @@ public class FillerPresetEditViewModelValidator : AbstractValidator<FillerPreset
|
||||
.TelevisionShow or ProgramScheduleItemCollectionType.TelevisionSeason,
|
||||
() => RuleFor(fp => fp.MediaItem).NotNull());
|
||||
}
|
||||
|
||||
public Func<object, string, Task<IEnumerable<string>>> ValidateValue => async (model, propertyName) =>
|
||||
{
|
||||
ValidationResult result = await ValidateAsync(
|
||||
ValidationContext<FillerPresetEditViewModel>.CreateWithOptions(
|
||||
(FillerPresetEditViewModel)model,
|
||||
x => x.IncludeProperties(propertyName)));
|
||||
if (result.IsValid)
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
return result.Errors.Select(e => e.ErrorMessage);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using ErsatzTV.ViewModels;
|
||||
using FluentValidation;
|
||||
using FluentValidation.Results;
|
||||
|
||||
namespace ErsatzTV.Validators;
|
||||
|
||||
@@ -11,4 +12,18 @@ public class PlayoutEditViewModelValidator : AbstractValidator<PlayoutEditViewMo
|
||||
RuleFor(p => p.ProgramSchedule).NotNull().When(p => string.IsNullOrWhiteSpace(p.Kind));
|
||||
RuleFor(p => p.ExternalJsonFile).NotNull().When(p => p.Kind == PlayoutKind.ExternalJson);
|
||||
}
|
||||
|
||||
public Func<object, string, Task<IEnumerable<string>>> ValidateValue => async (model, propertyName) =>
|
||||
{
|
||||
ValidationResult result = await ValidateAsync(
|
||||
ValidationContext<PlayoutEditViewModel>.CreateWithOptions(
|
||||
(PlayoutEditViewModel)model,
|
||||
x => x.IncludeProperties(propertyName)));
|
||||
if (result.IsValid)
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
return result.Errors.Select(e => e.ErrorMessage);
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user