diff --git a/back/src/Kyoo.Abstractions/Models/Resources/Season.cs b/back/src/Kyoo.Abstractions/Models/Resources/Season.cs index fbe62588..2b7d38d2 100644 --- a/back/src/Kyoo.Abstractions/Models/Resources/Season.cs +++ b/back/src/Kyoo.Abstractions/Models/Resources/Season.cs @@ -137,7 +137,7 @@ namespace Kyoo.Abstractions.Models from episodes as e where - e.season_id = id) as episode_count + e.season_id = id) as episodes_count """ )] public int EpisodesCount { get; set; } diff --git a/back/src/Kyoo.Abstractions/Models/Resources/Show.cs b/back/src/Kyoo.Abstractions/Models/Resources/Show.cs index bb5311fd..8c2a6897 100644 --- a/back/src/Kyoo.Abstractions/Models/Resources/Show.cs +++ b/back/src/Kyoo.Abstractions/Models/Resources/Show.cs @@ -179,10 +179,22 @@ namespace Kyoo.Abstractions.Models .FirstOrDefault(); /// - /// The number of episodes in this season. + /// The number of episodes in this show. /// [Projectable(UseMemberBody = nameof(_EpisodesCount), OnlyOnInclude = true)] [NotMapped] + [LoadableRelation( + // language=PostgreSQL + Projected = """ + ( + select + count(*)::int + from + episodes as e + where + e.show_id = "this".id) as episodes_count + """ + )] public int EpisodesCount { get; set; } private int _EpisodesCount => Episodes!.Count; diff --git a/back/src/Kyoo.Core/Controllers/Repositories/DapperHelper.cs b/back/src/Kyoo.Core/Controllers/Repositories/DapperHelper.cs index fba4c5b4..cfe8cc49 100644 --- a/back/src/Kyoo.Core/Controllers/Repositories/DapperHelper.cs +++ b/back/src/Kyoo.Core/Controllers/Repositories/DapperHelper.cs @@ -204,13 +204,14 @@ public static class DapperHelper return $"\nwhere {Process(filter)}"; } - public static string ExpendProjections(string type, string? prefix, Include include) + public static string ExpendProjections(Type type, string? prefix, Include include) { IEnumerable projections = include.Metadatas - .Select(x => x is Include.ProjectedRelation(var name, var sql) ? sql : null!) + .Select(x => (x as Include.ProjectedRelation)!) .Where(x => x != null) - .Select(x => x.Replace("\"this\".", prefix)); - return string.Join(string.Empty, projections.Select(x => $", {x}")); + .Where(x => type.GetProperty(x.Name) != null) + .Select(x => x.Sql.Replace("\"this\".", prefix)); + return string.Join(", ", projections); } public static async Task> Query( @@ -265,18 +266,20 @@ public static class DapperHelper string? prefix = match.Groups[4].Value; prefix = !string.IsNullOrEmpty(prefix) ? $"{prefix}." : string.Empty; + Type typeV = types.First(x => x.Name == type); + // Only project top level items with explicit includes. string? projection = config.Any(x => x.Value.Name == type) - ? ExpendProjections(type, prefix, include) + ? ExpendProjections(typeV, prefix, include) : null; - Type? typeV = types.FirstOrDefault(x => x.Name == type); - if (typeV?.IsAssignableTo(typeof(IThumbnails)) == true) + + if (typeV.IsAssignableTo(typeof(IThumbnails))) { string posterProj = string.Join(", ", new[] { "poster", "thumbnail", "logo" } .Select(x => $"{prefix}{x}_source as source, {prefix}{x}_blurhash as blurhash")); projection = string.IsNullOrEmpty(projection) ? posterProj - : $"{posterProj}, {projection}"; + : $"{projection}, {posterProj}"; types.InsertRange(types.IndexOf(typeV) + 1, Enumerable.Repeat(typeof(Image), 3)); } diff --git a/back/src/Kyoo.Core/Controllers/Repositories/WatchStatusRepository.cs b/back/src/Kyoo.Core/Controllers/Repositories/WatchStatusRepository.cs index dd17cf86..d27f3e32 100644 --- a/back/src/Kyoo.Core/Controllers/Repositories/WatchStatusRepository.cs +++ b/back/src/Kyoo.Core/Controllers/Repositories/WatchStatusRepository.cs @@ -19,7 +19,6 @@ using System; using System.ComponentModel.DataAnnotations; using System.Linq; -using System.Text.Json; using System.Threading.Tasks; using Kyoo.Abstractions.Controllers; using Kyoo.Abstractions.Models; diff --git a/front/packages/models/src/resources/show.ts b/front/packages/models/src/resources/show.ts index 0fa3b97c..7c5fce74 100644 --- a/front/packages/models/src/resources/show.ts +++ b/front/packages/models/src/resources/show.ts @@ -89,14 +89,6 @@ export const ShowP = withImages( * The studio that made this show. */ studio: StudioP.optional().nullable(), - /** - * The collection this movie is part of. - */ - collections: z.array(CollectionP).optional(), - /** - * The list of seasons of this show. - */ - seasons: z.array(SeasonP).optional(), /** * The first episode of this show */ @@ -109,6 +101,10 @@ export const ShowP = withImages( * Metadata of what an user as started/planned to watch. */ watchStatus: ShowWatchStatusP.nullable().optional(), + /** + * The number of episodes in this show. + */ + episodesCount: z.number().int().gte(0).optional(), }), "shows", )