diff --git a/API/Data/Repositories/UserRepository.cs b/API/Data/Repositories/UserRepository.cs index b2caa9d89..3bf5757bb 100644 --- a/API/Data/Repositories/UserRepository.cs +++ b/API/Data/Repositories/UserRepository.cs @@ -14,6 +14,7 @@ using API.DTOs.SeriesDetail; using API.Entities; using API.Extensions; using API.Extensions.QueryExtensions; +using API.Extensions.QueryExtensions.Filtering; using AutoMapper; using AutoMapper.QueryableExtensions; using Microsoft.AspNetCore.Identity; @@ -389,10 +390,11 @@ public class UserRepository : IUserRepository .ToListAsync(); var queryString = filterStatement.Value.ToNormalized(); - var filterSeriesQuery = query.Join(_context.Series, b => b.SeriesId, s => s.Id, (bookmark, series) => new + var filterSeriesQuery = query.Join(_context.Series, b => b.SeriesId, s => s.Id, + (bookmark, series) => new BookmarkSeriesPair() { - bookmark, - series + bookmark = bookmark, + series = series }); switch (filterStatement.Comparison) @@ -441,14 +443,21 @@ public class UserRepository : IUserRepository break; } - query = filterSeriesQuery.Select(o => o.bookmark); - return await query + return await ApplyLimit(filterSeriesQuery + .Sort(filter.SortOptions) + .AsSplitQuery(), filter.LimitTo) + .Select(o => o.bookmark) .ProjectTo(_mapper.ConfigurationProvider) .ToListAsync(); } + private static IQueryable ApplyLimit(IQueryable query, int limit) + { + return limit <= 0 ? query : query.Take(limit); + } + /// /// Fetches the UserId by API Key. This does not include any extra information /// diff --git a/API/Extensions/QueryExtensions/Filtering/BookmarkSort.cs b/API/Extensions/QueryExtensions/Filtering/BookmarkSort.cs new file mode 100644 index 000000000..d5b1a6d9b --- /dev/null +++ b/API/Extensions/QueryExtensions/Filtering/BookmarkSort.cs @@ -0,0 +1,59 @@ +using System.Linq; +using API.DTOs.Filtering; +using API.Entities; + +namespace API.Extensions.QueryExtensions.Filtering; + +public class BookmarkSeriesPair +{ + public AppUserBookmark bookmark { get; set; } + public Series series { get; set; } +} + +public static class BookmarkSort +{ + /// + /// Applies the correct sort based on + /// + /// + /// + /// + public static IQueryable Sort(this IQueryable query, SortOptions? sortOptions) + { + // If no sort options, default to using SortName + sortOptions ??= new SortOptions() + { + IsAscending = true, + SortField = SortField.SortName + }; + + if (sortOptions.IsAscending) + { + query = sortOptions.SortField switch + { + SortField.SortName => query.OrderBy(s => s.series.SortName.ToLower()), + SortField.CreatedDate => query.OrderBy(s => s.series.Created), + SortField.LastModifiedDate => query.OrderBy(s => s.series.LastModified), + SortField.LastChapterAdded => query.OrderBy(s => s.series.LastChapterAdded), + SortField.TimeToRead => query.OrderBy(s => s.series.AvgHoursToRead), + SortField.ReleaseYear => query.OrderBy(s => s.series.Metadata.ReleaseYear), + _ => query + }; + } + else + { + query = sortOptions.SortField switch + { + SortField.SortName => query.OrderByDescending(s => s.series.SortName.ToLower()), + SortField.CreatedDate => query.OrderByDescending(s => s.series.Created), + SortField.LastModifiedDate => query.OrderByDescending(s => s.series.LastModified), + SortField.LastChapterAdded => query.OrderByDescending(s => s.series.LastChapterAdded), + SortField.TimeToRead => query.OrderByDescending(s => s.series.AvgHoursToRead), + SortField.ReleaseYear => query.OrderByDescending(s => s.series.Metadata.ReleaseYear), + _ => query + }; + } + + return query; + } +} diff --git a/UI/Web/src/app/cards/list-item/list-item.component.html b/UI/Web/src/app/cards/list-item/list-item.component.html index fcc88d32c..3c2db4e3d 100644 --- a/UI/Web/src/app/cards/list-item/list-item.component.html +++ b/UI/Web/src/app/cards/list-item/list-item.component.html @@ -30,7 +30,7 @@ -
+
diff --git a/UI/Web/src/app/dashboard/_components/dashboard.component.ts b/UI/Web/src/app/dashboard/_components/dashboard.component.ts index 2affd8f55..c750fde98 100644 --- a/UI/Web/src/app/dashboard/_components/dashboard.component.ts +++ b/UI/Web/src/app/dashboard/_components/dashboard.component.ts @@ -184,6 +184,7 @@ export class DashboardComponent implements OnInit { const filter = this.filterUtilityService.createSeriesV2Filter(); filter.statements.push({field: FilterField.ReadProgress, comparison: FilterComparison.GreaterThan, value: '0'}); + filter.statements.push({field: FilterField.ReadProgress, comparison: FilterComparison.LessThan, value: '100'}); if (filter.sortOptions) { filter.sortOptions.sortField = SortField.LastChapterAdded; filter.sortOptions.isAscending = false; diff --git a/UI/Web/src/app/series-detail/_components/metadata-detail/metadata-detail.component.html b/UI/Web/src/app/series-detail/_components/metadata-detail/metadata-detail.component.html index 2f3392f01..2f98c87b8 100644 --- a/UI/Web/src/app/series-detail/_components/metadata-detail/metadata-detail.component.html +++ b/UI/Web/src/app/series-detail/_components/metadata-detail/metadata-detail.component.html @@ -1,8 +1,8 @@
-
+
{{heading}}
-
+