Automatic Collection Creation (#1768)
* Made the unread badges slightly smaller and rounded on top right. * A bit more tweaks on the not read badges. Looking really nice now. * In order to start the work on managing collections from ScanLoop, I needed to refactor collection apis into the service layer and add unit tests. Removed ToUpper Normalization for new tags. * Hooked up ability to auto generate collections from SeriesGroup metadata tag.
This commit is contained in:
parent
91a2a6854f
commit
1da27f085c
26 changed files with 2222 additions and 121 deletions
|
@ -6,7 +6,10 @@ using API.Data;
|
|||
using API.DTOs.CollectionTags;
|
||||
using API.Entities.Metadata;
|
||||
using API.Extensions;
|
||||
using API.Services;
|
||||
using API.Services.Tasks.Metadata;
|
||||
using API.SignalR;
|
||||
using Kavita.Common;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
|
@ -18,13 +21,13 @@ namespace API.Controllers;
|
|||
public class CollectionController : BaseApiController
|
||||
{
|
||||
private readonly IUnitOfWork _unitOfWork;
|
||||
private readonly IEventHub _eventHub;
|
||||
private readonly ICollectionTagService _collectionService;
|
||||
|
||||
/// <inheritdoc />
|
||||
public CollectionController(IUnitOfWork unitOfWork, IEventHub eventHub)
|
||||
public CollectionController(IUnitOfWork unitOfWork, ICollectionTagService collectionService)
|
||||
{
|
||||
_unitOfWork = unitOfWork;
|
||||
_eventHub = eventHub;
|
||||
_collectionService = collectionService;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -71,8 +74,7 @@ public class CollectionController : BaseApiController
|
|||
[HttpGet("name-exists")]
|
||||
public async Task<ActionResult<bool>> DoesNameExists(string name)
|
||||
{
|
||||
if (string.IsNullOrEmpty(name.Trim())) return Ok(true);
|
||||
return Ok(await _unitOfWork.CollectionTagRepository.TagExists(name));
|
||||
return Ok(await _collectionService.TagExistsByName(name));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -85,28 +87,13 @@ public class CollectionController : BaseApiController
|
|||
[HttpPost("update")]
|
||||
public async Task<ActionResult> UpdateTag(CollectionTagDto updatedTag)
|
||||
{
|
||||
var existingTag = await _unitOfWork.CollectionTagRepository.GetTagAsync(updatedTag.Id);
|
||||
if (existingTag == null) return BadRequest("This tag does not exist");
|
||||
var title = updatedTag.Title.Trim();
|
||||
if (string.IsNullOrEmpty(title)) return BadRequest("Title cannot be empty");
|
||||
if (!title.Equals(existingTag.Title) && await _unitOfWork.CollectionTagRepository.TagExists(updatedTag.Title))
|
||||
return BadRequest("A tag with this name already exists");
|
||||
|
||||
existingTag.Title = title;
|
||||
existingTag.Promoted = updatedTag.Promoted;
|
||||
existingTag.NormalizedTitle = Services.Tasks.Scanner.Parser.Parser.Normalize(updatedTag.Title);
|
||||
existingTag.Summary = updatedTag.Summary.Trim();
|
||||
|
||||
if (_unitOfWork.HasChanges())
|
||||
try
|
||||
{
|
||||
if (await _unitOfWork.CommitAsync())
|
||||
{
|
||||
return Ok("Tag updated successfully");
|
||||
}
|
||||
if (await _collectionService.UpdateTag(updatedTag)) return Ok("Tag updated successfully");
|
||||
}
|
||||
else
|
||||
catch (KavitaException ex)
|
||||
{
|
||||
return Ok("Tag updated successfully");
|
||||
return BadRequest(ex.Message);
|
||||
}
|
||||
|
||||
return BadRequest("Something went wrong, please try again");
|
||||
|
@ -121,29 +108,11 @@ public class CollectionController : BaseApiController
|
|||
[HttpPost("update-for-series")]
|
||||
public async Task<ActionResult> AddToMultipleSeries(CollectionTagBulkAddDto dto)
|
||||
{
|
||||
var tag = await _unitOfWork.CollectionTagRepository.GetFullTagAsync(dto.CollectionTagId);
|
||||
if (tag == null)
|
||||
{
|
||||
tag = DbFactory.CollectionTag(0, dto.CollectionTagTitle, String.Empty, false);
|
||||
_unitOfWork.CollectionTagRepository.Add(tag);
|
||||
}
|
||||
// Create a new tag and save
|
||||
var tag = await _collectionService.GetTagOrCreate(dto.CollectionTagId, dto.CollectionTagTitle);
|
||||
|
||||
if (await _collectionService.AddTagToSeries(tag, dto.SeriesIds)) return Ok();
|
||||
|
||||
var seriesMetadatas = await _unitOfWork.SeriesRepository.GetSeriesMetadataForIdsAsync(dto.SeriesIds);
|
||||
foreach (var metadata in seriesMetadatas)
|
||||
{
|
||||
if (!metadata.CollectionTags.Any(t => t.Title.Equals(tag.Title, StringComparison.InvariantCulture)))
|
||||
{
|
||||
metadata.CollectionTags.Add(tag);
|
||||
_unitOfWork.SeriesMetadataRepository.Update(metadata);
|
||||
}
|
||||
}
|
||||
|
||||
if (!_unitOfWork.HasChanges()) return Ok();
|
||||
if (await _unitOfWork.CommitAsync())
|
||||
{
|
||||
return Ok();
|
||||
}
|
||||
return BadRequest("There was an issue updating series with collection tag");
|
||||
}
|
||||
|
||||
|
@ -154,7 +123,7 @@ public class CollectionController : BaseApiController
|
|||
/// <returns></returns>
|
||||
[Authorize(Policy = "RequireAdminRole")]
|
||||
[HttpPost("update-series")]
|
||||
public async Task<ActionResult> UpdateSeriesForTag(UpdateSeriesForTagDto updateSeriesForTagDto)
|
||||
public async Task<ActionResult> RemoveTagFromMultipleSeries(UpdateSeriesForTagDto updateSeriesForTagDto)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
@ -162,41 +131,8 @@ public class CollectionController : BaseApiController
|
|||
if (tag == null) return BadRequest("Not a valid Tag");
|
||||
tag.SeriesMetadatas ??= new List<SeriesMetadata>();
|
||||
|
||||
// Check if Tag has updated (Summary)
|
||||
if (tag.Summary == null || !tag.Summary.Equals(updateSeriesForTagDto.Tag.Summary))
|
||||
{
|
||||
tag.Summary = updateSeriesForTagDto.Tag.Summary;
|
||||
_unitOfWork.CollectionTagRepository.Update(tag);
|
||||
}
|
||||
|
||||
tag.CoverImageLocked = updateSeriesForTagDto.Tag.CoverImageLocked;
|
||||
|
||||
if (!updateSeriesForTagDto.Tag.CoverImageLocked)
|
||||
{
|
||||
tag.CoverImageLocked = false;
|
||||
tag.CoverImage = string.Empty;
|
||||
await _eventHub.SendMessageAsync(MessageFactory.CoverUpdate,
|
||||
MessageFactory.CoverUpdateEvent(tag.Id, MessageFactoryEntityTypes.CollectionTag), false);
|
||||
_unitOfWork.CollectionTagRepository.Update(tag);
|
||||
}
|
||||
|
||||
foreach (var seriesIdToRemove in updateSeriesForTagDto.SeriesIdsToRemove)
|
||||
{
|
||||
tag.SeriesMetadatas.Remove(tag.SeriesMetadatas.Single(sm => sm.SeriesId == seriesIdToRemove));
|
||||
}
|
||||
|
||||
|
||||
if (tag.SeriesMetadatas.Count == 0)
|
||||
{
|
||||
_unitOfWork.CollectionTagRepository.Remove(tag);
|
||||
}
|
||||
|
||||
if (!_unitOfWork.HasChanges()) return Ok("No updates");
|
||||
|
||||
if (await _unitOfWork.CommitAsync())
|
||||
{
|
||||
if (await _collectionService.RemoveTagFromSeries(tag, updateSeriesForTagDto.SeriesIdsToRemove))
|
||||
return Ok("Tag updated");
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
|
|
|
@ -247,11 +247,9 @@ public class LibraryController : BaseApiController
|
|||
var library = await _unitOfWork.LibraryRepository.GetLibraryForIdAsync(libraryId, LibraryIncludes.None);
|
||||
if (TaskScheduler.HasScanTaskRunningForLibrary(libraryId))
|
||||
{
|
||||
// TODO: Figure out how to cancel a job
|
||||
|
||||
_logger.LogInformation("User is attempting to delete a library while a scan is in progress");
|
||||
return BadRequest(
|
||||
"You cannot delete a library while a scan is in progress. Please wait for scan to continue then try to delete");
|
||||
"You cannot delete a library while a scan is in progress. Please wait for scan to complete or restart Kavita then try to delete");
|
||||
}
|
||||
|
||||
// Due to a bad schema that I can't figure out how to fix, we need to erase all RelatedSeries before we delete the library
|
||||
|
@ -336,6 +334,7 @@ public class LibraryController : BaseApiController
|
|||
library.IncludeInDashboard = dto.IncludeInDashboard;
|
||||
library.IncludeInRecommended = dto.IncludeInRecommended;
|
||||
library.IncludeInSearch = dto.IncludeInSearch;
|
||||
library.ManageCollections = dto.CreateCollections;
|
||||
|
||||
_unitOfWork.LibraryRepository.Update(library);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue