* Updated number inputs with a more mobile friendly control

* Started writing lots of unit tests on PersonHelper to try and hammer out foreign constraint

* Fixes side-nav actionable alignment

* Added some unit tests

* Buffed out the unit tests

* Applied input modes throughout the app

* Fixed a small bug in refresh token validation to make it work correctly

* Try out a new way to block multithreading from interacting with people during series metadata update.

* Fixed the lock code to properly lock, which should help with any constraint issues.

* Locking notes

* Tweaked locking on people to prevent a constraint issue. This slows down the scanner a bit, but not much. Will tweak after validating on a user's server.

* Replaced all DBFactory.Series with SeriesBuilder.

* Replaced all DBFactory.Volume() with VolumeBuilder

* Replaced SeriesMetadata with Builder

* Replaced DBFactory.CollectionTag

* Lots of refactoring to streamline entity creation

* Fixed one of the unit tests

* Refactored all of new Library()

* Removed tag and genre

* Removed new SeriesMetadata

* Refactored new Volume()

* MangaFile()

* ReadingList()

* Refactored all of Chapter and ReadingList

* Add title to all event widget flows

* Updated Base Url to inform user it doesn't work for docker users with non-root user.

* Added unit test coverage to FormatChapterTitle and FormatChapterName.

* Started on Unit test for scanner, but need to finish it later.

---------

Co-authored-by: Robbie Davis <robbie@therobbiedavis.com>
This commit is contained in:
Joe Milazzo 2023-03-19 12:52:44 -05:00 committed by GitHub
parent eec03d7e96
commit 385f61f9f0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
105 changed files with 2257 additions and 2660 deletions

View file

@ -1,198 +0,0 @@
using System.Collections.Generic;
using System.IO;
using API.Entities;
using API.Entities.Enums;
using API.Entities.Metadata;
using API.Extensions;
using API.Parser;
using API.Services.Tasks;
using Kavita.Common;
namespace API.Data;
/// <summary>
/// Responsible for creating Series, Volume, Chapter, MangaFiles for use in <see cref="ScannerService"/>
/// </summary>
public static class DbFactory
{
public static Library Library(string name, LibraryType type)
{
return new Library()
{
Name = name,
Type = type,
Series = new List<Series>(),
Folders = new List<FolderPath>(),
AppUsers = new List<AppUser>()
};
}
public static Series Series(string name)
{
return new Series
{
Name = name,
OriginalName = name,
LocalizedName = name,
NormalizedName = name.ToNormalized(),
NormalizedLocalizedName = name.ToNormalized(),
SortName = name,
Volumes = new List<Volume>(),
Metadata = SeriesMetadata(new List<CollectionTag>())
};
}
public static Series Series(string name, string localizedName)
{
if (string.IsNullOrEmpty(localizedName))
{
localizedName = name;
}
return new Series
{
Name = name,
OriginalName = name,
LocalizedName = localizedName,
NormalizedName = name.ToNormalized(),
NormalizedLocalizedName = localizedName.ToNormalized(),
SortName = name,
Volumes = new List<Volume>(),
Metadata = SeriesMetadata(new List<CollectionTag>())
};
}
public static Volume Volume(string volumeNumber)
{
return new Volume()
{
Name = volumeNumber,
Number = (int) Services.Tasks.Scanner.Parser.Parser.MinNumberFromRange(volumeNumber),
Chapters = new List<Chapter>()
};
}
public static Chapter Chapter(ParserInfo info)
{
var specialTreatment = info.IsSpecialInfo();
var specialTitle = specialTreatment ? info.Filename : info.Chapters;
return new Chapter()
{
Number = specialTreatment ? "0" : Services.Tasks.Scanner.Parser.Parser.MinNumberFromRange(info.Chapters) + string.Empty,
Range = specialTreatment ? info.Filename : info.Chapters,
Title = (specialTreatment && info.Format == MangaFormat.Epub)
? info.Title
: specialTitle,
Files = new List<MangaFile>(),
IsSpecial = specialTreatment,
};
}
public static SeriesMetadata SeriesMetadata(ICollection<CollectionTag> collectionTags)
{
return new SeriesMetadata()
{
CollectionTags = collectionTags,
Summary = string.Empty
};
}
public static CollectionTag CollectionTag(int id, string title, string? summary = null, bool promoted = false)
{
title = title.Trim();
return new CollectionTag()
{
Id = id,
NormalizedTitle = title.ToNormalized(),
Title = title,
Summary = summary?.Trim(),
Promoted = promoted,
SeriesMetadatas = new List<SeriesMetadata>()
};
}
public static ReadingList ReadingList(string title, string? summary = null, bool promoted = false, AgeRating rating = AgeRating.Unknown)
{
title = title.Trim();
return new ReadingList()
{
NormalizedTitle = title.ToNormalized(),
Title = title,
Summary = summary?.Trim(),
Promoted = promoted,
Items = new List<ReadingListItem>(),
AgeRating = rating
};
}
public static ReadingListItem ReadingListItem(int index, int seriesId, int volumeId, int chapterId)
{
return new ReadingListItem()
{
Order = index,
ChapterId = chapterId,
SeriesId = seriesId,
VolumeId = volumeId
};
}
public static Genre Genre(string name)
{
return new Genre()
{
Title = name.Trim().SentenceCase(),
NormalizedTitle = name.ToNormalized()
};
}
public static Tag Tag(string name)
{
return new Tag()
{
Title = name.Trim().SentenceCase(),
NormalizedTitle = name.ToNormalized()
};
}
public static Person Person(string name, PersonRole role)
{
return new Person()
{
Name = name.Trim(),
NormalizedName = name.ToNormalized(),
Role = role
};
}
public static MangaFile MangaFile(string filePath, MangaFormat format, int pages)
{
return new MangaFile()
{
FilePath = filePath,
Format = format,
Pages = pages,
LastModified = File.GetLastWriteTime(filePath),
LastModifiedUtc = File.GetLastWriteTimeUtc(filePath),
};
}
public static Device Device(string name)
{
return new Device()
{
Name = name,
};
}
public static AppUser AppUser(string username, string email, SiteTheme defaultTheme)
{
return new AppUser()
{
UserName = username,
Email = email,
ApiKey = HashUtil.ApiKey(),
UserPreferences = new AppUserPreferences
{
Theme = defaultTheme
}
};
}
}

View file

@ -9,6 +9,7 @@ namespace API.Data;
/// v0.7 introduced UTC dates and GMT+1 users would sometimes have dates stored as '0000-12-31 23:00:00'.
/// This Migration will update those dates.
/// </summary>
// ReSharper disable once InconsistentNaming
public static class MigrateBrokenGMT1Dates
{
public static async Task Migrate(IUnitOfWork unitOfWork, DataContext dataContext, ILogger<Program> logger)