add all search results to collection (#150)
This commit is contained in:
@@ -1,7 +0,0 @@
|
||||
using ErsatzTV.Core.Search;
|
||||
using MediatR;
|
||||
|
||||
namespace ErsatzTV.Application.Search.Queries
|
||||
{
|
||||
public record QuerySearchIndex(string Query) : IRequest<SearchResult>;
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
using MediatR;
|
||||
|
||||
namespace ErsatzTV.Application.Search.Queries
|
||||
{
|
||||
public record QuerySearchIndexAllItems(string Query) : IRequest<SearchResultAllItemsViewModel>;
|
||||
}
|
||||
@@ -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<QuerySearchIndexAllItems, SearchResultAllItemsViewModel>
|
||||
{
|
||||
private readonly ISearchIndex _searchIndex;
|
||||
|
||||
public QuerySearchIndexAllItemsHandler(ISearchIndex searchIndex) => _searchIndex = searchIndex;
|
||||
|
||||
public async Task<SearchResultAllItemsViewModel> Handle(
|
||||
QuerySearchIndexAllItems request,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
List<int> movieIds = await _searchIndex.Search($"type:movie AND ({request.Query})", 0, 0)
|
||||
.Map(result => result.Items.Map(i => i.Id).ToList());
|
||||
List<int> showIds = await _searchIndex.Search($"type:show AND ({request.Query})", 0, 0)
|
||||
.Map(result => result.Items.Map(i => i.Id).ToList());
|
||||
List<int> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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<QuerySearchIndex, SearchResult>
|
||||
{
|
||||
private readonly ISearchIndex _searchIndex;
|
||||
|
||||
public QuerySearchIndexHandler(ISearchIndex searchIndex) => _searchIndex = searchIndex;
|
||||
|
||||
public Task<SearchResult> Handle(QuerySearchIndex request, CancellationToken cancellationToken) =>
|
||||
_searchIndex.Search(request.Query, 0, 100);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace ErsatzTV.Application.Search
|
||||
{
|
||||
public record SearchResultAllItemsViewModel(List<int> MovieIds, List<int> ShowIds, List<int> MusicVideoIds);
|
||||
}
|
||||
@@ -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<ScoreDoc> selectedHits = topDocs.ScoreDocs.Skip(skip).Take(limit);
|
||||
IEnumerable<ScoreDoc> 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);
|
||||
|
||||
if (limit > 0)
|
||||
{
|
||||
searchResult.PageMap = GetSearchPageMap(searcher, query, filter, sort, limit);
|
||||
}
|
||||
|
||||
return searchResult.AsTask();
|
||||
}
|
||||
|
||||
@@ -94,21 +94,28 @@ namespace ErsatzTV.Pages
|
||||
}
|
||||
}
|
||||
|
||||
protected async Task AddSelectionToCollection()
|
||||
protected Task AddSelectionToCollection() => AddItemsToCollection(
|
||||
_selectedItems.OfType<MovieCardViewModel>().Map(m => m.MovieId).ToList(),
|
||||
_selectedItems.OfType<TelevisionShowCardViewModel>().Map(s => s.TelevisionShowId).ToList(),
|
||||
_selectedItems.OfType<MusicVideoCardViewModel>().Map(mv => mv.MusicVideoId).ToList());
|
||||
|
||||
protected async Task AddItemsToCollection(
|
||||
List<int> movieIds,
|
||||
List<int> showIds,
|
||||
List<int> 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<AddToCollectionDialog>("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<MovieCardViewModel>().Map(m => m.MovieId).ToList(),
|
||||
_selectedItems.OfType<TelevisionShowCardViewModel>().Map(s => s.TelevisionShowId).ToList(),
|
||||
_selectedItems.OfType<MusicVideoCardViewModel>().Map(mv => mv.MusicVideoId).ToList());
|
||||
var request = new AddItemsToCollection(collection.Id, movieIds, showIds, musicVideoIds);
|
||||
|
||||
Either<BaseError, Unit> 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();
|
||||
});
|
||||
|
||||
@@ -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
|
||||
{
|
||||
<MudText>@_query</MudText>
|
||||
<MudText Style="margin-bottom: auto; margin-top: auto">@_query</MudText>
|
||||
if (_movies.Count > 0)
|
||||
{
|
||||
<MudLink Class="ml-4" Href="@(NavigationManager.Uri.Split("#").Head() + "#movies")">@_movies.Count Movies</MudLink>
|
||||
<MudLink Class="ml-4" Href="@(NavigationManager.Uri.Split("#").Head() + "#movies")" Style="margin-bottom: auto; margin-top: auto">@_movies.Count Movies</MudLink>
|
||||
}
|
||||
else
|
||||
{
|
||||
<MudText Class="ml-4">0 Movies</MudText>
|
||||
<MudText Class="ml-4" Style="margin-bottom: auto; margin-top: auto">0 Movies</MudText>
|
||||
}
|
||||
|
||||
if (_shows.Count > 0)
|
||||
{
|
||||
<MudLink Class="ml-4" Href="@(NavigationManager.Uri.Split("#").Head() + "#shows")">@_shows.Count Shows</MudLink>
|
||||
<MudLink Class="ml-4" Href="@(NavigationManager.Uri.Split("#").Head() + "#shows")" Style="margin-bottom: auto; margin-top: auto">@_shows.Count Shows</MudLink>
|
||||
}
|
||||
else
|
||||
{
|
||||
<MudText Class="ml-4">0 Shows</MudText>
|
||||
<MudText Class="ml-4" Style="margin-bottom: auto; margin-top: auto">0 Shows</MudText>
|
||||
}
|
||||
|
||||
if (_musicVideos.Count > 0)
|
||||
{
|
||||
<MudLink Class="ml-4" Href="@(NavigationManager.Uri.Split("#").Head() + "#music_videos")">@_musicVideos.Count Music Videos</MudLink>
|
||||
<MudLink Class="ml-4" Href="@(NavigationManager.Uri.Split("#").Head() + "#music_videos")" Style="margin-bottom: auto; margin-top: auto">@_musicVideos.Count Music Videos</MudLink>
|
||||
}
|
||||
else
|
||||
{
|
||||
<MudText Class="ml-4">0 Music Videos</MudText>
|
||||
<MudText Class="ml-4" Style="margin-bottom: auto; margin-top: auto">0 Music Videos</MudText>
|
||||
}
|
||||
<div style="margin-left: auto">
|
||||
<MudButton Variant="Variant.Filled"
|
||||
Color="Color.Primary"
|
||||
StartIcon="@Icons.Material.Filled.Add"
|
||||
OnClick="@AddAllToCollection">
|
||||
Add All To Collection
|
||||
</MudButton>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</MudPaper>
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user