Bugfixes (#2458)
Co-authored-by: Andre Smith <Hobogrammer@users.noreply.github.com>
This commit is contained in:
parent
565a93f2d2
commit
915bf13a7c
28 changed files with 606 additions and 342 deletions
|
@ -160,7 +160,7 @@
|
|||
<button class="btn btn-secondary col-2 col-xs-1" (click)="closeReader()"><i class="fa fa-times-circle" aria-hidden="true"></i></button>
|
||||
<button class="btn btn-outline-secondary btn-icon col-2 col-xs-1"
|
||||
[disabled]="readingDirection === ReadingDirection.LeftToRight ? IsNextDisabled : IsPrevDisabled"
|
||||
(click)="movePage(readingDirection === ReadingDirection.LeftToRight ? PAGING_DIRECTION.FORWARD : PAGING_DIRECTION.BACKWARDS)" title="{{readingDirection === ReadingDirection.LeftToRight ? t('next') : t('previous')}} Page">
|
||||
title="{{readingDirection === ReadingDirection.LeftToRight ? t('next') : t('previous')}} Page">
|
||||
<i class="fa {{(readingDirection === ReadingDirection.LeftToRight ? IsNextChapter : IsPrevChapter) ? 'fa-angle-double-right' : 'fa-angle-right'}} {{readingDirection === ReadingDirection.LeftToRight ? 'next-page-highlight' : ''}}" aria-hidden="true"></i>
|
||||
</button>
|
||||
</div>
|
||||
|
|
|
@ -102,10 +102,29 @@ const elementLevelStyles = ['line-height', 'font-family'];
|
|||
])
|
||||
],
|
||||
standalone: true,
|
||||
imports: [NgTemplateOutlet, DrawerComponent, NgIf, NgbProgressbar, NgbNav, NgbNavItem, NgbNavItemRole, NgbNavLink, NgbNavContent, ReaderSettingsComponent, TableOfContentsComponent, NgbNavOutlet, NgStyle, NgClass, NgbTooltip, BookLineOverlayComponent, PersonalTableOfContentsComponent, TranslocoDirective]
|
||||
imports: [NgTemplateOutlet, DrawerComponent, NgIf, NgbProgressbar, NgbNav, NgbNavItem, NgbNavItemRole, NgbNavLink,
|
||||
NgbNavContent, ReaderSettingsComponent, TableOfContentsComponent, NgbNavOutlet, NgStyle, NgClass, NgbTooltip,
|
||||
BookLineOverlayComponent, PersonalTableOfContentsComponent, TranslocoDirective]
|
||||
})
|
||||
export class BookReaderComponent implements OnInit, AfterViewInit, OnDestroy {
|
||||
|
||||
private readonly route = inject(ActivatedRoute);
|
||||
private readonly router = inject(Router);
|
||||
private readonly accountService = inject(AccountService);
|
||||
private readonly seriesService = inject(SeriesService);
|
||||
private readonly readerService = inject(ReaderService);
|
||||
private readonly renderer = inject(Renderer2);
|
||||
private readonly navService = inject(NavService);
|
||||
private readonly toastr = inject(ToastrService);
|
||||
private readonly domSanitizer = inject(DomSanitizer);
|
||||
private readonly bookService = inject(BookService);
|
||||
private readonly memberService = inject(MemberService);
|
||||
private readonly scrollService = inject(ScrollService);
|
||||
private readonly utilityService = inject(UtilityService);
|
||||
private readonly libraryService = inject(LibraryService);
|
||||
private readonly themeService = inject(ThemeService);
|
||||
private readonly cdRef = inject(ChangeDetectorRef);
|
||||
|
||||
libraryId!: number;
|
||||
seriesId!: number;
|
||||
volumeId!: number;
|
||||
|
@ -194,11 +213,11 @@ export class BookReaderComponent implements OnInit, AfterViewInit, OnDestroy {
|
|||
*/
|
||||
page: SafeHtml | undefined = undefined;
|
||||
/**
|
||||
* Next Chapter Id. This is not garunteed to be a valid ChapterId. Prefetched on page load (non-blocking).
|
||||
* Next Chapter Id. This is not guaranteed to be a valid ChapterId. Prefetched on page load (non-blocking).
|
||||
*/
|
||||
nextChapterId: number = CHAPTER_ID_NOT_FETCHED;
|
||||
/**
|
||||
* Previous Chapter Id. This is not garunteed to be a valid ChapterId. Prefetched on page load (non-blocking).
|
||||
* Previous Chapter Id. This is not guaranteed to be a valid ChapterId. Prefetched on page load (non-blocking).
|
||||
*/
|
||||
prevChapterId: number = CHAPTER_ID_NOT_FETCHED;
|
||||
/**
|
||||
|
@ -480,13 +499,7 @@ export class BookReaderComponent implements OnInit, AfterViewInit, OnDestroy {
|
|||
return (this.windowHeight) - (this.topOffset * 2) + 'px';
|
||||
}
|
||||
|
||||
|
||||
constructor(private route: ActivatedRoute, private router: Router, private accountService: AccountService,
|
||||
private seriesService: SeriesService, private readerService: ReaderService, private location: Location,
|
||||
private renderer: Renderer2, private navService: NavService, private toastr: ToastrService,
|
||||
private domSanitizer: DomSanitizer, private bookService: BookService, private memberService: MemberService,
|
||||
private scrollService: ScrollService, private utilityService: UtilityService, private libraryService: LibraryService,
|
||||
@Inject(DOCUMENT) private document: Document, private themeService: ThemeService, private readonly cdRef: ChangeDetectorRef) {
|
||||
constructor(@Inject(DOCUMENT) private document: Document) {
|
||||
this.navService.hideNavBar();
|
||||
this.themeService.clearThemes();
|
||||
this.navService.hideSideNav();
|
||||
|
@ -1620,7 +1633,7 @@ export class BookReaderComponent implements OnInit, AfterViewInit, OnDestroy {
|
|||
// Responsible for handling pagination only
|
||||
handleContainerClick(event: MouseEvent) {
|
||||
|
||||
if (this.drawerOpen || ['action-bar'].some(className => (event.target as Element).classList.contains(className))) {
|
||||
if (this.drawerOpen || ['action-bar', 'offcanvas-backdrop'].some(className => (event.target as Element).classList.contains(className))) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -3,11 +3,12 @@
|
|||
<app-image borderRadius=".25rem .25rem 0 0" height="230px" width="158px" classes="extreme-blur" [imageUrl]="imageUrl"></app-image>
|
||||
|
||||
<div class="card-overlay"></div>
|
||||
<ng-container *ngIf="overlayInformation | safeHtml as info">
|
||||
<div class="overlay-information overlay-information--centered" *ngIf="info !== '' || info !== undefined">
|
||||
<ng-container *ngIf="entity.title | safeHtml as info">
|
||||
<div class="overlay-information overlay-information--centered" *ngIf="info !== ''">
|
||||
<div class="position-relative">
|
||||
<span class="card-title library mx-auto" style="width: auto;">
|
||||
<i class="fa-regular fa-clock mb-2" style="font-size: 26px" aria-hidden="true"></i>
|
||||
<div class="upcoming-header">Upcoming</div>
|
||||
<span [innerHTML]="info"></span>
|
||||
</span>
|
||||
</div>
|
||||
|
|
|
@ -6,6 +6,10 @@
|
|||
background-color: transparent;
|
||||
}
|
||||
|
||||
.upcoming-header {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.card-title {
|
||||
width: 146px;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import {ChangeDetectionStrategy, ChangeDetectorRef, Component, inject, Input} from '@angular/core';
|
||||
import {ChangeDetectionStrategy, ChangeDetectorRef, Component, inject, Input, OnInit} from '@angular/core';
|
||||
import {CommonModule} from '@angular/common';
|
||||
import {ImageComponent} from "../../shared/image/image.component";
|
||||
import {NextExpectedChapter} from "../../_models/series-detail/next-expected-chapter";
|
||||
|
@ -14,7 +14,7 @@ import {translate} from "@ngneat/transloco";
|
|||
styleUrl: './next-expected-card.component.scss',
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
})
|
||||
export class NextExpectedCardComponent {
|
||||
export class NextExpectedCardComponent implements OnInit {
|
||||
private readonly cdRef = inject(ChangeDetectorRef);
|
||||
|
||||
/**
|
||||
|
@ -25,19 +25,9 @@ export class NextExpectedCardComponent {
|
|||
* This is the entity we are representing. It will be returned if an action is executed.
|
||||
*/
|
||||
@Input({required: true}) entity!: NextExpectedChapter;
|
||||
|
||||
/**
|
||||
* Additional information to show on the overlay area. Will always render.
|
||||
*/
|
||||
@Input() overlayInformation: string = '';
|
||||
title: string = '';
|
||||
|
||||
|
||||
|
||||
ngOnInit(): void {
|
||||
const tokens = this.entity.title.split(':');
|
||||
this.overlayInformation = `<div>${tokens[0]}</div><div>${tokens[1]}</div>`;
|
||||
|
||||
if (this.entity.expectedDate) {
|
||||
const utcPipe = new UtcToLocalTimePipe();
|
||||
this.title = translate('next-expected-card.title', {date: utcPipe.transform(this.entity.expectedDate, 'shortDate')});
|
||||
|
|
|
@ -67,7 +67,7 @@ import { FittingIconPipe } from '../../../_pipes/fitting-icon.pipe';
|
|||
import { InfiniteScrollerComponent } from '../infinite-scroller/infinite-scroller.component';
|
||||
import { SwipeDirective } from '../../../ng-swipe/ng-swipe.directive';
|
||||
import { LoadingComponent } from '../../../shared/loading/loading.component';
|
||||
import {translate, TranslocoDirective, TranslocoService} from "@ngneat/transloco";
|
||||
import {translate, TranslocoDirective} from "@ngneat/transloco";
|
||||
|
||||
|
||||
const PREFETCH_PAGES = 10;
|
||||
|
|
|
@ -22,39 +22,41 @@
|
|||
<p>{{t('validate-description')}}</p>
|
||||
<div class="row g-0">
|
||||
|
||||
<ngb-accordion #a="ngbAccordion">
|
||||
<ngb-panel *ngFor="let fileToProcess of filesToProcess">
|
||||
<ng-container *ngIf="fileToProcess.validateSummary as summary">
|
||||
<ng-template ngbPanelTitle>
|
||||
<ng-container [ngTemplateOutlet]="heading" [ngTemplateOutletContext]="{ summary: summary, filename: fileToProcess.fileName }"></ng-container>
|
||||
</ng-template>
|
||||
|
||||
<ng-template ngbPanelContent>
|
||||
<ng-container *ngIf="summary.results.length > 0; else noValidateIssues">
|
||||
<h5>{{t('validate-warning')}}</h5>
|
||||
<ol class="list-group list-group-numbered list-group-flush" >
|
||||
<li class="list-group-item no-hover" *ngFor="let result of summary.results"
|
||||
[innerHTML]="result | cblConflictReason | safeHtml">
|
||||
</li>
|
||||
</ol>
|
||||
</ng-container>
|
||||
<ng-template #noValidateIssues>
|
||||
<div class="justify-content-center col">
|
||||
<div class="d-flex align-items-center">
|
||||
<div class="flex-shrink-0">
|
||||
<i class="fa-solid fa-circle-check" style="font-size: 24px" aria-hidden="true"></i>
|
||||
</div>
|
||||
<div class="flex-grow-1 ms-3">
|
||||
{{t('validate-no-issue')}}
|
||||
<div ngbAccordion #accordion="ngbAccordion">
|
||||
@for(fileToProcess of filesToProcess; track fileToProcess.fileName) {
|
||||
<div ngbAccordionItem *ngIf="fileToProcess.validateSummary as summary">
|
||||
<h5 ngbAccordionHeader>
|
||||
<button ngbAccordionButton>
|
||||
<ng-container [ngTemplateOutlet]="heading" [ngTemplateOutletContext]="{ summary: summary, filename: fileToProcess.fileName }"></ng-container>
|
||||
</button>
|
||||
</h5>
|
||||
<div ngbAccordionCollapse>
|
||||
<div ngbAccordionBody>
|
||||
@if(summary.results.length > 0) {
|
||||
<h5>{{t('validate-warning')}}</h5>
|
||||
<ol class="list-group list-group-numbered list-group-flush" >
|
||||
<li class="list-group-item no-hover" *ngFor="let result of summary.results"
|
||||
[innerHTML]="result | cblConflictReason | safeHtml">
|
||||
</li>
|
||||
</ol>
|
||||
} @else {
|
||||
<div class="justify-content-center col">
|
||||
<div class="d-flex align-items-center">
|
||||
<div class="flex-shrink-0">
|
||||
<i class="fa-solid fa-circle-check" style="font-size: 24px" aria-hidden="true"></i>
|
||||
</div>
|
||||
<div class="flex-grow-1 ms-3">
|
||||
{{t('validate-no-issue')}}
|
||||
</div>
|
||||
</div>
|
||||
{{t('validate-no-issue-description')}}
|
||||
</div>
|
||||
{{t('validate-no-issue-description')}}
|
||||
</div>
|
||||
</ng-template>
|
||||
</ng-template>
|
||||
</ng-container>
|
||||
</ngb-panel>
|
||||
</ngb-accordion>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</ng-container>
|
||||
|
||||
|
@ -62,57 +64,65 @@
|
|||
<div class="row g-0">
|
||||
<p>{{t('dry-run-description')}}</p>
|
||||
|
||||
<ngb-accordion #a="ngbAccordion">
|
||||
<ngb-panel *ngFor="let fileToProcess of filesToProcess">
|
||||
<ng-container *ngIf="fileToProcess.dryRunSummary as summary">
|
||||
<ng-template ngbPanelTitle>
|
||||
<ng-container [ngTemplateOutlet]="heading" [ngTemplateOutletContext]="{ summary: summary, filename: fileToProcess.fileName }"></ng-container>
|
||||
</ng-template>
|
||||
|
||||
<ng-template ngbPanelContent>
|
||||
<ng-container [ngTemplateOutlet]="resultsList" [ngTemplateOutletContext]="{ summary: summary }"></ng-container>
|
||||
</ng-template>
|
||||
</ng-container>
|
||||
</ngb-panel>
|
||||
</ngb-accordion>
|
||||
<div ngbAccordion #a="ngbAccordion">
|
||||
@for(fileToProcess of filesToProcess; track fileToProcess.fileName) {
|
||||
<div ngbAccordionItem *ngIf="fileToProcess.dryRunSummary as summary">
|
||||
<h5 ngbAccordionHeader>
|
||||
<button ngbAccordionButton>
|
||||
<ng-container [ngTemplateOutlet]="heading" [ngTemplateOutletContext]="{ summary: summary, filename: fileToProcess.fileName }"></ng-container>
|
||||
</button>
|
||||
</h5>
|
||||
<div ngbAccordionCollapse>
|
||||
<div ngbAccordionBody>
|
||||
<ng-container [ngTemplateOutlet]="resultsList" [ngTemplateOutletContext]="{ summary: summary }"></ng-container>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</ng-container>
|
||||
|
||||
<ng-container *ngIf="currentStepIndex === Step.Finalize">
|
||||
<div class="row g-0">
|
||||
<ngb-accordion #a="ngbAccordion">
|
||||
<ngb-panel *ngFor="let fileToProcess of filesToProcess">
|
||||
<ng-container *ngIf="fileToProcess.finalizeSummary as summary">
|
||||
<ng-template ngbPanelTitle>
|
||||
<ng-container [ngTemplateOutlet]="heading" [ngTemplateOutletContext]="{ summary: summary, filename: fileToProcess.fileName }"></ng-container>
|
||||
</ng-template>
|
||||
|
||||
<ng-template ngbPanelContent>
|
||||
<ng-container [ngTemplateOutlet]="resultsList" [ngTemplateOutletContext]="{ summary: summary }"></ng-container>
|
||||
</ng-template>
|
||||
</ng-container>
|
||||
</ngb-panel>
|
||||
</ngb-accordion>
|
||||
<div ngbAccordion #a="ngbAccordion">
|
||||
@for(fileToProcess of filesToProcess; track fileToProcess.fileName) {
|
||||
<div ngbAccordionItem *ngIf="fileToProcess.finalizeSummary as summary">
|
||||
<h5 ngbAccordionHeader>
|
||||
<button ngbAccordionButton>
|
||||
<ng-container [ngTemplateOutlet]="heading" [ngTemplateOutletContext]="{ summary: summary, filename: fileToProcess.fileName }"></ng-container>
|
||||
</button>
|
||||
</h5>
|
||||
<div ngbAccordionCollapse>
|
||||
<div ngbAccordionBody>
|
||||
<ng-container [ngTemplateOutlet]="resultsList" [ngTemplateOutletContext]="{ summary: summary }"></ng-container>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</ng-container>
|
||||
</div>
|
||||
|
||||
<ng-template #resultsList let-summary="summary">
|
||||
<ul class="list-group list-group-flush">
|
||||
<li class="list-group-item no-hover" *ngFor="let result of summary.results"
|
||||
innerHTML="{{result.order + 1}}. {{result | cblConflictReason | safeHtml}}"></li>
|
||||
@for(result of summary.results; track result.order) {
|
||||
<li class="list-group-item no-hover"
|
||||
innerHTML="{{result.order + 1}}. {{result | cblConflictReason | safeHtml}}"></li>
|
||||
}
|
||||
</ul>
|
||||
</ng-template>
|
||||
|
||||
<ng-template #heading let-filename="filename" let-summary="summary">
|
||||
<ng-container *ngIf="summary.success | cblImportResult as success">
|
||||
<ng-container [ngSwitch]="summary.success">
|
||||
<span *ngSwitchCase="CblImportResult.Success" class="badge bg-primary me-1">{{success}}</span>
|
||||
<span *ngSwitchCase="CblImportResult.Fail" class="badge bg-danger me-1">{{success}}</span>
|
||||
<span *ngSwitchCase="CblImportResult.Partial" class="badge bg-warning me-1">{{success}}</span>
|
||||
<ng-container *ngIf="summary.success | cblImportResult as success">
|
||||
<ng-container [ngSwitch]="summary.success">
|
||||
<span *ngSwitchCase="CblImportResult.Success" class="badge bg-primary me-1">{{success}}</span>
|
||||
<span *ngSwitchCase="CblImportResult.Fail" class="badge bg-danger me-1">{{success}}</span>
|
||||
<span *ngSwitchCase="CblImportResult.Partial" class="badge bg-warning me-1">{{success}}</span>
|
||||
</ng-container>
|
||||
</ng-container>
|
||||
</ng-container>
|
||||
<span>{{filename}}<span *ngIf="summary.cblName">: ({{summary.cblName}})</span></span>
|
||||
<span>{{filename}}<span *ngIf="summary.cblName">: ({{summary.cblName}})</span></span>
|
||||
</ng-template>
|
||||
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ import {CommonModule} from "@angular/common";
|
|||
import {SafeHtmlPipe} from "../../../_pipes/safe-html.pipe";
|
||||
import {CblConflictReasonPipe} from "../../../_pipes/cbl-conflict-reason.pipe";
|
||||
import {CblImportResultPipe} from "../../../_pipes/cbl-import-result.pipe";
|
||||
import {TranslocoDirective, TranslocoService} from "@ngneat/transloco";
|
||||
import {translate, TranslocoDirective, TranslocoService} from "@ngneat/transloco";
|
||||
|
||||
interface FileStep {
|
||||
fileName: string;
|
||||
|
@ -48,8 +48,6 @@ export class ImportCblModalComponent {
|
|||
|
||||
@ViewChild('fileUpload') fileUpload!: ElementRef<HTMLInputElement>;
|
||||
|
||||
translocoService = inject(TranslocoService);
|
||||
|
||||
fileUploadControl = new FormControl<undefined | Array<File>>(undefined, [
|
||||
FileUploadValidators.accept(['.cbl']),
|
||||
]);
|
||||
|
@ -61,10 +59,10 @@ export class ImportCblModalComponent {
|
|||
isLoading: boolean = false;
|
||||
|
||||
steps: Array<TimelineStep> = [
|
||||
{title: this.translocoService.translate('import-cbl-modal.import-step'), index: Step.Import, active: true, icon: 'fa-solid fa-file-arrow-up'},
|
||||
{title: this.translocoService.translate('import-cbl-modal.validate-cbl-step'), index: Step.Validate, active: false, icon: 'fa-solid fa-spell-check'},
|
||||
{title: this.translocoService.translate('import-cbl-modal.dry-run-step'), index: Step.DryRun, active: false, icon: 'fa-solid fa-gears'},
|
||||
{title: this.translocoService.translate('import-cbl-modal.final-import-step'), index: Step.Finalize, active: false, icon: 'fa-solid fa-floppy-disk'},
|
||||
{title: translate('import-cbl-modal.import-step'), index: Step.Import, active: true, icon: 'fa-solid fa-file-arrow-up'},
|
||||
{title: translate('import-cbl-modal.validate-cbl-step'), index: Step.Validate, active: false, icon: 'fa-solid fa-spell-check'},
|
||||
{title: translate('import-cbl-modal.dry-run-step'), index: Step.DryRun, active: false, icon: 'fa-solid fa-gears'},
|
||||
{title: translate('import-cbl-modal.final-import-step'), index: Step.Finalize, active: false, icon: 'fa-solid fa-floppy-disk'},
|
||||
];
|
||||
currentStepIndex = this.steps[0].index;
|
||||
|
||||
|
@ -103,7 +101,7 @@ export class ImportCblModalComponent {
|
|||
case Step.Import:
|
||||
const files = this.uploadForm.get('files')?.value;
|
||||
if (!files) {
|
||||
this.toastr.error(this.translocoService.translate('toasts.select-files-warning'));
|
||||
this.toastr.error(translate('toasts.select-files-warning'));
|
||||
return;
|
||||
}
|
||||
// Load each file into filesToProcess and group their data
|
||||
|
@ -236,7 +234,7 @@ export class ImportCblModalComponent {
|
|||
|
||||
this.isLoading = false;
|
||||
this.currentStepIndex++;
|
||||
this.toastr.success(this.translocoService.translate('toasts.reading-list-imported'));
|
||||
this.toastr.success(translate('toasts.reading-list-imported'));
|
||||
this.cdRef.markForCheck();
|
||||
});
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<div class="col-lg-10 col-md-12 pe-2">
|
||||
<div class="mb-3">
|
||||
<label for="item--{{i}}" class="visually-hidden">{{label}}</label>
|
||||
<input type="text" class="form-control" formControlName="link{{i}}" attr.id="item--{{i}}">
|
||||
<input type="text" class="form-control" formControlName="link{{i}}" id="item--{{i}}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-2">
|
||||
|
|
|
@ -27,7 +27,8 @@ enum TabID {
|
|||
selector: 'app-customize-dashboard-modal',
|
||||
standalone: true,
|
||||
imports: [CommonModule, SafeHtmlPipe, TranslocoDirective, DraggableOrderedListComponent, ReadingListItemComponent, DashboardStreamListItemComponent,
|
||||
NgbNav, NgbNavContent, NgbNavLink, NgbNavItem, NgbNavOutlet, CustomizeDashboardStreamsComponent, CustomizeSidenavStreamsComponent, ManageExternalSourcesComponent, ManageSmartFiltersComponent],
|
||||
NgbNav, NgbNavContent, NgbNavLink, NgbNavItem, NgbNavOutlet, CustomizeDashboardStreamsComponent, CustomizeSidenavStreamsComponent,
|
||||
ManageExternalSourcesComponent, ManageSmartFiltersComponent],
|
||||
templateUrl: './customize-dashboard-modal.component.html',
|
||||
styleUrls: ['./customize-dashboard-modal.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
|
|
|
@ -13,6 +13,7 @@ import {forkJoin} from "rxjs";
|
|||
import {TranslocoDirective} from "@ngneat/transloco";
|
||||
import {FormControl, FormGroup, ReactiveFormsModule} from "@angular/forms";
|
||||
import {FilterPipe} from "../../../_pipes/filter.pipe";
|
||||
import {Breakpoint, UtilityService} from "../../../shared/_services/utility.service";
|
||||
|
||||
@Component({
|
||||
selector: 'app-customize-dashboard-streams',
|
||||
|
@ -31,6 +32,7 @@ export class CustomizeDashboardStreamsComponent {
|
|||
private readonly dashboardService = inject(DashboardService);
|
||||
private readonly filterService = inject(FilterService);
|
||||
private readonly cdRef = inject(ChangeDetectorRef);
|
||||
private readonly utilityService = inject(UtilityService);
|
||||
|
||||
listForm: FormGroup = new FormGroup({
|
||||
'filterQuery': new FormControl('', [])
|
||||
|
@ -50,7 +52,7 @@ export class CustomizeDashboardStreamsComponent {
|
|||
this.items = results[0];
|
||||
|
||||
// After 100 items, drag and drop is disabled to use virtualization
|
||||
if (this.items.length > 100) {
|
||||
if (this.items.length > 100 || this.utilityService.getActiveBreakpoint() <= Breakpoint.Tablet) {
|
||||
this.accessibilityMode = true;
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ import {
|
|||
ChangeDetectionStrategy,
|
||||
ChangeDetectorRef,
|
||||
Component,
|
||||
DestroyRef, EventEmitter,
|
||||
DestroyRef,
|
||||
HostListener,
|
||||
inject,
|
||||
OnDestroy
|
||||
|
@ -29,9 +29,9 @@ import {FilterPipe} from "../../../_pipes/filter.pipe";
|
|||
import {BulkOperationsComponent} from "../../../cards/bulk-operations/bulk-operations.component";
|
||||
import {Action, ActionItem} from "../../../_services/action-factory.service";
|
||||
import {BulkSelectionService} from "../../../cards/bulk-selection.service";
|
||||
import {filter, tap} from "rxjs/operators";
|
||||
import {tap} from "rxjs/operators";
|
||||
import {takeUntilDestroyed} from "@angular/core/rxjs-interop";
|
||||
import {KEY_CODES} from "../../../shared/_services/utility.service";
|
||||
import {Breakpoint, KEY_CODES, UtilityService} from "../../../shared/_services/utility.service";
|
||||
|
||||
@Component({
|
||||
selector: 'app-customize-sidenav-streams',
|
||||
|
@ -43,7 +43,6 @@ import {KEY_CODES} from "../../../shared/_services/utility.service";
|
|||
})
|
||||
export class CustomizeSidenavStreamsComponent implements OnDestroy {
|
||||
|
||||
//@Input({required: true}) parentScrollElem!: Element | Window;
|
||||
items: SideNavStream[] = [];
|
||||
smartFilters: SmartFilter[] = [];
|
||||
externalSources: ExternalSource[] = [];
|
||||
|
@ -108,6 +107,7 @@ export class CustomizeSidenavStreamsComponent implements OnDestroy {
|
|||
private readonly cdRef = inject(ChangeDetectorRef);
|
||||
private readonly destroyRef = inject(DestroyRef);
|
||||
public readonly bulkSelectionService = inject(BulkSelectionService);
|
||||
public readonly utilityService = inject(UtilityService);
|
||||
|
||||
@HostListener('document:keydown.shift', ['$event'])
|
||||
handleKeypress(event: KeyboardEvent) {
|
||||
|
@ -172,7 +172,7 @@ export class CustomizeSidenavStreamsComponent implements OnDestroy {
|
|||
this.items = results[0];
|
||||
|
||||
// After X items, drag and drop is disabled to use virtualization
|
||||
if (this.items.length > this.virtualizeAfter) {
|
||||
if (this.items.length > this.virtualizeAfter || this.utilityService.getActiveBreakpoint() <= Breakpoint.Tablet) {
|
||||
this.pageOperationsForm.get('accessibilityMode')?.setValue(true);
|
||||
}
|
||||
|
||||
|
|
|
@ -66,10 +66,10 @@
|
|||
</button>
|
||||
</div>
|
||||
<div class="row mt-2">
|
||||
<p>{{t('help-us-part-1')}}<a href="https://wiki.kavitareader.com/en/guides/managing-your-files" rel="noopener noreferrer" target="_blank" referrerpolicy="no-refer">{{t('help-us-part-2')}}</a> {{t('help-us-part-3')}}</p>
|
||||
<p>{{t('help-us-part-1')}}<a href="https://wiki.kavitareader.com/en/guides/managing-your-files" rel="noopener noreferrer" target="_blank" referrerpolicy="no-referrer">{{t('help-us-part-2')}}</a> {{t('help-us-part-3')}}</p>
|
||||
</div>
|
||||
<div class="row mt-2">
|
||||
<p>{{t('naming-conventions-part-1')}}<a href="https://wiki.kavitareader.com/en/guides/managing-your-files/scanner#introduction" rel="noopener noreferrer" target="_blank" referrerpolicy="no-refer">{{t('naming-conventions-part-2')}}</a> {{t('naming-conventions-part-3')}}</p>
|
||||
<p>{{t('naming-conventions-part-1')}}<a href="https://wiki.kavitareader.com/en/guides/managing-your-files/scanner#introduction" rel="noopener noreferrer" target="_blank" referrerpolicy="no-referrer">{{t('naming-conventions-part-2')}}</a> {{t('naming-conventions-part-3')}}</p>
|
||||
</div>
|
||||
</ng-template>
|
||||
</li>
|
||||
|
|
|
@ -11,7 +11,6 @@ import {takeUntilDestroyed} from "@angular/core/rxjs-interop";
|
|||
import { LineChartModule } from '@swimlane/ngx-charts';
|
||||
import { NgIf, NgFor, AsyncPipe } from '@angular/common';
|
||||
import {TranslocoDirective, TranslocoService} from "@ngneat/transloco";
|
||||
import {UtcToLocalTimePipe} from "../../../_pipes/utc-to-local-time.pipe";
|
||||
|
||||
const options: Intl.DateTimeFormatOptions = { month: "short", day: "numeric" };
|
||||
|
||||
|
@ -32,10 +31,10 @@ export class ReadingActivityComponent implements OnInit {
|
|||
@Input() isAdmin: boolean = true;
|
||||
@Input() individualUserMode: boolean = false;
|
||||
|
||||
private readonly utcDatePipe = new UtcToLocalTimePipe();
|
||||
private readonly destroyRef = inject(DestroyRef);
|
||||
private readonly translocoService = inject(TranslocoService);
|
||||
private readonly cdRef = inject(ChangeDetectorRef);
|
||||
//private readonly translocoService = inject(TranslocoService);
|
||||
private readonly statService = inject(StatisticsService);
|
||||
private readonly memberService = inject(MemberService);
|
||||
|
||||
view: [number, number] = [0, 400];
|
||||
formGroup: FormGroup = new FormGroup({
|
||||
|
@ -45,14 +44,14 @@ export class ReadingActivityComponent implements OnInit {
|
|||
users$: Observable<Member[]> | undefined;
|
||||
data$: Observable<Array<PieDataItem>>;
|
||||
timePeriods = TimePeriods;
|
||||
mangaFormatPipe = new MangaFormatPipe(this.translocoService);
|
||||
//mangaFormatPipe = new MangaFormatPipe(this.translocoService);
|
||||
|
||||
constructor(private statService: StatisticsService, private memberService: MemberService) {
|
||||
constructor() {
|
||||
this.data$ = this.formGroup.valueChanges.pipe(
|
||||
switchMap(_ => this.statService.getReadCountByDay(this.formGroup.get('users')!.value, this.formGroup.get('days')!.value)),
|
||||
map(data => {
|
||||
const gList = data.reduce((formats, entry) => {
|
||||
const formatTranslated = this.mangaFormatPipe.transform(entry.format);
|
||||
const formatTranslated = this.statService.mangaFormatPipe.transform(entry.format);
|
||||
if (!formats[formatTranslated]) {
|
||||
formats[formatTranslated] = {
|
||||
name: formatTranslated,
|
||||
|
@ -76,7 +75,10 @@ export class ReadingActivityComponent implements OnInit {
|
|||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.users$ = (this.isAdmin ? this.memberService.getMembers() : of([])).pipe(filter(_ => this.isAdmin), takeUntilDestroyed(this.destroyRef), shareReplay());
|
||||
this.users$ = (this.isAdmin ? this.memberService.getMembers() : of([])).pipe(
|
||||
filter(_ => this.isAdmin),
|
||||
takeUntilDestroyed(this.destroyRef),
|
||||
shareReplay());
|
||||
this.formGroup.get('users')?.setValue(this.userId, {emitValue: true});
|
||||
|
||||
if (!this.isAdmin) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue