Bugfix/misc cleanup (#745)

* Change update check to be between noon and 6pm.

* Added a UI change that was missed

* Fixed an issue on register user where input boxes were not styled correctly

* Fixed renaming a series to an existing series name of a different format.

* Change webtoon reader debug mode
This commit is contained in:
Joseph Milazzo 2021-11-11 17:15:28 -06:00 committed by GitHub
parent 46b2bebeb6
commit dd4aedc323
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 60 additions and 12 deletions

View File

@ -180,7 +180,7 @@ namespace API.Controllers
if (series == null) return BadRequest("Series does not exist"); if (series == null) return BadRequest("Series does not exist");
if (series.Name != updateSeries.Name && await _unitOfWork.SeriesRepository.DoesSeriesNameExistInLibrary(updateSeries.Name)) if (series.Name != updateSeries.Name && await _unitOfWork.SeriesRepository.DoesSeriesNameExistInLibrary(updateSeries.Name, series.Format))
{ {
return BadRequest("A series already exists in this library with this name. Series Names must be unique to a library."); return BadRequest("A series already exists in this library with this name. Series Names must be unique to a library.");
} }

View File

@ -7,6 +7,7 @@ using API.DTOs;
using API.DTOs.CollectionTags; using API.DTOs.CollectionTags;
using API.DTOs.Filtering; using API.DTOs.Filtering;
using API.Entities; using API.Entities;
using API.Entities.Enums;
using API.Extensions; using API.Extensions;
using API.Helpers; using API.Helpers;
using API.Interfaces.Repositories; using API.Interfaces.Repositories;
@ -47,16 +48,22 @@ namespace API.Data.Repositories
_context.Series.RemoveRange(series); _context.Series.RemoveRange(series);
} }
public async Task<bool> DoesSeriesNameExistInLibrary(string name) /// <summary>
/// Returns if a series name and format exists already in a library
/// </summary>
/// <param name="name">Name of series</param>
/// <param name="format">Format of series</param>
/// <returns></returns>
public async Task<bool> DoesSeriesNameExistInLibrary(string name, MangaFormat format)
{ {
var libraries = _context.Series var libraries = _context.Series
.AsNoTracking() .AsNoTracking()
.Where(x => x.Name == name) .Where(x => x.Name.Equals(name) && x.Format == format)
.Select(s => s.LibraryId); .Select(s => s.LibraryId);
return await _context.Series return await _context.Series
.AsNoTracking() .AsNoTracking()
.Where(s => libraries.Contains(s.LibraryId) && s.Name == name) .Where(s => libraries.Contains(s.LibraryId) && s.Name.Equals(name) && s.Format == format)
.CountAsync() > 1; .CountAsync() > 1;
} }

View File

@ -41,7 +41,7 @@ namespace API.Data
IList<ServerSetting> defaultSettings = new List<ServerSetting>() IList<ServerSetting> defaultSettings = new List<ServerSetting>()
{ {
new() {Key = ServerSettingKey.CacheDirectory, Value = DirectoryService.CacheDirectory}, new () {Key = ServerSettingKey.CacheDirectory, Value = DirectoryService.CacheDirectory},
new () {Key = ServerSettingKey.TaskScan, Value = "daily"}, new () {Key = ServerSettingKey.TaskScan, Value = "daily"},
new () {Key = ServerSettingKey.LoggingLevel, Value = "Information"}, // Not used from DB, but DB is sync with appSettings.json new () {Key = ServerSettingKey.LoggingLevel, Value = "Information"}, // Not used from DB, but DB is sync with appSettings.json
new () {Key = ServerSettingKey.TaskBackup, Value = "weekly"}, new () {Key = ServerSettingKey.TaskBackup, Value = "weekly"},
@ -51,6 +51,7 @@ namespace API.Data
new () {Key = ServerSettingKey.EnableOpds, Value = "false"}, new () {Key = ServerSettingKey.EnableOpds, Value = "false"},
new () {Key = ServerSettingKey.EnableAuthentication, Value = "true"}, new () {Key = ServerSettingKey.EnableAuthentication, Value = "true"},
new () {Key = ServerSettingKey.BaseUrl, Value = "/"}, new () {Key = ServerSettingKey.BaseUrl, Value = "/"},
new () {Key = ServerSettingKey.InstallId, Value = HashUtil.AnonymousToken()},
}; };
foreach (var defaultSetting in defaultSettings) foreach (var defaultSetting in defaultSettings)

View File

@ -4,26 +4,61 @@ namespace API.Entities.Enums
{ {
public enum ServerSettingKey public enum ServerSettingKey
{ {
/// <summary>
/// Cron format for how often full library scans are performed.
/// </summary>
[Description("TaskScan")] [Description("TaskScan")]
TaskScan = 0, TaskScan = 0,
/// <summary>
/// Where files are cached. Not currently used.
/// </summary>
[Description("CacheDirectory")] [Description("CacheDirectory")]
CacheDirectory = 1, CacheDirectory = 1,
/// <summary>
/// Cron format for how often backups are taken.
/// </summary>
[Description("TaskBackup")] [Description("TaskBackup")]
TaskBackup = 2, TaskBackup = 2,
/// <summary>
/// Logging level for Server. Not managed in DB. Managed in appsettings.json and synced to DB.
/// </summary>
[Description("LoggingLevel")] [Description("LoggingLevel")]
LoggingLevel = 3, LoggingLevel = 3,
/// <summary>
/// Port server listens on. Not managed in DB. Managed in appsettings.json and synced to DB.
/// </summary>
[Description("Port")] [Description("Port")]
Port = 4, Port = 4,
/// <summary>
/// Where the backups are stored.
/// </summary>
[Description("BackupDirectory")] [Description("BackupDirectory")]
BackupDirectory = 5, BackupDirectory = 5,
/// <summary>
/// Allow anonymous data to be reported to KavitaStats
/// </summary>
[Description("AllowStatCollection")] [Description("AllowStatCollection")]
AllowStatCollection = 6, AllowStatCollection = 6,
/// <summary>
/// Is OPDS enabled for the server
/// </summary>
[Description("EnableOpds")] [Description("EnableOpds")]
EnableOpds = 7, EnableOpds = 7,
/// <summary>
/// Is Authentication needed for non-admin accounts
/// </summary>
[Description("EnableAuthentication")] [Description("EnableAuthentication")]
EnableAuthentication = 8, EnableAuthentication = 8,
/// <summary>
/// Base Url for the server. Not Implemented.
/// </summary>
[Description("BaseUrl")] [Description("BaseUrl")]
BaseUrl = 9 BaseUrl = 9,
/// <summary>
/// Represents this installation of Kavita. Is tied to Stat reporting but has no information about user or files.
/// </summary>
[Description("InstallId")]
InstallId = 10
} }
} }

View File

@ -23,7 +23,7 @@ namespace API.Entities
/// </summary> /// </summary>
public string SortName { get; set; } public string SortName { get; set; }
/// <summary> /// <summary>
/// Name in Japanese. By default, will be same as Name. /// Name in original language (Japanese for Manga). By default, will be same as Name.
/// </summary> /// </summary>
public string LocalizedName { get; set; } public string LocalizedName { get; set; }
/// <summary> /// <summary>

View File

@ -4,6 +4,7 @@ using API.Data.Scanner;
using API.DTOs; using API.DTOs;
using API.DTOs.Filtering; using API.DTOs.Filtering;
using API.Entities; using API.Entities;
using API.Entities.Enums;
using API.Helpers; using API.Helpers;
namespace API.Interfaces.Repositories namespace API.Interfaces.Repositories
@ -14,7 +15,7 @@ namespace API.Interfaces.Repositories
void Update(Series series); void Update(Series series);
void Remove(Series series); void Remove(Series series);
void Remove(IEnumerable<Series> series); void Remove(IEnumerable<Series> series);
Task<bool> DoesSeriesNameExistInLibrary(string name); Task<bool> DoesSeriesNameExistInLibrary(string name, MangaFormat format);
/// <summary> /// <summary>
/// Adds user information like progress, ratings, etc /// Adds user information like progress, ratings, etc
/// </summary> /// </summary>

View File

@ -26,6 +26,7 @@ namespace API.Services
private const string SendDataTask = "finalize-stats"; private const string SendDataTask = "finalize-stats";
public static BackgroundJobServer Client => new BackgroundJobServer(); public static BackgroundJobServer Client => new BackgroundJobServer();
private static readonly Random Rnd = new Random();
public TaskScheduler(ICacheService cacheService, ILogger<TaskScheduler> logger, IScannerService scannerService, public TaskScheduler(ICacheService cacheService, ILogger<TaskScheduler> logger, IScannerService scannerService,
@ -73,7 +74,8 @@ namespace API.Services
RecurringJob.AddOrUpdate("cleanup", () => _cleanupService.Cleanup(), Cron.Daily, TimeZoneInfo.Local); RecurringJob.AddOrUpdate("cleanup", () => _cleanupService.Cleanup(), Cron.Daily, TimeZoneInfo.Local);
RecurringJob.AddOrUpdate("check-for-updates", () => _scannerService.ScanLibraries(), Cron.Daily, TimeZoneInfo.Local); // Schedule update check between noon and 6pm local time
RecurringJob.AddOrUpdate("check-for-updates", () => _scannerService.ScanLibraries(), Cron.Daily(Rnd.Next(12, 18)), TimeZoneInfo.Local);
} }
#region StatsTasks #region StatsTasks

View File

@ -75,7 +75,7 @@ export class LibraryComponent implements OnInit, OnDestroy {
reloadSeries() { reloadSeries() {
this.loadRecentlyAdded(); this.loadRecentlyAdded();
this.loadInProgress(); this.loadOnDeck();
} }
reloadInProgress(series: Series | boolean) { reloadInProgress(series: Series | boolean) {
@ -88,10 +88,10 @@ export class LibraryComponent implements OnInit, OnDestroy {
return; return;
} }
this.loadInProgress(); this.loadOnDeck();
} }
loadInProgress() { loadOnDeck() {
this.seriesService.getOnDeck().pipe(takeUntil(this.onDestroy)).subscribe((updatedSeries) => { this.seriesService.getOnDeck().pipe(takeUntil(this.onDestroy)).subscribe((updatedSeries) => {
this.inProgress = updatedSeries.result; this.inProgress = updatedSeries.result;
}); });

View File

@ -251,6 +251,7 @@ export class InfiniteScrollerComponent implements OnInit, OnChanges, OnDestroy {
if (totalScroll === totalHeight && !this.atBottom) { if (totalScroll === totalHeight && !this.atBottom) {
this.atBottom = true; this.atBottom = true;
this.setPageNum(this.totalPages); this.setPageNum(this.totalPages);
this.debugLog('At last page, saving last page ', this.totalPages);
// Scroll user back to original location // Scroll user back to original location
this.previousScrollHeightMinusTop = this.getScrollTop(); this.previousScrollHeightMinusTop = this.getScrollTop();
requestAnimationFrame(() => document.documentElement.scrollTop = this.previousScrollHeightMinusTop + (SPACER_SCROLL_INTO_PX / 2)); requestAnimationFrame(() => document.documentElement.scrollTop = this.previousScrollHeightMinusTop + (SPACER_SCROLL_INTO_PX / 2));

View File

@ -14,4 +14,5 @@
input { input {
background-color: #fff !important; background-color: #fff !important;
color: black !important;
} }