diff --git a/src/DevilDaggersInfo.Web.Client/DevilDaggersInfo.Web.Client.csproj b/src/DevilDaggersInfo.Web.Client/DevilDaggersInfo.Web.Client.csproj index 977cb0d6d..56dfdde25 100644 --- a/src/DevilDaggersInfo.Web.Client/DevilDaggersInfo.Web.Client.csproj +++ b/src/DevilDaggersInfo.Web.Client/DevilDaggersInfo.Web.Client.csproj @@ -14,6 +14,7 @@ + diff --git a/src/DevilDaggersInfo.Web.Client/HttpClients/AdminApiHttpClient.cs b/src/DevilDaggersInfo.Web.Client/HttpClients/AdminApiHttpClient.cs index ab8f6b37b..401bb05c8 100644 --- a/src/DevilDaggersInfo.Web.Client/HttpClients/AdminApiHttpClient.cs +++ b/src/DevilDaggersInfo.Web.Client/HttpClients/AdminApiHttpClient.cs @@ -37,17 +37,9 @@ public async Task ClearCache(string cacheType) return await SendRequest(HttpMethod.Post, "api/admin/cache/clear-cache", JsonContent.Create(cacheType)); } - public async Task> GetCustomEntries(string? filter, int pageIndex, int pageSize, CustomEntrySorting? sortBy, bool ascending) + public async Task> GetCustomEntries() { - Dictionary queryParameters = new() - { - { nameof(filter), filter }, - { nameof(pageIndex), pageIndex }, - { nameof(pageSize), pageSize }, - { nameof(sortBy), sortBy }, - { nameof(ascending), ascending }, - }; - return await SendGetRequest>(BuildUrlWithQuery("api/admin/custom-entries/", queryParameters)); + return await SendGetRequest>("api/admin/custom-entries/"); } public async Task GetCustomEntryById(int id) diff --git a/src/DevilDaggersInfo.Web.Client/Pages/Admin/CustomEntries/Index.razor b/src/DevilDaggersInfo.Web.Client/Pages/Admin/CustomEntries/Index.razor index da3051f18..5e65937ec 100644 --- a/src/DevilDaggersInfo.Web.Client/Pages/Admin/CustomEntries/Index.razor +++ b/src/DevilDaggersInfo.Web.Client/Pages/Admin/CustomEntries/Index.razor @@ -2,60 +2,63 @@ @inherits BaseAdminPage @using DevilDaggersInfo.Core.Common @using DevilDaggersInfo.Web.ApiSpec.Admin.CustomEntries -@using DevilDaggersInfo.Web.Client.Components.Admin -@using DevilDaggersInfo.Web.Core.Claims +@using Microsoft.AspNetCore.Components.QuickGrid - - - - Id - Name - Player - - - - - - - - - - - - - - - - - - - -
@customLeaderboard.Id
-
@customLeaderboard.SpawnsetName
-
@customLeaderboard.PlayerName
- - - - - - - - - - - - - - - - - -
-
-
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + @code { - // ! Blazor ref. - private AdminOverview _overview = null!; + private readonly PaginationState _pagination = new() { ItemsPerPage = 25 }; + + private IQueryable? _itemsQueryable; + private string _spawnsetNameFilter = string.Empty; + private string _playerNameFilter = string.Empty; + + IQueryable? FilteredItems => _itemsQueryable? + .Where(ce => + ce.SpawnsetName.Contains(_spawnsetNameFilter, StringComparison.CurrentCultureIgnoreCase) && + ce.PlayerName.Contains(_playerNameFilter, StringComparison.CurrentCultureIgnoreCase)); + + protected override async Task OnInitializedAsync() + { + List customEntries = await Http.GetCustomEntries(); + _itemsQueryable = customEntries.AsQueryable(); + } } diff --git a/src/DevilDaggersInfo.Web.Client/Pages/Admin/CustomEntries/Index.razor.css b/src/DevilDaggersInfo.Web.Client/Pages/Admin/CustomEntries/Index.razor.css new file mode 100644 index 000000000..7e06240fb --- /dev/null +++ b/src/DevilDaggersInfo.Web.Client/Pages/Admin/CustomEntries/Index.razor.css @@ -0,0 +1,21 @@ +/* Assign default width to country name column */ +::deep thead .search-box-name { width: 15rem; } + +/* Stop country name text from wrapping, and truncate with ellipsis */ +::deep tbody .search-box-name { + white-space: nowrap; + overflow: hidden; + max-width: 0; + text-overflow: ellipsis; +} + +/* Stop the last page from collapsing to the number of rows on it */ +::deep tr { height: 1.8rem; } + +/* Subtle stripe effect */ +::deep tr:nth-child(even) { background: rgba(255,255,255,0.1); } + +/* Magnifying glass */ +::deep .search-box-name .col-options-button { + background-image: url('data:image/svg+xml;utf8, '); +} diff --git a/src/DevilDaggersInfo.Web.Server.Domain.Admin/Repositories/CustomEntryRepository.cs b/src/DevilDaggersInfo.Web.Server.Domain.Admin/Repositories/CustomEntryRepository.cs index 0ff3f8eff..d3ebf228b 100644 --- a/src/DevilDaggersInfo.Web.Server.Domain.Admin/Repositories/CustomEntryRepository.cs +++ b/src/DevilDaggersInfo.Web.Server.Domain.Admin/Repositories/CustomEntryRepository.cs @@ -1,9 +1,7 @@ -using DevilDaggersInfo.Web.ApiSpec.Admin; using DevilDaggersInfo.Web.ApiSpec.Admin.CustomEntries; using DevilDaggersInfo.Web.Server.Domain.Admin.Converters.DomainToApi; using DevilDaggersInfo.Web.Server.Domain.Entities; using DevilDaggersInfo.Web.Server.Domain.Exceptions; -using DevilDaggersInfo.Web.Server.Domain.Extensions; using Microsoft.EntityFrameworkCore; namespace DevilDaggersInfo.Web.Server.Domain.Admin.Repositories; @@ -17,56 +15,17 @@ public CustomEntryRepository(ApplicationDbContext dbContext) _dbContext = dbContext; } - public async Task> GetCustomEntriesAsync(string? filter, int pageIndex, int pageSize, CustomEntrySorting? sortBy, bool ascending) + public async Task> GetCustomEntriesAsync(CancellationToken cancellationToken) { // ! Navigation property. - IQueryable customEntriesQuery = _dbContext.CustomEntries + List customEntries = await _dbContext.CustomEntries .AsNoTracking() - .Include(ce => ce.Player) + .Include(ce => ce.Player) .Include(ce => ce.CustomLeaderboard) - .ThenInclude(cl => cl!.Spawnset); + .ThenInclude(cl => cl!.Spawnset) + .ToListAsync(cancellationToken); - if (!string.IsNullOrWhiteSpace(filter)) - { - // ! Navigation property. - customEntriesQuery = customEntriesQuery.Where(ce => ce.Player!.PlayerName.Contains(filter) || ce.CustomLeaderboard!.Spawnset!.Name.Contains(filter)); - } - - // ! Navigation property. - customEntriesQuery = sortBy switch - { - CustomEntrySorting.ClientVersion => customEntriesQuery.OrderBy(ce => ce.ClientVersion, ascending).ThenBy(ce => ce.Id), - CustomEntrySorting.DaggersFired => customEntriesQuery.OrderBy(ce => ce.DaggersFired, ascending).ThenBy(ce => ce.Id), - CustomEntrySorting.DaggersHit => customEntriesQuery.OrderBy(ce => ce.DaggersHit, ascending).ThenBy(ce => ce.Id), - CustomEntrySorting.DeathType => customEntriesQuery.OrderBy(ce => ce.DeathType, ascending).ThenBy(ce => ce.Id), - CustomEntrySorting.EnemiesAlive => customEntriesQuery.OrderBy(ce => ce.EnemiesAlive, ascending).ThenBy(ce => ce.Id), - CustomEntrySorting.EnemiesKilled => customEntriesQuery.OrderBy(ce => ce.EnemiesKilled, ascending).ThenBy(ce => ce.Id), - CustomEntrySorting.GemsCollected => customEntriesQuery.OrderBy(ce => ce.GemsCollected, ascending).ThenBy(ce => ce.Id), - CustomEntrySorting.GemsDespawned => customEntriesQuery.OrderBy(ce => ce.GemsDespawned, ascending).ThenBy(ce => ce.Id), - CustomEntrySorting.GemsEaten => customEntriesQuery.OrderBy(ce => ce.GemsEaten, ascending).ThenBy(ce => ce.Id), - CustomEntrySorting.GemsTotal => customEntriesQuery.OrderBy(ce => ce.GemsTotal, ascending).ThenBy(ce => ce.Id), - CustomEntrySorting.HomingStored => customEntriesQuery.OrderBy(ce => ce.HomingStored, ascending).ThenBy(ce => ce.Id), - CustomEntrySorting.HomingEaten => customEntriesQuery.OrderBy(ce => ce.HomingEaten, ascending).ThenBy(ce => ce.Id), - CustomEntrySorting.LevelUpTime2 => customEntriesQuery.OrderBy(ce => ce.LevelUpTime2, ascending).ThenBy(ce => ce.Id), - CustomEntrySorting.LevelUpTime3 => customEntriesQuery.OrderBy(ce => ce.LevelUpTime3, ascending).ThenBy(ce => ce.Id), - CustomEntrySorting.LevelUpTime4 => customEntriesQuery.OrderBy(ce => ce.LevelUpTime4, ascending).ThenBy(ce => ce.Id), - CustomEntrySorting.PlayerName => customEntriesQuery.OrderBy(ce => ce.Player!.PlayerName, ascending).ThenBy(ce => ce.Id), - CustomEntrySorting.SpawnsetName => customEntriesQuery.OrderBy(ce => ce.CustomLeaderboard!.Spawnset!.Name, ascending).ThenBy(ce => ce.Id), - CustomEntrySorting.SubmitDate => customEntriesQuery.OrderBy(ce => ce.SubmitDate, ascending).ThenBy(ce => ce.Id), - CustomEntrySorting.Time => customEntriesQuery.OrderBy(ce => ce.Time, ascending).ThenBy(ce => ce.Id), - _ => customEntriesQuery.OrderBy(ce => ce.Id, ascending), - }; - - List customEntries = await customEntriesQuery - .Skip(pageIndex * pageSize) - .Take(pageSize) - .ToListAsync(); - - return new Page - { - Results = customEntries.ConvertAll(ce => ce.ToAdminApiOverview()), - TotalResults = customEntriesQuery.Count(), - }; + return customEntries.ConvertAll(ce => ce.ToAdminApiOverview()); } public async Task GetCustomEntryAsync(int id) diff --git a/src/DevilDaggersInfo.Web.Server/Controllers/Admin/CustomEntriesController.cs b/src/DevilDaggersInfo.Web.Server/Controllers/Admin/CustomEntriesController.cs index 7d930dd14..a0b44f305 100644 --- a/src/DevilDaggersInfo.Web.Server/Controllers/Admin/CustomEntriesController.cs +++ b/src/DevilDaggersInfo.Web.Server/Controllers/Admin/CustomEntriesController.cs @@ -1,12 +1,9 @@ -using DevilDaggersInfo.Web.ApiSpec.Admin; using DevilDaggersInfo.Web.ApiSpec.Admin.CustomEntries; -using DevilDaggersInfo.Web.Client; using DevilDaggersInfo.Web.Core.Claims; using DevilDaggersInfo.Web.Server.Domain.Admin.Repositories; using DevilDaggersInfo.Web.Server.Domain.Admin.Services; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; -using System.ComponentModel.DataAnnotations; namespace DevilDaggersInfo.Web.Server.Controllers.Admin; @@ -26,13 +23,10 @@ public CustomEntriesController(CustomEntryRepository customEntryRepository, Cust [HttpGet] [ProducesResponseType(StatusCodes.Status200OK)] - public async Task>> GetCustomEntries( - string? filter = null, - [Range(0, 1000)] int pageIndex = 0, - [Range(Constants.PageSizeMin, Constants.PageSizeMax)] int pageSize = Constants.PageSizeDefault, - CustomEntrySorting? sortBy = null, - bool ascending = false) - => await _customEntryRepository.GetCustomEntriesAsync(filter, pageIndex, pageSize, sortBy, ascending); + public async Task>> GetCustomEntries(CancellationToken cancellationToken) + { + return await _customEntryRepository.GetCustomEntriesAsync(cancellationToken); + } [HttpGet("{id}")] [ProducesResponseType(StatusCodes.Status200OK)] diff --git a/src/Directory.Packages.props b/src/Directory.Packages.props index ffa263bb9..ae78325c8 100644 --- a/src/Directory.Packages.props +++ b/src/Directory.Packages.props @@ -2,6 +2,7 @@ +