Smart Collection UI Changes (#3332)

This commit is contained in:
Joe Milazzo 2024-11-04 11:16:17 -06:00 committed by GitHub
parent dcd281c5c3
commit 9e299d08b9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
29 changed files with 431 additions and 189 deletions

View file

@ -58,16 +58,30 @@ public class ChapterController : BaseApiController
if (chapter == null)
return BadRequest(_localizationService.Translate(User.GetUserId(), "chapter-doesnt-exist"));
var vol = (await _unitOfWork.VolumeRepository.GetVolumeAsync(chapter.VolumeId))!;
_unitOfWork.ChapterRepository.Remove(chapter);
var vol = await _unitOfWork.VolumeRepository.GetVolumeAsync(chapter.VolumeId, VolumeIncludes.Chapters);
if (vol == null) return BadRequest(_localizationService.Translate(User.GetUserId(), "volume-doesnt-exist"));
if (await _unitOfWork.CommitAsync())
// If there is only 1 chapter within the volume, then we need to remove the volume
var needToRemoveVolume = vol.Chapters.Count == 1;
if (needToRemoveVolume)
{
await _eventHub.SendMessageAsync(MessageFactory.ChapterRemoved, MessageFactory.ChapterRemovedEvent(chapter.Id, vol.SeriesId), false);
return Ok(true);
_unitOfWork.VolumeRepository.Remove(vol);
}
else
{
_unitOfWork.ChapterRepository.Remove(chapter);
}
return Ok(false);
if (!await _unitOfWork.CommitAsync()) return Ok(false);
await _eventHub.SendMessageAsync(MessageFactory.ChapterRemoved, MessageFactory.ChapterRemovedEvent(chapter.Id, vol.SeriesId), false);
if (needToRemoveVolume)
{
await _eventHub.SendMessageAsync(MessageFactory.VolumeRemoved, MessageFactory.VolumeRemovedEvent(chapter.VolumeId, vol.SeriesId), false);
}
return Ok(true);
}
/// <summary>

View file

@ -5,6 +5,7 @@ using System.Linq;
using System.Threading.Tasks;
using API.Constants;
using API.Data;
using API.Data.Repositories;
using API.DTOs;
using API.DTOs.Filtering;
using API.DTOs.Metadata;
@ -33,18 +34,12 @@ public class MetadataController(IUnitOfWork unitOfWork, ILocalizationService loc
/// <param name="libraryIds">String separated libraryIds or null for all genres</param>
/// <returns></returns>
[HttpGet("genres")]
[ResponseCache(CacheProfileName = ResponseCacheProfiles.Instant, VaryByQueryKeys = new []{"libraryIds"})]
public async Task<ActionResult<IList<GenreTagDto>>> GetAllGenres(string? libraryIds)
[ResponseCache(CacheProfileName = ResponseCacheProfiles.Instant, VaryByQueryKeys = ["libraryIds", "context"])]
public async Task<ActionResult<IList<GenreTagDto>>> GetAllGenres(string? libraryIds, QueryContext context = QueryContext.None)
{
var ids = libraryIds?.Split(',', StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries).Select(int.Parse).ToList();
// NOTE: libraryIds isn't hooked up in the frontend
if (ids is {Count: > 0})
{
return Ok(await unitOfWork.GenreRepository.GetAllGenreDtosForLibrariesAsync(User.GetUserId(), ids));
}
return Ok(await unitOfWork.GenreRepository.GetAllGenreDtosForLibrariesAsync(User.GetUserId()));
return Ok(await unitOfWork.GenreRepository.GetAllGenreDtosForLibrariesAsync(User.GetUserId(), ids, context));
}
/// <summary>

View file

@ -163,6 +163,7 @@ public class SettingsController : BaseApiController
bookmarkDirectory = _directoryService.BookmarkDirectory;
}
var updateTask = false;
foreach (var setting in currentSettings)
{
if (setting.Key == ServerSettingKey.OnDeckProgressDays &&
@ -204,7 +205,7 @@ public class SettingsController : BaseApiController
_unitOfWork.SettingsRepository.Update(setting);
}
UpdateSchedulingSettings(setting, updateSettingsDto);
updateTask = updateTask || UpdateSchedulingSettings(setting, updateSettingsDto);
UpdateEmailSettings(setting, updateSettingsDto);
@ -348,6 +349,11 @@ public class SettingsController : BaseApiController
UpdateBookmarkDirectory(originalBookmarkDirectory, bookmarkDirectory);
}
if (updateTask)
{
BackgroundJob.Enqueue(() => _taskScheduler.ScheduleTasks());
}
if (updateSettingsDto.EnableFolderWatching)
{
BackgroundJob.Enqueue(() => _libraryWatcher.StartWatching());
@ -379,25 +385,31 @@ public class SettingsController : BaseApiController
_directoryService.ClearAndDeleteDirectory(originalBookmarkDirectory);
}
private void UpdateSchedulingSettings(ServerSetting setting, ServerSettingDto updateSettingsDto)
private bool UpdateSchedulingSettings(ServerSetting setting, ServerSettingDto updateSettingsDto)
{
if (setting.Key == ServerSettingKey.TaskBackup && updateSettingsDto.TaskBackup != setting.Value)
{
//if (updateSettingsDto.TotalBackup)
setting.Value = updateSettingsDto.TaskBackup;
_unitOfWork.SettingsRepository.Update(setting);
return true;
}
if (setting.Key == ServerSettingKey.TaskScan && updateSettingsDto.TaskScan != setting.Value)
{
setting.Value = updateSettingsDto.TaskScan;
_unitOfWork.SettingsRepository.Update(setting);
return true;
}
if (setting.Key == ServerSettingKey.TaskCleanup && updateSettingsDto.TaskCleanup != setting.Value)
{
setting.Value = updateSettingsDto.TaskCleanup;
_unitOfWork.SettingsRepository.Update(setting);
return true;
}
return false;
}
private void UpdateEmailSettings(ServerSetting setting, ServerSettingDto updateSettingsDto)

View file

@ -21,7 +21,7 @@ public interface IGenreRepository
Task<IList<Genre>> GetAllGenresAsync();
Task<IList<Genre>> GetAllGenresByNamesAsync(IEnumerable<string> normalizedNames);
Task RemoveAllGenreNoLongerAssociated(bool removeExternal = false);
Task<IList<GenreTagDto>> GetAllGenreDtosForLibrariesAsync(int userId, IList<int>? libraryIds = null);
Task<IList<GenreTagDto>> GetAllGenreDtosForLibrariesAsync(int userId, IList<int>? libraryIds = null, QueryContext context = QueryContext.None);
Task<int> GetCountAsync();
Task<GenreTagDto> GetRandomGenre();
Task<GenreTagDto> GetGenreById(int id);
@ -115,10 +115,10 @@ public class GenreRepository : IGenreRepository
/// <param name="userId"></param>
/// <param name="libraryIds"></param>
/// <returns></returns>
public async Task<IList<GenreTagDto>> GetAllGenreDtosForLibrariesAsync(int userId, IList<int>? libraryIds = null)
public async Task<IList<GenreTagDto>> GetAllGenreDtosForLibrariesAsync(int userId, IList<int>? libraryIds = null, QueryContext context = QueryContext.None)
{
var userRating = await _context.AppUser.GetUserAgeRestriction(userId);
var userLibs = await _context.Library.GetUserLibraries(userId).ToListAsync();
var userLibs = await _context.Library.GetUserLibraries(userId, context).ToListAsync();
if (libraryIds is {Count: > 0})
{

View file

@ -65,6 +65,7 @@ public enum QueryContext
{
None = 1,
Search = 2,
[Obsolete("Use Dashboard")]
Recommended = 3,
Dashboard = 4,
}
@ -1509,7 +1510,7 @@ public class SeriesRepository : ISeriesRepository
public async Task<PagedList<SeriesDto>> GetMoreIn(int userId, int libraryId, int genreId, UserParams userParams)
{
var libraryIds = GetLibraryIdsForUser(userId, libraryId, QueryContext.Recommended)
var libraryIds = GetLibraryIdsForUser(userId, libraryId, QueryContext.Dashboard)
.Where(id => libraryId == 0 || id == libraryId);
var usersSeriesIds = GetSeriesIdsForLibraryIds(libraryIds);

View file

@ -12,6 +12,7 @@ using API.Services.Tasks;
using API.Services.Tasks.Metadata;
using API.SignalR;
using Hangfire;
using Kavita.Common.Helpers;
using Microsoft.Extensions.Logging;
namespace API.Services;
@ -121,23 +122,32 @@ public class TaskScheduler : ITaskScheduler
public async Task ScheduleTasks()
{
_logger.LogInformation("Scheduling reoccurring tasks");
var nonCronOptions = new List<string>(["disabled", "daily", "weekly"]);
var setting = (await _unitOfWork.SettingsRepository.GetSettingAsync(ServerSettingKey.TaskScan)).Value;
if (setting != null)
if (setting == null || (!nonCronOptions.Contains(setting) && !CronHelper.IsValidCron(setting)))
{
_logger.LogError("Scan Task has invalid cron, defaulting to Daily");
RecurringJob.AddOrUpdate(ScanLibrariesTaskId, () => ScanLibraries(false),
Cron.Daily, RecurringJobOptions);
}
else
{
var scanLibrarySetting = setting;
_logger.LogDebug("Scheduling Scan Library Task for {Setting}", scanLibrarySetting);
RecurringJob.AddOrUpdate(ScanLibrariesTaskId, () => ScanLibraries(false),
() => CronConverter.ConvertToCronNotation(scanLibrarySetting), RecurringJobOptions);
}
else
{
RecurringJob.AddOrUpdate(ScanLibrariesTaskId, () => ScanLibraries(false),
Cron.Daily, RecurringJobOptions);
}
setting = (await _unitOfWork.SettingsRepository.GetSettingAsync(ServerSettingKey.TaskBackup)).Value;
if (setting != null)
if (setting == null || (!nonCronOptions.Contains(setting) && !CronHelper.IsValidCron(setting)))
{
_logger.LogError("Backup Task has invalid cron, defaulting to Daily");
RecurringJob.AddOrUpdate(BackupTaskId, () => _backupService.BackupDatabase(),
Cron.Weekly, RecurringJobOptions);
}
else
{
_logger.LogDebug("Scheduling Backup Task for {Setting}", setting);
var schedule = CronConverter.ConvertToCronNotation(setting);
@ -149,16 +159,21 @@ public class TaskScheduler : ITaskScheduler
RecurringJob.AddOrUpdate(BackupTaskId, () => _backupService.BackupDatabase(),
() => schedule, RecurringJobOptions);
}
else
{
RecurringJob.AddOrUpdate(BackupTaskId, () => _backupService.BackupDatabase(),
Cron.Weekly, RecurringJobOptions);
}
setting = (await _unitOfWork.SettingsRepository.GetSettingAsync(ServerSettingKey.TaskCleanup)).Value;
_logger.LogDebug("Scheduling Cleanup Task for {Setting}", setting);
RecurringJob.AddOrUpdate(CleanupTaskId, () => _cleanupService.Cleanup(),
CronConverter.ConvertToCronNotation(setting), RecurringJobOptions);
if (setting == null || (!nonCronOptions.Contains(setting) && !CronHelper.IsValidCron(setting)))
{
_logger.LogDebug("Scheduling Cleanup Task for {Setting}", setting);
RecurringJob.AddOrUpdate(CleanupTaskId, () => _cleanupService.Cleanup(),
CronConverter.ConvertToCronNotation(setting), RecurringJobOptions);
}
else
{
_logger.LogError("Cleanup Task has invalid cron, defaulting to Daily");
RecurringJob.AddOrUpdate(CleanupTaskId, () => _cleanupService.Cleanup(),
Cron.Daily, RecurringJobOptions);
}
RecurringJob.AddOrUpdate(RemoveFromWantToReadTaskId, () => _cleanupService.CleanupWantToRead(),
Cron.Daily, RecurringJobOptions);