Updated Blazor UI tag/creator views. Altered logic for sorting favorite/blacklisted fields for tags/creators.
This commit is contained in:
@@ -39,15 +39,15 @@ else
|
||||
|
||||
@if (item.Favorite)
|
||||
{
|
||||
<MudChip T="string" Label="true" Color="Color.Info" Style="width: 100%" Variant="MudBlazor.Variant.Outlined">Favorite</MudChip>
|
||||
<MudChip T="string" Label="true" Color="MudBlazor.Color.Info" Style="width: 100%" Variant="MudBlazor.Variant.Outlined">Favorite</MudChip>
|
||||
}
|
||||
else if (item.Blacklisted)
|
||||
{
|
||||
<MudChip T="string" Label="true" Color="Color.Warning" Style="width: 100%" Variant="MudBlazor.Variant.Outlined">Blacklisted</MudChip>
|
||||
<MudChip T="string" Label="true" Color="MudBlazor.Color.Warning" Style="width: 100%" Variant="MudBlazor.Variant.Outlined">Blacklisted</MudChip>
|
||||
}
|
||||
else if (item.Spam)
|
||||
{
|
||||
<MudChip T="string" Label="true" Color="Color.Error" Style="width: 100%" Variant="MudBlazor.Variant.Outlined">Spam</MudChip>
|
||||
<MudChip T="string" Label="true" Color="MudBlazor.Color.Error" Style="width: 100%" Variant="MudBlazor.Variant.Outlined">Spam</MudChip>
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -13,37 +13,48 @@
|
||||
|
||||
<MudTextField T="string" Value="Keywords" ValueChanged="OnKeywordsChanged" Immediate="true" DebounceInterval="500" Label="Filter" Variant="MudBlazor.Variant.Text" Adornment="@Adornment.Start" AdornmentIcon="@Icons.Material.Outlined.Search" />
|
||||
|
||||
@if (searchResults is null)
|
||||
{
|
||||
<p>Loading…</p>
|
||||
}
|
||||
else if (searchResults.Items.Length == 0)
|
||||
{
|
||||
<p>No results.</p>
|
||||
}
|
||||
else
|
||||
{
|
||||
<MudTable Items="@searchResults.Items" Style="table-layout: fixed" Virtualize="true">
|
||||
<HeaderContent>
|
||||
<MudTh>Name</MudTh>
|
||||
<MudTh>Voice Works</MudTh>
|
||||
<MudTh>Favorite</MudTh>
|
||||
<MudTh>Blacklisted</MudTh>
|
||||
</HeaderContent>
|
||||
<RowTemplate>
|
||||
<MudTd DataLabel="Name">@context.Name</MudTd>
|
||||
<MudTd DataLabel="Voice Works">@context.VoiceWorkCount</MudTd>
|
||||
<MudTd DataLabel="Favorite">
|
||||
<MudIconButton Size="@Size.Small" Icon="@Icons.Material.Filled.Favorite" Color="@(context.Favorite? Color.Secondary: Color.Dark)" />
|
||||
</MudTd>
|
||||
<MudTd DataLabel="Blacklisted">
|
||||
<MudIconButton Size="@Size.Small" Icon="@Icons.Material.Filled.Block" Color="@(context.Blacklisted? Color.Secondary: Color.Dark)" />
|
||||
</MudTd>
|
||||
</RowTemplate>
|
||||
</MudTable>
|
||||
|
||||
<JPagination PageNumber="PageNumber" PageNumberChanged="OnPageNumberChanged" PageSize="PageSize" PageSizeChanged="OnPageSizeChanged" @bind-TotalItems="searchResults.TotalItems" />
|
||||
}
|
||||
<AntDesign.Table DataSource="@(searchResults?.Items ?? Enumerable.Empty<CreatorSearchItem>())"
|
||||
Total="@(searchResults?.TotalItems ?? 0)"
|
||||
TItem="CreatorSearchItem"
|
||||
Loading="LoadingData"
|
||||
HidePagination="@true"
|
||||
RemoteDataSource="@true"
|
||||
RowKey="x=>x.CreatorId"
|
||||
OnChange="HandleTableChange">
|
||||
<ColumnDefinitions>
|
||||
<AntDesign.PropertyColumn Property="c => c.Name" Title="Name" Sortable="true" SorterMultiple="4" />
|
||||
<AntDesign.PropertyColumn Property="c => c.VoiceWorkCount" Title="Voice Works" Format="n0" HeaderStyle="width: 14em" Sortable="true" SorterMultiple="4" />
|
||||
<AntDesign.PropertyColumn Property="c => c.Favorite" Title="Favorite" HeaderStyle="width: 8em" Sortable="true" SortDirections="new[] { AntDesign.SortDirection.Descending }" SorterMultiple="4">
|
||||
@if (context.Favorite)
|
||||
{
|
||||
<AntDesign.Tag Color="AntDesign.TagColor.PurpleInverse">Favorite</AntDesign.Tag>
|
||||
}
|
||||
</AntDesign.PropertyColumn>
|
||||
<AntDesign.PropertyColumn Property="c => c.Blacklisted" Title="Blacklisted" HeaderStyle="width: 8em" Sortable="true" SortDirections="new[] { AntDesign.SortDirection.Descending }" SorterMultiple="4">
|
||||
@if (context.Blacklisted)
|
||||
{
|
||||
<AntDesign.Tag Color="AntDesign.TagColor.RedInverse">Blacklisted</AntDesign.Tag>
|
||||
}
|
||||
</AntDesign.PropertyColumn>
|
||||
@* <AntDesign.ActionColumn HeaderStyle="width: 2em">
|
||||
<AntDesign.Dropdown Trigger="@(new AntDesign.Trigger[] { AntDesign.Trigger.Click })">
|
||||
<Overlay>
|
||||
<AntDesign.Menu>
|
||||
<AntDesign.MenuItem>
|
||||
<span>Some Menu Item</span>
|
||||
</AntDesign.MenuItem>
|
||||
</AntDesign.Menu>
|
||||
</Overlay>
|
||||
<ChildContent>
|
||||
<AntDesign.Button Shape="AntDesign.ButtonShape.Circle" Icon="@AntDesign.IconType.Outline.More" Type="AntDesign.ButtonType.Default"></AntDesign.Button>
|
||||
</ChildContent>
|
||||
</AntDesign.Dropdown>
|
||||
</AntDesign.ActionColumn> *@
|
||||
</ColumnDefinitions>
|
||||
</AntDesign.Table>
|
||||
|
||||
<JPagination PageNumber="PageNumber" PageNumberChanged="OnPageNumberChanged" PageSize="PageSize" PageSizeChanged="OnPageSizeChanged" TotalItems="TotalItems" />
|
||||
|
||||
<style>
|
||||
.mud-table-root {
|
||||
@@ -66,12 +77,15 @@ else
|
||||
public string? Keywords { get; set; }
|
||||
public int PageNumber { get; set; } = 1;
|
||||
public int PageSize { get; set; } = 100;
|
||||
public int TotalItems => searchResults?.TotalItems ?? 0;
|
||||
|
||||
public bool LoadingData { get; set; }
|
||||
|
||||
SearchResult<CreatorSearchItem>? searchResults;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
await UpdateDataAsync(true);
|
||||
//await UpdateDataAsync(true);
|
||||
}
|
||||
|
||||
public async Task OnKeywordsChanged(string? newKeywords)
|
||||
@@ -102,6 +116,8 @@ else
|
||||
|
||||
private async Task LoadCreatorsAsync()
|
||||
{
|
||||
LoadingData = true;
|
||||
|
||||
SearchCreatorsRequest request = new(
|
||||
Options: new()
|
||||
{
|
||||
@@ -111,10 +127,7 @@ else
|
||||
{
|
||||
Name = Keywords
|
||||
},
|
||||
SortOptions =
|
||||
[
|
||||
new(CreatorSortField.Name, Application.Common.Search.SortDirection.Ascending)
|
||||
]
|
||||
SortOptions = [.. _sortOptions]
|
||||
}
|
||||
);
|
||||
|
||||
@@ -123,6 +136,68 @@ else
|
||||
|
||||
searchResults = result?.Results ?? new();
|
||||
|
||||
LoadingData = false;
|
||||
|
||||
//await InvokeAsync(StateHasChanged);
|
||||
}
|
||||
|
||||
private List<SortOption<CreatorSortField>> _sortOptions =
|
||||
[
|
||||
new(CreatorSortField.Name, Application.Common.Search.SortDirection.Ascending)
|
||||
];
|
||||
|
||||
private async Task HandleTableChange(AntDesign.TableModels.QueryModel<CreatorSearchItem> queryModel)
|
||||
{
|
||||
//PageNumber = queryModel.PageIndex;
|
||||
//PageSize = queryModel.PageSize;
|
||||
|
||||
_sortOptions = MapSortOptions(queryModel);
|
||||
|
||||
await LoadCreatorsAsync();
|
||||
}
|
||||
|
||||
private List<SortOption<CreatorSortField>> MapSortOptions(AntDesign.TableModels.QueryModel<CreatorSearchItem> queryModel)
|
||||
{
|
||||
var requestedSorts = queryModel.SortModel
|
||||
.Select(sort => new
|
||||
{
|
||||
Field = sort.FieldName switch
|
||||
{
|
||||
nameof(CreatorSearchItem.Favorite) => CreatorSortField.Favorite,
|
||||
nameof(CreatorSearchItem.Blacklisted) => CreatorSortField.Blacklisted,
|
||||
nameof(CreatorSearchItem.VoiceWorkCount) => CreatorSortField.VoiceWorkCount,
|
||||
nameof(CreatorSearchItem.Name) => CreatorSortField.Name,
|
||||
_ => (CreatorSortField?)null
|
||||
},
|
||||
Direction = sort.SortDirection switch
|
||||
{
|
||||
AntDesign.SortDirection.Ascending => Application.Common.Search.SortDirection.Ascending,
|
||||
AntDesign.SortDirection.Descending => Application.Common.Search.SortDirection.Descending,
|
||||
_ => (Application.Common.Search.SortDirection?)null
|
||||
}
|
||||
})
|
||||
.Where(x => x.Field is not null && x.Direction is not null)
|
||||
.ToDictionary(x => x.Field!.Value, x => x.Direction!.Value);
|
||||
|
||||
var finalSorts = new List<SortOption<CreatorSortField>>();
|
||||
|
||||
// Force your preferred precedence
|
||||
if (requestedSorts.TryGetValue(CreatorSortField.Favorite, out var favoriteDir))
|
||||
finalSorts.Add(new(CreatorSortField.Favorite, favoriteDir));
|
||||
|
||||
if (requestedSorts.TryGetValue(CreatorSortField.Blacklisted, out var blacklistedDir))
|
||||
finalSorts.Add(new(CreatorSortField.Blacklisted, blacklistedDir));
|
||||
|
||||
if (requestedSorts.TryGetValue(CreatorSortField.VoiceWorkCount, out var countDir))
|
||||
finalSorts.Add(new(CreatorSortField.VoiceWorkCount, countDir));
|
||||
|
||||
if (requestedSorts.TryGetValue(CreatorSortField.Name, out var nameDir))
|
||||
finalSorts.Add(new(CreatorSortField.Name, nameDir));
|
||||
|
||||
// Default fallback
|
||||
if (finalSorts.Count == 0)
|
||||
finalSorts.Add(new(CreatorSortField.Name, Application.Common.Search.SortDirection.Ascending));
|
||||
|
||||
return finalSorts;
|
||||
}
|
||||
}
|
||||
@@ -11,44 +11,54 @@
|
||||
|
||||
<h1>Tags</h1>
|
||||
|
||||
<MudTextField @bind-Value="Keywords" Immediate="true" DebounceInterval="500" Label="Filter" Variant="MudBlazor.Variant.Text" Adornment="@Adornment.Start" AdornmentIcon="@Icons.Material.Outlined.Search" />
|
||||
<MudTextField T="string" Value="Keywords" ValueChanged="OnKeywordsChanged" Immediate="true" DebounceInterval="500" Label="Filter" Variant="MudBlazor.Variant.Text" Adornment="@Adornment.Start" AdornmentIcon="@Icons.Material.Outlined.Search" />
|
||||
|
||||
@if (searchResults is null)
|
||||
{
|
||||
<p>Loading…</p>
|
||||
}
|
||||
else if (searchResults.Items.Length == 0)
|
||||
{
|
||||
<p>No results.</p>
|
||||
}
|
||||
else
|
||||
{
|
||||
<MudDataGrid Items="@searchResults.Items" Style="table-layout: fixed">
|
||||
<Columns>
|
||||
<PropertyColumn Property="x => x.Name" Title="Name" />
|
||||
<PropertyColumn Property="x => x.EnglishName" Title="English Name" />
|
||||
<PropertyColumn Property="x => x.VoiceWorkCount" Title="Voice Works" HeaderStyle="width: 14em" />
|
||||
<TemplateColumn Title="Favorite" HeaderStyle="width: 8em">
|
||||
<CellTemplate>
|
||||
<MudIconButton Size="@Size.Small" Icon="@Icons.Material.Filled.Favorite" Color="@(context.Item.Favorite ? Color.Secondary : Color.Dark)" @onclick="@(e => IncrementCount(context.Item))" />
|
||||
</CellTemplate>
|
||||
</TemplateColumn>
|
||||
<TemplateColumn Title="Blacklisted" HeaderStyle="width: 8em">
|
||||
<CellTemplate>
|
||||
<MudIconButton Size="@Size.Small" Icon="@Icons.Material.Filled.Block" Color="@(context.Item.Blacklisted? Color.Secondary: Color.Dark)" />
|
||||
</CellTemplate>
|
||||
</TemplateColumn>
|
||||
</Columns>
|
||||
</MudDataGrid>
|
||||
@* <AntDesign.Input @bind-Value="Keywords" DebounceMilliseconds="500" Placeholder="Filter">
|
||||
<Prefix>
|
||||
<AntDesign.Icon Type="@AntDesign.IconType.Outline.Search" />
|
||||
</Prefix>
|
||||
</AntDesign.Input> *@
|
||||
|
||||
<JPagination @bind-PageNumber="PageNumber" @bind-PageSize="PageSize" @bind-TotalItems="searchResults.TotalItems" />
|
||||
}
|
||||
<AntDesign.Table
|
||||
Responsive
|
||||
DataSource="@(searchResults?.Items ?? Enumerable.Empty<TagSearchItem>())"
|
||||
Total="@(searchResults?.TotalItems ?? 0)"
|
||||
TItem="TagSearchItem"
|
||||
Loading="LoadingData"
|
||||
HidePagination="@true"
|
||||
RemoteDataSource="@true"
|
||||
RowKey="x=>x.TagId"
|
||||
OnChange="HandleTableChange">
|
||||
<ColumnDefinitions>
|
||||
<AntDesign.PropertyColumn Property="c => c.Name" Title="Name" Sortable SorterMultiple="5" />
|
||||
<AntDesign.PropertyColumn Property="c => c.EnglishName" Title="English Name" Sortable SorterMultiple="5" />
|
||||
<AntDesign.PropertyColumn Property="c => c.VoiceWorkCount" Title="Voice Works" Format="n0" HeaderStyle="width: 14em" Sortable SorterMultiple="5" />
|
||||
<AntDesign.PropertyColumn Property="c => c.Favorite" Title="Favorite" HeaderStyle="width: 8em" Sortable SortDirections="new[] { AntDesign.SortDirection.Descending }" SorterMultiple="5">
|
||||
@if (context.Favorite)
|
||||
{
|
||||
<AntDesign.Tag Color="AntDesign.TagColor.PurpleInverse">Favorite</AntDesign.Tag>
|
||||
}
|
||||
</AntDesign.PropertyColumn>
|
||||
<AntDesign.PropertyColumn Property="c => c.Blacklisted" Title="Blacklisted" HeaderStyle="width: 9em" Sortable SortDirections="new[] { AntDesign.SortDirection.Descending }" SorterMultiple="5">
|
||||
@if (context.Blacklisted)
|
||||
{
|
||||
<AntDesign.Tag Color="AntDesign.TagColor.RedInverse">Blacklisted</AntDesign.Tag>
|
||||
}
|
||||
</AntDesign.PropertyColumn>
|
||||
</ColumnDefinitions>
|
||||
</AntDesign.Table>
|
||||
|
||||
<JPagination PageNumber="PageNumber" PageNumberChanged="OnPageNumberChanged" PageSize="PageSize" PageSizeChanged="OnPageSizeChanged" TotalItems="TotalItems" />
|
||||
|
||||
<style>
|
||||
.mud-table-root {
|
||||
table-layout: fixed;
|
||||
}
|
||||
|
||||
.ant-table table {
|
||||
table-layout: fixed;
|
||||
}
|
||||
|
||||
.j-pager {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
@@ -62,74 +72,60 @@ else
|
||||
</style>
|
||||
|
||||
@code {
|
||||
private string? keywords;
|
||||
public string? Keywords { get; set; }
|
||||
public int PageNumber { get; set; } = 1;
|
||||
public int PageSize { get; set; } = 100;
|
||||
public int TotalItems => searchResults?.TotalItems ?? 0;
|
||||
|
||||
public string? Keywords
|
||||
{
|
||||
get { return keywords; }
|
||||
set
|
||||
{
|
||||
keywords = value;
|
||||
_ = UpdateDataAsync(true);
|
||||
}
|
||||
}
|
||||
|
||||
private int pageNumber = 1;
|
||||
|
||||
public int PageNumber
|
||||
{
|
||||
get { return pageNumber; }
|
||||
set
|
||||
{
|
||||
pageNumber = value;
|
||||
_ = UpdateDataAsync(false);
|
||||
}
|
||||
}
|
||||
|
||||
int pageSize = 100;
|
||||
|
||||
public int PageSize
|
||||
{
|
||||
get { return pageSize; }
|
||||
set
|
||||
{
|
||||
pageSize = value;
|
||||
_ = UpdateDataAsync(true);
|
||||
}
|
||||
}
|
||||
public bool LoadingData { get; set; }
|
||||
|
||||
SearchResult<TagSearchItem>? searchResults;
|
||||
|
||||
protected override Task OnInitializedAsync()
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
_ = LoadTagsAsync();
|
||||
//await UpdateDataAsync(true);
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
public async Task OnKeywordsChanged(string? newKeywords)
|
||||
{
|
||||
Keywords = newKeywords;
|
||||
await UpdateDataAsync(true);
|
||||
}
|
||||
|
||||
public async Task OnPageNumberChanged(int newPageNumber)
|
||||
{
|
||||
PageNumber = newPageNumber;
|
||||
await UpdateDataAsync(false);
|
||||
}
|
||||
|
||||
public async Task OnPageSizeChanged(int newPageSize)
|
||||
{
|
||||
PageSize = newPageSize;
|
||||
await UpdateDataAsync(true);
|
||||
}
|
||||
|
||||
private async Task UpdateDataAsync(bool resetPageNumber)
|
||||
{
|
||||
if (resetPageNumber)
|
||||
pageNumber = 1;
|
||||
PageNumber = 1;
|
||||
|
||||
await LoadTagsAsync();
|
||||
}
|
||||
|
||||
private async Task LoadTagsAsync()
|
||||
{
|
||||
LoadingData = true;
|
||||
|
||||
SearchTagsRequest request = new(
|
||||
Options: new()
|
||||
{
|
||||
PageNumber = PageNumber,
|
||||
PageSize = pageSize,
|
||||
PageSize = PageSize,
|
||||
Criteria = new()
|
||||
{
|
||||
Name = Keywords
|
||||
},
|
||||
SortOptions =
|
||||
[
|
||||
new(TagSortField.Name, Application.Common.Search.SortDirection.Ascending)
|
||||
]
|
||||
SortOptions = [.. _sortOptions]
|
||||
}
|
||||
);
|
||||
|
||||
@@ -138,11 +134,72 @@ else
|
||||
|
||||
searchResults = result?.Results ?? new();
|
||||
|
||||
await InvokeAsync(StateHasChanged);
|
||||
LoadingData = false;
|
||||
|
||||
//await InvokeAsync(StateHasChanged);
|
||||
}
|
||||
|
||||
private void IncrementCount(TagSearchItem item)
|
||||
private List<SortOption<TagSortField>> _sortOptions =
|
||||
[
|
||||
new(TagSortField.Name, Application.Common.Search.SortDirection.Ascending)
|
||||
];
|
||||
|
||||
private async Task HandleTableChange(AntDesign.TableModels.QueryModel<TagSearchItem> queryModel)
|
||||
{
|
||||
//item.Favorite = !item.Favorite;
|
||||
//PageNumber = queryModel.PageIndex;
|
||||
//PageSize = queryModel.PageSize;
|
||||
|
||||
_sortOptions = MapSortOptions(queryModel);
|
||||
|
||||
await LoadTagsAsync();
|
||||
}
|
||||
|
||||
private List<SortOption<TagSortField>> MapSortOptions(AntDesign.TableModels.QueryModel<TagSearchItem> queryModel)
|
||||
{
|
||||
var requestedSorts = queryModel.SortModel
|
||||
.Select(sort => new
|
||||
{
|
||||
Field = sort.FieldName switch
|
||||
{
|
||||
nameof(TagSearchItem.Favorite) => TagSortField.Favorite,
|
||||
nameof(TagSearchItem.Blacklisted) => TagSortField.Blacklisted,
|
||||
nameof(TagSearchItem.VoiceWorkCount) => TagSortField.VoiceWorkCount,
|
||||
nameof(TagSearchItem.EnglishName) => TagSortField.EnglishName,
|
||||
nameof(TagSearchItem.Name) => TagSortField.Name,
|
||||
_ => (TagSortField?)null
|
||||
},
|
||||
Direction = sort.SortDirection switch
|
||||
{
|
||||
AntDesign.SortDirection.Ascending => Application.Common.Search.SortDirection.Ascending,
|
||||
AntDesign.SortDirection.Descending => Application.Common.Search.SortDirection.Descending,
|
||||
_ => (Application.Common.Search.SortDirection?)null
|
||||
}
|
||||
})
|
||||
.Where(x => x.Field is not null && x.Direction is not null)
|
||||
.ToDictionary(x => x.Field!.Value, x => x.Direction!.Value);
|
||||
|
||||
var finalSorts = new List<SortOption<TagSortField>>();
|
||||
|
||||
// Force your preferred precedence
|
||||
if (requestedSorts.TryGetValue(TagSortField.Favorite, out var favoriteDir))
|
||||
finalSorts.Add(new(TagSortField.Favorite, favoriteDir));
|
||||
|
||||
if (requestedSorts.TryGetValue(TagSortField.Blacklisted, out var blacklistedDir))
|
||||
finalSorts.Add(new(TagSortField.Blacklisted, blacklistedDir));
|
||||
|
||||
if (requestedSorts.TryGetValue(TagSortField.VoiceWorkCount, out var countDir))
|
||||
finalSorts.Add(new(TagSortField.VoiceWorkCount, countDir));
|
||||
|
||||
if (requestedSorts.TryGetValue(TagSortField.EnglishName, out var englishNameDir))
|
||||
finalSorts.Add(new(TagSortField.EnglishName, englishNameDir));
|
||||
|
||||
if (requestedSorts.TryGetValue(TagSortField.Name, out var nameDir))
|
||||
finalSorts.Add(new(TagSortField.Name, nameDir));
|
||||
|
||||
// Default fallback
|
||||
if (finalSorts.Count == 0)
|
||||
finalSorts.Add(new(TagSortField.Name, Application.Common.Search.SortDirection.Ascending));
|
||||
|
||||
return finalSorts;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user