Added tag filter state persistence.
This commit is contained in:
109
JSMR.UI.Blazor/Filters/TagFilterState.cs
Normal file
109
JSMR.UI.Blazor/Filters/TagFilterState.cs
Normal file
@@ -0,0 +1,109 @@
|
||||
using JSMR.Application.Common.Search;
|
||||
using JSMR.Application.Tags.Queries.Search;
|
||||
using JSMR.Application.Tags.Queries.Search.Contracts;
|
||||
using Microsoft.AspNetCore.WebUtilities;
|
||||
using System.Globalization;
|
||||
|
||||
namespace JSMR.UI.Blazor.Filters;
|
||||
|
||||
public sealed record TagFilterState : IFilterState<SearchTagsRequest>
|
||||
{
|
||||
public string? Keywords { get; init; }
|
||||
public int PageNumber { get; init; } = 1;
|
||||
public int PageSize { get; init; } = 100;
|
||||
|
||||
public IReadOnlyList<SortOption<TagSortField>> SortOptions { get; init; } =
|
||||
[
|
||||
new(TagSortField.Name, SortDirection.Ascending)
|
||||
];
|
||||
|
||||
public QueryParameters ToQuery()
|
||||
{
|
||||
QueryParameters query = [];
|
||||
|
||||
query.Set("keywords", Keywords);
|
||||
|
||||
if (PageNumber != 1)
|
||||
query.Set("pageNumber", PageNumber.ToString(CultureInfo.InvariantCulture));
|
||||
|
||||
if (PageSize != 100)
|
||||
query.Set("pageSize", PageSize.ToString(CultureInfo.InvariantCulture));
|
||||
|
||||
if (!IsDefaultSort(SortOptions))
|
||||
{
|
||||
query.Set("sort", string.Join(",", SortOptions.Select(x =>
|
||||
$"{x.Field}:{ToQueryDirection(x.Direction)}")));
|
||||
}
|
||||
|
||||
return query;
|
||||
}
|
||||
|
||||
public static TagFilterState FromQuery(string query)
|
||||
{
|
||||
QueryParameters queryParameters = new(QueryHelpers.ParseQuery(query));
|
||||
|
||||
return new TagFilterState
|
||||
{
|
||||
Keywords = queryParameters.GetValue("keywords"),
|
||||
PageNumber = Math.Max(1, queryParameters.GetInteger("pageNumber", 1)),
|
||||
PageSize = queryParameters.GetInteger("pageSize", 100),
|
||||
SortOptions = ParseSortOptions(queryParameters.GetValue("sort"))
|
||||
};
|
||||
}
|
||||
|
||||
public SearchTagsRequest ToSearchRequest()
|
||||
{
|
||||
return new(
|
||||
Options: new()
|
||||
{
|
||||
PageNumber = PageNumber,
|
||||
PageSize = PageSize,
|
||||
Criteria = new()
|
||||
{
|
||||
Name = Keywords
|
||||
},
|
||||
SortOptions = [.. SortOptions]
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
private static IReadOnlyList<SortOption<TagSortField>> ParseSortOptions(string? value)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(value))
|
||||
return DefaultSort();
|
||||
|
||||
var result = new List<SortOption<TagSortField>>();
|
||||
|
||||
foreach (var part in value.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries))
|
||||
{
|
||||
var pieces = part.Split(':', 2, StringSplitOptions.TrimEntries);
|
||||
|
||||
if (pieces.Length != 2)
|
||||
continue;
|
||||
|
||||
if (!Enum.TryParse<TagSortField>(pieces[0], ignoreCase: true, out var field))
|
||||
continue;
|
||||
|
||||
var direction = pieces[1].Equals("desc", StringComparison.OrdinalIgnoreCase)
|
||||
? Application.Common.Search.SortDirection.Descending
|
||||
: Application.Common.Search.SortDirection.Ascending;
|
||||
|
||||
result.Add(new(field, direction));
|
||||
}
|
||||
|
||||
return result.Count > 0 ? result : DefaultSort();
|
||||
}
|
||||
|
||||
private static IReadOnlyList<SortOption<TagSortField>> DefaultSort() =>
|
||||
[
|
||||
new(TagSortField.Name, Application.Common.Search.SortDirection.Ascending)
|
||||
];
|
||||
|
||||
private static string ToQueryDirection(Application.Common.Search.SortDirection direction)
|
||||
=> direction == Application.Common.Search.SortDirection.Descending ? "desc" : "asc";
|
||||
|
||||
private static bool IsDefaultSort(IReadOnlyList<SortOption<TagSortField>> sortOptions)
|
||||
=> sortOptions.Count == 1
|
||||
&& sortOptions[0].Field == TagSortField.Name
|
||||
&& sortOptions[0].Direction == Application.Common.Search.SortDirection.Ascending;
|
||||
}
|
||||
Reference in New Issue
Block a user