diff --git a/API/Controllers/CBLController.cs b/API/Controllers/CBLController.cs
index e84ef00e2..79d5b4896 100644
--- a/API/Controllers/CBLController.cs
+++ b/API/Controllers/CBLController.cs
@@ -34,7 +34,7 @@ public class CblController : BaseApiController
/// Use comic vine matching or not. Defaults to false
///
[HttpPost("validate")]
- public async Task> ValidateCbl(IFormFile cbl, bool comicVineMatching = false)
+ public async Task> ValidateCbl(IFormFile cbl, [FromForm] bool comicVineMatching = false)
{
var userId = User.GetUserId();
try
@@ -85,7 +85,7 @@ public class CblController : BaseApiController
/// Use comic vine matching or not. Defaults to false
///
[HttpPost("import")]
- public async Task> ImportCbl(IFormFile cbl, bool dryRun = false, bool comicVineMatching = false)
+ public async Task> ImportCbl(IFormFile cbl, [FromForm] bool dryRun = false, [FromForm] bool comicVineMatching = false)
{
try
{
diff --git a/API/Controllers/OPDSController.cs b/API/Controllers/OPDSController.cs
index 6d0f7e8dd..d25321ad8 100644
--- a/API/Controllers/OPDSController.cs
+++ b/API/Controllers/OPDSController.cs
@@ -881,6 +881,8 @@ public class OpdsController : BaseApiController
foreach (var chapter in chaptersForVolume)
{
var chapterId = chapter.Id;
+ if (chapterDict.ContainsKey(chapterId)) continue;
+
var chapterDto = _mapper.Map(chapter);
foreach (var mangaFile in chapter.Files)
{
@@ -889,7 +891,6 @@ public class OpdsController : BaseApiController
chapterDto, apiKey, prefix, baseUrl));
}
}
-
}
var chapters = seriesDetail.StorylineChapters;
diff --git a/API/Controllers/UploadController.cs b/API/Controllers/UploadController.cs
index bfa958546..e89904deb 100644
--- a/API/Controllers/UploadController.cs
+++ b/API/Controllers/UploadController.cs
@@ -318,7 +318,7 @@ public class UploadController : BaseApiController
///
/// Replaces volume cover image and locks it with a base64 encoded image.
///
- /// This is a helper API for Komf - Kavita UI does not use. Volume will find first chapter to update.
+ /// This will not update the underlying chapter
///
///
[Authorize(Policy = "RequireAdminRole")]
@@ -333,24 +333,15 @@ public class UploadController : BaseApiController
var volume = await _unitOfWork.VolumeRepository.GetVolumeAsync(uploadFileDto.Id, VolumeIncludes.Chapters);
if (volume == null) return BadRequest(await _localizationService.Translate(User.GetUserId(), "volume-doesnt-exist"));
- // Find the first chapter of the volume
- var chapter = volume.Chapters[0];
-
var filePath = string.Empty;
var lockState = false;
if (!string.IsNullOrEmpty(uploadFileDto.Url))
{
- filePath = await CreateThumbnail(uploadFileDto, $"{ImageService.GetChapterFormat(chapter.Id, uploadFileDto.Id)}");
+ filePath = await CreateThumbnail(uploadFileDto, $"{ImageService.GetVolumeFormat(uploadFileDto.Id)}");
lockState = uploadFileDto.LockCover;
}
-
- chapter.CoverImage = filePath;
- chapter.CoverImageLocked = lockState;
- _imageService.UpdateColorScape(chapter);
- _unitOfWork.ChapterRepository.Update(chapter);
-
- volume.CoverImage = chapter.CoverImage;
+ volume.CoverImage = filePath;
volume.CoverImageLocked = lockState;
_imageService.UpdateColorScape(volume);
_unitOfWork.VolumeRepository.Update(volume);
@@ -368,7 +359,7 @@ public class UploadController : BaseApiController
await _eventHub.SendMessageAsync(MessageFactory.CoverUpdate,
- MessageFactory.CoverUpdateEvent(chapter.VolumeId, MessageFactoryEntityTypes.Volume), false);
+ MessageFactory.CoverUpdateEvent(uploadFileDto.Id, MessageFactoryEntityTypes.Volume), false);
await _eventHub.SendMessageAsync(MessageFactory.CoverUpdate,
MessageFactory.CoverUpdateEvent(volume.Id, MessageFactoryEntityTypes.Chapter), false);
return Ok();
diff --git a/API/DTOs/SeriesDto.cs b/API/DTOs/SeriesDto.cs
index abe1b5000..15fe6a9a1 100644
--- a/API/DTOs/SeriesDto.cs
+++ b/API/DTOs/SeriesDto.cs
@@ -59,6 +59,11 @@ public class SeriesDto : IHasReadTimeEstimate, IHasCoverImage
///
public string FolderPath { get; set; } = default!;
///
+ /// Lowest path (that is under library root) that contains all files for the series.
+ ///
+ /// must be used before setting
+ public string? LowestFolderPath { get; set; }
+ ///
/// The last time the folder for this series was scanned
///
public DateTime LastFolderScanned { get; set; }
diff --git a/API/Data/Repositories/VolumeRepository.cs b/API/Data/Repositories/VolumeRepository.cs
index 0e1050c49..48159386d 100644
--- a/API/Data/Repositories/VolumeRepository.cs
+++ b/API/Data/Repositories/VolumeRepository.cs
@@ -44,6 +44,7 @@ public interface IVolumeRepository
Task> GetVolumes(int seriesId);
Task GetVolumeByIdAsync(int volumeId);
Task> GetAllWithCoversInDifferentEncoding(EncodeFormat encodeFormat);
+ Task> GetCoverImagesForLockedVolumesAsync();
}
public class VolumeRepository : IVolumeRepository
{
@@ -252,4 +253,17 @@ public class VolumeRepository : IVolumeRepository
.Sum(p => p.PagesRead);
}
}
+
+ ///
+ /// Returns cover images for locked chapters
+ ///
+ ///
+ public async Task> GetCoverImagesForLockedVolumesAsync()
+ {
+ return (await _context.Volume
+ .Where(c => c.CoverImageLocked)
+ .Select(c => c.CoverImage)
+ .Where(t => !string.IsNullOrEmpty(t))
+ .ToListAsync())!;
+ }
}
diff --git a/API/Services/ImageService.cs b/API/Services/ImageService.cs
index 22b1349d5..eb9f49263 100644
--- a/API/Services/ImageService.cs
+++ b/API/Services/ImageService.cs
@@ -739,6 +739,16 @@ public class ImageService : IImageService
return $"v{volumeId}_c{chapterId}";
}
+ ///
+ /// Returns the name format for a volume cover image (custom)
+ ///
+ ///
+ ///
+ public static string GetVolumeFormat(int volumeId)
+ {
+ return $"v{volumeId}";
+ }
+
///
/// Returns the name format for a library cover image
///
diff --git a/API/Services/ReadingListService.cs b/API/Services/ReadingListService.cs
index 00d968ec1..36048ae3d 100644
--- a/API/Services/ReadingListService.cs
+++ b/API/Services/ReadingListService.cs
@@ -550,6 +550,7 @@ public class ReadingListService : IReadingListService
Results = new List(),
SuccessfulInserts = new List()
};
+
if (IsCblEmpty(cblReading, importSummary, out var readingListFromCbl)) return readingListFromCbl;
// Is there another reading list with the same name?
diff --git a/API/Services/Tasks/BackupService.cs b/API/Services/Tasks/BackupService.cs
index 60e0e8dc3..e2ed61ba1 100644
--- a/API/Services/Tasks/BackupService.cs
+++ b/API/Services/Tasks/BackupService.cs
@@ -179,6 +179,10 @@ public class BackupService : IBackupService
_directoryService.CopyFilesToDirectory(
chapterImages.Select(s => _directoryService.FileSystem.Path.Join(_directoryService.CoverImageDirectory, s)), outputTempDir);
+ var volumeImages = await _unitOfWork.VolumeRepository.GetCoverImagesForLockedVolumesAsync();
+ _directoryService.CopyFilesToDirectory(
+ volumeImages.Select(s => _directoryService.FileSystem.Path.Join(_directoryService.CoverImageDirectory, s)), outputTempDir);
+
var libraryImages = await _unitOfWork.LibraryRepository.GetAllCoverImagesAsync();
_directoryService.CopyFilesToDirectory(
libraryImages.Select(s => _directoryService.FileSystem.Path.Join(_directoryService.CoverImageDirectory, s)), outputTempDir);
diff --git a/UI/Web/src/_card-item-common.scss b/UI/Web/src/_card-item-common.scss
index 486f2b61d..0634e574f 100644
--- a/UI/Web/src/_card-item-common.scss
+++ b/UI/Web/src/_card-item-common.scss
@@ -49,7 +49,7 @@ $image-width: 160px;
pointer-events: none;
position: absolute;
top: 0;
- width: 158px;
+ width: 160px;
}
.not-read-badge {
@@ -158,7 +158,6 @@ $image-width: 160px;
bottom: 0;
right: 0;
z-index: 115;
- visibility: hidden;
}
.library {
@@ -186,7 +185,7 @@ $image-width: 160px;
display: none;
}
-.chapter,
+.chapter,
.volume,
.series,
.expected {
@@ -200,4 +199,4 @@ $image-width: 160px;
}
}
}
-}
\ No newline at end of file
+}
diff --git a/UI/Web/src/app/_models/series.ts b/UI/Web/src/app/_models/series.ts
index 49930b891..ef460a9f5 100644
--- a/UI/Web/src/app/_models/series.ts
+++ b/UI/Web/src/app/_models/series.ts
@@ -62,6 +62,7 @@ export interface Series extends IHasCover, IHasReadingTime {
* Highest level folder containing this series
*/
folderPath: string;
+ lowestFolderPath: string;
/**
* This is currently only used on Series detail page for recommendations
*/
diff --git a/UI/Web/src/app/_pipes/cbl-conflict-reason.pipe.ts b/UI/Web/src/app/_pipes/cbl-conflict-reason.pipe.ts
index 3f4da39a7..6f5463cf2 100644
--- a/UI/Web/src/app/_pipes/cbl-conflict-reason.pipe.ts
+++ b/UI/Web/src/app/_pipes/cbl-conflict-reason.pipe.ts
@@ -23,7 +23,7 @@ export class CblConflictReasonPipe implements PipeTransform {
case CblImportReason.EmptyFile:
return failIcon + this.translocoService.translate('cbl-conflict-reason-pipe.empty-file');
case CblImportReason.NameConflict:
- return failIcon + this.translocoService.translate('cbl-conflict-reason-pipe.chapter-missing', {readingListName: result.readingListName});
+ return failIcon + this.translocoService.translate('cbl-conflict-reason-pipe.name-conflict', {readingListName: result.readingListName});
case CblImportReason.SeriesCollision:
return failIcon + this.translocoService.translate('cbl-conflict-reason-pipe.series-collision', {seriesLink: `${result.series} `});
case CblImportReason.SeriesMissing:
diff --git a/UI/Web/src/app/_services/nav.service.ts b/UI/Web/src/app/_services/nav.service.ts
index 7a2fa2f5a..5364234b9 100644
--- a/UI/Web/src/app/_services/nav.service.ts
+++ b/UI/Web/src/app/_services/nav.service.ts
@@ -99,6 +99,7 @@ export class NavService {
*/
showNavBar() {
this.renderer.setStyle(this.document.querySelector('body'), 'margin-top', 'var(--nav-offset)');
+ this.renderer.removeStyle(this.document.querySelector('body'), 'scrollbar-gutter');
this.renderer.setStyle(this.document.querySelector('body'), 'height', 'calc(var(--vh)*100 - var(--nav-offset))');
this.renderer.setStyle(this.document.querySelector('html'), 'height', 'calc(var(--vh)*100 - var(--nav-offset))');
this.navbarVisibleSource.next(true);
@@ -109,6 +110,7 @@ export class NavService {
*/
hideNavBar() {
this.renderer.setStyle(this.document.querySelector('body'), 'margin-top', '0px');
+ this.renderer.setStyle(this.document.querySelector('body'), 'scrollbar-gutter', 'initial');
this.renderer.removeStyle(this.document.querySelector('body'), 'height');
this.renderer.removeStyle(this.document.querySelector('html'), 'height');
this.navbarVisibleSource.next(false);
diff --git a/UI/Web/src/app/_single-module/edit-volume-modal/edit-volume-modal.component.html b/UI/Web/src/app/_single-module/edit-volume-modal/edit-volume-modal.component.html
index a8acc7a9c..b3ef54146 100644
--- a/UI/Web/src/app/_single-module/edit-volume-modal/edit-volume-modal.component.html
+++ b/UI/Web/src/app/_single-module/edit-volume-modal/edit-volume-modal.component.html
@@ -16,7 +16,7 @@
{{t('cover-image-description')}}
+ [showReset]="true" (resetClicked)="handleReset()">
@@ -34,15 +34,15 @@
-
-
-
-
-
-
-
-
-
+
+
+
+
+ {{t('words-count', {num: volume.wordCount | compactNumber})}}
+
+
+
+
diff --git a/UI/Web/src/app/_single-module/edit-volume-modal/edit-volume-modal.component.ts b/UI/Web/src/app/_single-module/edit-volume-modal/edit-volume-modal.component.ts
index 760f38f47..92e08cfef 100644
--- a/UI/Web/src/app/_single-module/edit-volume-modal/edit-volume-modal.component.ts
+++ b/UI/Web/src/app/_single-module/edit-volume-modal/edit-volume-modal.component.ts
@@ -1,5 +1,5 @@
-import {ChangeDetectionStrategy, ChangeDetectorRef, Component, DestroyRef, inject, Input, OnInit} from '@angular/core';
-import {FormControl, FormGroup, FormsModule, ReactiveFormsModule, Validators} from "@angular/forms";
+import {ChangeDetectionStrategy, ChangeDetectorRef, Component, inject, Input, OnInit} from '@angular/core';
+import {FormControl, FormGroup, FormsModule, ReactiveFormsModule} from "@angular/forms";
import {
NgbActiveModal,
NgbInputDatepicker,
@@ -29,26 +29,15 @@ import {SafeHtmlPipe} from "../../_pipes/safe-html.pipe";
import {ReadTimePipe} from "../../_pipes/read-time.pipe";
import {Action, ActionFactoryService, ActionItem} from "../../_services/action-factory.service";
import {Volume} from "../../_models/volume";
-import {SeriesService} from "../../_services/series.service";
import {Breakpoint, UtilityService} from "../../shared/_services/utility.service";
import {ImageService} from "../../_services/image.service";
import {UploadService} from "../../_services/upload.service";
-import {MetadataService} from "../../_services/metadata.service";
import {AccountService} from "../../_services/account.service";
import {ActionService} from "../../_services/action.service";
import {DownloadService} from "../../shared/_services/download.service";
-import {Chapter} from "../../_models/chapter";
import {LibraryType} from "../../_models/library/library";
-import {TypeaheadSettings} from "../../typeahead/_models/typeahead-settings";
-import {Tag} from "../../_models/tag";
-import {Language} from "../../_models/metadata/language";
-import {Person, PersonRole} from "../../_models/metadata/person";
-import {Genre} from "../../_models/metadata/genre";
-import {AgeRatingDto} from "../../_models/metadata/age-rating-dto";
-import {takeUntilDestroyed} from "@angular/core/rxjs-interop";
-import {forkJoin, Observable, of} from "rxjs";
-import {map} from "rxjs/operators";
-import {EditChapterModalCloseResult} from "../edit-chapter-modal/edit-chapter-modal.component";
+import {PersonRole} from "../../_models/metadata/person";
+import {forkJoin} from "rxjs";
import { MangaFormat } from 'src/app/_models/manga-format';
import {MangaFile} from "../../_models/manga-file";
import {VolumeService} from "../../_services/volume.service";
@@ -167,18 +156,16 @@ export class EditVolumeModalComponent implements OnInit {
}
save() {
- const model = this.editForm.value;
const selectedIndex = this.editForm.get('coverImageIndex')?.value || 0;
const apis = [];
-
if (selectedIndex > 0 || this.coverImageReset) {
- apis.push(this.uploadService.updateVolumeCoverImage(model.id, this.selectedCover, !this.coverImageReset));
+ apis.push(this.uploadService.updateVolumeCoverImage(this.volume.id, this.selectedCover, !this.coverImageReset));
}
forkJoin(apis).subscribe(results => {
- this.modal.close({success: true, volume: model, coverImageUpdate: selectedIndex > 0 || this.coverImageReset, needsReload: false, isDeleted: false} as EditVolumeModalCloseResult);
+ this.modal.close({success: true, volume: this.volume, coverImageUpdate: selectedIndex > 0 || this.coverImageReset, needsReload: false, isDeleted: false} as EditVolumeModalCloseResult);
});
}
diff --git a/UI/Web/src/app/book-reader/_components/book-reader/book-reader.component.scss b/UI/Web/src/app/book-reader/_components/book-reader/book-reader.component.scss
index 8d9a36f78..abab89f35 100644
--- a/UI/Web/src/app/book-reader/_components/book-reader/book-reader.component.scss
+++ b/UI/Web/src/app/book-reader/_components/book-reader/book-reader.component.scss
@@ -54,6 +54,7 @@ $primary-color: #0062cc;
$action-bar-height: 38px;
+
// Drawer
.control-container {
padding-bottom: 5px;
diff --git a/UI/Web/src/app/book-reader/_components/book-reader/book-reader.component.ts b/UI/Web/src/app/book-reader/_components/book-reader/book-reader.component.ts
index 434b6a85a..2c4337efa 100644
--- a/UI/Web/src/app/book-reader/_components/book-reader/book-reader.component.ts
+++ b/UI/Web/src/app/book-reader/_components/book-reader/book-reader.component.ts
@@ -482,10 +482,10 @@ export class BookReaderComponent implements OnInit, AfterViewInit, OnDestroy {
}
constructor(@Inject(DOCUMENT) private document: Document) {
- this.navService.hideNavBar();
- this.themeService.clearThemes();
- this.navService.hideSideNav();
- this.cdRef.markForCheck();
+ this.navService.hideNavBar();
+ this.navService.hideSideNav();
+ this.themeService.clearThemes();
+ this.cdRef.markForCheck();
}
/**
diff --git a/UI/Web/src/app/cards/_modals/bulk-add-to-collection/bulk-add-to-collection.component.html b/UI/Web/src/app/cards/_modals/bulk-add-to-collection/bulk-add-to-collection.component.html
index 38fbff6c8..96c33bb08 100644
--- a/UI/Web/src/app/cards/_modals/bulk-add-to-collection/bulk-add-to-collection.component.html
+++ b/UI/Web/src/app/cards/_modals/bulk-add-to-collection/bulk-add-to-collection.component.html
@@ -17,7 +17,7 @@
}
- @for(collectionTag of lists | filter: filterList; let i = $index; track collectionTag.title) {
+ @for(collectionTag of lists | filter: filterList; let i = $index; track collectionTag.title + collectionTag.promoted) {
{{collectionTag.title}}
@if (collectionTag.promoted) {
diff --git a/UI/Web/src/app/cards/_modals/bulk-add-to-collection/bulk-add-to-collection.component.ts b/UI/Web/src/app/cards/_modals/bulk-add-to-collection/bulk-add-to-collection.component.ts
index b8f65061b..19fbb5257 100644
--- a/UI/Web/src/app/cards/_modals/bulk-add-to-collection/bulk-add-to-collection.component.ts
+++ b/UI/Web/src/app/cards/_modals/bulk-add-to-collection/bulk-add-to-collection.component.ts
@@ -10,15 +10,16 @@ import {
ViewChild,
ViewEncapsulation
} from '@angular/core';
-import {FormGroup, FormControl, ReactiveFormsModule} from '@angular/forms';
+import {FormControl, FormGroup, ReactiveFormsModule} from '@angular/forms';
import {NgbActiveModal, NgbModalModule} from '@ng-bootstrap/ng-bootstrap';
-import { ToastrService } from 'ngx-toastr';
+import {ToastrService} from 'ngx-toastr';
import {UserCollection} from 'src/app/_models/collection-tag';
-import { ReadingList } from 'src/app/_models/reading-list';
-import { CollectionTagService } from 'src/app/_services/collection-tag.service';
+import {ReadingList} from 'src/app/_models/reading-list';
+import {CollectionTagService} from 'src/app/_services/collection-tag.service';
import {CommonModule} from "@angular/common";
import {FilterPipe} from "../../../_pipes/filter.pipe";
-import {translate, TranslocoDirective, TranslocoService} from "@jsverse/transloco";
+import {translate, TranslocoDirective} from "@jsverse/transloco";
+import {ScrobbleProvider} from "../../../_services/scrobbling.service";
@Component({
selector: 'app-bulk-add-to-collection',
@@ -60,7 +61,8 @@ export class BulkAddToCollectionComponent implements OnInit, AfterViewInit {
this.loading = true;
this.cdRef.markForCheck();
this.collectionService.allCollections(true).subscribe(tags => {
- this.lists = tags;
+ // Don't allow Smart Collections in
+ this.lists = tags.filter(t => t.source === ScrobbleProvider.Kavita);
this.loading = false;
this.cdRef.markForCheck();
});
diff --git a/UI/Web/src/app/cards/_modals/edit-series-modal/edit-series-modal.component.html b/UI/Web/src/app/cards/_modals/edit-series-modal/edit-series-modal.component.html
index 1926b77dc..ec7ce2e8f 100644
--- a/UI/Web/src/app/cards/_modals/edit-series-modal/edit-series-modal.component.html
+++ b/UI/Web/src/app/cards/_modals/edit-series-modal/edit-series-modal.component.html
@@ -489,85 +489,215 @@
{{t(tabs[TabID.Info])}}
{{t('info-title')}}
-
-
{{t('library-title')}} {{libraryName | sentenceCase}}
-
{{t('format-title')}} {{series.format | mangaFormat}}
-
-
-
{{t('created-title')}} {{series.created | date:'shortDate'}}
-
{{t('last-read-title')}} {{series.latestReadDate | defaultDate | timeAgo}}
-
{{t('last-added-title')}} {{series.lastChapterAdded | defaultDate | timeAgo}}
-
{{t('last-scanned-title')}} {{series.lastFolderScanned | defaultDate | timeAgo}}
+
+
+
+
+
+
+ {{libraryName! | sentenceCase}}
+
+
+
+
+
+
+
+
+ {{series.format | mangaFormat}}
+
+
+
+
-
-
{{t('folder-path-title')}} {{series.folderPath | defaultValue}}
-
-
-
-
{{t('max-items-title')}} {{metadata.maxCount}}
-
+
+
+
+
+
+ {{series.folderPath | defaultValue}}
+
+
+
-
-
{{t('total-items-title')}} {{metadata.totalCount}}
-
+
+
+
+
+ {{series.lowestFolderPath | defaultValue}}
+
+
+
-
{{t('publication-status-title')}} {{metadata.publicationStatus | publicationStatus}}
-
{{t('total-pages-title')}} {{series.pages}}
-
{{t('size-title')}} {{size | bytes}}
-
Volumes
-
- {{t('loading')}}
-
-
-
-
-
-
{{formatVolumeName(volume)}}
-
-
-
- {{t('added-title')}} {{volume.createdUtc | utcToLocalTime | defaultDate}}
-
-
- {{t('last-modified-title')}} {{volume.lastModifiedUtc | utcToLocalTime | translocoDate: {dateStyle: 'short' } | defaultDate}}
-
-
-
-
-
- {{t('view-files')}}
-
-
-
- {{t('pages-title')}} {{volume.pages}}
-
-
-
-
-
- {{file.filePath}}
-
-
- {{t('chapter-title')}} {{file.chapter}}
-
-
- {{t('pages-title')}} {{file.pages}}
-
-
- {{t('format-title')}} {{utilityService.mangaFormatToText(file.format)}}
-
-
-
-
-
+ @if (metadata) {
+
+
+
+
+
+ {{metadata.maxCount}}
+
+
-
-
+
+
+
+
+ {{metadata.totalCount}}
+
+
+
+
+
+
+
+
+
+
+
+ {{metadata.publicationStatus | publicationStatus}}
+
+
+
+
+
+
+
+
+ {{size | bytes}}
+
+
+
+
+
+ }
+
+
+
+
+
+
+ {{series.created | date:'shortDate'}}
+
+
+
+
+
+
+
+
+ {{series.lastChapterAdded | defaultDate | timeAgo}}
+
+
+
+
+
+
+
+
+
+
+
+ {{series.lastFolderScanned | defaultDate | timeAgo}}
+
+
+
+
+
+
+
+
+ {{series.lastChapterAdded | defaultDate | timeAgo}}
+
+
+
+
+
+
+
+
+
+
+
+ {{series.pages | number}}
+
+
+
+
+
+
+
+
+ {{series.wordCount | number}}
+
+
+
+
+
+
+
Volumes
+ @if (isLoadingVolumes) {
+
+ {{t('loading')}}
+
+ } @else {
+
+ @for (volume of seriesVolumes; track volume.id) {
+
+
+
+
{{formatVolumeName(volume)}}
+
+
+
+ {{t('added-title')}} {{volume.createdUtc | utcToLocalTime | defaultDate}}
+
+
+ {{t('last-modified-title')}} {{volume.lastModifiedUtc | utcToLocalTime | translocoDate: {dateStyle: 'short' } | defaultDate}}
+
+
+
+
+
+ {{t('view-files')}}
+
+
+
+ {{t('pages-title')}} {{volume.pages}}
+
+
+
+
+
+ @for(file of volume.volumeFiles; track file.id) {
+
+ {{file.filePath}}
+
+
+ {{t('chapter-title')}} {{file.chapter}}
+
+
+ {{t('pages-title')}} {{file.pages}}
+
+
+ {{t('format-title')}} {{utilityService.mangaFormatToText(file.format)}}
+
+
+
+ }
+
+
+
+
+
+ }
+
+ }
diff --git a/UI/Web/src/app/cards/_modals/edit-series-modal/edit-series-modal.component.ts b/UI/Web/src/app/cards/_modals/edit-series-modal/edit-series-modal.component.ts
index ad1f9ef29..a96568ed6 100644
--- a/UI/Web/src/app/cards/_modals/edit-series-modal/edit-series-modal.component.ts
+++ b/UI/Web/src/app/cards/_modals/edit-series-modal/edit-series-modal.component.ts
@@ -54,7 +54,6 @@ import {TranslocoDatePipe} from "@jsverse/transloco-locale";
import {UtcToLocalTimePipe} from "../../../_pipes/utc-to-local-time.pipe";
import {EditListComponent} from "../../../shared/edit-list/edit-list.component";
import {AccountService} from "../../../_services/account.service";
-import {LibraryType} from "../../../_models/library/library";
import {ToastrService} from "ngx-toastr";
import {Volume} from "../../../_models/volume";
import {Action, ActionFactoryService, ActionItem} from "../../../_services/action-factory.service";
@@ -62,6 +61,7 @@ import {SettingButtonComponent} from "../../../settings/_components/setting-butt
import {ActionService} from "../../../_services/action.service";
import {DownloadService} from "../../../shared/_services/download.service";
import {SettingItemComponent} from "../../../settings/_components/setting-item/setting-item.component";
+import {ReadTimePipe} from "../../../_pipes/read-time.pipe";
enum TabID {
General = 0,
@@ -116,6 +116,7 @@ const blackList = [Action.Edit, Action.Info, Action.IncognitoRead, Action.Read,
EditListComponent,
SettingButtonComponent,
SettingItemComponent,
+ ReadTimePipe,
],
templateUrl: './edit-series-modal.component.html',
styleUrls: ['./edit-series-modal.component.scss'],
diff --git a/UI/Web/src/app/cards/card-detail-layout/card-detail-layout.component.scss b/UI/Web/src/app/cards/card-detail-layout/card-detail-layout.component.scss
index c6cf51fa3..b19f6a381 100644
--- a/UI/Web/src/app/cards/card-detail-layout/card-detail-layout.component.scss
+++ b/UI/Web/src/app/cards/card-detail-layout/card-detail-layout.component.scss
@@ -25,7 +25,7 @@
.grid {
display: grid;
- grid-template-columns: repeat(auto-fill, 158px);
+ grid-template-columns: repeat(auto-fill, 160px);
grid-gap: 0.5rem;
justify-content: space-between;
width: 100%;
diff --git a/UI/Web/src/app/cards/card-item/card-item.component.html b/UI/Web/src/app/cards/card-item/card-item.component.html
index 47adc7573..1a666c48f 100644
--- a/UI/Web/src/app/cards/card-item/card-item.component.html
+++ b/UI/Web/src/app/cards/card-item/card-item.component.html
@@ -2,9 +2,9 @@
@if (total > 0 || suppressArchiveWarning) {
-
+
} @else if (total === 0 && !suppressArchiveWarning) {
-
+
}
diff --git a/UI/Web/src/app/cards/chapter-card/chapter-card.component.html b/UI/Web/src/app/cards/chapter-card/chapter-card.component.html
index 61ba81ce6..c57c533ca 100644
--- a/UI/Web/src/app/cards/chapter-card/chapter-card.component.html
+++ b/UI/Web/src/app/cards/chapter-card/chapter-card.component.html
@@ -2,9 +2,9 @@
@if (chapter.pages > 0 || suppressArchiveWarning) {
-
+
} @else if (chapter.pages === 0 && !suppressArchiveWarning) {
-
+
}
diff --git a/UI/Web/src/app/cards/cover-image-chooser/cover-image-chooser.component.html b/UI/Web/src/app/cards/cover-image-chooser/cover-image-chooser.component.html
index e4ad639e2..41dddfa59 100644
--- a/UI/Web/src/app/cards/cover-image-chooser/cover-image-chooser.component.html
+++ b/UI/Web/src/app/cards/cover-image-chooser/cover-image-chooser.component.html
@@ -55,7 +55,7 @@
-
+
{{t('reset')}}
@@ -65,7 +65,7 @@
-
0">
+
0">
-
+
diff --git a/UI/Web/src/app/cards/list-item/list-item.component.ts b/UI/Web/src/app/cards/list-item/list-item.component.ts
index 1b6731b09..5f85735fc 100644
--- a/UI/Web/src/app/cards/list-item/list-item.component.ts
+++ b/UI/Web/src/app/cards/list-item/list-item.component.ts
@@ -61,13 +61,13 @@ export class ListItemComponent implements OnInit {
@Input() seriesName: string = '';
/**
- * Size of the Image Height. Defaults to 230px.
+ * Size of the Image Height. Defaults to 232.91px.
*/
- @Input() imageHeight: string = '230px';
+ @Input() imageHeight: string = '232.91px';
/**
- * Size of the Image Width Defaults to 158px.
+ * Size of the Image Width Defaults to 160px.
*/
- @Input() imageWidth: string = '158px';
+ @Input() imageWidth: string = '160px';
@Input() seriesLink: string = '';
@Input() pagesRead: number = 0;
diff --git a/UI/Web/src/app/cards/next-expected-card/next-expected-card.component.html b/UI/Web/src/app/cards/next-expected-card/next-expected-card.component.html
index 365279414..9a5519450 100644
--- a/UI/Web/src/app/cards/next-expected-card/next-expected-card.component.html
+++ b/UI/Web/src/app/cards/next-expected-card/next-expected-card.component.html
@@ -1,6 +1,6 @@
-
diff --git a/UI/Web/src/app/cards/series-card/series-card.component.html b/UI/Web/src/app/cards/series-card/series-card.component.html
index a4fa2bf95..4d67a6894 100644
--- a/UI/Web/src/app/cards/series-card/series-card.component.html
+++ b/UI/Web/src/app/cards/series-card/series-card.component.html
@@ -2,9 +2,9 @@
@if (series.pages > 0) {
-
+
} @else if (series.pages === 0) {
-
+
}
diff --git a/UI/Web/src/app/cards/volume-card/volume-card.component.html b/UI/Web/src/app/cards/volume-card/volume-card.component.html
index 7268a4d16..53467480b 100644
--- a/UI/Web/src/app/cards/volume-card/volume-card.component.html
+++ b/UI/Web/src/app/cards/volume-card/volume-card.component.html
@@ -2,9 +2,9 @@
@if (volume.pages > 0 || suppressArchiveWarning) {
-
+
} @else if (volume.pages === 0 && !suppressArchiveWarning) {
-
+
}
@@ -50,11 +50,13 @@
-
-
- {{volume.name}}
+ @if (libraryType === LibraryType.LightNovel || libraryType === LibraryType.Book) {
+
-
+ }
diff --git a/UI/Web/src/app/cards/volume-card/volume-card.component.ts b/UI/Web/src/app/cards/volume-card/volume-card.component.ts
index da265d449..ed434b623 100644
--- a/UI/Web/src/app/cards/volume-card/volume-card.component.ts
+++ b/UI/Web/src/app/cards/volume-card/volume-card.component.ts
@@ -216,4 +216,5 @@ export class VolumeCardComponent implements OnInit {
this.readerService.readVolume(this.libraryId, this.seriesId, this.volume, false);
}
+ protected readonly LibraryType = LibraryType;
}
diff --git a/UI/Web/src/app/chapter-detail/chapter-detail.component.ts b/UI/Web/src/app/chapter-detail/chapter-detail.component.ts
index 1e959f0db..4d2bf5f66 100644
--- a/UI/Web/src/app/chapter-detail/chapter-detail.component.ts
+++ b/UI/Web/src/app/chapter-detail/chapter-detail.component.ts
@@ -8,8 +8,7 @@ import {
ViewChild
} from '@angular/core';
import {BulkOperationsComponent} from "../cards/bulk-operations/bulk-operations.component";
-import {TagBadgeComponent, TagBadgeCursor} from "../shared/tag-badge/tag-badge.component";
-import {PageLayoutMode} from "../_models/page-layout-mode";
+import {TagBadgeComponent} from "../shared/tag-badge/tag-badge.component";
import {AsyncPipe, DecimalPipe, DOCUMENT, NgStyle} from "@angular/common";
import {CardActionablesComponent} from "../_single-module/card-actionables/card-actionables.component";
import {CarouselReelComponent} from "../carousel/_components/carousel-reel/carousel-reel.component";
@@ -31,15 +30,12 @@ import {
import {PersonBadgeComponent} from "../shared/person-badge/person-badge.component";
import {ReviewCardComponent} from "../_single-module/review-card/review-card.component";
import {SeriesCardComponent} from "../cards/series-card/series-card.component";
-import {
- SeriesMetadataDetailComponent
-} from "../series-detail/_components/series-metadata-detail/series-metadata-detail.component";
import {VirtualScrollerModule} from "@iharbeck/ngx-virtual-scroller";
import {ActivatedRoute, Router, RouterLink} from "@angular/router";
import {ImageService} from "../_services/image.service";
import {ChapterService} from "../_services/chapter.service";
import {Chapter} from "../_models/chapter";
-import {forkJoin, map, Observable, shareReplay, tap} from "rxjs";
+import {forkJoin, map, Observable, tap} from "rxjs";
import {SeriesService} from "../_services/series.service";
import {Series} from "../_models/series";
import {AgeRating} from "../_models/metadata/age-rating";
@@ -68,7 +64,6 @@ import {DefaultValuePipe} from "../_pipes/default-value.pipe";
import {ReadingList} from "../_models/reading-list";
import {ReadingListService} from "../_services/reading-list.service";
import {CardItemComponent} from "../cards/card-item/card-item.component";
-import {PageBookmark} from "../_models/readers/page-bookmark";
import {RelatedTabComponent} from "../_single-modules/related-tab/related-tab.component";
import {AgeRatingImageComponent} from "../_single-modules/age-rating-image/age-rating-image.component";
import {CompactNumberPipe} from "../_pipes/compact-number.pipe";
@@ -76,7 +71,6 @@ import {BadgeExpanderComponent} from "../shared/badge-expander/badge-expander.co
import {
MetadataDetailRowComponent
} from "../series-detail/_components/metadata-detail-row/metadata-detail-row.component";
-import {HourEstimateRange} from "../_models/series-detail/hour-estimate-range";
import {DownloadButtonComponent} from "../series-detail/_components/download-button/download-button.component";
import {hasAnyCast} from "../_models/common/i-has-cast";
import {CarouselTabComponent} from "../carousel/_components/carousel-tab/carousel-tab.component";
@@ -113,7 +107,6 @@ enum TabID {
PersonBadgeComponent,
ReviewCardComponent,
SeriesCardComponent,
- SeriesMetadataDetailComponent,
TagBadgeComponent,
VirtualScrollerModule,
NgStyle,
@@ -308,7 +301,7 @@ export class ChapterDetailComponent implements OnInit {
updateUrl(activeTab: TabID) {
const newUrl = `${this.router.url.split('#')[0]}#${activeTab}`;
- this.router.navigateByUrl(newUrl, { onSameUrlNavigation: 'ignore' });
+ //this.router.navigateByUrl(newUrl, { onSameUrlNavigation: 'ignore' });
}
openPerson(field: FilterField, value: number) {
diff --git a/UI/Web/src/app/collections/_components/collection-detail/collection-detail.component.scss b/UI/Web/src/app/collections/_components/collection-detail/collection-detail.component.scss
index c1cc4c260..8c21e2b4b 100644
--- a/UI/Web/src/app/collections/_components/collection-detail/collection-detail.component.scss
+++ b/UI/Web/src/app/collections/_components/collection-detail/collection-detail.component.scss
@@ -17,7 +17,7 @@
.card-container {
display: grid;
- grid-template-columns: repeat(auto-fill, 158px);
+ grid-template-columns: repeat(auto-fill, 160px);
grid-gap: 0.5rem;
justify-content: space-around;
}
diff --git a/UI/Web/src/app/series-detail/_components/series-detail/series-detail.component.html b/UI/Web/src/app/series-detail/_components/series-detail/series-detail.component.html
index 961974622..189ae9064 100644
--- a/UI/Web/src/app/series-detail/_components/series-detail/series-detail.component.html
+++ b/UI/Web/src/app/series-detail/_components/series-detail/series-detail.component.html
@@ -115,7 +115,7 @@
@@ -161,37 +161,70 @@
- @if (WebLinks.length > 0) {
-
-
-
-
{{t('weblinks-title')}}
-
- @for(link of WebLinks; track link) {
-
-
-
- }
-
+
+
+
+
{{t('genres-title')}}
+
+
-
-
{{t('publication-status-title')}}
-
- @if (seriesMetadata.publicationStatus | publicationStatus; as pubStatus) {
-
-
- {{pubStatus}}
-
- }
-
+
- }
+
+
+
+
+
+
+
{{t('weblinks-title')}}
+
+ @for(link of WebLinks; track link) {
+
+
+
+ } @empty {
+ {{null | defaultValue}}
+ }
+
+
+
+
+
{{t('publication-status-title')}}
+
+ @if (seriesMetadata.publicationStatus | publicationStatus; as pubStatus) {
+
+ {{pubStatus}}
+
+ }
+
+
+
+
+
diff --git a/UI/Web/src/app/series-detail/_components/series-detail/series-detail.component.scss b/UI/Web/src/app/series-detail/_components/series-detail/series-detail.component.scss
index 3253a393d..88835f221 100644
--- a/UI/Web/src/app/series-detail/_components/series-detail/series-detail.component.scss
+++ b/UI/Web/src/app/series-detail/_components/series-detail/series-detail.component.scss
@@ -22,7 +22,7 @@
//
.card-container{
display: grid;
- grid-template-columns: repeat(auto-fill, 158px);
+ grid-template-columns: repeat(auto-fill, 160px);
grid-gap: 0.5rem;
justify-content: space-around;
}
diff --git a/UI/Web/src/app/series-detail/_components/series-detail/series-detail.component.ts b/UI/Web/src/app/series-detail/_components/series-detail/series-detail.component.ts
index 56e4a57f8..1c7d800b2 100644
--- a/UI/Web/src/app/series-detail/_components/series-detail/series-detail.component.ts
+++ b/UI/Web/src/app/series-detail/_components/series-detail/series-detail.component.ts
@@ -91,7 +91,6 @@ import {VirtualScrollerModule} from '@iharbeck/ngx-virtual-scroller';
import {BulkOperationsComponent} from '../../../cards/bulk-operations/bulk-operations.component';
import {ReviewCardComponent} from '../../../_single-module/review-card/review-card.component';
import {CarouselReelComponent} from '../../../carousel/_components/carousel-reel/carousel-reel.component';
-import {SeriesMetadataDetailComponent} from '../series-metadata-detail/series-metadata-detail.component';
import {ImageComponent} from '../../../shared/image/image.component';
import {TagBadgeComponent} from '../../../shared/tag-badge/tag-badge.component';
import {
@@ -175,7 +174,7 @@ interface StoryLineItem {
standalone: true,
imports: [SideNavCompanionBarComponent, CardActionablesComponent, ReactiveFormsModule, NgStyle,
TagBadgeComponent, ImageComponent, NgbTooltip, NgbProgressbar, NgbDropdown, NgbDropdownToggle, NgbDropdownMenu,
- NgbDropdownItem, SeriesMetadataDetailComponent, CarouselReelComponent, ReviewCardComponent, BulkOperationsComponent,
+ NgbDropdownItem, CarouselReelComponent, ReviewCardComponent, BulkOperationsComponent,
NgbNav, NgbNavItem, NgbNavLink, NgbNavContent, VirtualScrollerModule, CardItemComponent,
EntityTitleComponent, SeriesCardComponent, ExternalSeriesCardComponent, NgbNavOutlet,
LoadingComponent, DecimalPipe, TranslocoDirective, NgTemplateOutlet, NextExpectedCardComponent,
@@ -446,7 +445,7 @@ export class SeriesDetailComponent implements OnInit, AfterContentChecked {
constructor(@Inject(DOCUMENT) private document: Document) {
- //this.router.routeReuseStrategy.shouldReuseRoute = () => false;
+ this.router.routeReuseStrategy.shouldReuseRoute = () => false;
this.accountService.currentUser$.subscribe(user => {
@@ -553,8 +552,15 @@ export class SeriesDetailComponent implements OnInit, AfterContentChecked {
}
updateUrl(activeTab: TabID) {
- const newUrl = `${this.router.url.split('#')[0]}#${activeTab}`;
- this.router.navigateByUrl(newUrl, { onSameUrlNavigation: 'ignore' });
+ var tokens = this.router.url.split('#');
+ const newUrl = `${tokens[0]}#${activeTab}`;
+
+ // if (tokens.length === 1 || tokens[1] === activeTab + '') {
+ // return;
+ // }
+ console.log('url:', newUrl);
+
+ //this.router.navigateByUrl(newUrl, { skipLocationChange: true, replaceUrl: true });
}
handleSeriesActionCallback(action: ActionItem
, series: Series) {
@@ -869,7 +875,6 @@ export class SeriesDetailComponent implements OnInit, AfterContentChecked {
* This assumes loadPage() has already primed all the calculations and state variables. Do not call directly.
*/
updateSelectedTab() {
- console.log('updateSelectedTab')
// Book libraries only have Volumes or Specials enabled
if (this.libraryType === LibraryType.Book || this.libraryType === LibraryType.LightNovel) {
if (this.volumes.length === 0) {
diff --git a/UI/Web/src/app/series-detail/_components/series-metadata-detail/series-metadata-detail.component.html b/UI/Web/src/app/series-detail/_components/series-metadata-detail/series-metadata-detail.component.html
deleted file mode 100644
index 51d689f87..000000000
--- a/UI/Web/src/app/series-detail/_components/series-metadata-detail/series-metadata-detail.component.html
+++ /dev/null
@@ -1,168 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {{item.title}}
-
-
-
-
- {{item.title}}
-
-
-
- @if (collections$) {
-
-
-
- {{item.title}}
-
-
-
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/UI/Web/src/app/series-detail/_components/series-metadata-detail/series-metadata-detail.component.scss b/UI/Web/src/app/series-detail/_components/series-metadata-detail/series-metadata-detail.component.scss
deleted file mode 100644
index 8f69ccb39..000000000
--- a/UI/Web/src/app/series-detail/_components/series-metadata-detail/series-metadata-detail.component.scss
+++ /dev/null
@@ -1,3 +0,0 @@
-.favicon {
- border-radius: 5px;
-}
diff --git a/UI/Web/src/app/series-detail/_components/series-metadata-detail/series-metadata-detail.component.ts b/UI/Web/src/app/series-detail/_components/series-metadata-detail/series-metadata-detail.component.ts
deleted file mode 100644
index 316c33c35..000000000
--- a/UI/Web/src/app/series-detail/_components/series-metadata-detail/series-metadata-detail.component.ts
+++ /dev/null
@@ -1,153 +0,0 @@
-import {
- ChangeDetectionStrategy,
- ChangeDetectorRef,
- Component, DestroyRef,
- inject,
- Input,
- OnChanges, OnInit,
- SimpleChanges,
- ViewEncapsulation
-} from '@angular/core';
-import {Router} from '@angular/router';
-import {TagBadgeComponent, TagBadgeCursor} from '../../../shared/tag-badge/tag-badge.component';
-import {FilterUtilitiesService} from '../../../shared/_services/filter-utilities.service';
-import {Breakpoint, UtilityService} from '../../../shared/_services/utility.service';
-import {MangaFormat} from '../../../_models/manga-format';
-import {ReadingList} from '../../../_models/reading-list';
-import {Series} from '../../../_models/series';
-import {SeriesMetadata} from '../../../_models/metadata/series-metadata';
-import {ImageService} from 'src/app/_services/image.service';
-import {CommonModule} from "@angular/common";
-import {BadgeExpanderComponent} from "../../../shared/badge-expander/badge-expander.component";
-import {SafeHtmlPipe} from "../../../_pipes/safe-html.pipe";
-import {ExternalRatingComponent} from "../external-rating/external-rating.component";
-import {ReadMoreComponent} from "../../../shared/read-more/read-more.component";
-import {A11yClickDirective} from "../../../shared/a11y-click.directive";
-import {PersonBadgeComponent} from "../../../shared/person-badge/person-badge.component";
-import {NgbCollapse} from "@ng-bootstrap/ng-bootstrap";
-import {SeriesInfoCardsComponent} from "../../../cards/series-info-cards/series-info-cards.component";
-import {LibraryType} from "../../../_models/library/library";
-import {MetadataDetailComponent} from "../metadata-detail/metadata-detail.component";
-import {TranslocoDirective} from "@jsverse/transloco";
-import {FilterField} from "../../../_models/metadata/v2/filter-field";
-import {FilterComparison} from "../../../_models/metadata/v2/filter-comparison";
-import {ImageComponent} from "../../../shared/image/image.component";
-import {Rating} from "../../../_models/rating";
-import {CollectionTagService} from "../../../_services/collection-tag.service";
-import {takeUntilDestroyed} from "@angular/core/rxjs-interop";
-import {shareReplay} from "rxjs/operators";
-import {PromotedIconComponent} from "../../../shared/_components/promoted-icon/promoted-icon.component";
-import {Observable} from "rxjs";
-import {UserCollection} from "../../../_models/collection-tag";
-
-
-@Component({
- selector: 'app-series-metadata-detail',
- standalone: true,
- imports: [CommonModule, TagBadgeComponent, BadgeExpanderComponent, SafeHtmlPipe, ExternalRatingComponent,
- ReadMoreComponent, A11yClickDirective, PersonBadgeComponent, NgbCollapse, SeriesInfoCardsComponent,
- MetadataDetailComponent, TranslocoDirective, ImageComponent, PromotedIconComponent],
- templateUrl: './series-metadata-detail.component.html',
- styleUrls: ['./series-metadata-detail.component.scss'],
- changeDetection: ChangeDetectionStrategy.OnPush,
- encapsulation: ViewEncapsulation.None
-})
-export class SeriesMetadataDetailComponent implements OnChanges, OnInit {
-
- protected readonly imageService = inject(ImageService);
- protected readonly utilityService = inject(UtilityService);
- private readonly router = inject(Router);
- private readonly cdRef = inject(ChangeDetectorRef);
- private readonly filterUtilityService = inject(FilterUtilitiesService);
- private readonly collectionTagService = inject(CollectionTagService);
- private readonly destroyRef = inject(DestroyRef);
-
- protected readonly FilterField = FilterField;
- protected readonly LibraryType = LibraryType;
- protected readonly MangaFormat = MangaFormat;
- protected readonly TagBadgeCursor = TagBadgeCursor;
- protected readonly Breakpoint = Breakpoint;
-
- @Input({required: true}) seriesMetadata!: SeriesMetadata;
- @Input({required: true}) libraryType!: LibraryType;
- @Input() hasReadingProgress: boolean = false;
- /**
- * Reading lists with a connection to the Series
- */
- @Input() readingLists: Array = [];
- @Input({required: true}) series!: Series;
- @Input({required: true}) ratings: Array = [];
-
- isCollapsed: boolean = true;
- hasExtendedProperties: boolean = false;
-
- /**
- * Html representation of Series Summary
- */
- seriesSummary: string = '';
- collections$: Observable | undefined;
-
- get WebLinks() {
- if (this.seriesMetadata?.webLinks === '') return [];
- return this.seriesMetadata?.webLinks.split(',') || [];
- }
-
- ngOnInit() {
- // If on desktop, we can just have all the data expanded by default:
- this.isCollapsed = true; // this.utilityService.getActiveBreakpoint() < Breakpoint.Desktop;
- // Check if there is a lot of extended data, if so, re-collapse
- const sum = (this.seriesMetadata.colorists.length + this.seriesMetadata.editors.length
- + this.seriesMetadata.coverArtists.length + this.seriesMetadata.inkers.length
- + this.seriesMetadata.letterers.length + this.seriesMetadata.pencillers.length
- + this.seriesMetadata.publishers.length + this.seriesMetadata.characters.length
- + this.seriesMetadata.imprints.length + this.seriesMetadata.translators.length
- + this.seriesMetadata.writers.length + this.seriesMetadata.teams.length + this.seriesMetadata.locations.length) / 13;
- if (sum > 10) {
- this.isCollapsed = true;
- }
-
- this.collections$ = this.collectionTagService.allCollectionsForSeries(this.series.id).pipe(
- takeUntilDestroyed(this.destroyRef), shareReplay({bufferSize: 1, refCount: true}));
- this.cdRef.markForCheck();
-
-
- }
-
- ngOnChanges(changes: SimpleChanges): void {
- this.hasExtendedProperties = this.seriesMetadata.colorists.length > 0 ||
- this.seriesMetadata.editors.length > 0 ||
- this.seriesMetadata.coverArtists.length > 0 ||
- this.seriesMetadata.inkers.length > 0 ||
- this.seriesMetadata.letterers.length > 0 ||
- this.seriesMetadata.pencillers.length > 0 ||
- this.seriesMetadata.publishers.length > 0 ||
- this.seriesMetadata.characters.length > 0 ||
- this.seriesMetadata.imprints.length > 0 ||
- this.seriesMetadata.teams.length > 0 ||
- this.seriesMetadata.locations.length > 0 ||
- this.seriesMetadata.translators.length > 0
- ;
-
-
- this.seriesSummary = (this.seriesMetadata?.summary === null ? '' : this.seriesMetadata.summary).replace(/\n/g, ' ');
- this.cdRef.markForCheck();
- }
-
- toggleView() {
- this.isCollapsed = !this.isCollapsed;
- this.cdRef.markForCheck();
- }
-
- handleGoTo(event: {queryParamName: FilterField, filter: any}) {
- this.goTo(event.queryParamName, event.filter);
- }
-
- goTo(queryParamName: FilterField, filter: any) {
- this.filterUtilityService.applyFilter(['library', this.series.libraryId], queryParamName,
- FilterComparison.Equal, filter).subscribe();
- }
-
- navigate(basePage: string, id: number) {
- this.router.navigate([basePage, id]);
- }
-}
diff --git a/UI/Web/src/app/sidenav/_components/side-nav-item/side-nav-item.component.ts b/UI/Web/src/app/sidenav/_components/side-nav-item/side-nav-item.component.ts
index 25798d70a..589e9b54d 100644
--- a/UI/Web/src/app/sidenav/_components/side-nav-item/side-nav-item.component.ts
+++ b/UI/Web/src/app/sidenav/_components/side-nav-item/side-nav-item.component.ts
@@ -88,6 +88,7 @@ export class SideNavItemComponent implements OnInit {
triggerHighlightCheck(routeUrl: string) {
const [url, queryParams] = routeUrl.split('?');
const [page, fragment = ''] = url.split('#');
+
this.updateHighlight(page, queryParams, url.includes('#') ? fragment : undefined);
}
@@ -99,7 +100,7 @@ export class SideNavItemComponent implements OnInit {
return;
}
- if (!page.endsWith('/') && !queryParams && this.fragment === undefined) {
+ if (!page.endsWith('/') && !queryParams && this.fragment === undefined && queryParams === undefined) {
page = page + '/';
}
@@ -111,8 +112,9 @@ export class SideNavItemComponent implements OnInit {
fragmentEqual = true;
}
+ const queryParamsEqual = this.queryParams === queryParams;
- if (this.comparisonMethod === 'equals' && page === this.link && fragmentEqual) {
+ if (this.comparisonMethod === 'equals' && page === this.link && fragmentEqual && queryParamsEqual) {
this.highlighted = true;
this.cdRef.markForCheck();
return;
diff --git a/UI/Web/src/app/user-settings/manga-user-preferences/manage-user-preferences.component.html b/UI/Web/src/app/user-settings/manga-user-preferences/manage-user-preferences.component.html
index c7f702fbe..0d5ca9dd0 100644
--- a/UI/Web/src/app/user-settings/manga-user-preferences/manage-user-preferences.component.html
+++ b/UI/Web/src/app/user-settings/manga-user-preferences/manage-user-preferences.component.html
@@ -7,22 +7,6 @@