New Scanner + People Pages (#3286)
Co-authored-by: Robbie Davis <robbie@therobbiedavis.com>
This commit is contained in:
parent
1ed0eae22d
commit
ba20ad4ecc
142 changed files with 17529 additions and 3038 deletions
|
@ -24,6 +24,8 @@ public static class ApplicationServiceExtensions
|
|||
{
|
||||
services.AddAutoMapper(typeof(AutoMapperProfiles).Assembly);
|
||||
|
||||
//services.AddScoped<DataContext>();
|
||||
|
||||
services.AddScoped<IUnitOfWork, UnitOfWork>();
|
||||
services.AddScoped<ITokenService, TokenService>();
|
||||
services.AddScoped<IFileService, FileService>();
|
||||
|
@ -45,7 +47,6 @@ public static class ApplicationServiceExtensions
|
|||
services.AddScoped<IBookmarkService, BookmarkService>();
|
||||
services.AddScoped<IThemeService, ThemeService>();
|
||||
services.AddScoped<ISeriesService, SeriesService>();
|
||||
services.AddScoped<IProcessSeries, ProcessSeries>();
|
||||
services.AddScoped<IReadingListService, ReadingListService>();
|
||||
services.AddScoped<IDeviceService, DeviceService>();
|
||||
services.AddScoped<IStatisticService, StatisticService>();
|
||||
|
@ -55,12 +56,12 @@ public static class ApplicationServiceExtensions
|
|||
services.AddScoped<IStreamService, StreamService>();
|
||||
|
||||
services.AddScoped<IScannerService, ScannerService>();
|
||||
services.AddScoped<IProcessSeries, ProcessSeries>();
|
||||
services.AddScoped<IMetadataService, MetadataService>();
|
||||
services.AddScoped<IWordCountAnalyzerService, WordCountAnalyzerService>();
|
||||
services.AddScoped<ILibraryWatcher, LibraryWatcher>();
|
||||
services.AddScoped<ITachiyomiService, TachiyomiService>();
|
||||
services.AddScoped<ICollectionTagService, CollectionTagService>();
|
||||
services.AddScoped<ITagManagerService, TagManagerService>();
|
||||
|
||||
services.AddScoped<IFileSystem, FileSystem>();
|
||||
services.AddScoped<IDirectoryService, DirectoryService>();
|
||||
|
|
|
@ -4,6 +4,7 @@ using API.Data.Misc;
|
|||
using API.Data.Repositories;
|
||||
using API.Entities;
|
||||
using API.Entities.Metadata;
|
||||
using AutoMapper.QueryableExtensions;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace API.Extensions.QueryExtensions.Filtering;
|
||||
|
@ -45,10 +46,25 @@ public static class SearchQueryableExtensions
|
|||
public static IQueryable<Person> SearchPeople(this IQueryable<SeriesMetadata> queryable,
|
||||
string searchQuery, IEnumerable<int> seriesIds)
|
||||
{
|
||||
return queryable
|
||||
// Get people from SeriesMetadata
|
||||
var peopleFromSeriesMetadata = queryable
|
||||
.Where(sm => seriesIds.Contains(sm.SeriesId))
|
||||
.SelectMany(sm => sm.People.Where(t => t.Name != null && EF.Functions.Like(t.Name, $"%{searchQuery}%")))
|
||||
.AsSplitQuery()
|
||||
.SelectMany(sm => sm.People)
|
||||
.Where(p => p.Person.Name != null && EF.Functions.Like(p.Person.Name, $"%{searchQuery}%"))
|
||||
.Select(p => p.Person);
|
||||
|
||||
// Get people from ChapterPeople by navigating through Volume -> Series
|
||||
var peopleFromChapterPeople = queryable
|
||||
.Where(sm => seriesIds.Contains(sm.SeriesId))
|
||||
.SelectMany(sm => sm.Series.Volumes)
|
||||
.SelectMany(v => v.Chapters)
|
||||
.SelectMany(ch => ch.People)
|
||||
.Where(cp => cp.Person.Name != null && EF.Functions.Like(cp.Person.Name, $"%{searchQuery}%"))
|
||||
.Select(cp => cp.Person);
|
||||
|
||||
// Combine both queries and ensure distinct results
|
||||
return peopleFromSeriesMetadata
|
||||
.Union(peopleFromChapterPeople)
|
||||
.Distinct()
|
||||
.OrderBy(p => p.NormalizedName);
|
||||
}
|
||||
|
|
|
@ -471,22 +471,22 @@ public static class SeriesFilter
|
|||
{
|
||||
case FilterComparison.Equal:
|
||||
case FilterComparison.Contains:
|
||||
return queryable.Where(s => s.Metadata.People.Any(p => people.Contains(p.Id)));
|
||||
return queryable.Where(s => s.Metadata.People.Any(p => people.Contains(p.PersonId)));
|
||||
case FilterComparison.NotEqual:
|
||||
case FilterComparison.NotContains:
|
||||
return queryable.Where(s => s.Metadata.People.All(t => !people.Contains(t.Id)));
|
||||
return queryable.Where(s => s.Metadata.People.All(t => !people.Contains(t.PersonId)));
|
||||
case FilterComparison.MustContains:
|
||||
// Deconstruct and do a Union of a bunch of where statements since this doesn't translate
|
||||
var queries = new List<IQueryable<Series>>()
|
||||
{
|
||||
queryable
|
||||
};
|
||||
queries.AddRange(people.Select(gId => queryable.Where(s => s.Metadata.People.Any(p => p.Id == gId))));
|
||||
queries.AddRange(people.Select(gId => queryable.Where(s => s.Metadata.People.Any(p => p.PersonId == gId))));
|
||||
|
||||
return queries.Aggregate((q1, q2) => q1.Intersect(q2));
|
||||
case FilterComparison.IsEmpty:
|
||||
// Check if there are no people with specific roles (e.g., Writer, Penciller, etc.)
|
||||
return queryable.Where(s => !s.Metadata.People.Any(p => p.Role == role));
|
||||
return queryable.Where(s => s.Metadata.People.All(p => p.Role != role));
|
||||
case FilterComparison.GreaterThan:
|
||||
case FilterComparison.GreaterThanEqual:
|
||||
case FilterComparison.LessThan:
|
||||
|
@ -513,17 +513,17 @@ public static class SeriesFilter
|
|||
{
|
||||
case FilterComparison.Equal:
|
||||
case FilterComparison.Contains:
|
||||
return queryable.Where(s => s.Metadata.People.Any(p => people.Contains(p.Id)));
|
||||
return queryable.Where(s => s.Metadata.People.Any(p => people.Contains(p.PersonId)));
|
||||
case FilterComparison.NotEqual:
|
||||
case FilterComparison.NotContains:
|
||||
return queryable.Where(s => s.Metadata.People.All(t => !people.Contains(t.Id)));
|
||||
return queryable.Where(s => s.Metadata.People.All(t => !people.Contains(t.PersonId)));
|
||||
case FilterComparison.MustContains:
|
||||
// Deconstruct and do a Union of a bunch of where statements since this doesn't translate
|
||||
var queries = new List<IQueryable<Series>>()
|
||||
{
|
||||
queryable
|
||||
};
|
||||
queries.AddRange(people.Select(gId => queryable.Where(s => s.Metadata.People.Any(p => p.Id == gId))));
|
||||
queries.AddRange(people.Select(gId => queryable.Where(s => s.Metadata.People.Any(p => p.PersonId == gId))));
|
||||
|
||||
return queries.Aggregate((q1, q2) => q1.Intersect(q2));
|
||||
case FilterComparison.IsEmpty:
|
||||
|
|
|
@ -56,7 +56,8 @@ public static class IncludesExtensions
|
|||
if (includes.HasFlag(ChapterIncludes.People))
|
||||
{
|
||||
queryable = queryable
|
||||
.Include(c => c.People);
|
||||
.Include(c => c.People)
|
||||
.ThenInclude(cp => cp.Person);
|
||||
}
|
||||
|
||||
if (includes.HasFlag(ChapterIncludes.Genres))
|
||||
|
@ -161,17 +162,16 @@ public static class IncludesExtensions
|
|||
|
||||
if (includeFlags.HasFlag(SeriesIncludes.Metadata))
|
||||
{
|
||||
query = query.Include(s => s.Metadata)
|
||||
.ThenInclude(m => m.CollectionTags.OrderBy(g => g.NormalizedTitle))
|
||||
query = query
|
||||
.Include(s => s.Metadata)
|
||||
.ThenInclude(m => m.Genres.OrderBy(g => g.NormalizedTitle))
|
||||
.Include(s => s.Metadata)
|
||||
.ThenInclude(m => m.People)
|
||||
.ThenInclude(smp => smp.Person)
|
||||
.Include(s => s.Metadata)
|
||||
.ThenInclude(m => m.Tags.OrderBy(g => g.NormalizedTitle));
|
||||
}
|
||||
|
||||
|
||||
return query.AsSplitQuery();
|
||||
}
|
||||
|
||||
|
|
|
@ -25,6 +25,19 @@ public static class RestrictByAgeExtensions
|
|||
return q;
|
||||
}
|
||||
|
||||
public static IQueryable<Chapter> RestrictAgainstAgeRestriction(this IQueryable<Chapter> queryable, AgeRestriction restriction)
|
||||
{
|
||||
if (restriction.AgeRating == AgeRating.NotApplicable) return queryable;
|
||||
var q = queryable.Where(chapter => chapter.Volume.Series.Metadata.AgeRating <= restriction.AgeRating);
|
||||
|
||||
if (!restriction.IncludeUnknowns)
|
||||
{
|
||||
return q.Where(s => s.Volume.Series.Metadata.AgeRating != AgeRating.Unknown);
|
||||
}
|
||||
|
||||
return q;
|
||||
}
|
||||
|
||||
[Obsolete]
|
||||
public static IQueryable<CollectionTag> RestrictAgainstAgeRestriction(this IQueryable<CollectionTag> queryable, AgeRestriction restriction)
|
||||
{
|
||||
|
@ -88,12 +101,12 @@ public static class RestrictByAgeExtensions
|
|||
|
||||
if (restriction.IncludeUnknowns)
|
||||
{
|
||||
return queryable.Where(c => c.SeriesMetadatas.All(sm =>
|
||||
sm.AgeRating <= restriction.AgeRating));
|
||||
return queryable.Where(c => c.SeriesMetadataPeople.All(sm =>
|
||||
sm.SeriesMetadata.AgeRating <= restriction.AgeRating));
|
||||
}
|
||||
|
||||
return queryable.Where(c => c.SeriesMetadatas.All(sm =>
|
||||
sm.AgeRating <= restriction.AgeRating && sm.AgeRating > AgeRating.Unknown));
|
||||
return queryable.Where(c => c.SeriesMetadataPeople.All(sm =>
|
||||
sm.SeriesMetadata.AgeRating <= restriction.AgeRating && sm.SeriesMetadata.AgeRating > AgeRating.Unknown));
|
||||
}
|
||||
|
||||
public static IQueryable<ReadingList> RestrictAgainstAgeRestriction(this IQueryable<ReadingList> queryable, AgeRestriction restriction)
|
||||
|
|
|
@ -28,6 +28,12 @@ public static class SeriesExtensions
|
|||
firstVolume = volumes[1];
|
||||
}
|
||||
|
||||
// If the first volume is 0, then use Volume 1
|
||||
if (firstVolume.MinNumber.Is(0f) && volumes.Count > 1)
|
||||
{
|
||||
firstVolume = volumes[1];
|
||||
}
|
||||
|
||||
var chapters = firstVolume.Chapters
|
||||
.OrderBy(c => c.SortOrder)
|
||||
.ToList();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue