Shakeout Fixes (#422)
# Fixed - Fixed: Clean the pdf extension from Series title for PDF types - Fixed: Fixed a bug where a forced metadata refresh wouldn't trigger a volume to force a refresh of cover image - Fixed: Fixed an issue where Removing series no longer on disk would not use the Series Format and thus after deleting files, they would not be removed. - Fixed: Fixed an issue with reading a single image file, where the cache code would not properly move the file - Fixed: For Specials, Get Next/Prev Chapter should use the filename instead of arbitrary Number (which is always 0). Use the same sorting logic when requesting volumes on series detail, so sorting can happen in the backend. # Added - Added: (Accessibility) Nearly every page has had a title set for it =============================================================================== * Clean the pdf extension from ParseSeries * Fixed a bug where forced metadata refresh wouldn't trigger the volume to update it's image. * Added titles to most pages to help distinguish back/forward history. Fixed a bug in the scanner which didn't account for Format when calculating if we need to remove a series not on disk. * For Specials, Get Next/Prev Chapter should use the filename instead of arbitrary Number (which is always 0). Use the same sorting logic when requesting volumes on series detail, so sorting can happen in the backend. * Fixed unit tests
This commit is contained in:
parent
29edadb506
commit
ebd4ec25bf
23 changed files with 143 additions and 97 deletions
|
@ -21,7 +21,7 @@ export class AuthGuard implements CanActivate {
|
|||
}
|
||||
this.toastr.error('You are not authorized to view this page.');
|
||||
localStorage.setItem(this.urlKey, window.location.pathname);
|
||||
this.router.navigateByUrl('/home');
|
||||
this.router.navigateByUrl('/libraries');
|
||||
return false;
|
||||
})
|
||||
);
|
||||
|
|
|
@ -3,6 +3,7 @@ import { ActivatedRoute } from '@angular/router';
|
|||
import { ToastrService } from 'ngx-toastr';
|
||||
import { ServerService } from 'src/app/_services/server.service';
|
||||
import { saveAs } from 'file-saver';
|
||||
import { Title } from '@angular/platform-browser';
|
||||
|
||||
|
||||
|
||||
|
@ -22,7 +23,7 @@ export class DashboardComponent implements OnInit {
|
|||
counter = this.tabs.length + 1;
|
||||
active = this.tabs[0];
|
||||
|
||||
constructor(public route: ActivatedRoute, private serverService: ServerService, private toastr: ToastrService) {
|
||||
constructor(public route: ActivatedRoute, private serverService: ServerService, private toastr: ToastrService, private titleService: Title) {
|
||||
this.route.fragment.subscribe(frag => {
|
||||
const tab = this.tabs.filter(item => item.fragment === frag);
|
||||
if (tab.length > 0) {
|
||||
|
@ -34,7 +35,9 @@ export class DashboardComponent implements OnInit {
|
|||
|
||||
}
|
||||
|
||||
ngOnInit() {}
|
||||
ngOnInit() {
|
||||
this.titleService.setTitle('Kavita - Admin Dashboard');
|
||||
}
|
||||
|
||||
restartServer() {
|
||||
this.serverService.restart().subscribe(() => {
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { Component, OnInit } from '@angular/core';
|
||||
import { Title } from '@angular/platform-browser';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
|
||||
import { ToastrService } from 'ngx-toastr';
|
||||
|
@ -28,7 +29,9 @@ export class AllCollectionsComponent implements OnInit {
|
|||
seriesPagination!: Pagination;
|
||||
collectionTagActions: ActionItem<CollectionTag>[] = [];
|
||||
|
||||
constructor(private collectionService: CollectionTagService, private router: Router, private route: ActivatedRoute, private seriesService: SeriesService, private toastr: ToastrService, private actionFactoryService: ActionFactoryService, private modalService: NgbModal) {
|
||||
constructor(private collectionService: CollectionTagService, private router: Router, private route: ActivatedRoute,
|
||||
private seriesService: SeriesService, private toastr: ToastrService, private actionFactoryService: ActionFactoryService,
|
||||
private modalService: NgbModal, private titleService: Title) {
|
||||
this.router.routeReuseStrategy.shouldReuseRoute = () => false;
|
||||
|
||||
const routeId = this.route.snapshot.paramMap.get('id');
|
||||
|
@ -43,6 +46,7 @@ export class AllCollectionsComponent implements OnInit {
|
|||
return;
|
||||
}
|
||||
this.collectionTagName = tags.filter(item => item.id === this.collectionTagId)[0].title;
|
||||
this.titleService.setTitle('Kavita - ' + this.collectionTagName + ' Collection');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import { Router } from '@angular/router';
|
|||
import { take } from 'rxjs/operators';
|
||||
import { MemberService } from '../_services/member.service';
|
||||
import { AccountService } from '../_services/account.service';
|
||||
import { Title } from '@angular/platform-browser';
|
||||
|
||||
@Component({
|
||||
selector: 'app-home',
|
||||
|
@ -19,7 +20,7 @@ export class HomeComponent implements OnInit {
|
|||
password: new FormControl('', [Validators.required])
|
||||
});
|
||||
|
||||
constructor(public accountService: AccountService, private memberService: MemberService, private router: Router) {
|
||||
constructor(public accountService: AccountService, private memberService: MemberService, private router: Router, private titleService: Title) {
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
|
@ -31,6 +32,7 @@ export class HomeComponent implements OnInit {
|
|||
return;
|
||||
}
|
||||
|
||||
this.titleService.setTitle('Kavita');
|
||||
this.accountService.currentUser$.pipe(take(1)).subscribe(user => {
|
||||
if (user) {
|
||||
this.router.navigateByUrl('/library');
|
||||
|
|
|
@ -28,7 +28,7 @@ export class LibraryDetailComponent implements OnInit {
|
|||
private libraryService: LibraryService, private titleService: Title, private actionFactoryService: ActionFactoryService, private actionService: ActionService) {
|
||||
const routeId = this.route.snapshot.paramMap.get('id');
|
||||
if (routeId === null) {
|
||||
this.router.navigateByUrl('/home');
|
||||
this.router.navigateByUrl('/libraries');
|
||||
return;
|
||||
}
|
||||
this.router.routeReuseStrategy.shouldReuseRoute = () => false;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { Component, OnInit } from '@angular/core';
|
||||
import { Title } from '@angular/platform-browser';
|
||||
import { Router } from '@angular/router';
|
||||
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
|
||||
import { take } from 'rxjs/operators';
|
||||
|
@ -34,9 +35,13 @@ export class LibraryComponent implements OnInit {
|
|||
|
||||
seriesTrackBy = (index: number, item: any) => `${item.name}_${item.pagesRead}`;
|
||||
|
||||
constructor(public accountService: AccountService, private libraryService: LibraryService, private seriesService: SeriesService, private actionFactoryService: ActionFactoryService, private collectionService: CollectionTagService, private router: Router, private modalService: NgbModal) { }
|
||||
constructor(public accountService: AccountService, private libraryService: LibraryService,
|
||||
private seriesService: SeriesService, private actionFactoryService: ActionFactoryService,
|
||||
private collectionService: CollectionTagService, private router: Router,
|
||||
private modalService: NgbModal, private titleService: Title) { }
|
||||
|
||||
ngOnInit(): void {
|
||||
this.titleService.setTitle('Kavita - Dashboard');
|
||||
this.isLoading = true;
|
||||
this.accountService.currentUser$.pipe(take(1)).subscribe(user => {
|
||||
this.user = user;
|
||||
|
|
|
@ -245,7 +245,7 @@ export class MangaReaderComponent implements OnInit, AfterViewInit, OnDestroy {
|
|||
const chapterId = this.route.snapshot.paramMap.get('chapterId');
|
||||
|
||||
if (libraryId === null || seriesId === null || chapterId === null) {
|
||||
this.router.navigateByUrl('/home');
|
||||
this.router.navigateByUrl('/libraries');
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -61,7 +61,7 @@ export class NavHeaderComponent implements OnInit, OnDestroy {
|
|||
logout() {
|
||||
this.accountService.logout();
|
||||
this.navService.hideNavBar();
|
||||
this.router.navigateByUrl('/home');
|
||||
this.router.navigateByUrl('/login');
|
||||
}
|
||||
|
||||
moveFocus() {
|
||||
|
|
|
@ -1,14 +1,13 @@
|
|||
import { Component, OnInit } from '@angular/core';
|
||||
import { Title } from '@angular/platform-browser';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import { NgbModal, NgbRatingConfig } from '@ng-bootstrap/ng-bootstrap';
|
||||
import { ToastrService } from 'ngx-toastr';
|
||||
import { forkJoin } from 'rxjs';
|
||||
import { take } from 'rxjs/operators';
|
||||
import { ConfirmConfig } from '../shared/confirm-dialog/_models/confirm-config';
|
||||
import { ConfirmService } from '../shared/confirm.service';
|
||||
import { CardDetailsModalComponent } from '../shared/_modals/card-details-modal/card-details-modal.component';
|
||||
import { DownloadService } from '../shared/_services/download.service';
|
||||
import { NaturalSortService } from '../shared/_services/natural-sort.service';
|
||||
import { UtilityService } from '../shared/_services/utility.service';
|
||||
import { EditSeriesModalComponent } from '../_modals/edit-series-modal/edit-series-modal.component';
|
||||
import { ReviewSeriesModalComponent } from '../_modals/review-series-modal/review-series-modal.component';
|
||||
|
@ -81,7 +80,7 @@ export class SeriesDetailComponent implements OnInit {
|
|||
public utilityService: UtilityService, private toastr: ToastrService,
|
||||
private accountService: AccountService, public imageService: ImageService,
|
||||
private actionFactoryService: ActionFactoryService, private libraryService: LibraryService,
|
||||
private confirmService: ConfirmService, private naturalSort: NaturalSortService,
|
||||
private confirmService: ConfirmService, private titleService: Title,
|
||||
private downloadService: DownloadService, private actionService: ActionService) {
|
||||
ratingConfig.max = 5;
|
||||
this.router.routeReuseStrategy.shouldReuseRoute = () => false;
|
||||
|
@ -97,7 +96,7 @@ export class SeriesDetailComponent implements OnInit {
|
|||
const routeId = this.route.snapshot.paramMap.get('seriesId');
|
||||
const libraryId = this.route.snapshot.paramMap.get('libraryId');
|
||||
if (routeId === null || libraryId == null) {
|
||||
this.router.navigateByUrl('/home');
|
||||
this.router.navigateByUrl('/libraries');
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -227,6 +226,8 @@ export class SeriesDetailComponent implements OnInit {
|
|||
this.seriesService.getSeries(seriesId).subscribe(series => {
|
||||
this.series = series;
|
||||
this.createHTML();
|
||||
|
||||
this.titleService.setTitle('Kavita - ' + this.series.name + ' Details');
|
||||
|
||||
|
||||
this.seriesService.getVolumes(this.series.id).subscribe(volumes => {
|
||||
|
@ -240,7 +241,6 @@ export class SeriesDetailComponent implements OnInit {
|
|||
this.specials = vol0.map(v => v.chapters || [])
|
||||
.flat()
|
||||
.filter(c => c.isSpecial || isNaN(parseInt(c.range, 10)))
|
||||
.sort((a, b) => this.naturalSort.compare(a.range, b.range, true))
|
||||
.map(c => {
|
||||
c.title = this.utilityService.cleanSpecialTitle(c.title);
|
||||
c.range = this.utilityService.cleanSpecialTitle(c.range);
|
||||
|
@ -255,6 +255,8 @@ export class SeriesDetailComponent implements OnInit {
|
|||
|
||||
this.isLoading = false;
|
||||
});
|
||||
}, err => {
|
||||
this.router.navigateByUrl('/libraries');
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -5,7 +5,6 @@ import { MangaFile } from 'src/app/_models/manga-file';
|
|||
import { MangaFormat } from 'src/app/_models/manga-format';
|
||||
import { Volume } from 'src/app/_models/volume';
|
||||
import { ImageService } from 'src/app/_services/image.service';
|
||||
import { NaturalSortService } from '../../_services/natural-sort.service';
|
||||
import { UtilityService } from '../../_services/utility.service';
|
||||
|
||||
|
||||
|
@ -27,7 +26,7 @@ export class CardDetailsModalComponent implements OnInit {
|
|||
formatKeys = Object.keys(MangaFormat);
|
||||
|
||||
constructor(private modalService: NgbModal, public modal: NgbActiveModal, public utilityService: UtilityService,
|
||||
public imageService: ImageService, public naturalSort: NaturalSortService) { }
|
||||
public imageService: ImageService) { }
|
||||
|
||||
ngOnInit(): void {
|
||||
this.isChapter = this.isObjectChapter(this.data);
|
||||
|
|
|
@ -2,6 +2,7 @@ import { Injectable, OnDestroy } from '@angular/core';
|
|||
|
||||
/**
|
||||
* Soley repsonsible for performing a "natural" sort. This is the UI counterpart to the BE NaturalSortComparer.
|
||||
* Note: This does not work the same. Better to have the Backend perform the sort before sending to UI.
|
||||
*/
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
|
|
|
@ -8,6 +8,7 @@ import { AccountService } from '../_services/account.service';
|
|||
import { Options } from '@angular-slider/ngx-slider';
|
||||
import { BookService } from '../book-reader/book.service';
|
||||
import { NavService } from '../_services/nav.service';
|
||||
import { Title } from '@angular/platform-browser';
|
||||
|
||||
@Component({
|
||||
selector: 'app-user-preferences',
|
||||
|
@ -47,11 +48,12 @@ export class UserPreferencesComponent implements OnInit, OnDestroy {
|
|||
};
|
||||
fontFamilies: Array<string> = [];
|
||||
|
||||
constructor(private accountService: AccountService, private toastr: ToastrService, private bookService: BookService, private navService: NavService) {
|
||||
constructor(private accountService: AccountService, private toastr: ToastrService, private bookService: BookService, private navService: NavService, private titleService: Title) {
|
||||
this.fontFamilies = this.bookService.getFontFamilies();
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.titleService.setTitle('Kavita - User Preferences');
|
||||
this.accountService.currentUser$.pipe(take(1)).subscribe((user: User) => {
|
||||
if (user) {
|
||||
this.user = user;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue