Bulk Operations (#596)
* Implemented the ability to perform multi-selections on cards. Basic selection code is done, CSS needed and exposing actions. * Implemented a bulk selection bar. Added logic to the card on when to force show checkboxes. * Fixed some bad parsing groups and cases for Comic Chapters. * Hooked up some bulk actions on series detail page. Not hooked up to backend yet. * Fixes #593. URI Enocde library names as sometimes they can have & in them. * Implemented the ability to mark volume/chapters as read/unread. * Hooked up mark as unread with specials as well. * Add to reading list hooked up for Series Detail * Implemented ability to add multiple series to a reading list. * Implemented bulk selection for series cards * Added comments to the new code in ReaderService.cs * Implemented proper styling on bulk operation bar and integrated for collections. * Fixed an issue with shift clicking * Cleaned up css of bulk operations bar * Code cleanup
This commit is contained in:
parent
52c4285168
commit
f5229fd0e6
38 changed files with 1129 additions and 172 deletions
|
|
@ -1,17 +1,18 @@
|
|||
import { Component, OnDestroy, OnInit } from '@angular/core';
|
||||
import { Component, HostListener, OnDestroy, 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 { Subject } from 'rxjs';
|
||||
import { finalize, take, takeUntil, takeWhile } from 'rxjs/operators';
|
||||
import { BulkSelectionService } from '../cards/bulk-selection.service';
|
||||
import { CardDetailsModalComponent } from '../cards/_modals/card-details-modal/card-details-modal.component';
|
||||
import { EditSeriesModalComponent } from '../cards/_modals/edit-series-modal/edit-series-modal.component';
|
||||
import { ConfirmConfig } from '../shared/confirm-dialog/_models/confirm-config';
|
||||
import { ConfirmService } from '../shared/confirm.service';
|
||||
import { TagBadgeCursor } from '../shared/tag-badge/tag-badge.component';
|
||||
import { DownloadService } from '../shared/_services/download.service';
|
||||
import { UtilityService } from '../shared/_services/utility.service';
|
||||
import { KEY_CODES, UtilityService } from '../shared/_services/utility.service';
|
||||
import { ReviewSeriesModalComponent } from '../_modals/review-series-modal/review-series-modal.component';
|
||||
import { Chapter } from '../_models/chapter';
|
||||
import { ScanSeriesEvent } from '../_models/events/scan-series-event';
|
||||
|
|
@ -53,6 +54,7 @@ export class SeriesDetailComponent implements OnInit, OnDestroy {
|
|||
seriesActions: ActionItem<Series>[] = [];
|
||||
volumeActions: ActionItem<Volume>[] = [];
|
||||
chapterActions: ActionItem<Chapter>[] = [];
|
||||
bulkActions: ActionItem<any>[] = [];
|
||||
|
||||
hasSpecials = false;
|
||||
specials: Array<Chapter> = [];
|
||||
|
|
@ -88,6 +90,48 @@ export class SeriesDetailComponent implements OnInit, OnDestroy {
|
|||
*/
|
||||
trackByChapterIdentity = (index: number, item: Chapter) => `${item.title}_${item.number}_${item.pagesRead}`;
|
||||
|
||||
bulkActionCallback = (action: Action, data: any) => {
|
||||
console.log('handling bulk action callback');
|
||||
if (this.series === undefined) {
|
||||
return;
|
||||
}
|
||||
const seriesId = this.series.id;
|
||||
// we need to figure out what is actually selected now
|
||||
const selectedVolumeIndexes = this.bulkSelectionService.getSelectedCardsForSource('volume');
|
||||
const selectedChapterIndexes = this.bulkSelectionService.getSelectedCardsForSource('chapter');
|
||||
const selectedSpecialIndexes = this.bulkSelectionService.getSelectedCardsForSource('special');
|
||||
|
||||
const selectedChapterIds = this.chapters.filter((chapter, index: number) => selectedChapterIndexes.includes(index + ''));
|
||||
const selectedVolumeIds = this.volumes.filter((volume, index: number) => selectedVolumeIndexes.includes(index + ''));
|
||||
const selectedSpecials = this.specials.filter((chapter, index: number) => selectedSpecialIndexes.includes(index + ''));
|
||||
const chapters = [...selectedChapterIds, ...selectedSpecials];
|
||||
|
||||
switch (action) {
|
||||
case Action.AddToReadingList:
|
||||
this.actionService.addMultipleToReadingList(seriesId, selectedVolumeIds, chapters, () => this.actionInProgress = false);
|
||||
break;
|
||||
case Action.MarkAsRead:
|
||||
console.log('marking volumes as read: ', selectedVolumeIds)
|
||||
console.log('marking chapters as read: ', chapters)
|
||||
|
||||
this.actionService.markMultipleAsRead(seriesId, selectedVolumeIds, chapters, () => {
|
||||
this.setContinuePoint();
|
||||
this.actionInProgress = false;
|
||||
});
|
||||
|
||||
break;
|
||||
case Action.MarkAsUnread:
|
||||
console.log('marking volumes as unread: ', selectedVolumeIds)
|
||||
console.log('marking chapters as unread: ', chapters)
|
||||
|
||||
this.actionService.markMultipleAsUnread(seriesId, selectedVolumeIds, chapters, () => {
|
||||
this.setContinuePoint();
|
||||
this.actionInProgress = false;
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private onDestroy: Subject<void> = new Subject();
|
||||
|
||||
|
||||
|
|
@ -111,7 +155,8 @@ export class SeriesDetailComponent implements OnInit, OnDestroy {
|
|||
private actionFactoryService: ActionFactoryService, private libraryService: LibraryService,
|
||||
private confirmService: ConfirmService, private titleService: Title,
|
||||
private downloadService: DownloadService, private actionService: ActionService,
|
||||
public imageSerivce: ImageService, private messageHub: MessageHubService) {
|
||||
public imageSerivce: ImageService, private messageHub: MessageHubService,
|
||||
public bulkSelectionService: BulkSelectionService) {
|
||||
ratingConfig.max = 5;
|
||||
this.router.routeReuseStrategy.shouldReuseRoute = () => false;
|
||||
this.accountService.currentUser$.pipe(take(1)).subscribe(user => {
|
||||
|
|
@ -151,6 +196,20 @@ export class SeriesDetailComponent implements OnInit, OnDestroy {
|
|||
this.onDestroy.complete();
|
||||
}
|
||||
|
||||
@HostListener('document:keydown.shift', ['$event'])
|
||||
handleKeypress(event: KeyboardEvent) {
|
||||
if (event.key === KEY_CODES.SHIFT) {
|
||||
this.bulkSelectionService.isShiftDown = true;
|
||||
}
|
||||
}
|
||||
|
||||
@HostListener('document:keyup.shift', ['$event'])
|
||||
handleKeyUp(event: KeyboardEvent) {
|
||||
if (event.key === KEY_CODES.SHIFT) {
|
||||
this.bulkSelectionService.isShiftDown = false;
|
||||
}
|
||||
}
|
||||
|
||||
handleSeriesActionCallback(action: Action, series: Series) {
|
||||
this.actionInProgress = true;
|
||||
switch(action) {
|
||||
|
|
@ -281,6 +340,7 @@ export class SeriesDetailComponent implements OnInit, OnDestroy {
|
|||
this.volumeActions = this.actionFactoryService.getVolumeActions(this.handleVolumeActionCallback.bind(this));
|
||||
this.chapterActions = this.actionFactoryService.getChapterActions(this.handleChapterActionCallback.bind(this));
|
||||
|
||||
|
||||
|
||||
this.seriesService.getVolumes(this.series.id).subscribe(volumes => {
|
||||
this.chapters = volumes.filter(v => v.number === 0).map(v => v.chapters || []).flat().sort(this.utilityService.sortChapters);
|
||||
|
|
@ -490,7 +550,6 @@ export class SeriesDetailComponent implements OnInit, OnDestroy {
|
|||
}
|
||||
|
||||
downloadSeries() {
|
||||
|
||||
this.downloadService.downloadSeriesSize(this.series.id).pipe(take(1)).subscribe(async (size) => {
|
||||
const wantToDownload = await this.downloadService.confirmSize(size, 'series');
|
||||
if (!wantToDownload) { return; }
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue