Linked Series (#1230)

* Implemented the ability to link different series together through Edit Series. CSS pending.

* Fixed up the css for related cards to show the relation

* Working on making all tabs in edit seris modal save in one go. Taking a break.

* Some fixes for Robbie to help with styling on

* Linked series pill, center library

* Centering library detail and related pill spacing

- Library detail cards are now centered if total number of items is > 6 or if mobile.
- Added ability to determine if mobile (viewport width <= 480px
- Fixed related card spacing
- Fixed related card pill spacing

* Updating relation form spacing

* Fixed a bug in card detail layout when there is no pagination, we create one in a way that all items render at once.

* Only auto-close side nav on phones, not tablets

* Fixed a bug where we had flipped state on sideNavCollapsed$

* Cleaned up some misleading comments

* Implemented RBS back in and now  if you have a relationship besides prequel/sequel, the target series will show a link back to it's parent.

* Added Parentto pipe

* Missed a relationship type

Co-authored-by: Robbie Davis <robbie@therobbiedavis.com>
This commit is contained in:
Joseph Milazzo 2022-04-24 11:59:09 -05:00 committed by GitHub
parent 7253765f1d
commit 4206ae3e22
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
47 changed files with 2571 additions and 195 deletions

View file

@ -6,8 +6,10 @@ using API.Data;
using API.Data.Repositories;
using API.DTOs;
using API.DTOs.Filtering;
using API.DTOs.SeriesDetail;
using API.Entities;
using API.Entities.Enums;
using API.Entities.Metadata;
using API.Extensions;
using API.Helpers;
using API.Services;
@ -339,5 +341,79 @@ namespace API.Controllers
var userId = await _unitOfWork.UserRepository.GetUserIdByUsernameAsync(User.GetUsername());
return await _seriesService.GetSeriesDetail(seriesId, userId);
}
/// <summary>
/// Fetches the related series for a given series
/// </summary>
/// <param name="seriesId"></param>
/// <param name="relation">Type of Relationship to pull back</param>
/// <returns></returns>
[HttpGet("related")]
public async Task<ActionResult<IEnumerable<SeriesDto>>> GetRelatedSeries(int seriesId, RelationKind relation)
{
// Send back a custom DTO with each type or maybe sorted in some way
var userId = await _unitOfWork.UserRepository.GetUserIdByUsernameAsync(User.GetUsername());
return Ok(await _unitOfWork.SeriesRepository.GetSeriesForRelationKind(userId, seriesId, relation));
}
[HttpGet("all-related")]
public async Task<ActionResult<RelatedSeriesDto>> GetAllRelatedSeries(int seriesId)
{
// Send back a custom DTO with each type or maybe sorted in some way
var userId = await _unitOfWork.UserRepository.GetUserIdByUsernameAsync(User.GetUsername());
return Ok(await _unitOfWork.SeriesRepository.GetRelatedSeries(userId, seriesId));
}
[Authorize(Policy="RequireAdminRole")]
[HttpPost("update-related")]
public async Task<ActionResult> 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();
return BadRequest("There was an issue updating relationships");
}
private void UpdateRelationForKind(IList<int> dtoTargetSeriesIds, IEnumerable<SeriesRelation> 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);
}
}
}
}