diff --git a/back/src/Kyoo.Abstractions/Module.cs b/back/src/Kyoo.Abstractions/Module.cs index 1abfd1e9..373fcd8c 100644 --- a/back/src/Kyoo.Abstractions/Module.cs +++ b/back/src/Kyoo.Abstractions/Module.cs @@ -42,6 +42,7 @@ namespace Kyoo.Abstractions where T : IBaseRepository { return builder.RegisterType() + .AsSelf() .As() .As(Utility.GetGenericDefinition(typeof(T), typeof(IRepository<>))!) .InstancePerLifetimeScope(); @@ -62,7 +63,7 @@ namespace Kyoo.Abstractions where T : notnull where T2 : IBaseRepository, T { - return builder.RegisterRepository().As(); + return builder.RegisterRepository().AsSelf().As(); } } } diff --git a/back/src/Kyoo.Core/Controllers/Repositories/CollectionRepository.cs b/back/src/Kyoo.Core/Controllers/Repositories/CollectionRepository.cs index a8fe9241..6d219148 100644 --- a/back/src/Kyoo.Core/Controllers/Repositories/CollectionRepository.cs +++ b/back/src/Kyoo.Core/Controllers/Repositories/CollectionRepository.cs @@ -19,6 +19,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Linq.Expressions; using System.Threading.Tasks; using Kyoo.Abstractions.Controllers; using Kyoo.Abstractions.Models; @@ -81,6 +82,18 @@ namespace Kyoo.Core.Controllers throw new ArgumentException("The collection's name must be set and not empty"); } + public async Task AddMovie(int id, int movieId) + { + _database.AddLinks(id, movieId); + await _database.SaveChangesAsync(); + } + + public async Task AddShow(int id, int showId) + { + _database.AddLinks(id, showId); + await _database.SaveChangesAsync(); + } + /// public override async Task Delete(Collection obj) { diff --git a/back/src/Kyoo.Core/Views/Resources/CollectionApi.cs b/back/src/Kyoo.Core/Views/Resources/CollectionApi.cs index 137a5797..497df34a 100644 --- a/back/src/Kyoo.Core/Views/Resources/CollectionApi.cs +++ b/back/src/Kyoo.Core/Views/Resources/CollectionApi.cs @@ -24,6 +24,7 @@ using Kyoo.Abstractions.Models; using Kyoo.Abstractions.Models.Attributes; using Kyoo.Abstractions.Models.Permissions; using Kyoo.Abstractions.Models.Utils; +using Kyoo.Core.Controllers; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using static Kyoo.Abstractions.Models.Utils.Constants; @@ -40,23 +41,78 @@ namespace Kyoo.Core.Api [ApiDefinition("Collections", Group = ResourcesGroup)] public class CollectionApi : CrudThumbsApi { - /// - /// The library manager used to modify or retrieve information about the data store. - /// private readonly ILibraryManager _libraryManager; + private readonly CollectionRepository _collections; - /// - /// Create a new . - /// - /// - /// The library manager used to modify or retrieve information about the data store. - /// - /// The thumbnail manager used to retrieve images paths. public CollectionApi(ILibraryManager libraryManager, + CollectionRepository collections, IThumbnailsManager thumbs) : base(libraryManager.Collections, thumbs) { _libraryManager = libraryManager; + _collections = collections; + } + + /// + /// Add a movie + /// + /// + /// Add a movie in the collection. + /// + /// The ID or slug of the . + /// The ID or slug of the to add. + /// Nothing if successful. + /// No collection or movie with the given ID could be found. + /// The specified movie is already in this collection. + [HttpPut("{identifier:id}/movies/{movie:id}")] + [HttpPut("{identifier:id}/movie/{movie:id}", Order = AlternativeRoute)] + [PartialPermission(Kind.Write)] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status409Conflict)] + public async Task AddMovie(Identifier identifier, Identifier movie) + { + int collectionId = await identifier.Match( + async id => (await _libraryManager.Collections.Get(id)).Id, + async slug => (await _libraryManager.Collections.Get(slug)).Id + ); + int movieId = await movie.Match( + async id => (await _libraryManager.Movies.Get(id)).Id, + async slug => (await _libraryManager.Movies.Get(slug)).Id + ); + await _collections.AddMovie(collectionId, movieId); + return NoContent(); + } + + /// + /// Add a show + /// + /// + /// Add a show in the collection. + /// + /// The ID or slug of the . + /// The ID or slug of the to add. + /// Nothing if successful. + /// No collection or show with the given ID could be found. + /// The specified show is already in this collection. + [HttpPut("{identifier:id}/shows/{show:id}")] + [HttpPut("{identifier:id}/show/{show:id}", Order = AlternativeRoute)] + [PartialPermission(Kind.Write)] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status409Conflict)] + public async Task AddShow(Identifier identifier, Identifier show) + { + int collectionId = await identifier.Match( + async id => (await _libraryManager.Collections.Get(id)).Id, + async slug => (await _libraryManager.Collections.Get(slug)).Id + ); + int showId = await show.Match( + async id => (await _libraryManager.Shows.Get(id)).Id, + async slug => (await _libraryManager.Shows.Get(slug)).Id + ); + await _collections.AddShow(collectionId, showId); + return NoContent(); } /// @@ -83,11 +139,11 @@ namespace Kyoo.Core.Api [FromQuery] Sort sortBy, [FromQuery] Dictionary where, [FromQuery] Pagination pagination, - [FromQuery] Include fields) + [FromQuery] Include? fields) { ICollection resources = await _libraryManager.Shows.GetAll( ApiHelper.ParseWhere(where, identifier.IsContainedIn(x => x.Collections!)), - sortBy, + sortBy ?? new Sort.By(x => x.StartAir), pagination, fields ); diff --git a/back/src/Kyoo.Postgresql/DatabaseContext.cs b/back/src/Kyoo.Postgresql/DatabaseContext.cs index 4399841d..9509da6b 100644 --- a/back/src/Kyoo.Postgresql/DatabaseContext.cs +++ b/back/src/Kyoo.Postgresql/DatabaseContext.cs @@ -116,13 +116,12 @@ namespace Kyoo.Postgresql /// The ID of the second resource. /// The first resource type of the relation. It is the owner of the second /// The second resource type of the relation. It is the contained resource. - /// A representing the asynchronous operation. - public async Task AddLinks(int first, int second) + public void AddLinks(int first, int second) where T1 : class, IResource where T2 : class, IResource { - await Set>(LinkName()) - .AddAsync(new Dictionary + Set>(LinkName()) + .Add(new Dictionary { [LinkNameFk()] = first, [LinkNameFk()] = second