* add cancellation token support to playout builds and collection enumerators * fix playout bug with shuffle in order * update changelog
251 lines
10 KiB
Plaintext
251 lines
10 KiB
Plaintext
@page "/media/multi-collections/{Id:int}/edit"
|
|
@page "/media/multi-collections/add"
|
|
@using ErsatzTV.Application.MediaCollections
|
|
@implements IDisposable
|
|
@inject IMediator _mediator
|
|
@inject NavigationManager _navigationManager
|
|
@inject ISnackbar _snackbar
|
|
@inject ILogger<MultiCollectionEditor> _logger
|
|
|
|
<MudContainer MaxWidth="MaxWidth.ExtraLarge" Class="pt-8">
|
|
<div style="max-width: 400px;">
|
|
<MudText Typo="Typo.h4" Class="mb-4">@(IsEdit ? "Edit Multi Collection" : "Add Multi Collection")</MudText>
|
|
|
|
<EditForm EditContext="_editContext" OnSubmit="@HandleSubmitAsync">
|
|
<FluentValidator/>
|
|
<MudCard>
|
|
<MudCardContent>
|
|
<MudTextField Class="mt-3" Label="Name" @bind-Value="_model.Name" For="@(() => _model.Name)"/>
|
|
<MudSelect @ref="_collectionSelect"
|
|
Class="mt-4"
|
|
T="MediaCollectionViewModel"
|
|
Label="Collection"
|
|
@bind-value="_selectedCollection"
|
|
HelperText="Disabled collections are already present in this multi collection">
|
|
@foreach (MediaCollectionViewModel collection in _collections)
|
|
{
|
|
<MudSelectItem Disabled="@(_model.Items.Any(i => i.Collection.Id == collection.Id))"
|
|
Value="@collection">
|
|
@collection.Name
|
|
</MudSelectItem>
|
|
}
|
|
</MudSelect>
|
|
<MudButton Variant="Variant.Filled" Color="Color.Secondary" OnClick="@(_ => AddCollection())" Class="mt-4 mr-auto">
|
|
Add Collection
|
|
</MudButton>
|
|
<MudSelect @ref="_smartCollectionSelect"
|
|
Class="mt-4"
|
|
T="SmartCollectionViewModel"
|
|
Label="Smart Collection"
|
|
@bind-value="_selectedSmartCollection"
|
|
HelperText="Disabled collections are already present in this multi collection">
|
|
@foreach (SmartCollectionViewModel collection in _smartCollections)
|
|
{
|
|
<MudSelectItem Disabled="@(_model.Items.Any(i => i.Collection.Id == collection.Id))"
|
|
Value="@collection">
|
|
@collection.Name
|
|
</MudSelectItem>
|
|
}
|
|
</MudSelect>
|
|
<MudButton Variant="Variant.Filled" Color="Color.Secondary" OnClick="@(_ => AddSmartCollection())" Class="mt-4 mr-auto">
|
|
Add Smart Collection
|
|
</MudButton>
|
|
</MudCardContent>
|
|
<MudCardActions>
|
|
<MudButton ButtonType="ButtonType.Submit" Variant="Variant.Filled" Color="Color.Primary" Class="mr-2 ml-auto">
|
|
@(IsEdit ? "Save Changes" : "Add Multi Collection")
|
|
</MudButton>
|
|
</MudCardActions>
|
|
</MudCard>
|
|
</EditForm>
|
|
</div>
|
|
|
|
<MudTable Hover="true" Items="_model.Items.OrderBy(i => i.Collection.Name, StringComparer.CurrentCultureIgnoreCase)" Dense="true" Class="mt-6">
|
|
<ToolBarContent>
|
|
<MudText Typo="Typo.h6">@_model.Name Items</MudText>
|
|
</ToolBarContent>
|
|
<ColGroup>
|
|
<col/>
|
|
<col style="width: 20%"/>
|
|
<col style="width: 30%"/>
|
|
<col style="width: 60px;"/>
|
|
</ColGroup>
|
|
<HeaderContent>
|
|
<MudTh>Collection</MudTh>
|
|
<MudTh>Schedule As Group</MudTh>
|
|
<MudTh>Playback Order</MudTh>
|
|
<MudTh/>
|
|
</HeaderContent>
|
|
<RowTemplate>
|
|
<MudTd DataLabel="Collection">
|
|
<MudText Typo="Typo.body2">
|
|
@context.Collection.Name
|
|
</MudText>
|
|
</MudTd>
|
|
<MudTd DataLabel="Schedule As Group">
|
|
<MudCheckBox @bind-Checked="@context.ScheduleAsGroup" For="@(() => context.ScheduleAsGroup)"/>
|
|
</MudTd>
|
|
<MudTd DataLabel="Playback Order">
|
|
@if (context.ScheduleAsGroup)
|
|
{
|
|
<MudText Typo="Typo.body2">
|
|
@(context.Collection.UseCustomPlaybackOrder ? "Custom" : "Chronological")
|
|
</MudText>
|
|
}
|
|
</MudTd>
|
|
<MudTd>
|
|
<MudIconButton Icon="@Icons.Material.Filled.Delete"
|
|
OnClick="@(_ => RemoveCollection(context))">
|
|
</MudIconButton>
|
|
</MudTd>
|
|
</RowTemplate>
|
|
</MudTable>
|
|
</MudContainer>
|
|
|
|
@code {
|
|
private readonly CancellationTokenSource _cts = new();
|
|
|
|
[Parameter]
|
|
public int Id { get; set; }
|
|
|
|
private readonly MultiCollectionEditViewModel _model = new();
|
|
private EditContext _editContext;
|
|
private ValidationMessageStore _messageStore;
|
|
private List<MediaCollectionViewModel> _collections;
|
|
private List<SmartCollectionViewModel> _smartCollections;
|
|
private MediaCollectionViewModel _selectedCollection;
|
|
private SmartCollectionViewModel _selectedSmartCollection;
|
|
private MudSelect<MediaCollectionViewModel> _collectionSelect;
|
|
private MudSelect<SmartCollectionViewModel> _smartCollectionSelect;
|
|
|
|
public void Dispose()
|
|
{
|
|
_cts.Cancel();
|
|
_cts.Dispose();
|
|
}
|
|
|
|
protected override async Task OnParametersSetAsync()
|
|
{
|
|
_collections = await _mediator.Send(new GetAllCollections(), _cts.Token)
|
|
.Map(list => list.OrderBy(vm => vm.Name, StringComparer.CurrentCultureIgnoreCase).ToList());
|
|
|
|
_smartCollections = await _mediator.Send(new GetAllSmartCollections(), _cts.Token)
|
|
.Map(list => list.OrderBy(vm => vm.Name, StringComparer.CurrentCultureIgnoreCase).ToList());
|
|
|
|
if (IsEdit)
|
|
{
|
|
Option<MultiCollectionViewModel> maybeCollection = await _mediator.Send(new GetMultiCollectionById(Id), _cts.Token);
|
|
maybeCollection.IfSome(collection =>
|
|
{
|
|
_model.Id = collection.Id;
|
|
_model.Name = collection.Name;
|
|
_model.Items = collection.Items
|
|
.Map(item =>
|
|
new MultiCollectionItemEditViewModel
|
|
{
|
|
Collection = item.Collection,
|
|
ScheduleAsGroup = item.ScheduleAsGroup,
|
|
PlaybackOrder = item.PlaybackOrder
|
|
})
|
|
.Append(collection.SmartItems.Map(item =>
|
|
new MultiCollectionSmartItemEditViewModel
|
|
{
|
|
SmartCollection = item.SmartCollection,
|
|
ScheduleAsGroup = item.ScheduleAsGroup,
|
|
PlaybackOrder = item.PlaybackOrder
|
|
})).ToList();
|
|
});
|
|
}
|
|
else
|
|
{
|
|
_model.Name = "New Multi Collection";
|
|
_model.Items = new List<MultiCollectionItemEditViewModel>();
|
|
}
|
|
}
|
|
|
|
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())
|
|
{
|
|
Seq<BaseError> errorMessage = IsEdit ?
|
|
(await _mediator.Send(new UpdateMultiCollection(Id, _model.Name, GetUpdateItems()), _cts.Token)).LeftToSeq() :
|
|
(await _mediator.Send(new CreateMultiCollection(_model.Name, GetCreateItems()), _cts.Token)).LeftToSeq();
|
|
|
|
errorMessage.HeadOrNone().Match(
|
|
error =>
|
|
{
|
|
_snackbar.Add(error.Value, Severity.Error);
|
|
_logger.LogError("Error saving collection: {Error}", error.Value);
|
|
},
|
|
() => _navigationManager.NavigateTo("media/collections"));
|
|
}
|
|
}
|
|
|
|
private List<UpdateMultiCollectionItem> GetUpdateItems() =>
|
|
_model.Items.Map(i =>
|
|
i switch
|
|
{
|
|
MultiCollectionSmartItemEditViewModel smartVm =>
|
|
new UpdateMultiCollectionItem(
|
|
null,
|
|
smartVm.SmartCollection.Id,
|
|
smartVm.ScheduleAsGroup,
|
|
smartVm.PlaybackOrder),
|
|
_ => new UpdateMultiCollectionItem(i.Collection.Id, null, i.ScheduleAsGroup, i.PlaybackOrder)
|
|
}).ToList();
|
|
|
|
private List<CreateMultiCollectionItem> GetCreateItems() =>
|
|
_model.Items.Map(i =>
|
|
i switch
|
|
{
|
|
MultiCollectionSmartItemEditViewModel smartVm =>
|
|
new CreateMultiCollectionItem(
|
|
null,
|
|
smartVm.SmartCollection.Id,
|
|
smartVm.ScheduleAsGroup,
|
|
smartVm.PlaybackOrder),
|
|
_ => new CreateMultiCollectionItem(i.Collection.Id, null, i.ScheduleAsGroup, i.PlaybackOrder)
|
|
}).ToList();
|
|
|
|
private void RemoveCollection(MultiCollectionItemEditViewModel item) => _model.Items.Remove(item);
|
|
|
|
private async Task AddCollection()
|
|
{
|
|
if (_selectedCollection != null && _model.Items.All(i => i.Collection != _selectedCollection))
|
|
{
|
|
_model.Items.Add(new MultiCollectionItemEditViewModel
|
|
{
|
|
Collection = _selectedCollection,
|
|
PlaybackOrder = PlaybackOrder.Chronological
|
|
});
|
|
|
|
_selectedCollection = null;
|
|
await _collectionSelect.ResetAsync();
|
|
}
|
|
}
|
|
|
|
private async Task AddSmartCollection()
|
|
{
|
|
if (_selectedSmartCollection != null && _model.Items.OfType<MultiCollectionSmartItemEditViewModel>().All(i => i.SmartCollection != _selectedSmartCollection))
|
|
{
|
|
_model.Items.Add(new MultiCollectionSmartItemEditViewModel
|
|
{
|
|
SmartCollection = _selectedSmartCollection,
|
|
PlaybackOrder = PlaybackOrder.Chronological
|
|
});
|
|
|
|
_selectedSmartCollection = null;
|
|
await _smartCollectionSelect.ResetAsync();
|
|
}
|
|
}
|
|
|
|
} |