From 436c9119faf53ea1fff52edd6f54118807c27fc5 Mon Sep 17 00:00:00 2001 From: Jason Dove Date: Tue, 6 Apr 2021 20:43:44 -0500 Subject: [PATCH] add all search results to collection (#150) --- .../Search/Queries/QuerySearchIndex.cs | 7 ---- .../Queries/QuerySearchIndexAllItems.cs | 6 ++++ .../QuerySearchIndexAllItemsHandler.cs | 32 +++++++++++++++++++ .../Search/Queries/QuerySearchIndexHandler.cs | 18 ----------- .../Search/SearchResultAllItemsViewModel.cs | 6 ++++ ErsatzTV.Infrastructure/Search/SearchIndex.cs | 14 ++++++-- ErsatzTV/Pages/MultiSelectBase.cs | 23 ++++++++----- ErsatzTV/Pages/Search.razor | 29 +++++++++++++---- ErsatzTV/Shared/AddToCollectionDialog.razor | 2 +- 9 files changed, 93 insertions(+), 44 deletions(-) delete mode 100644 ErsatzTV.Application/Search/Queries/QuerySearchIndex.cs create mode 100644 ErsatzTV.Application/Search/Queries/QuerySearchIndexAllItems.cs create mode 100644 ErsatzTV.Application/Search/Queries/QuerySearchIndexAllItemsHandler.cs delete mode 100644 ErsatzTV.Application/Search/Queries/QuerySearchIndexHandler.cs create mode 100644 ErsatzTV.Application/Search/SearchResultAllItemsViewModel.cs diff --git a/ErsatzTV.Application/Search/Queries/QuerySearchIndex.cs b/ErsatzTV.Application/Search/Queries/QuerySearchIndex.cs deleted file mode 100644 index a6e8a210c..000000000 --- a/ErsatzTV.Application/Search/Queries/QuerySearchIndex.cs +++ /dev/null @@ -1,7 +0,0 @@ -using ErsatzTV.Core.Search; -using MediatR; - -namespace ErsatzTV.Application.Search.Queries -{ - public record QuerySearchIndex(string Query) : IRequest; -} diff --git a/ErsatzTV.Application/Search/Queries/QuerySearchIndexAllItems.cs b/ErsatzTV.Application/Search/Queries/QuerySearchIndexAllItems.cs new file mode 100644 index 000000000..f623432d8 --- /dev/null +++ b/ErsatzTV.Application/Search/Queries/QuerySearchIndexAllItems.cs @@ -0,0 +1,6 @@ +using MediatR; + +namespace ErsatzTV.Application.Search.Queries +{ + public record QuerySearchIndexAllItems(string Query) : IRequest; +} diff --git a/ErsatzTV.Application/Search/Queries/QuerySearchIndexAllItemsHandler.cs b/ErsatzTV.Application/Search/Queries/QuerySearchIndexAllItemsHandler.cs new file mode 100644 index 000000000..220e31d13 --- /dev/null +++ b/ErsatzTV.Application/Search/Queries/QuerySearchIndexAllItemsHandler.cs @@ -0,0 +1,32 @@ +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using ErsatzTV.Core.Interfaces.Search; +using LanguageExt; +using MediatR; + +namespace ErsatzTV.Application.Search.Queries +{ + public class + QuerySearchIndexAllItemsHandler : IRequestHandler + { + private readonly ISearchIndex _searchIndex; + + public QuerySearchIndexAllItemsHandler(ISearchIndex searchIndex) => _searchIndex = searchIndex; + + public async Task Handle( + QuerySearchIndexAllItems request, + CancellationToken cancellationToken) + { + List movieIds = await _searchIndex.Search($"type:movie AND ({request.Query})", 0, 0) + .Map(result => result.Items.Map(i => i.Id).ToList()); + List showIds = await _searchIndex.Search($"type:show AND ({request.Query})", 0, 0) + .Map(result => result.Items.Map(i => i.Id).ToList()); + List musicVideoIds = await _searchIndex.Search($"type:music_video AND ({request.Query})", 0, 0) + .Map(result => result.Items.Map(i => i.Id).ToList()); + + return new SearchResultAllItemsViewModel(movieIds, showIds, musicVideoIds); + } + } +} diff --git a/ErsatzTV.Application/Search/Queries/QuerySearchIndexHandler.cs b/ErsatzTV.Application/Search/Queries/QuerySearchIndexHandler.cs deleted file mode 100644 index c93f7b65e..000000000 --- a/ErsatzTV.Application/Search/Queries/QuerySearchIndexHandler.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using ErsatzTV.Core.Interfaces.Search; -using ErsatzTV.Core.Search; -using MediatR; - -namespace ErsatzTV.Application.Search.Queries -{ - public class QuerySearchIndexHandler : IRequestHandler - { - private readonly ISearchIndex _searchIndex; - - public QuerySearchIndexHandler(ISearchIndex searchIndex) => _searchIndex = searchIndex; - - public Task Handle(QuerySearchIndex request, CancellationToken cancellationToken) => - _searchIndex.Search(request.Query, 0, 100); - } -} diff --git a/ErsatzTV.Application/Search/SearchResultAllItemsViewModel.cs b/ErsatzTV.Application/Search/SearchResultAllItemsViewModel.cs new file mode 100644 index 000000000..d95c60671 --- /dev/null +++ b/ErsatzTV.Application/Search/SearchResultAllItemsViewModel.cs @@ -0,0 +1,6 @@ +using System.Collections.Generic; + +namespace ErsatzTV.Application.Search +{ + public record SearchResultAllItemsViewModel(List MovieIds, List ShowIds, List MusicVideoIds); +} diff --git a/ErsatzTV.Infrastructure/Search/SearchIndex.cs b/ErsatzTV.Infrastructure/Search/SearchIndex.cs index d63a4ce33..646f593a8 100644 --- a/ErsatzTV.Infrastructure/Search/SearchIndex.cs +++ b/ErsatzTV.Infrastructure/Search/SearchIndex.cs @@ -138,7 +138,7 @@ namespace ErsatzTV.Infrastructure.Search using DirectoryReader reader = _writer.GetReader(true); var searcher = new IndexSearcher(reader); - int hitsLimit = skip + limit; + int hitsLimit = limit == 0 ? searcher.IndexReader.MaxDoc : skip + limit; using var analyzer = new StandardAnalyzer(AppLuceneVersion); QueryParser parser = !string.IsNullOrWhiteSpace(searchField) ? new QueryParser(AppLuceneVersion, searchField, analyzer) @@ -148,13 +148,21 @@ namespace ErsatzTV.Infrastructure.Search var filter = new DuplicateFilter(TitleAndYearField); var sort = new Sort(new SortField(SortTitleField, SortFieldType.STRING)); TopFieldDocs topDocs = searcher.Search(query, filter, hitsLimit, sort, true, true); - IEnumerable selectedHits = topDocs.ScoreDocs.Skip(skip).Take(limit); + IEnumerable selectedHits = topDocs.ScoreDocs.Skip(skip); + + if (limit > 0) + { + selectedHits = selectedHits.Take(limit); + } var searchResult = new SearchResult( selectedHits.Map(d => ProjectToSearchItem(searcher.Doc(d.Doc))).ToList(), topDocs.TotalHits); - searchResult.PageMap = GetSearchPageMap(searcher, query, filter, sort, limit); + if (limit > 0) + { + searchResult.PageMap = GetSearchPageMap(searcher, query, filter, sort, limit); + } return searchResult.AsTask(); } diff --git a/ErsatzTV/Pages/MultiSelectBase.cs b/ErsatzTV/Pages/MultiSelectBase.cs index 4c3db105e..fed8b12b7 100644 --- a/ErsatzTV/Pages/MultiSelectBase.cs +++ b/ErsatzTV/Pages/MultiSelectBase.cs @@ -94,21 +94,28 @@ namespace ErsatzTV.Pages } } - protected async Task AddSelectionToCollection() + protected Task AddSelectionToCollection() => AddItemsToCollection( + _selectedItems.OfType().Map(m => m.MovieId).ToList(), + _selectedItems.OfType().Map(s => s.TelevisionShowId).ToList(), + _selectedItems.OfType().Map(mv => mv.MusicVideoId).ToList()); + + protected async Task AddItemsToCollection( + List movieIds, + List showIds, + List musicVideoIds, + string entityName = "selected items") { + int count = movieIds.Count + showIds.Count + musicVideoIds.Count; + var parameters = new DialogParameters - { { "EntityType", _selectedItems.Count.ToString() }, { "EntityName", "selected items" } }; + { { "EntityType", count.ToString() }, { "EntityName", entityName } }; var options = new DialogOptions { CloseButton = true, MaxWidth = MaxWidth.ExtraSmall }; IDialogReference dialog = Dialog.Show("Add To Collection", parameters, options); DialogResult result = await dialog.Result; if (!result.Cancelled && result.Data is MediaCollectionViewModel collection) { - var request = new AddItemsToCollection( - collection.Id, - _selectedItems.OfType().Map(m => m.MovieId).ToList(), - _selectedItems.OfType().Map(s => s.TelevisionShowId).ToList(), - _selectedItems.OfType().Map(mv => mv.MusicVideoId).ToList()); + var request = new AddItemsToCollection(collection.Id, movieIds, showIds, musicVideoIds); Either addResult = await Mediator.Send(request); addResult.Match( @@ -120,7 +127,7 @@ namespace ErsatzTV.Pages Right: _ => { Snackbar.Add( - $"Added {_selectedItems.Count} items to collection {collection.Name}", + $"Added {count} items to collection {collection.Name}", Severity.Success); ClearSelection(); }); diff --git a/ErsatzTV/Pages/Search.razor b/ErsatzTV/Pages/Search.razor index 9c5ec91eb..da43fd403 100644 --- a/ErsatzTV/Pages/Search.razor +++ b/ErsatzTV/Pages/Search.razor @@ -2,6 +2,7 @@ @using ErsatzTV.Application.MediaCards @using ErsatzTV.Application.MediaCollections @using ErsatzTV.Application.MediaCollections.Commands +@using ErsatzTV.Application.Search @using ErsatzTV.Application.Search.Queries @using Microsoft.AspNetCore.WebUtilities @using Microsoft.Extensions.Primitives @@ -33,33 +34,41 @@ } else { - @_query + @_query if (_movies.Count > 0) { - @_movies.Count Movies + @_movies.Count Movies } else { - 0 Movies + 0 Movies } if (_shows.Count > 0) { - @_shows.Count Shows + @_shows.Count Shows } else { - 0 Shows + 0 Shows } if (_musicVideos.Count > 0) { - @_musicVideos.Count Music Videos + @_musicVideos.Count Music Videos } else { - 0 Music Videos + 0 Music Videos } +
+ + Add All To Collection + +
} @@ -276,4 +285,10 @@ return uri; } + private async Task AddAllToCollection(MouseEventArgs _) + { + SearchResultAllItemsViewModel results = await Mediator.Send(new QuerySearchIndexAllItems(_query)); + await AddItemsToCollection(results.MovieIds, results.ShowIds, results.MusicVideoIds, "search results"); + } + } \ No newline at end of file diff --git a/ErsatzTV/Shared/AddToCollectionDialog.razor b/ErsatzTV/Shared/AddToCollectionDialog.razor index cec43055f..afab180c5 100644 --- a/ErsatzTV/Shared/AddToCollectionDialog.razor +++ b/ErsatzTV/Shared/AddToCollectionDialog.razor @@ -70,7 +70,7 @@ if (MemoryCache.TryGetValue("AddToCollectionDialog.SelectedCollectionId", out int id)) { - _selectedCollection = _collections.SingleOrDefault(c => c.Id == id); + _selectedCollection = _collections.SingleOrDefault(c => c.Id == id) ?? _newCollection; } else {