Kavita/UI/Web/src/app/cards/series-card/series-card.component.ts
Joseph Milazzo 9d7476a367
Send To Device Support (#1557)
* Tweaked the logging output

* Started implementing some basic idea for devices

* Updated Email Service with new API routes

* Implemented basic DB structure and some APIs to prep for the UI and flows.

* Added an abstract class to make Unit testing easier.

* Removed dependency we don't need

* Updated the UI to be able to show devices and add new devices. Email field will update the platform if the user hasn't interacted with it already.

* Added ability to delete a device as well

* Basic ability to send files to devices works

* Refactored Action code to pass ActionItem back and allow for dynamic children based on an Observable (api).

Hooked in ability to send a chapter to a device. There is no logic in the FE to validate type.

* Fixed a broken unit test

* Implemented the ability to edit a device

* Code cleanup

* Fixed a bad success message

* Fixed broken unit test from updating mock layer
2022-09-23 15:41:29 -07:00

179 lines
5.7 KiB
TypeScript

import { ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, Input, OnChanges, OnDestroy, OnInit, Output } from '@angular/core';
import { NavigationStart, Router } from '@angular/router';
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
import { ToastrService } from 'ngx-toastr';
import { filter, take } from 'rxjs/operators';
import { Series } from 'src/app/_models/series';
import { AccountService } from 'src/app/_services/account.service';
import { ImageService } from 'src/app/_services/image.service';
import { ActionFactoryService, Action, ActionItem } from 'src/app/_services/action-factory.service';
import { SeriesService } from 'src/app/_services/series.service';
import { ActionService } from 'src/app/_services/action.service';
import { EditSeriesModalComponent } from '../_modals/edit-series-modal/edit-series-modal.component';
import { Subject } from 'rxjs';
import { RelationKind } from 'src/app/_models/series-detail/relation-kind';
@Component({
selector: 'app-series-card',
templateUrl: './series-card.component.html',
styleUrls: ['./series-card.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class SeriesCardComponent implements OnInit, OnChanges, OnDestroy {
@Input() data!: Series;
@Input() libraryId = 0;
@Input() suppressLibraryLink = false;
/**
* If the entity is selected or not.
*/
@Input() selected: boolean = false;
/**
* If the entity should show selection code
*/
@Input() allowSelection: boolean = false;
/**
* If the Series has a relationship to display
*/
@Input() relation: RelationKind | undefined = undefined;
@Output() clicked = new EventEmitter<Series>();
@Output() reload = new EventEmitter<boolean>();
@Output() dataChanged = new EventEmitter<Series>();
/**
* When the card is selected.
*/
@Output() selection = new EventEmitter<boolean>();
actions: ActionItem<Series>[] = [];
imageUrl: string = '';
onDestroy: Subject<void> = new Subject<void>();
constructor(private router: Router, private cdRef: ChangeDetectorRef,
private seriesService: SeriesService, private toastr: ToastrService,
private modalService: NgbModal, private imageService: ImageService,
private actionFactoryService: ActionFactoryService,
private actionService: ActionService) {}
ngOnInit(): void {
if (this.data) {
this.imageUrl = this.imageService.getSeriesCoverImage(this.data.id);
this.cdRef.markForCheck();
}
}
ngOnChanges(changes: any) {
if (this.data) {
this.actions = this.actionFactoryService.getSeriesActions((action: ActionItem<Series>, series: Series) => this.handleSeriesActionCallback(action, series));
this.cdRef.markForCheck();
}
}
ngOnDestroy() {
this.onDestroy.next();
this.onDestroy.complete();
}
handleSeriesActionCallback(action: ActionItem<Series>, series: Series) {
switch (action.action) {
case(Action.MarkAsRead):
this.markAsRead(series);
break;
case(Action.MarkAsUnread):
this.markAsUnread(series);
break;
case(Action.Scan):
this.scanLibrary(series);
break;
case(Action.RefreshMetadata):
this.refreshMetdata(series);
break;
case(Action.Delete):
this.deleteSeries(series);
break;
case(Action.Edit):
this.openEditModal(series);
break;
case(Action.AddToReadingList):
this.actionService.addSeriesToReadingList(series);
break;
case Action.AddToWantToReadList:
this.actionService.addMultipleSeriesToWantToReadList([series.id]);
break;
case Action.RemoveFromWantToReadList:
this.actionService.removeMultipleSeriesFromWantToReadList([series.id]);
if (this.router.url.startsWith('/want-to-read')) {
this.reload.emit(true);
}
break;
case(Action.AddToCollection):
this.actionService.addMultipleSeriesToCollectionTag([series]);
break;
case (Action.AnalyzeFiles):
this.actionService.analyzeFilesForSeries(series);
break;
default:
break;
}
}
openEditModal(data: Series) {
const modalRef = this.modalService.open(EditSeriesModalComponent, { size: 'lg' });
modalRef.componentInstance.series = data;
modalRef.closed.subscribe((closeResult: {success: boolean, series: Series, coverImageUpdate: boolean}) => {
if (closeResult.success) {
this.seriesService.getSeries(data.id).subscribe(series => {
this.data = series;
this.cdRef.markForCheck();
this.reload.emit(true);
this.dataChanged.emit(series);
});
}
});
}
async refreshMetdata(series: Series) {
this.actionService.refreshMetdata(series);
}
async scanLibrary(series: Series) {
this.seriesService.scan(series.libraryId, series.id).subscribe((res: any) => {
this.toastr.success('Scan queued for ' + series.name);
});
}
async deleteSeries(series: Series) {
this.actionService.deleteSeries(series, (result: boolean) => {
if (result) {
this.reload.emit(true);
}
});
}
markAsUnread(series: Series) {
this.actionService.markSeriesAsUnread(series, () => {
if (this.data) {
this.data.pagesRead = 0;
this.cdRef.markForCheck();
}
this.dataChanged.emit(series);
});
}
markAsRead(series: Series) {
this.actionService.markSeriesAsRead(series, () => {
if (this.data) {
this.data.pagesRead = series.pages;
this.cdRef.markForCheck();
}
this.dataChanged.emit(series);
});
}
handleClick() {
this.clicked.emit(this.data);
this.router.navigate(['library', this.libraryId, 'series', this.data?.id]);
}
}