Bulk Actions for Reading Lists (#3035)
This commit is contained in:
parent
1918c9305e
commit
6434ed7c9b
13 changed files with 965 additions and 16 deletions
|
|
@ -4,8 +4,12 @@
|
|||
<app-card-actionables [actions]="globalActions" (actionHandler)="performGlobalAction($event)"></app-card-actionables>
|
||||
<span>{{t('title')}}</span>
|
||||
</h2>
|
||||
<h6 subtitle class="subtitle-with-actionables" *ngIf="pagination">{{t('item-count', {num: pagination.totalItems | number})}}</h6>
|
||||
@if (pagination) {
|
||||
<h6 subtitle class="subtitle-with-actionables">{{t('item-count', {num: pagination.totalItems | number})}}</h6>
|
||||
}
|
||||
|
||||
</app-side-nav-companion-bar>
|
||||
<app-bulk-operations [actionCallback]="bulkActionCallback"></app-bulk-operations>
|
||||
|
||||
<app-card-detail-layout
|
||||
[isLoading]="loadingLists"
|
||||
|
|
@ -18,7 +22,9 @@
|
|||
<ng-template #cardItem let-item let-position="idx" >
|
||||
<app-card-item [title]="item.title" [entity]="item" [actions]="actions[item.id]"
|
||||
[suppressLibraryLink]="true" [imageUrl]="imageService.getReadingListCoverImage(item.id)"
|
||||
(clicked)="handleClick(item)"></app-card-item>
|
||||
(clicked)="handleClick(item)"
|
||||
(selection)="bulkSelectionService.handleCardSelection('readingList', position, lists.length, $event)"
|
||||
[selected]="bulkSelectionService.isCardSelected('readingList', position)" [allowSelection]="true"></app-card-item>
|
||||
</ng-template>
|
||||
|
||||
<ng-template #noData>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import {ChangeDetectionStrategy, ChangeDetectorRef, Component, inject, OnInit} from '@angular/core';
|
||||
import {ChangeDetectionStrategy, ChangeDetectorRef, Component, HostListener, inject, OnInit} from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
|
||||
import { ToastrService } from 'ngx-toastr';
|
||||
|
|
@ -21,6 +21,12 @@ import {translate, TranslocoDirective, TranslocoService} from "@ngneat/transloco
|
|||
import {CardActionablesComponent} from "../../../_single-module/card-actionables/card-actionables.component";
|
||||
import {Title} from "@angular/platform-browser";
|
||||
import {WikiLink} from "../../../_models/wiki";
|
||||
import {BulkSelectionService} from "../../../cards/bulk-selection.service";
|
||||
import {BulkOperationsComponent} from "../../../cards/bulk-operations/bulk-operations.component";
|
||||
import {KEY_CODES} from "../../../shared/_services/utility.service";
|
||||
import {UserCollection} from "../../../_models/collection-tag";
|
||||
import {User} from "../../../_models/user";
|
||||
import {takeUntilDestroyed} from "@angular/core/rxjs-interop";
|
||||
|
||||
@Component({
|
||||
selector: 'app-reading-lists',
|
||||
|
|
@ -28,30 +34,51 @@ import {WikiLink} from "../../../_models/wiki";
|
|||
styleUrls: ['./reading-lists.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
standalone: true,
|
||||
imports: [SideNavCompanionBarComponent, CardActionablesComponent, NgIf, CardDetailLayoutComponent, CardItemComponent, DecimalPipe, TranslocoDirective]
|
||||
imports: [SideNavCompanionBarComponent, CardActionablesComponent, NgIf, CardDetailLayoutComponent, CardItemComponent, DecimalPipe, TranslocoDirective, BulkOperationsComponent]
|
||||
})
|
||||
export class ReadingListsComponent implements OnInit {
|
||||
|
||||
public readonly bulkSelectionService = inject(BulkSelectionService);
|
||||
public readonly actionService = inject(ActionService);
|
||||
|
||||
protected readonly WikiLink = WikiLink;
|
||||
|
||||
lists: ReadingList[] = [];
|
||||
loadingLists = false;
|
||||
pagination!: Pagination;
|
||||
isAdmin: boolean = false;
|
||||
hasPromote: boolean = false;
|
||||
jumpbarKeys: Array<JumpKey> = [];
|
||||
actions: {[key: number]: Array<ActionItem<ReadingList>>} = {};
|
||||
globalActions: Array<ActionItem<any>> = [{action: Action.Import, title: 'import-cbl', children: [], requiresAdmin: true, callback: this.importCbl.bind(this)}];
|
||||
trackByIdentity = (index: number, item: ReadingList) => `${item.id}_${item.title}`;
|
||||
|
||||
translocoService = inject(TranslocoService);
|
||||
@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;
|
||||
}
|
||||
}
|
||||
|
||||
constructor(private readingListService: ReadingListService, public imageService: ImageService, private actionFactoryService: ActionFactoryService,
|
||||
private accountService: AccountService, private toastr: ToastrService, private router: Router, private actionService: ActionService,
|
||||
private accountService: AccountService, private toastr: ToastrService, private router: Router,
|
||||
private jumpbarService: JumpbarService, private readonly cdRef: ChangeDetectorRef, private ngbModal: NgbModal, private titleService: Title) { }
|
||||
|
||||
ngOnInit(): void {
|
||||
this.accountService.currentUser$.pipe(take(1)).subscribe(user => {
|
||||
if (user) {
|
||||
this.isAdmin = this.accountService.hasAdminRole(user);
|
||||
this.hasPromote = this.accountService.hasPromoteRole(user);
|
||||
|
||||
this.cdRef.markForCheck();
|
||||
|
||||
this.loadPage();
|
||||
this.titleService.setTitle('Kavita - ' + translate('side-nav.reading-lists'));
|
||||
}
|
||||
|
|
@ -59,8 +86,10 @@ export class ReadingListsComponent implements OnInit {
|
|||
}
|
||||
|
||||
getActions(readingList: ReadingList) {
|
||||
const d = this.actionFactoryService.getReadingListActions(this.handleReadingListActionCallback.bind(this))
|
||||
.filter(action => this.readingListService.actionListFilter(action, readingList, this.isAdmin || this.hasPromote));
|
||||
return this.actionFactoryService.getReadingListActions(this.handleReadingListActionCallback.bind(this))
|
||||
.filter(action => this.readingListService.actionListFilter(action, readingList, this.isAdmin));
|
||||
.filter(action => this.readingListService.actionListFilter(action, readingList, this.isAdmin || this.hasPromote));
|
||||
}
|
||||
|
||||
performAction(action: ActionItem<ReadingList>, readingList: ReadingList) {
|
||||
|
|
@ -85,7 +114,7 @@ export class ReadingListsComponent implements OnInit {
|
|||
switch(action.action) {
|
||||
case Action.Delete:
|
||||
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.loadPage();
|
||||
});
|
||||
break;
|
||||
|
|
@ -126,4 +155,33 @@ export class ReadingListsComponent implements OnInit {
|
|||
handleClick(list: ReadingList) {
|
||||
this.router.navigateByUrl('lists/' + list.id);
|
||||
}
|
||||
|
||||
bulkActionCallback = (action: ActionItem<any>, data: any) => {
|
||||
const selectedReadingListIndexies = this.bulkSelectionService.getSelectedCardsForSource('readingList');
|
||||
const selectedReadingLists = this.lists.filter((col, index: number) => selectedReadingListIndexies.includes(index + ''));
|
||||
|
||||
switch (action.action) {
|
||||
case Action.Promote:
|
||||
this.actionService.promoteMultipleReadingLists(selectedReadingLists, true, (success) => {
|
||||
if (!success) return;
|
||||
this.bulkSelectionService.deselectAll();
|
||||
this.loadPage();
|
||||
});
|
||||
break;
|
||||
case Action.UnPromote:
|
||||
this.actionService.promoteMultipleReadingLists(selectedReadingLists, false, (success) => {
|
||||
if (!success) return;
|
||||
this.bulkSelectionService.deselectAll();
|
||||
this.loadPage();
|
||||
});
|
||||
break;
|
||||
case Action.Delete:
|
||||
this.actionService.deleteMultipleReadingLists(selectedReadingLists, (successful) => {
|
||||
if (!successful) return;
|
||||
this.loadPage();
|
||||
this.bulkSelectionService.deselectAll();
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue