Added SearchPageBase class and implemented it on the voice works page and circles page. Turned off AOT compilation.
This commit is contained in:
@@ -4,136 +4,41 @@
|
||||
@using JSMR.UI.Blazor.Components
|
||||
@using JSMR.UI.Blazor.Filters
|
||||
@using JSMR.UI.Blazor.Services
|
||||
@using JSMR.UI.Blazor.Shared
|
||||
@using Microsoft.AspNetCore.WebUtilities
|
||||
@inject VoiceWorksClient Client
|
||||
@inject IJSRuntime JS
|
||||
@inject NavigationManager NavigationManager
|
||||
@implements IAsyncDisposable;
|
||||
|
||||
@inherits SearchPageBase<VoiceWorkFilterState, VoiceWorkSearchResult>
|
||||
|
||||
<PageTitle>Voice Works</PageTitle>
|
||||
|
||||
<h3>Voice Works</h3>
|
||||
|
||||
<VoiceWorkFilters Value="@FilterState" ValueChanged="OnFilterStateChanged" />
|
||||
<JProductCollection Products="searchResults?.Items"></JProductCollection>
|
||||
<VoiceWorkFilters Value="@State" ValueChanged="UpdateAsync" />
|
||||
<JProductCollection Products="Result?.Items"></JProductCollection>
|
||||
|
||||
@if (searchResults is not null)
|
||||
@if (Result is not null)
|
||||
{
|
||||
<JPagination PageNumber="@FilterState.PageNumber"
|
||||
PageNumberChanged="@(pageNumber => OnFilterStateChanged(FilterState with { PageNumber = pageNumber }))"
|
||||
PageSize="@FilterState.PageSize"
|
||||
PageSizeChanged="@(pageSize => OnFilterStateChanged(FilterState with { PageSize = pageSize, PageNumber = 1 }))"
|
||||
@bind-TotalItems="searchResults.TotalItems" />
|
||||
<JPagination PageNumber="@State.PageNumber"
|
||||
PageNumberChanged="@(pageNumber => UpdateAsync(State with { PageNumber = pageNumber }))"
|
||||
PageSize="@State.PageSize"
|
||||
PageSizeChanged="@(pageSize => UpdateAsync(State with { PageSize = pageSize, PageNumber = 1 }))"
|
||||
@bind-TotalItems="Result.TotalItems" />
|
||||
}
|
||||
|
||||
@code {
|
||||
private bool _suppressNextLocation;
|
||||
private bool _isAlive = true;
|
||||
//private bool IsLoading;
|
||||
private CancellationTokenSource _cts = new();
|
||||
protected override VoiceWorkFilterState ParseStateFromUri(string absoluteUri)
|
||||
=> VoiceWorkFilterState.FromQuery(new Uri(absoluteUri).Query);
|
||||
|
||||
VoiceWorkFilterState FilterState = new();
|
||||
SearchResult<VoiceWorkSearchResult>? searchResults;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
protected override string BuildUri(VoiceWorkFilterState state)
|
||||
{
|
||||
NavigationManager.LocationChanged += OnLocationChanged;
|
||||
|
||||
FilterState = VoiceWorkFilterState.FromQuery(new Uri(NavigationManager.Uri).Query);
|
||||
await RunSearchAsync();
|
||||
var basePath = new Uri(Nav.Uri).GetLeftPart(UriPartial.Path);
|
||||
return Microsoft.AspNetCore.WebUtilities.QueryHelpers.AddQueryString(basePath, state.ToQuery());
|
||||
}
|
||||
|
||||
private async void OnLocationChanged(object? sender, LocationChangedEventArgs e)
|
||||
{
|
||||
if (_suppressNextLocation)
|
||||
{
|
||||
_suppressNextLocation = false;
|
||||
return;
|
||||
}
|
||||
protected override bool IsThisPage(string absoluteUri)
|
||||
=> Nav.ToBaseRelativePath(absoluteUri).StartsWith("voiceworks", StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
if (!_isAlive)
|
||||
return;
|
||||
|
||||
if (!IsThisPage(e.Location))
|
||||
return;
|
||||
|
||||
string query = NavigationManager.ToAbsoluteUri(e.Location).Query;
|
||||
VoiceWorkFilterState next = VoiceWorkFilterState.FromQuery(query);
|
||||
|
||||
if (next != FilterState)
|
||||
{
|
||||
FilterState = next;
|
||||
await InvokeAsync(StateHasChanged);
|
||||
RunSearchAsync();
|
||||
}
|
||||
}
|
||||
|
||||
private bool IsThisPage(string absoluteUri)
|
||||
{
|
||||
string baseRelativePath = NavigationManager.ToBaseRelativePath(absoluteUri);
|
||||
|
||||
return baseRelativePath.StartsWith("voiceworks", StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
async Task OnFilterStateChanged(VoiceWorkFilterState next)
|
||||
{
|
||||
if (next == FilterState)
|
||||
return;
|
||||
|
||||
FilterState = next;
|
||||
|
||||
// Optional immediate paint if you want instant visual feedback on filters:
|
||||
//await InvokeAsync(StateHasChanged);
|
||||
|
||||
UpdateUrl(next, false);
|
||||
RunSearchAsync();
|
||||
}
|
||||
|
||||
void UpdateUrl(VoiceWorkFilterState next, bool replace)
|
||||
{
|
||||
string basePath = new Uri(NavigationManager.Uri).GetLeftPart(UriPartial.Path);
|
||||
string uri = QueryHelpers.AddQueryString(basePath, next.ToQuery());
|
||||
|
||||
_suppressNextLocation = true;
|
||||
|
||||
NavigationManager.NavigateTo(uri, replace: replace);
|
||||
}
|
||||
|
||||
async Task RunSearchAsync()
|
||||
{
|
||||
await JS.InvokeVoidAsync("pageHelpers.scrollToTop");
|
||||
|
||||
try
|
||||
{
|
||||
//IsLoading = true; // show skeletons NOW
|
||||
//StateHasChanged(); // paint immediately
|
||||
|
||||
_cts.Cancel();
|
||||
_cts = new();
|
||||
|
||||
SearchVoiceWorksResponse? response = await Client.SearchAsync(FilterState.ToSearchRequest(), _cts.Token);
|
||||
searchResults = response?.Results;
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (_isAlive)
|
||||
{
|
||||
//IsLoading = false; // hide skeletons
|
||||
await InvokeAsync(StateHasChanged);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public async ValueTask DisposeAsync()
|
||||
{
|
||||
_isAlive = false;
|
||||
NavigationManager.LocationChanged -= OnLocationChanged;
|
||||
_cts.Cancel();
|
||||
_cts.Dispose();
|
||||
await Task.CompletedTask;
|
||||
}
|
||||
protected override Task<SearchResult<VoiceWorkSearchResult>> ExecuteSearchAsync(VoiceWorkFilterState state, CancellationToken ct)
|
||||
=> Client.SearchAsync(state.ToSearchRequest(), ct).ContinueWith(t => t.Result?.Results ?? new SearchResult<VoiceWorkSearchResult>(), ct);
|
||||
}
|
||||
Reference in New Issue
Block a user