Finished refining the search page
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
@page "/search"
|
||||
@page "/search/{SearchTerms}"
|
||||
|
||||
@using Microsoft.AspNetCore.Components.Web
|
||||
@using Microsoft.EntityFrameworkCore
|
||||
@using Microsoft.Extensions.Logging
|
||||
@using MudBlazor
|
||||
@@ -16,14 +17,22 @@
|
||||
|
||||
@namespace OpenArchival.Blazor.ArchiveDisplay
|
||||
|
||||
<ArchiveSearchBar @bind-SelectedFilter="_selectedFilter"
|
||||
SearchTermsChanged="OnSearchSubmittedAsync" />
|
||||
<ArchiveSearchBar SearchTermsChanged="OnSearchSubmittedAsync"/>
|
||||
<FilterSelectorComponent
|
||||
@bind-SelectedFilter="_selectedFilter"
|
||||
@bind-SelectedTitlePrefix="_selectedLetter"
|
||||
ApplyFiltersClicked="OnApplyFilters"></FilterSelectorComponent>
|
||||
|
||||
@if (_totalResults > 0)
|
||||
@if (_totalResults > 0 && !_allArtifactsMode)
|
||||
{
|
||||
<MudGrid Justify="Justify.FlexStart" Class="mt-1 ml-1 mb-2">
|
||||
<MudText Typo="Typo.subtitle2" Class="my-2">@_totalResults results found</MudText>
|
||||
<MudButton Class="ml-1" StartIcon="@Icons.Material.Filled.Clear" OnClick="OnClearResults" Variant="Variant.Filled" Color="Color.Primary" Size="Size.Small">Clear</MudButton>
|
||||
<MudButton Class="ml-1"
|
||||
StartIcon="@Icons.Material.Filled.Clear"
|
||||
OnClick="@(args => OnClearResults(args, true, true))"
|
||||
Variant="Variant.Filled"
|
||||
Color="Color.Primary"
|
||||
Size="Size.Small">Clear</MudButton>
|
||||
</MudGrid>
|
||||
}
|
||||
|
||||
@@ -42,13 +51,7 @@
|
||||
<MudPagination Count="_totalPages" Selected="_currentPage" SelectedChanged="OnPageChangedAsync" />
|
||||
</MudPaper>
|
||||
}
|
||||
else
|
||||
{
|
||||
@foreach (SearchPageSliderEntry entry in _sliderEntries)
|
||||
{
|
||||
<SearchPageSlider SliderEntry="entry"></SearchPageSlider>
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@inject IDbContextFactory<ApplicationDbContext> ContextFactory;
|
||||
@inject ILogger<SearchArchive> Logger;
|
||||
@@ -59,26 +62,45 @@ else
|
||||
|
||||
private ArchiveSearchFilterType _selectedFilter = ArchiveSearchFilterType.All;
|
||||
|
||||
// Field to store the current filter logic
|
||||
private Expression<Func<ArtifactGrouping, bool>> _currentFilterPredicate;
|
||||
|
||||
private List<ArtifactGrouping> _artifactGroupings { get; set; } = [];
|
||||
private int _currentPage { get; set; } = 1;
|
||||
private int _totalPages { get; set; } = 0;
|
||||
private int _totalResults { get; set; } = 0;
|
||||
private const int PageSize = 20;
|
||||
|
||||
private List<SearchPageSliderEntry> _sliderEntries { get; set; } = [];
|
||||
|
||||
// Field to store the current filter logic
|
||||
private Expression<Func<ArtifactGrouping, bool>> _currentFilterPredicate;
|
||||
private bool _allArtifactsMode = true;
|
||||
private string? _selectedLetter;
|
||||
|
||||
protected override async Task OnParametersSetAsync()
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(SearchTerms))
|
||||
if (string.IsNullOrWhiteSpace(SearchTerms))
|
||||
{
|
||||
_allArtifactsMode = true;
|
||||
await LoadPageAsync(1);
|
||||
} else
|
||||
{
|
||||
_allArtifactsMode = false;
|
||||
await PerformSearchAsync();
|
||||
}
|
||||
}
|
||||
|
||||
await using var context = await ContextFactory.CreateDbContextAsync();
|
||||
_sliderEntries = await context.SearchPageSliderEntries.Include(e => e.FilterTags).ToListAsync();
|
||||
private IQueryable<ArtifactGrouping> BuildFilterQuery(IQueryable<ArtifactGrouping> startingQuery)
|
||||
{
|
||||
// Filter
|
||||
if (_currentFilterPredicate != null && !_allArtifactsMode)
|
||||
{
|
||||
startingQuery = startingQuery.Where(_currentFilterPredicate);
|
||||
}
|
||||
if (!string.IsNullOrWhiteSpace(_selectedLetter))
|
||||
{
|
||||
string likePattern = $"{_selectedLetter}%";
|
||||
startingQuery = startingQuery.Where(artifact => EF.Functions.ILike(artifact.Title, likePattern));
|
||||
}
|
||||
|
||||
return startingQuery;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -86,14 +108,20 @@ else
|
||||
/// </summary>
|
||||
private async Task OnSearchSubmittedAsync(string searchTerms)
|
||||
{
|
||||
|
||||
await OnClearResults(null, false, true);
|
||||
if (string.IsNullOrWhiteSpace(searchTerms))
|
||||
{
|
||||
OnClearResults(null);
|
||||
// Tell the clear operation not to navigate back to the search page and refresh
|
||||
_allArtifactsMode = true;
|
||||
await PerformSearchAsync();
|
||||
return;
|
||||
}
|
||||
|
||||
SearchTerms = searchTerms;
|
||||
NavigationManager.NavigateTo($"/search/{Uri.EscapeDataString(SearchTerms)}", replace: true);
|
||||
_allArtifactsMode = false;
|
||||
// This eventually calls LoadPageAsync
|
||||
await PerformSearchAsync();
|
||||
}
|
||||
|
||||
@@ -132,11 +160,6 @@ else
|
||||
break;
|
||||
}
|
||||
|
||||
// Get the total count using the chosen filter
|
||||
await using var context = await ContextFactory.CreateDbContextAsync();
|
||||
_totalResults = await context.ArtifactGroupings.Where(_currentFilterPredicate).CountAsync();
|
||||
_totalPages = (int)Math.Ceiling(_totalResults / (double)PageSize);
|
||||
|
||||
// Load the first page with the chosen filter
|
||||
await LoadPageAsync(1);
|
||||
}
|
||||
@@ -151,29 +174,40 @@ else
|
||||
/// </summary>
|
||||
private async Task LoadPageAsync(int page)
|
||||
{
|
||||
_currentPage = page;
|
||||
await using var context = await ContextFactory.CreateDbContextAsync();
|
||||
IQueryable<ArtifactGrouping> query = context.ArtifactGroupings;
|
||||
|
||||
if (_currentFilterPredicate == null) // Don't run if no search has been performed
|
||||
query = BuildFilterQuery(query);
|
||||
|
||||
// Select child data we want
|
||||
query = query
|
||||
.Include(x => x.ChildArtifactEntries)
|
||||
.ThenInclude(x => x.Files);
|
||||
|
||||
// If we are showing all artifacts, then order results alphabetically
|
||||
if (_allArtifactsMode)
|
||||
{
|
||||
return;
|
||||
query = query.OrderBy(artifact => artifact.Title);
|
||||
} else
|
||||
{
|
||||
query = query.OrderBy(artifact => artifact.Id);
|
||||
}
|
||||
|
||||
await using var context = await ContextFactory.CreateDbContextAsync();
|
||||
_totalResults = await query.CountAsync();
|
||||
_totalPages = (int)Math.Ceiling(_totalResults / (double)PageSize);
|
||||
_currentPage = page;
|
||||
|
||||
// The query uses the dynamically set filter predicate
|
||||
_artifactGroupings = await context.ArtifactGroupings
|
||||
.Where(_currentFilterPredicate)
|
||||
.Include(x => x.ChildArtifactEntries)
|
||||
.ThenInclude(x => x.Files)
|
||||
.OrderBy(x => x.Id)
|
||||
.Skip((_currentPage - 1) * PageSize)
|
||||
.Take(PageSize)
|
||||
.ToListAsync();
|
||||
query = query
|
||||
.Skip((_currentPage - 1) * PageSize)
|
||||
.Take(PageSize);
|
||||
|
||||
|
||||
_artifactGroupings = await query.ToListAsync();
|
||||
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
private void OnClearResults(Microsoft.AspNetCore.Components.Web.MouseEventArgs args)
|
||||
private async Task OnClearResults(Microsoft.AspNetCore.Components.Web.MouseEventArgs args, bool navigate = true, bool resetFirstLetterFilter = false)
|
||||
{
|
||||
_totalResults = 0;
|
||||
_artifactGroupings.Clear();
|
||||
@@ -181,8 +215,28 @@ else
|
||||
_totalPages = 0;
|
||||
SearchTerms = "";
|
||||
|
||||
NavigationManager.NavigateTo("/search", replace: true);
|
||||
if (navigate)
|
||||
{
|
||||
NavigationManager.NavigateTo("/search", replace: true);
|
||||
}
|
||||
|
||||
if (resetFirstLetterFilter)
|
||||
{
|
||||
_selectedLetter = "";
|
||||
}
|
||||
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
private async Task OnApplyFilters(MouseEventArgs args)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(SearchTerms))
|
||||
{
|
||||
_allArtifactsMode = true;
|
||||
} else
|
||||
{
|
||||
_allArtifactsMode = false;
|
||||
}
|
||||
await PerformSearchAsync();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user