Files
ersatztv/ErsatzTV/Pages/OtherVideoList.razor
Jon Crall daff1c6533 Add select all controls to media lists (#2738)
* Add select all controls to media lists

* Refine select-all helper and add coverage

* Adjust select-all button alignment

* Tighten select-all helper semantics

* Allow tests to access internal members

* Rename select-all helper and avoid shift tracking

* Simplify select-all reset helper

* Keep pager centered and move select-all right

* Add missing div

* create test project for main app; move and rename new tests

* remove core => main app reference

* cleanup unused imports

* Fix button behavior when the screen is small

* update changelog

---------

Co-authored-by: Jason Dove <1695733+jasongdove@users.noreply.github.com>
2025-12-31 15:18:07 -06:00

135 lines
5.2 KiB
Plaintext

@page "/media/other/videos"
@page "/media/other/videos/page/{PageNumber:int}"
@using ErsatzTV.Application.MediaCards
@using ErsatzTV.Application.MediaCollections
@using ErsatzTV.Application.Search
@using ErsatzTV.Extensions
@inherits MultiSelectBase<OtherVideoList>
@inject NavigationManager NavigationManager
<MudForm Style="max-height: 100%">
<MudPaper Square="true" Style="display: flex; height: 64px; min-height: 64px; width: 100%; z-index: 100;">
<MediaCardPager Query="@_query"
PageNumber="@PageNumber"
PageSize="@PageSize"
TotalCount="@_data.Count"
NextPage="@NextPage"
PrevPage="@PrevPage"
AddSelectionToCollection="@AddSelectionToCollection"
AddSelectionToPlaylist="@AddSelectionToPlaylist"
ClearSelection="@ClearSelection"
CanSelectAllOnPage="@(() => _data.Cards.Count > 0)"
SelectAllOnPage="@(() => SelectAllPageItems(_data.Cards))"
IsSelectMode="@IsSelectMode"
SelectionLabel="@SelectionLabel"/>
</MudPaper>
<div class="d-flex flex-column" style="height: 100vh; overflow-x: auto">
<MudContainer MaxWidth="MaxWidth.ExtraLarge" Class="pt-8">
<MudStack Row="true" Wrap="Wrap.Wrap">
<FragmentLetterAnchor TCard="OtherVideoCardViewModel" Cards="@_data.Cards">
<MediaCard Data="@context"
Href=""
ArtworkKind="ArtworkKind.Thumbnail"
AddToCollectionClicked="@AddToCollection"
SelectClicked="@(e => SelectClicked(context, e))"
IsSelected="@IsSelected(context)"
IsSelectMode="@IsSelectMode()"/>
</FragmentLetterAnchor>
</MudStack>
</MudContainer>
</div>
</MudForm>
@if (_data.PageMap is not null)
{
<LetterBar PageMap="@_data.PageMap"
BaseUri="media/other/videos"
Query="@_query"/>
}
@code {
private static int PageSize => 100;
[Parameter]
public int PageNumber { get; set; }
private OtherVideoCardResultsViewModel _data = new(0, new List<OtherVideoCardViewModel>(), null);
private string _query;
protected override async Task OnParametersSetAsync()
{
if (PageNumber == 0)
{
PageNumber = 1;
}
_query = NavigationManager.Uri.GetSearchQuery();
await RefreshData(CancellationToken);
}
protected override async Task RefreshData(CancellationToken cancellationToken)
{
string searchQuery = string.IsNullOrWhiteSpace(_query) ? "type:other_video" : $"type:other_video AND ({_query})";
_data = await Mediator.Send(new QuerySearchIndexOtherVideos(searchQuery, PageNumber, PageSize), cancellationToken);
}
private void PrevPage()
{
var uri = $"media/other/videos/page/{PageNumber - 1}";
if (!string.IsNullOrWhiteSpace(_query))
{
(string key, string value) = _query.EncodeQuery();
uri = $"{uri}?{key}={value}";
}
NavigationManager.NavigateTo(uri);
}
private void NextPage()
{
var uri = $"media/other/videos/page/{PageNumber + 1}";
if (!string.IsNullOrWhiteSpace(_query))
{
(string key, string value) = _query.EncodeQuery();
uri = $"{uri}?{key}={value}";
}
NavigationManager.NavigateTo(uri);
}
private void SelectClicked(MediaCardViewModel card, MouseEventArgs e)
{
List<MediaCardViewModel> GetSortedItems()
{
return _data.Cards.OrderBy(m => m.SortTitle).ToList<MediaCardViewModel>();
}
SelectClicked(GetSortedItems, card, e);
}
private async Task AddToCollection(MediaCardViewModel card)
{
if (card is OtherVideoCardViewModel otherVideo)
{
var parameters = new DialogParameters { { "EntityType", "other video" }, { "EntityName", otherVideo.Title } };
var options = new DialogOptions { CloseButton = true, MaxWidth = MaxWidth.ExtraSmall };
IDialogReference dialog = await Dialog.ShowAsync<AddToCollectionDialog>("Add To Collection", parameters, options);
DialogResult result = await dialog.Result;
if (result is { Canceled: false, Data: MediaCollectionViewModel collection })
{
var request = new AddOtherVideoToCollection(collection.Id, otherVideo.OtherVideoId);
Either<BaseError, Unit> addResult = await Mediator.Send(request, CancellationToken);
addResult.Match(
Left: error =>
{
Snackbar.Add($"Unexpected error adding other video to collection: {error.Value}");
Logger.LogError("Unexpected error adding other video to collection: {Error}", error.Value);
},
Right: _ => Snackbar.Add($"Added {otherVideo.Title} to collection {collection.Name}", Severity.Success));
}
}
}
}