Few More Fixes (#2032)

* Fixed spreads stretching on PC

* Fixed a bug where reading list dates couldn't be cleared out.

* Reading list page refreshes after updating info in the modal

* Fixed an issue where create library wouldn't take into account advanced settings.

* Fixed an issue where selection of the first chapter of a series to pull series-level metadata could fail in cases where you had Volume 2 and Chapter 1, Volume 2 would be selected.
This commit is contained in:
Joe Milazzo 2023-06-05 10:29:28 -05:00 committed by GitHub
parent cb3c021573
commit 061be58496
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 81 additions and 63 deletions

View File

@ -343,7 +343,7 @@ public class SeriesServiceTests : AbstractDbTest
Assert.True(result); Assert.True(result);
var ratings = (await _unitOfWork.UserRepository.GetUserByUsernameAsync("majora2007", AppUserIncludes.Ratings)) var ratings = (await _unitOfWork.UserRepository.GetUserByUsernameAsync("majora2007", AppUserIncludes.Ratings))!
.Ratings; .Ratings;
Assert.NotEmpty(ratings); Assert.NotEmpty(ratings);
Assert.Equal(3, ratings.First().Rating); Assert.Equal(3, ratings.First().Rating);
@ -780,7 +780,7 @@ public class SeriesServiceTests : AbstractDbTest
{ {
var series = CreateSeriesMock(); var series = CreateSeriesMock();
var firstChapter = SeriesService.GetFirstChapterForMetadata(series, true); var firstChapter = SeriesService.GetFirstChapterForMetadata(series);
Assert.Same("1", firstChapter.Range); Assert.Same("1", firstChapter.Range);
} }
@ -789,7 +789,7 @@ public class SeriesServiceTests : AbstractDbTest
{ {
var series = CreateSeriesMock(); var series = CreateSeriesMock();
var firstChapter = SeriesService.GetFirstChapterForMetadata(series, false); var firstChapter = SeriesService.GetFirstChapterForMetadata(series);
Assert.Same("1", firstChapter.Range); Assert.Same("1", firstChapter.Range);
} }
@ -808,10 +808,35 @@ public class SeriesServiceTests : AbstractDbTest
new ChapterBuilder("1.2").WithFiles(files).WithPages(1).Build(), new ChapterBuilder("1.2").WithFiles(files).WithPages(1).Build(),
}; };
var firstChapter = SeriesService.GetFirstChapterForMetadata(series, false); var firstChapter = SeriesService.GetFirstChapterForMetadata(series);
Assert.Same("1.1", firstChapter.Range); Assert.Same("1.1", firstChapter.Range);
} }
[Fact]
public void GetFirstChapterForMetadata_NonBook_ShouldReturnChapter1_WhenFirstVolumeIs3()
{
var file = new MangaFileBuilder("Test.cbz", MangaFormat.Archive, 1).Build();
var series = new SeriesBuilder("Test")
.WithVolume(new VolumeBuilder("0")
.WithChapter(new ChapterBuilder("1").WithPages(1).WithFile(file).Build())
.WithChapter(new ChapterBuilder("2").WithPages(1).WithFile(file).Build())
.Build())
.WithVolume(new VolumeBuilder("2")
.WithChapter(new ChapterBuilder("21").WithPages(1).WithFile(file).Build())
.WithChapter(new ChapterBuilder("22").WithPages(1).WithFile(file).Build())
.Build())
.WithVolume(new VolumeBuilder("3")
.WithChapter(new ChapterBuilder("31").WithPages(1).WithFile(file).Build())
.WithChapter(new ChapterBuilder("32").WithPages(1).WithFile(file).Build())
.Build())
.Build();
series.Library = new LibraryBuilder("Test LIb", LibraryType.Book).Build();
var firstChapter = SeriesService.GetFirstChapterForMetadata(series);
Assert.Same("1", firstChapter.Range);
}
#endregion #endregion
#region SeriesRelation #region SeriesRelation

View File

@ -50,22 +50,28 @@ public class LibraryController : BaseApiController
/// <summary> /// <summary>
/// Creates a new Library. Upon library creation, adds new library to all Admin accounts. /// Creates a new Library. Upon library creation, adds new library to all Admin accounts.
/// </summary> /// </summary>
/// <param name="createLibraryDto"></param> /// <param name="dto"></param>
/// <returns></returns> /// <returns></returns>
[Authorize(Policy = "RequireAdminRole")] [Authorize(Policy = "RequireAdminRole")]
[HttpPost("create")] [HttpPost("create")]
public async Task<ActionResult> AddLibrary(CreateLibraryDto createLibraryDto) public async Task<ActionResult> AddLibrary(UpdateLibraryDto dto)
{ {
if (await _unitOfWork.LibraryRepository.LibraryExists(createLibraryDto.Name)) if (await _unitOfWork.LibraryRepository.LibraryExists(dto.Name))
{ {
return BadRequest("Library name already exists. Please choose a unique name to the server."); return BadRequest("Library name already exists. Please choose a unique name to the server.");
} }
var library = new Library var library = new Library
{ {
Name = createLibraryDto.Name, Name = dto.Name,
Type = createLibraryDto.Type, Type = dto.Type,
Folders = createLibraryDto.Folders.Select(x => new FolderPath {Path = x}).ToList() Folders = dto.Folders.Select(x => new FolderPath {Path = x}).Distinct().ToList(),
FolderWatching = dto.FolderWatching,
IncludeInDashboard = dto.IncludeInDashboard,
IncludeInRecommended = dto.IncludeInRecommended,
IncludeInSearch = dto.IncludeInSearch,
ManageCollections = dto.ManageCollections,
ManageReadingLists = dto.ManageReadingLists,
}; };
_unitOfWork.LibraryRepository.Add(library); _unitOfWork.LibraryRepository.Add(library);
@ -359,7 +365,7 @@ public class LibraryController : BaseApiController
var originalFolders = library.Folders.Select(x => x.Path).ToList(); var originalFolders = library.Folders.Select(x => x.Path).ToList();
library.Name = newName; library.Name = newName;
library.Folders = dto.Folders.Select(s => new FolderPath() {Path = s}).ToList(); library.Folders = dto.Folders.Select(s => new FolderPath() {Path = s}).Distinct().ToList();
var typeUpdate = library.Type != dto.Type; var typeUpdate = library.Type != dto.Type;
var folderWatchingUpdate = library.FolderWatching != dto.FolderWatching; var folderWatchingUpdate = library.FolderWatching != dto.FolderWatching;

View File

@ -157,19 +157,19 @@ public class ReadingListService : IReadingListService
readingList.CoverImageLocked = dto.CoverImageLocked; readingList.CoverImageLocked = dto.CoverImageLocked;
if (NumberHelper.IsValidMonth(dto.StartingMonth)) if (NumberHelper.IsValidMonth(dto.StartingMonth) || dto.StartingMonth == 0)
{ {
readingList.StartingMonth = dto.StartingMonth; readingList.StartingMonth = dto.StartingMonth;
} }
if (NumberHelper.IsValidYear(dto.StartingYear)) if (NumberHelper.IsValidYear(dto.StartingYear) || dto.StartingYear == 0)
{ {
readingList.StartingYear = dto.StartingYear; readingList.StartingYear = dto.StartingYear;
} }
if (NumberHelper.IsValidMonth(dto.EndingMonth)) if (NumberHelper.IsValidMonth(dto.EndingMonth) || dto.EndingMonth == 0)
{ {
readingList.EndingMonth = dto.EndingMonth; readingList.EndingMonth = dto.EndingMonth;
} }
if (NumberHelper.IsValidYear(dto.EndingYear)) if (NumberHelper.IsValidYear(dto.EndingYear) || dto.EndingYear == 0)
{ {
readingList.EndingYear = dto.EndingYear; readingList.EndingYear = dto.EndingYear;
} }

View File

@ -48,14 +48,25 @@ public class SeriesService : ISeriesService
/// <summary> /// <summary>
/// Returns the first chapter for a series to extract metadata from (ie Summary, etc) /// Returns the first chapter for a series to extract metadata from (ie Summary, etc)
/// </summary> /// </summary>
/// <param name="series"></param> /// <param name="series">The full series with all volumes and chapters on it</param>
/// <param name="isBookLibrary"></param>
/// <returns></returns> /// <returns></returns>
public static Chapter? GetFirstChapterForMetadata(Series series, bool isBookLibrary) public static Chapter? GetFirstChapterForMetadata(Series series)
{ {
return series.Volumes.OrderBy(v => v.Number, ChapterSortComparer.Default) var sortedVolumes = series.Volumes.OrderBy(v => v.Number, ChapterSortComparer.Default);
var minVolumeNumber = sortedVolumes
.Where(v => v.Number != 0)
.MinBy(v => v.Number);
var minChapter = series.Volumes
.SelectMany(v => v.Chapters.OrderBy(c => float.Parse(c.Number), ChapterSortComparer.Default)) .SelectMany(v => v.Chapters.OrderBy(c => float.Parse(c.Number), ChapterSortComparer.Default))
.FirstOrDefault(); .FirstOrDefault();
if (minVolumeNumber != null && minChapter != null && float.Parse(minChapter.Number) > minVolumeNumber.Number)
{
return minVolumeNumber.Chapters.MinBy(c => float.Parse(c.Number), ChapterSortComparer.Default);
}
return minChapter;
} }
public async Task<bool> UpdateSeriesMetadata(UpdateSeriesMetadataDto updateSeriesMetadataDto) public async Task<bool> UpdateSeriesMetadata(UpdateSeriesMetadataDto updateSeriesMetadataDto)

View File

@ -266,8 +266,7 @@ public class ProcessSeries : IProcessSeries
public void UpdateSeriesMetadata(Series series, Library library) public void UpdateSeriesMetadata(Series series, Library library)
{ {
series.Metadata ??= new SeriesMetadataBuilder().Build(); series.Metadata ??= new SeriesMetadataBuilder().Build();
var isBook = library.Type == LibraryType.Book; var firstChapter = SeriesService.GetFirstChapterForMetadata(series);
var firstChapter = SeriesService.GetFirstChapterForMetadata(series, isBook);
var firstFile = firstChapter?.Files.FirstOrDefault(); var firstFile = firstChapter?.Files.FirstOrDefault();
if (firstFile == null) return; if (firstFile == null) return;

View File

@ -42,13 +42,13 @@ img {
} }
.full-width { .full-width {
width: 100%;
margin: 0 auto; margin: 0 auto;
vertical-align: top; vertical-align: top;
max-width: fit-content; max-width: fit-content;
} }
.fit-to-screen.full-width { .fit-to-screen.full-width {
width: 100%;
max-height: calc(var(--vh)*100); max-height: calc(var(--vh)*100);
} }
} }

View File

@ -123,18 +123,20 @@ export class ReadingListDetailComponent implements OnInit {
this.router.navigate(this.readerService.getNavigationArray(item.libraryId, item.seriesId, item.chapterId, item.seriesFormat), {queryParams: params}); this.router.navigate(this.readerService.getNavigationArray(item.libraryId, item.seriesId, item.chapterId, item.seriesFormat), {queryParams: params});
} }
handleReadingListActionCallback(action: ActionItem<ReadingList>, readingList: ReadingList) { async handleReadingListActionCallback(action: ActionItem<ReadingList>, readingList: ReadingList) {
switch(action.action) { switch(action.action) {
case Action.Delete: case Action.Delete:
this.deleteList(readingList); await this.deleteList(readingList);
break; break;
case Action.Edit: case Action.Edit:
this.actionService.editReadingList(readingList, (readingList: ReadingList) => { this.actionService.editReadingList(readingList, (readingList: ReadingList) => {
// Reload information around list // Reload information around list
this.readingList = readingList; this.readingListService.getReadingList(this.listId).subscribe(rl => {
this.readingList = rl;
this.readingListSummary = (this.readingList.summary === null ? '' : this.readingList.summary).replace(/\n/g, '<br>'); this.readingListSummary = (this.readingList.summary === null ? '' : this.readingList.summary).replace(/\n/g, '<br>');
this.readingListImage = this.imageService.randomize(this.imageService.getReadingListCoverImage(this.listId)); this.readingListImage = this.imageService.randomize(this.imageService.getReadingListCoverImage(this.listId));
this.cdRef.markForCheck(); this.cdRef.markForCheck();
})
}); });
break; break;
} }

View File

@ -7,7 +7,7 @@
"name": "GPL-3.0", "name": "GPL-3.0",
"url": "https://github.com/Kareadita/Kavita/blob/develop/LICENSE" "url": "https://github.com/Kareadita/Kavita/blob/develop/LICENSE"
}, },
"version": "0.7.2.26" "version": "0.7.2.28"
}, },
"servers": [ "servers": [
{ {
@ -2129,17 +2129,17 @@
"content": { "content": {
"application/json": { "application/json": {
"schema": { "schema": {
"$ref": "#/components/schemas/CreateLibraryDto" "$ref": "#/components/schemas/UpdateLibraryDto"
} }
}, },
"text/json": { "text/json": {
"schema": { "schema": {
"$ref": "#/components/schemas/CreateLibraryDto" "$ref": "#/components/schemas/UpdateLibraryDto"
} }
}, },
"application/*+json": { "application/*+json": {
"schema": { "schema": {
"$ref": "#/components/schemas/CreateLibraryDto" "$ref": "#/components/schemas/UpdateLibraryDto"
} }
} }
} }
@ -11191,31 +11191,6 @@
}, },
"additionalProperties": false "additionalProperties": false
}, },
"CreateLibraryDto": {
"required": [
"folders",
"name",
"type"
],
"type": "object",
"properties": {
"name": {
"minLength": 1,
"type": "string"
},
"type": {
"$ref": "#/components/schemas/LibraryType"
},
"folders": {
"minItems": 1,
"type": "array",
"items": {
"type": "string"
}
}
},
"additionalProperties": false
},
"CreateReadingListDto": { "CreateReadingListDto": {
"type": "object", "type": "object",
"properties": { "properties": {