Lots of Bugfixes (#2960)

Co-authored-by: Samuel Martins <s@smartins.ch>
Co-authored-by: Robbie Davis <robbie@therobbiedavis.com>
This commit is contained in:
Joe Milazzo 2024-05-22 06:58:23 -05:00 committed by GitHub
parent 97ffdd0975
commit b50fa0fd1e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
45 changed files with 563 additions and 282 deletions

View file

@ -3,137 +3,145 @@
<h2 title>
<app-card-actionables (actionHandler)="performAction($event)" [actions]="actions" [attr.aria-labelledby]="readingList?.title" *ngIf="actions.length > 0"></app-card-actionables>
{{readingList?.title}}
<span *ngIf="readingList?.promoted" class="ms-1">(<i class="fa fa-angle-double-up" aria-hidden="true"></i>)</span>
@if (readingList?.promoted) {
<span class="ms-1">(<i class="fa fa-angle-double-up" aria-hidden="true"></i>)</span>
}
</h2>
<h6 subtitle class="subtitle-with-actionables">{{t('item-count', {num: items.length | number})}}</h6>
<ng-template #extrasDrawer let-offcanvas>
<div style="margin-top: 56px" *ngIf="readingList">
<div class="offcanvas-header">
<h4 class="offcanvas-title" id="offcanvas-basic-title">{{t('page-settings-title')}}</h4>
<button type="button" class="btn-close" aria-label="Close" (click)="offcanvas.dismiss()"></button>
</div>
<div class="offcanvas-body">
<div class="row g-0">
<div class="col-md-12 col-sm-12 pe-2 mb-3">
<button class="btn btn-danger" (click)="removeRead()" [disabled]="readingList.promoted && !this.isAdmin">
@if (readingList) {
<div style="margin-top: 56px">
<div class="offcanvas-header">
<h4 class="offcanvas-title" id="offcanvas-basic-title">{{t('page-settings-title')}}</h4>
<button type="button" class="btn-close" aria-label="Close" (click)="offcanvas.dismiss()"></button>
</div>
<div class="offcanvas-body">
<div class="row g-0">
<div class="col-md-12 col-sm-12 pe-2 mb-3">
<button class="btn btn-danger" (click)="removeRead()" [disabled]="readingList.promoted && !this.isAdmin">
<span>
<i class="fa fa-check"></i>
</span>
<span class="read-btn--text">&nbsp;{{t('remove-read')}}</span>
</button>
<span class="read-btn--text">&nbsp;{{t('remove-read')}}</span>
</button>
<div class="col-auto ms-2 mt-2" *ngIf="!(readingList?.promoted && !this.isAdmin)">
<div class="form-check form-check-inline">
<input class="form-check-input" type="checkbox" id="accessibility-mode" [value]="accessibilityMode" (change)="updateAccessibilityMode()">
<label class="form-check-label" for="accessibility-mode">{{t('order-numbers-label')}}</label>
</div>
@if (!(readingList.promoted && !this.isAdmin)) {
<div class="col-auto ms-2 mt-2">
<div class="form-check form-check-inline">
<input class="form-check-input" type="checkbox" id="accessibility-mode" [disabled]="this.utilityService.getActiveBreakpoint() < Breakpoint.Tablet" [value]="accessibilityMode" (change)="updateAccessibilityMode()">
<label class="form-check-label" for="accessibility-mode">{{t('order-numbers-label')}}</label>
</div>
</div>
}
</div>
</div>
</div>
</div>
</div>
}
</ng-template>
</app-side-nav-companion-bar>
<div class="container-fluid mt-2" *ngIf="readingList" >
<div class="row mb-2">
<div class="col-md-2 col-xs-4 col-sm-6 d-none d-sm-block">
<app-image [styles]="{'max-height': '400px', 'max-width': '300px'}" [imageUrl]="imageService.getReadingListCoverImage(readingList.id)"></app-image>
</div>
<div class="col-md-10 col-xs-8 col-sm-6 mt-2">
<div class="row g-0 mb-3">
<div class="col-auto me-2">
<!-- Action row-->
<div class="btn-group me-3">
<button type="button" class="btn btn-primary" (click)="continue()">
@if (readingList) {
<div class="container-fluid mt-2">
<div class="row mb-2">
<div class="col-md-2 col-xs-4 col-sm-6 d-none d-sm-block">
<app-image [styles]="{'max-height': '400px', 'max-width': '300px'}" [imageUrl]="imageService.getReadingListCoverImage(readingList.id)"></app-image>
</div>
<div class="col-md-10 col-xs-8 col-sm-6 mt-2">
<div class="row g-0 mb-3">
<div class="col-auto me-2">
<!-- Action row-->
<div class="btn-group me-3">
<button type="button" class="btn btn-primary" (click)="continue()">
<span>
<i class="fa fa-book-open me-1" aria-hidden="true"></i>
<span class="read-btn--text">{{t('continue')}}</span>
</span>
</button>
<div class="btn-group" ngbDropdown role="group" [attr.aria-label]="t('read-options-alt')">
<button type="button" class="btn btn-primary dropdown-toggle-split" ngbDropdownToggle></button>
<div class="dropdown-menu" ngbDropdownMenu>
<button ngbDropdownItem (click)="read()">
</button>
<div class="btn-group" ngbDropdown role="group" [attr.aria-label]="t('read-options-alt')">
<button type="button" class="btn btn-primary dropdown-toggle-split" ngbDropdownToggle></button>
<div class="dropdown-menu" ngbDropdownMenu>
<button ngbDropdownItem (click)="read()">
<span>
<i class="fa fa-book" aria-hidden="true"></i>
<span class="read-btn--text">&nbsp;{{t('read')}}</span>
</span>
</button>
<button ngbDropdownItem (click)="continue(true)">
</button>
<button ngbDropdownItem (click)="continue(true)">
<span>
<i class="fa fa-book-open me-1" aria-hidden="true"></i>
<span class="read-btn--text">{{t('continue')}}</span>
(<i class="fa fa-glasses ms-1" aria-hidden="true"></i>)
<span class="visually-hidden">{{t('incognito-alt')}}</span>
</span>
</button>
<button ngbDropdownItem (click)="read(true)">
</button>
<button ngbDropdownItem (click)="read(true)">
<span>
<i class="fa fa-book me-1" aria-hidden="true"></i>
<span class="read-btn--text">&nbsp;{{t('read')}}</span>
(<i class="fa fa-glasses ms-1" aria-hidden="true"></i>)
<span class="visually-hidden">{{t('incognito-alt')}}</span>
</span>
</button>
</button>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="row g-0 mt-2" *ngIf="readingList.startingYear !== 0">
<h4 class="reading-list-years">
<ng-container *ngIf="readingList.startingMonth > 0">{{(readingList.startingMonth +'/01/2020')| date:'MMM'}}</ng-container>
<ng-container *ngIf="readingList.startingMonth > 0 && readingList.startingYear > 0">, </ng-container>
<ng-container *ngIf="readingList.startingYear > 0">{{readingList.startingYear}}</ng-container>
<ng-container *ngIf="readingList.endingYear > 0">
<ng-container *ngIf="readingList.endingMonth > 0">{{(readingList.endingMonth +'/01/2020') | date:'MMM'}}</ng-container>
<ng-container *ngIf="readingList.endingMonth > 0 && readingList.endingYear > 0">, </ng-container>
<ng-container *ngIf="readingList.endingYear > 0">{{readingList.endingYear}}</ng-container>
</ng-container>
<div class="row g-0 mt-2" *ngIf="readingList.startingYear !== 0">
<h4 class="reading-list-years">
<ng-container *ngIf="readingList.startingMonth > 0">{{(readingList.startingMonth +'/01/2020')| date:'MMM'}}</ng-container>
<ng-container *ngIf="readingList.startingMonth > 0 && readingList.startingYear > 0">, </ng-container>
<ng-container *ngIf="readingList.startingYear > 0">{{readingList.startingYear}}</ng-container>
<ng-container *ngIf="readingList.endingYear > 0">
<ng-container *ngIf="readingList.endingMonth > 0">{{(readingList.endingMonth +'/01/2020') | date:'MMM'}}</ng-container>
<ng-container *ngIf="readingList.endingMonth > 0 && readingList.endingYear > 0">, </ng-container>
<ng-container *ngIf="readingList.endingYear > 0">{{readingList.endingYear}}</ng-container>
</ng-container>
</h4>
</div>
<!-- Summary row-->
<div class="row g-0 mt-2">
<app-read-more [text]="readingListSummary" [maxLength]="250"></app-read-more>
</h4>
</div>
<!-- Summary row-->
<div class="row g-0 mt-2">
<app-read-more [text]="readingListSummary" [maxLength]="250"></app-read-more>
</div>
</div>
</div>
</div>
<ng-container *ngIf="characters$ | async as characters">
<div class="row mb-2">
<div class="row" *ngIf="characters && characters.length > 0">
<h5>{{t('characters-title')}}</h5>
<app-badge-expander [items]="characters">
<ng-template #badgeExpanderItem let-item let-position="idx">
<app-person-badge a11y-click="13,32" class="col-auto" [person]="item" (click)="goToCharacter(item)"></app-person-badge>
</ng-template>
</app-badge-expander>
</div>
</div>
</ng-container>
<div class="row mb-1 scroll-container" #scrollingBlock>
<ng-container *ngIf="items.length === 0 && !isLoading; else loading">
<div class="mx-auto" style="width: 200px;">
{{t('no-data')}}
<ng-container *ngIf="characters$ | async as characters">
<div class="row mb-2">
<div class="row" *ngIf="characters && characters.length > 0">
<h5>{{t('characters-title')}}</h5>
<app-badge-expander [items]="characters">
<ng-template #badgeExpanderItem let-item let-position="idx">
<app-person-badge a11y-click="13,32" class="col-auto" [person]="item" (click)="goToCharacter(item)"></app-person-badge>
</ng-template>
</app-badge-expander>
</div>
</div>
</ng-container>
<ng-template #loading>
<app-loading *ngIf="isLoading" [loading]="isLoading"></app-loading>
</ng-template>
<app-draggable-ordered-list [items]="items" (orderUpdated)="orderUpdated($event)" [accessibilityMode]="accessibilityMode"
[showRemoveButton]="false">
<ng-template #draggableItem let-item let-position="idx">
<app-reading-list-item [ngClass]="{'content-container': items.length < 100, 'non-virtualized-container': items.length >= 100}" [item]="item" [position]="position" [libraryTypes]="libraryTypes"
[promoted]="item.promoted" (read)="readChapter($event)" (remove)="itemRemoved($event, position)"></app-reading-list-item>
<div class="row mb-1 scroll-container" #scrollingBlock>
<ng-container *ngIf="items.length === 0 && !isLoading; else loading">
<div class="mx-auto" style="width: 200px;">
{{t('no-data')}}
</div>
</ng-container>
<ng-template #loading>
<app-loading *ngIf="isLoading" [loading]="isLoading"></app-loading>
</ng-template>
</app-draggable-ordered-list>
</div>
</div>
<app-draggable-ordered-list [items]="items" (orderUpdated)="orderUpdated($event)" [accessibilityMode]="accessibilityMode"
[showRemoveButton]="false">
<ng-template #draggableItem let-item let-position="idx">
<app-reading-list-item [ngClass]="{'content-container': items.length < 100, 'non-virtualized-container': items.length >= 100}" [item]="item" [position]="position" [libraryTypes]="libraryTypes"
[promoted]="item.promoted" (read)="readChapter($event)" (remove)="itemRemoved($event, position)"></app-reading-list-item>
</ng-template>
</app-draggable-ordered-list>
</div>
</div>
}
</ng-container>

View file

@ -3,7 +3,7 @@ import {ActivatedRoute, Router} from '@angular/router';
import {ToastrService} from 'ngx-toastr';
import {take} from 'rxjs/operators';
import {ConfirmService} from 'src/app/shared/confirm.service';
import {UtilityService} from 'src/app/shared/_services/utility.service';
import {Breakpoint, UtilityService} from 'src/app/shared/_services/utility.service';
import {LibraryType} from 'src/app/_models/library/library';
import {MangaFormat} from 'src/app/_models/manga-format';
import {ReadingList, ReadingListItem} from 'src/app/_models/reading-list';
@ -32,7 +32,7 @@ import {AsyncPipe, DatePipe, DecimalPipe, NgClass, NgIf} from '@angular/common';
import {
SideNavCompanionBarComponent
} from '../../../sidenav/_components/side-nav-companion-bar/side-nav-companion-bar.component';
import {translate, TranslocoDirective, TranslocoService} from "@ngneat/transloco";
import {translate, TranslocoDirective} from "@ngneat/transloco";
import {CardActionablesComponent} from "../../../_single-module/card-actionables/card-actionables.component";
import {FilterUtilitiesService} from "../../../shared/_services/filter-utilities.service";
import {FilterField} from "../../../_models/metadata/v2/filter-field";
@ -53,6 +53,26 @@ import {Title} from "@angular/platform-browser";
MetadataDetailComponent]
})
export class ReadingListDetailComponent implements OnInit {
private route = inject(ActivatedRoute);
private router = inject(Router);
private readingListService = inject(ReadingListService);
private actionService = inject(ActionService);
private actionFactoryService = inject(ActionFactoryService);
public utilityService = inject(UtilityService);
public imageService = inject(ImageService);
private accountService = inject(AccountService);
private toastr = inject(ToastrService);
private confirmService = inject(ConfirmService);
private libraryService = inject(LibraryService);
private readerService = inject(ReaderService);
private cdRef = inject(ChangeDetectorRef);
private filterUtilityService = inject(FilterUtilitiesService);
private titleService = inject(Title);
protected readonly MangaFormat = MangaFormat;
protected readonly Breakpoint = Breakpoint;
items: Array<ReadingListItem> = [];
listId!: number;
readingList: ReadingList | undefined;
@ -65,15 +85,8 @@ export class ReadingListDetailComponent implements OnInit {
libraryTypes: {[key: number]: LibraryType} = {};
characters$!: Observable<Person[]>;
private translocoService = inject(TranslocoService);
protected readonly MangaFormat = MangaFormat;
constructor(private route: ActivatedRoute, private router: Router, private readingListService: ReadingListService,
private actionService: ActionService, private actionFactoryService: ActionFactoryService, public utilityService: UtilityService,
public imageService: ImageService, private accountService: AccountService, private toastr: ToastrService,
private confirmService: ConfirmService, private libraryService: LibraryService, private readerService: ReaderService,
private readonly cdRef: ChangeDetectorRef, private filterUtilityService: FilterUtilitiesService, private titleService: Title) {
}
ngOnInit(): void {
const listId = this.route.snapshot.paramMap.get('id');
@ -86,6 +99,9 @@ export class ReadingListDetailComponent implements OnInit {
this.listId = parseInt(listId, 10);
this.characters$ = this.readingListService.getCharacters(this.listId);
this.accessibilityMode = this.utilityService.getActiveBreakpoint() < Breakpoint.Tablet;
this.cdRef.markForCheck();
forkJoin([
this.libraryService.getLibraries(),
this.readingListService.getReadingList(this.listId)
@ -165,10 +181,10 @@ export class ReadingListDetailComponent implements OnInit {
}
async deleteList(readingList: ReadingList) {
if (!await this.confirmService.confirm(this.translocoService.translate('toasts.confirm-delete-reading-list'))) return;
if (!await this.confirmService.confirm(translate('toasts.confirm-delete-reading-list'))) return;
this.readingListService.delete(readingList.id).subscribe(() => {
this.toastr.success(this.translocoService.translate('toasts.reading-list-deleted'));
this.toastr.success(translate('toasts.reading-list-deleted'));
this.router.navigateByUrl('/lists');
});
}
@ -186,7 +202,7 @@ export class ReadingListDetailComponent implements OnInit {
this.items.splice(position, 1);
this.items = [...this.items];
this.cdRef.markForCheck();
this.toastr.success(this.translocoService.translate('toasts.item-removed'));
this.toastr.success(translate('toasts.item-removed'));
});
}
@ -196,7 +212,7 @@ export class ReadingListDetailComponent implements OnInit {
this.cdRef.markForCheck();
this.readingListService.removeRead(this.readingList.id).subscribe((resp) => {
if (resp === 'Nothing to remove') {
this.toastr.info(this.translocoService.translate('toasts.nothing-to-remove'));
this.toastr.info(translate('toasts.nothing-to-remove'));
return;
}
this.getListItems();