diff --git a/API.Tests/Services/SeriesServiceTests.cs b/API.Tests/Services/SeriesServiceTests.cs index d7c7f32d3..762a0ed9a 100644 --- a/API.Tests/Services/SeriesServiceTests.cs +++ b/API.Tests/Services/SeriesServiceTests.cs @@ -8,9 +8,10 @@ using API.Data.Repositories; using API.DTOs; using API.DTOs.CollectionTags; using API.DTOs.Metadata; -using API.DTOs.Reader; +using API.DTOs.SeriesDetail; using API.Entities; using API.Entities.Enums; +using API.Entities.Metadata; using API.Extensions; using API.Helpers; using API.Services; @@ -22,10 +23,7 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.Extensions.Logging; using NSubstitute; -using NSubstitute.Extensions; -using NSubstitute.ReceivedExtensions; using Xunit; -using Xunit.Sdk; namespace API.Tests.Services; @@ -127,6 +125,26 @@ public class SeriesServiceTests return fileSystem; } + private static UpdateRelatedSeriesDto InstantiateRelationsDto(Series series) + { + return new UpdateRelatedSeriesDto() + { + SeriesId = series.Id, + Prequels = new List(), + Adaptations = new List(), + Characters = new List(), + Contains = new List(), + Doujinshis = new List(), + Others = new List(), + Sequels = new List(), + AlternativeSettings = new List(), + AlternativeVersions = new List(), + SideStories = new List(), + SpinOffs = new List(), + Editions = new List() + }; + } + #endregion #region SeriesDetail @@ -1119,4 +1137,221 @@ public class SeriesServiceTests } #endregion + + #region SeriesRelation + [Fact] + public async Task UpdateRelatedSeries_ShouldAddAllRelations() + { + await ResetDb(); + _context.Library.Add(new Library() + { + AppUsers = new List() + { + new AppUser() + { + UserName = "majora2007" + } + }, + Name = "Test LIb", + Type = LibraryType.Book, + Series = new List() + { + new Series() + { + Name = "Test Series", + Volumes = new List(){} + }, + new Series() + { + Name = "Test Series Prequels", + Volumes = new List(){} + }, + new Series() + { + Name = "Test Series Sequels", + Volumes = new List(){} + } + } + }); + + await _context.SaveChangesAsync(); + + var series1 = await _unitOfWork.SeriesRepository.GetSeriesByIdAsync(1, SeriesIncludes.Related); + // Add relations + var addRelationDto = InstantiateRelationsDto(series1); + addRelationDto.Adaptations.Add(2); + addRelationDto.Sequels.Add(3); + await _seriesService.UpdateRelatedSeries(addRelationDto); + Assert.Equal(2, series1.Relations.Single(s => s.TargetSeriesId == 2).TargetSeriesId); + Assert.Equal(3, series1.Relations.Single(s => s.TargetSeriesId == 3).TargetSeriesId); + } + + [Fact] + public async Task UpdateRelatedSeries_DeleteAllRelations() + { + await ResetDb(); + _context.Library.Add(new Library() + { + AppUsers = new List() + { + new AppUser() + { + UserName = "majora2007" + } + }, + Name = "Test LIb", + Type = LibraryType.Book, + Series = new List() + { + new Series() + { + Name = "Test Series", + Volumes = new List(){} + }, + new Series() + { + Name = "Test Series Prequels", + Volumes = new List(){} + }, + new Series() + { + Name = "Test Series Sequels", + Volumes = new List(){} + } + } + }); + + await _context.SaveChangesAsync(); + + var series1 = await _unitOfWork.SeriesRepository.GetSeriesByIdAsync(1, SeriesIncludes.Related); + // Add relations + var addRelationDto = InstantiateRelationsDto(series1); + addRelationDto.Adaptations.Add(2); + addRelationDto.Sequels.Add(3); + await _seriesService.UpdateRelatedSeries(addRelationDto); + Assert.Equal(2, series1.Relations.Single(s => s.TargetSeriesId == 2).TargetSeriesId); + Assert.Equal(3, series1.Relations.Single(s => s.TargetSeriesId == 3).TargetSeriesId); + + // Remove relations + var removeRelationDto = InstantiateRelationsDto(series1); + await _seriesService.UpdateRelatedSeries(removeRelationDto); + Assert.Empty(series1.Relations.Where(s => s.TargetSeriesId == 1)); + Assert.Empty(series1.Relations.Where(s => s.TargetSeriesId == 2)); + } + + [Fact] + public async Task UpdateRelatedSeries_ShouldNotAllowDuplicates() + { + await ResetDb(); + _context.Library.Add(new Library() + { + AppUsers = new List() + { + new AppUser() + { + UserName = "majora2007" + } + }, + Name = "Test LIb", + Type = LibraryType.Book, + Series = new List() + { + new Series() + { + Name = "Test Series", + Volumes = new List(){} + }, + new Series() + { + Name = "Test Series Prequels", + Volumes = new List(){} + } + } + }); + + await _context.SaveChangesAsync(); + + var series1 = await _unitOfWork.SeriesRepository.GetSeriesByIdAsync(1, SeriesIncludes.Related); + var relation = new SeriesRelation() + { + Series = series1, + SeriesId = series1.Id, + TargetSeriesId = 2, // Target series id + RelationKind = RelationKind.Prequel + + }; + // Manually create a relation + series1.Relations.Add(relation); + + // Create a new dto with the previous relation as well + var relationDto = InstantiateRelationsDto(series1); + relationDto.Adaptations.Add(2); + + await _seriesService.UpdateRelatedSeries(relationDto); + // Expected is only one instance of the relation (hence not duping) + Assert.Equal(2, series1.Relations.Single(s => s.TargetSeriesId == 2).TargetSeriesId); + } + + [Fact] + public async Task GetRelatedSeries_EditionPrequelSequel_ShouldNotHaveParent() + { + await ResetDb(); + _context.Library.Add(new Library() + { + AppUsers = new List() + { + new AppUser() + { + UserName = "majora2007" + } + }, + Name = "Test LIb", + Type = LibraryType.Book, + Series = new List() + { + new Series() + { + Name = "Test Series", + Volumes = new List(){} + }, + new Series() + { + Name = "Test Series Editions", + Volumes = new List(){} + }, + new Series() + { + Name = "Test Series Prequels", + Volumes = new List(){} + }, + new Series() + { + Name = "Test Series Sequels", + Volumes = new List(){} + }, + new Series() + { + Name = "Test Series Adaption", + Volumes = new List(){} + } + } + }); + await _context.SaveChangesAsync(); + var series1 = await _unitOfWork.SeriesRepository.GetSeriesByIdAsync(1, SeriesIncludes.Related); + // Add relations + var addRelationDto = InstantiateRelationsDto(series1); + addRelationDto.Editions.Add(2); + addRelationDto.Prequels.Add(3); + addRelationDto.Sequels.Add(4); + addRelationDto.Adaptations.Add(5); + await _seriesService.UpdateRelatedSeries(addRelationDto); + + + Assert.Empty(_seriesService.GetRelatedSeries(1, 2).Result.Parent); + Assert.Empty(_seriesService.GetRelatedSeries(1, 3).Result.Parent); + Assert.Empty(_seriesService.GetRelatedSeries(1, 4).Result.Parent); + Assert.NotEmpty(_seriesService.GetRelatedSeries(1, 5).Result.Parent); + } + + #endregion } diff --git a/API/Controllers/SeriesController.cs b/API/Controllers/SeriesController.cs index e6c97ea1c..6e37da199 100644 --- a/API/Controllers/SeriesController.cs +++ b/API/Controllers/SeriesController.cs @@ -416,7 +416,7 @@ public class SeriesController : BaseApiController public async Task> GetAllRelatedSeries(int seriesId) { var userId = await _unitOfWork.UserRepository.GetUserIdByUsernameAsync(User.GetUsername()); - return Ok(await _unitOfWork.SeriesRepository.GetRelatedSeries(userId, seriesId)); + return Ok(await _seriesService.GetRelatedSeries(userId, seriesId)); } @@ -429,52 +429,12 @@ public class SeriesController : BaseApiController [HttpPost("update-related")] public async Task UpdateRelatedSeries(UpdateRelatedSeriesDto dto) { - var series = await _unitOfWork.SeriesRepository.GetSeriesByIdAsync(dto.SeriesId, SeriesIncludes.Related); - - UpdateRelationForKind(dto.Adaptations, series.Relations.Where(r => r.RelationKind == RelationKind.Adaptation).ToList(), series, RelationKind.Adaptation); - UpdateRelationForKind(dto.Characters, series.Relations.Where(r => r.RelationKind == RelationKind.Character).ToList(), series, RelationKind.Character); - UpdateRelationForKind(dto.Contains, series.Relations.Where(r => r.RelationKind == RelationKind.Contains).ToList(), series, RelationKind.Contains); - UpdateRelationForKind(dto.Others, series.Relations.Where(r => r.RelationKind == RelationKind.Other).ToList(), series, RelationKind.Other); - UpdateRelationForKind(dto.SideStories, series.Relations.Where(r => r.RelationKind == RelationKind.SideStory).ToList(), series, RelationKind.SideStory); - UpdateRelationForKind(dto.SpinOffs, series.Relations.Where(r => r.RelationKind == RelationKind.SpinOff).ToList(), series, RelationKind.SpinOff); - UpdateRelationForKind(dto.AlternativeSettings, series.Relations.Where(r => r.RelationKind == RelationKind.AlternativeSetting).ToList(), series, RelationKind.AlternativeSetting); - UpdateRelationForKind(dto.AlternativeVersions, series.Relations.Where(r => r.RelationKind == RelationKind.AlternativeVersion).ToList(), series, RelationKind.AlternativeVersion); - UpdateRelationForKind(dto.Doujinshis, series.Relations.Where(r => r.RelationKind == RelationKind.Doujinshi).ToList(), series, RelationKind.Doujinshi); - UpdateRelationForKind(dto.Prequels, series.Relations.Where(r => r.RelationKind == RelationKind.Prequel).ToList(), series, RelationKind.Prequel); - UpdateRelationForKind(dto.Sequels, series.Relations.Where(r => r.RelationKind == RelationKind.Sequel).ToList(), series, RelationKind.Sequel); - - if (!_unitOfWork.HasChanges()) return Ok(); - if (await _unitOfWork.CommitAsync()) return Ok(); - + if (await _seriesService.UpdateRelatedSeries(dto)) + { + return Ok(); + } return BadRequest("There was an issue updating relationships"); } - // TODO: Move this to a Service and Unit Test it - private void UpdateRelationForKind(ICollection dtoTargetSeriesIds, IEnumerable adaptations, Series series, RelationKind kind) - { - foreach (var adaptation in adaptations.Where(adaptation => !dtoTargetSeriesIds.Contains(adaptation.TargetSeriesId))) - { - // If the seriesId isn't in dto, it means we've removed or reclassified - series.Relations.Remove(adaptation); - } - - // At this point, we only have things to add - foreach (var targetSeriesId in dtoTargetSeriesIds) - { - // This ensures we don't allow any duplicates to be added - if (series.Relations.SingleOrDefault(r => - r.RelationKind == kind && r.TargetSeriesId == targetSeriesId) != - null) continue; - - series.Relations.Add(new SeriesRelation() - { - Series = series, - SeriesId = series.Id, - TargetSeriesId = targetSeriesId, - RelationKind = kind - }); - _unitOfWork.SeriesRepository.Update(series); - } - } } diff --git a/API/DTOs/SeriesDetail/RelatedSeriesDto.cs b/API/DTOs/SeriesDetail/RelatedSeriesDto.cs index f3c3fd644..452da9cf5 100644 --- a/API/DTOs/SeriesDetail/RelatedSeriesDto.cs +++ b/API/DTOs/SeriesDetail/RelatedSeriesDto.cs @@ -22,4 +22,5 @@ public class RelatedSeriesDto public IEnumerable AlternativeVersions { get; set; } public IEnumerable Doujinshis { get; set; } public IEnumerable Parent { get; set; } + public IEnumerable Editions { get; set; } } diff --git a/API/DTOs/SeriesDetail/UpdateRelatedSeriesDto.cs b/API/DTOs/SeriesDetail/UpdateRelatedSeriesDto.cs index b39f91244..d6976a05d 100644 --- a/API/DTOs/SeriesDetail/UpdateRelatedSeriesDto.cs +++ b/API/DTOs/SeriesDetail/UpdateRelatedSeriesDto.cs @@ -16,4 +16,5 @@ public class UpdateRelatedSeriesDto public IList AlternativeSettings { get; set; } public IList AlternativeVersions { get; set; } public IList Doujinshis { get; set; } + public IList Editions { get; set; } } diff --git a/API/Data/Repositories/SeriesRepository.cs b/API/Data/Repositories/SeriesRepository.cs index 73ed20cca..21de38ce2 100644 --- a/API/Data/Repositories/SeriesRepository.cs +++ b/API/Data/Repositories/SeriesRepository.cs @@ -1408,13 +1408,15 @@ public class SeriesRepository : ISeriesRepository s.RelationOf.Where(r => r.TargetSeriesId == seriesId && usersSeriesIds.Contains(r.TargetSeriesId) && r.RelationKind != RelationKind.Prequel - && r.RelationKind != RelationKind.Sequel) + && r.RelationKind != RelationKind.Sequel + && r.RelationKind != RelationKind.Edition) .Select(sr => sr.Series)) .RestrictAgainstAgeRestriction(userRating) .AsSplitQuery() .AsNoTracking() .ProjectTo(_mapper.ConfigurationProvider) - .ToListAsync() + .ToListAsync(), + Editions = await GetRelatedSeriesQuery(seriesId, usersSeriesIds, RelationKind.Edition, userRating) }; } diff --git a/API/Entities/Enums/RelationKind.cs b/API/Entities/Enums/RelationKind.cs index c01ab9571..aa10e6816 100644 --- a/API/Entities/Enums/RelationKind.cs +++ b/API/Entities/Enums/RelationKind.cs @@ -61,6 +61,16 @@ public enum RelationKind /// Doujinshi or Fan work /// [Description("Doujinshi")] - Doujinshi = 11 + Doujinshi = 11, + /// + /// This is a UI field only. Not to be used in backend + /// + [Description("Parent")] + Parent = 12, + /// + /// Same story, could be translation, colorization... Different edition of the series + /// + [Description("Edition")] + Edition = 13 } diff --git a/API/Services/SeriesService.cs b/API/Services/SeriesService.cs index 27f4cbc55..bba9876d2 100644 --- a/API/Services/SeriesService.cs +++ b/API/Services/SeriesService.cs @@ -5,12 +5,14 @@ using System.Linq; using System.Threading.Tasks; using API.Comparators; using API.Data; +using API.Data.Repositories; using API.DTOs; using API.DTOs.CollectionTags; using API.DTOs.Metadata; using API.DTOs.SeriesDetail; using API.Entities; using API.Entities.Enums; +using API.Entities.Metadata; using API.Helpers; using API.SignalR; using Microsoft.AspNetCore.Mvc; @@ -25,7 +27,8 @@ public interface ISeriesService Task UpdateSeriesMetadata(UpdateSeriesMetadataDto updateSeriesMetadataDto); Task UpdateRating(AppUser user, UpdateSeriesRatingDto updateSeriesRatingDto); Task DeleteMultipleSeries(IList seriesIds); - + Task UpdateRelatedSeries(UpdateRelatedSeriesDto dto); + Task GetRelatedSeries(int userId, int seriesId); } public class SeriesService : ISeriesService @@ -624,4 +627,76 @@ public class SeriesService : ISeriesService _ => "Chapter" }; } + + /// + /// Returns all related series against the passed series Id + /// + /// + /// + /// + public async Task GetRelatedSeries(int userId, int seriesId) + { + return await _unitOfWork.SeriesRepository.GetRelatedSeries(userId, seriesId); + } + + /// + /// Update the relations attached to the Series. Does not generate associated Sequel/Prequel pairs on target series. + /// + /// + /// + public async Task UpdateRelatedSeries(UpdateRelatedSeriesDto dto) + { + var series = await _unitOfWork.SeriesRepository.GetSeriesByIdAsync(dto.SeriesId, SeriesIncludes.Related); + + UpdateRelationForKind(dto.Adaptations, series.Relations.Where(r => r.RelationKind == RelationKind.Adaptation).ToList(), series, RelationKind.Adaptation); + UpdateRelationForKind(dto.Characters, series.Relations.Where(r => r.RelationKind == RelationKind.Character).ToList(), series, RelationKind.Character); + UpdateRelationForKind(dto.Contains, series.Relations.Where(r => r.RelationKind == RelationKind.Contains).ToList(), series, RelationKind.Contains); + UpdateRelationForKind(dto.Others, series.Relations.Where(r => r.RelationKind == RelationKind.Other).ToList(), series, RelationKind.Other); + UpdateRelationForKind(dto.SideStories, series.Relations.Where(r => r.RelationKind == RelationKind.SideStory).ToList(), series, RelationKind.SideStory); + UpdateRelationForKind(dto.SpinOffs, series.Relations.Where(r => r.RelationKind == RelationKind.SpinOff).ToList(), series, RelationKind.SpinOff); + UpdateRelationForKind(dto.AlternativeSettings, series.Relations.Where(r => r.RelationKind == RelationKind.AlternativeSetting).ToList(), series, RelationKind.AlternativeSetting); + UpdateRelationForKind(dto.AlternativeVersions, series.Relations.Where(r => r.RelationKind == RelationKind.AlternativeVersion).ToList(), series, RelationKind.AlternativeVersion); + UpdateRelationForKind(dto.Doujinshis, series.Relations.Where(r => r.RelationKind == RelationKind.Doujinshi).ToList(), series, RelationKind.Doujinshi); + UpdateRelationForKind(dto.Prequels, series.Relations.Where(r => r.RelationKind == RelationKind.Prequel).ToList(), series, RelationKind.Prequel); + UpdateRelationForKind(dto.Sequels, series.Relations.Where(r => r.RelationKind == RelationKind.Sequel).ToList(), series, RelationKind.Sequel); + UpdateRelationForKind(dto.Editions, series.Relations.Where(r => r.RelationKind == RelationKind.Edition).ToList(), series, RelationKind.Edition); + + if (!_unitOfWork.HasChanges()) return true; + return await _unitOfWork.CommitAsync(); + } + + + /// + /// Applies the provided list to the series. Adds new relations and removes deleted relations. + /// + /// + /// + /// + /// + private void UpdateRelationForKind(ICollection dtoTargetSeriesIds, IEnumerable adaptations, Series series, RelationKind kind) + { + foreach (var adaptation in adaptations.Where(adaptation => !dtoTargetSeriesIds.Contains(adaptation.TargetSeriesId))) + { + // If the seriesId isn't in dto, it means we've removed or reclassified + series.Relations.Remove(adaptation); + } + + // At this point, we only have things to add + foreach (var targetSeriesId in dtoTargetSeriesIds) + { + // This ensures we don't allow any duplicates to be added + if (series.Relations.SingleOrDefault(r => + r.RelationKind == kind && r.TargetSeriesId == targetSeriesId) != + null) continue; + + series.Relations.Add(new SeriesRelation() + { + Series = series, + SeriesId = series.Id, + TargetSeriesId = targetSeriesId, + RelationKind = kind + }); + _unitOfWork.SeriesRepository.Update(series); + } + } } diff --git a/UI/Web/src/app/_models/series-detail/related-series.ts b/UI/Web/src/app/_models/series-detail/related-series.ts index 02d394382..f0cfc230b 100644 --- a/UI/Web/src/app/_models/series-detail/related-series.ts +++ b/UI/Web/src/app/_models/series-detail/related-series.ts @@ -14,4 +14,5 @@ export interface RelatedSeries { alternativeVersions: Array; doujinshis: Array; parent: Array; -} \ No newline at end of file + editions: Array; +} diff --git a/UI/Web/src/app/_models/series-detail/relation-kind.ts b/UI/Web/src/app/_models/series-detail/relation-kind.ts index 203401af3..77470041c 100644 --- a/UI/Web/src/app/_models/series-detail/relation-kind.ts +++ b/UI/Web/src/app/_models/series-detail/relation-kind.ts @@ -13,7 +13,8 @@ export enum RelationKind { /** * This is UI only. Backend will generate Parent series for everything but Prequel/Sequel */ - Parent = 12 + Parent = 12, + Edition = 13 } export const RelationKinds = [ @@ -26,6 +27,7 @@ export const RelationKinds = [ {text: 'Side Story', value: RelationKind.SideStory}, {text: 'Character', value: RelationKind.Character}, {text: 'Contains', value: RelationKind.Contains}, + {text: 'Edition', value: RelationKind.Edition}, {text: 'Doujinshi', value: RelationKind.Doujinshi}, {text: 'Other', value: RelationKind.Other}, -]; \ No newline at end of file +]; diff --git a/UI/Web/src/app/_services/series.service.ts b/UI/Web/src/app/_services/series.service.ts index 9a7eb7677..3332fc771 100644 --- a/UI/Web/src/app/_services/series.service.ts +++ b/UI/Web/src/app/_services/series.service.ts @@ -186,13 +186,13 @@ export class SeriesService { return this.httpClient.get(this.baseUrl + 'series/all-related?seriesId=' + seriesId); } - updateRelationships(seriesId: number, adaptations: Array, characters: Array, - contains: Array, others: Array, prequels: Array, + updateRelationships(seriesId: number, adaptations: Array, characters: Array, + contains: Array, others: Array, prequels: Array, sequels: Array, sideStories: Array, spinOffs: Array, - alternativeSettings: Array, alternativeVersions: Array, doujinshis: Array) { - return this.httpClient.post(this.baseUrl + 'series/update-related?seriesId=' + seriesId, + alternativeSettings: Array, alternativeVersions: Array, doujinshis: Array, editions: Array) { + return this.httpClient.post(this.baseUrl + 'series/update-related?seriesId=' + seriesId, {seriesId, adaptations, characters, sequels, prequels, contains, others, sideStories, spinOffs, - alternativeSettings, alternativeVersions, doujinshis}); + alternativeSettings, alternativeVersions, doujinshis, editions}); } getSeriesDetail(seriesId: number) { diff --git a/UI/Web/src/app/cards/edit-series-relation/edit-series-relation.component.ts b/UI/Web/src/app/cards/edit-series-relation/edit-series-relation.component.ts index 31e89c5d5..d44f5535a 100644 --- a/UI/Web/src/app/cards/edit-series-relation/edit-series-relation.component.ts +++ b/UI/Web/src/app/cards/edit-series-relation/edit-series-relation.component.ts @@ -65,6 +65,7 @@ export class EditSeriesRelationComponent implements OnInit, OnDestroy { this.setupRelationRows(relations.doujinshis, RelationKind.Doujinshi); this.setupRelationRows(relations.contains, RelationKind.Contains); this.setupRelationRows(relations.parent, RelationKind.Parent); + this.setupRelationRows(relations.editions, RelationKind.Edition); this.cdRef.detectChanges(); }); @@ -110,7 +111,7 @@ export class EditSeriesRelationComponent implements OnInit, OnDestroy { this.cdRef.markForCheck(); } - + updateSeries(event: Array, relation: RelationControl) { if (event[0] === undefined) { relation.series = undefined; @@ -131,8 +132,8 @@ export class EditSeriesRelationComponent implements OnInit, OnDestroy { seriesSettings.fetchFn = (searchFilter: string) => this.searchService.search(searchFilter).pipe( map(group => group.series), map(items => seriesSettings.compareFn(items, searchFilter)), - map(series => series.filter(s => s.seriesId !== this.series.id)), - ); + map(series => series.filter(s => s.seriesId !== this.series.id)), + ); seriesSettings.compareFn = (options: SearchResult[], filter: string) => { return options.filter(m => this.utilityService.filter(m.name, filter)); @@ -165,10 +166,11 @@ export class EditSeriesRelationComponent implements OnInit, OnDestroy { const alternativeSettings = this.relations.filter(item => (parseInt(item.formControl.value, 10) as RelationKind) === RelationKind.AlternativeSetting && item.series !== undefined).map(item => item.series!.id); const alternativeVersions = this.relations.filter(item => (parseInt(item.formControl.value, 10) as RelationKind) === RelationKind.AlternativeVersion && item.series !== undefined).map(item => item.series!.id); const doujinshis = this.relations.filter(item => (parseInt(item.formControl.value, 10) as RelationKind) === RelationKind.Doujinshi && item.series !== undefined).map(item => item.series!.id); - + const editions = this.relations.filter(item => (parseInt(item.formControl.value, 10) as RelationKind) === RelationKind.Edition && item.series !== undefined).map(item => item.series!.id); + // NOTE: We can actually emit this onto an observable and in main parent, use mergeMap into the forkJoin - this.seriesService.updateRelationships(this.series.id, adaptations, characters, contains, others, prequels, sequels, sideStories, spinOffs, alternativeSettings, alternativeVersions, doujinshis).subscribe(() => {}); - + this.seriesService.updateRelationships(this.series.id, adaptations, characters, contains, others, prequels, sequels, sideStories, spinOffs, alternativeSettings, alternativeVersions, doujinshis, editions).subscribe(() => {}); + } } diff --git a/UI/Web/src/app/pipe/relationship.pipe.ts b/UI/Web/src/app/pipe/relationship.pipe.ts index f1778a5a6..eba8fbfda 100644 --- a/UI/Web/src/app/pipe/relationship.pipe.ts +++ b/UI/Web/src/app/pipe/relationship.pipe.ts @@ -33,6 +33,8 @@ export class RelationshipPipe implements PipeTransform { return 'Spin Off'; case RelationKind.Parent: return 'Parent'; + case RelationKind.Edition: + return 'Edition' default: return ''; } diff --git a/UI/Web/src/app/series-detail/series-detail.component.ts b/UI/Web/src/app/series-detail/series-detail.component.ts index 65e574d32..46f70b2c9 100644 --- a/UI/Web/src/app/series-detail/series-detail.component.ts +++ b/UI/Web/src/app/series-detail/series-detail.component.ts @@ -243,7 +243,7 @@ export class SeriesDetailComponent implements OnInit, OnDestroy, AfterContentChe private downloadService: DownloadService, private actionService: ActionService, public imageSerivce: ImageService, private messageHub: MessageHubService, private readingListService: ReadingListService, public navService: NavService, - private offcanvasService: NgbOffcanvas, @Inject(DOCUMENT) private document: Document, + private offcanvasService: NgbOffcanvas, @Inject(DOCUMENT) private document: Document, private changeDetectionRef: ChangeDetectorRef, private scrollService: ScrollService, private deviceSerivce: DeviceService ) { @@ -453,7 +453,7 @@ export class SeriesDetailComponent implements OnInit, OnDestroy, AfterContentChe this.seriesMetadata = metadata; this.changeDetectionRef.markForCheck(); }); - + this.readingListService.getReadingListsForSeries(seriesId).subscribe(lists => { this.readingLists = lists; this.changeDetectionRef.markForCheck(); @@ -482,16 +482,17 @@ export class SeriesDetailComponent implements OnInit, OnDestroy, AfterContentChe this.relations = [ ...relations.prequels.map(item => this.createRelatedSeries(item, RelationKind.Prequel)), ...relations.sequels.map(item => this.createRelatedSeries(item, RelationKind.Sequel)), - ...relations.sideStories.map(item => this.createRelatedSeries(item, RelationKind.SideStory)), + ...relations.sideStories.map(item => this.createRelatedSeries(item, RelationKind.SideStory)), ...relations.spinOffs.map(item => this.createRelatedSeries(item, RelationKind.SpinOff)), ...relations.adaptations.map(item => this.createRelatedSeries(item, RelationKind.Adaptation)), ...relations.contains.map(item => this.createRelatedSeries(item, RelationKind.Contains)), - ...relations.characters.map(item => this.createRelatedSeries(item, RelationKind.Character)), + ...relations.characters.map(item => this.createRelatedSeries(item, RelationKind.Character)), ...relations.others.map(item => this.createRelatedSeries(item, RelationKind.Other)), ...relations.alternativeSettings.map(item => this.createRelatedSeries(item, RelationKind.AlternativeSetting)), ...relations.alternativeVersions.map(item => this.createRelatedSeries(item, RelationKind.AlternativeVersion)), ...relations.doujinshis.map(item => this.createRelatedSeries(item, RelationKind.Doujinshi)), ...relations.parent.map(item => this.createRelatedSeries(item, RelationKind.Parent)), + ...relations.editions.map(item => this.createRelatedSeries(item, RelationKind.Edition)), ]; if (this.relations.length > 0) { this.hasRelations = true; @@ -690,7 +691,7 @@ export class SeriesDetailComponent implements OnInit, OnDestroy, AfterContentChe this.series = s; this.changeDetectionRef.detectChanges(); }); - + this.loadSeries(this.seriesId); }