mirror of
https://github.com/Kareadita/Kavita.git
synced 2025-07-09 03:04:19 -04:00
Nested Menus (#1554)
* added initial submenu * added submenu - needs a bit of more work * removed admin and nonadmin action split * the whole menu is build under the resetactions function * removed download from seriesAction * changed submenu layout changed submenu toggle icon fix for the hovering of submenu toggle * moved the cdMarkForCheck in the subscribe block
This commit is contained in:
parent
dec6802f88
commit
3cdf8df1db
6
UI/Web/package-lock.json
generated
6
UI/Web/package-lock.json
generated
@ -2637,9 +2637,9 @@
|
||||
}
|
||||
},
|
||||
"@angular/cdk": {
|
||||
"version": "13.2.2",
|
||||
"resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-13.2.2.tgz",
|
||||
"integrity": "sha512-cT5DIaz+NI9IGb3X61Wh26+L6zdRcOXT1BP37iRbK2Qa2qM8/0VNeK6hrBBIblyoHKR/WUmRlS8XYf6mmArpZw==",
|
||||
"version": "13.3.9",
|
||||
"resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-13.3.9.tgz",
|
||||
"integrity": "sha512-XCuCbeuxWFyo3EYrgEYx7eHzwl76vaWcxtWXl00ka8d+WAOtMQ6Tf1D98ybYT5uwF9889fFpXAPw98mVnlo3MA==",
|
||||
"requires": {
|
||||
"parse5": "^5.0.0",
|
||||
"tslib": "^2.3.0"
|
||||
|
@ -8,6 +8,8 @@ import { Volume } from '../_models/volume';
|
||||
import { AccountService } from './account.service';
|
||||
|
||||
export enum Action {
|
||||
AddTo = -2,
|
||||
Others = -1,
|
||||
/**
|
||||
* Mark entity as read
|
||||
*/
|
||||
@ -83,13 +85,13 @@ export interface ActionItem<T> {
|
||||
action: Action;
|
||||
callback: (action: Action, data: T) => void;
|
||||
requiresAdmin: boolean;
|
||||
children: Array<ActionItem<T>>;
|
||||
}
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class ActionFactoryService {
|
||||
|
||||
libraryActions: Array<ActionItem<Library>> = [];
|
||||
|
||||
seriesActions: Array<ActionItem<Series>> = [];
|
||||
@ -108,7 +110,7 @@ export class ActionFactoryService {
|
||||
hasDownloadRole = false;
|
||||
|
||||
constructor(private accountService: AccountService) {
|
||||
this.accountService.currentUser$.subscribe(user => {
|
||||
this.accountService.currentUser$.subscribe((user) => {
|
||||
if (user) {
|
||||
this.isAdmin = this.accountService.hasAdminRole(user);
|
||||
this.hasDownloadRole = this.accountService.hasDownloadRole(user);
|
||||
@ -118,243 +120,282 @@ export class ActionFactoryService {
|
||||
}
|
||||
|
||||
this._resetActions();
|
||||
|
||||
if (this.isAdmin) {
|
||||
this.collectionTagActions.push({
|
||||
action: Action.Edit,
|
||||
title: 'Edit',
|
||||
callback: this.dummyCallback,
|
||||
requiresAdmin: true
|
||||
});
|
||||
|
||||
this.seriesActions.push({
|
||||
action: Action.Scan,
|
||||
title: 'Scan Series',
|
||||
callback: this.dummyCallback,
|
||||
requiresAdmin: true
|
||||
});
|
||||
|
||||
this.seriesActions.push({
|
||||
action: Action.RefreshMetadata,
|
||||
title: 'Refresh Covers',
|
||||
callback: this.dummyCallback,
|
||||
requiresAdmin: true
|
||||
});
|
||||
|
||||
this.seriesActions.push({
|
||||
action: Action.AnalyzeFiles,
|
||||
title: 'Analyze Files',
|
||||
callback: this.dummyCallback,
|
||||
requiresAdmin: true
|
||||
});
|
||||
|
||||
this.seriesActions.push({
|
||||
action: Action.Delete,
|
||||
title: 'Delete',
|
||||
callback: this.dummyCallback,
|
||||
requiresAdmin: true
|
||||
});
|
||||
|
||||
this.seriesActions.push({
|
||||
action: Action.AddToCollection,
|
||||
title: 'Add to Collection',
|
||||
callback: this.dummyCallback,
|
||||
requiresAdmin: true
|
||||
});
|
||||
|
||||
this.seriesActions.push({
|
||||
action: Action.Edit,
|
||||
title: 'Edit',
|
||||
callback: this.dummyCallback,
|
||||
requiresAdmin: true
|
||||
});
|
||||
|
||||
this.libraryActions.push({
|
||||
action: Action.Scan,
|
||||
title: 'Scan Library',
|
||||
callback: this.dummyCallback,
|
||||
requiresAdmin: true
|
||||
});
|
||||
|
||||
this.libraryActions.push({
|
||||
action: Action.RefreshMetadata,
|
||||
title: 'Refresh Covers',
|
||||
callback: this.dummyCallback,
|
||||
requiresAdmin: true
|
||||
});
|
||||
|
||||
this.libraryActions.push({
|
||||
action: Action.AnalyzeFiles,
|
||||
title: 'Analyze Files',
|
||||
callback: this.dummyCallback,
|
||||
requiresAdmin: true
|
||||
});
|
||||
|
||||
this.chapterActions.push({
|
||||
action: Action.Edit,
|
||||
title: 'Details',
|
||||
callback: this.dummyCallback,
|
||||
requiresAdmin: false
|
||||
});
|
||||
}
|
||||
|
||||
if (this.hasDownloadRole || this.isAdmin) {
|
||||
this.volumeActions.push({
|
||||
action: Action.Download,
|
||||
title: 'Download',
|
||||
callback: this.dummyCallback,
|
||||
requiresAdmin: false
|
||||
});
|
||||
|
||||
this.chapterActions.push({
|
||||
action: Action.Download,
|
||||
title: 'Download',
|
||||
callback: this.dummyCallback,
|
||||
requiresAdmin: false
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
getLibraryActions(callback: (action: Action, library: Library) => void) {
|
||||
const actions = this.libraryActions.map(a => {return {...a}});
|
||||
actions.forEach(action => action.callback = callback);
|
||||
return actions;
|
||||
return this.applyCallbackToList(this.libraryActions, callback);
|
||||
}
|
||||
|
||||
getSeriesActions(callback: (action: Action, series: Series) => void) {
|
||||
const actions = this.seriesActions.map(a => {return {...a}});
|
||||
actions.forEach(action => action.callback = callback);
|
||||
return actions;
|
||||
return this.applyCallbackToList(this.seriesActions, callback);
|
||||
}
|
||||
|
||||
getVolumeActions(callback: (action: Action, volume: Volume) => void) {
|
||||
const actions = this.volumeActions.map(a => {return {...a}});
|
||||
actions.forEach(action => action.callback = callback);
|
||||
return actions;
|
||||
return this.applyCallbackToList(this.volumeActions, callback);
|
||||
}
|
||||
|
||||
getChapterActions(callback: (action: Action, chapter: Chapter) => void) {
|
||||
const actions = this.chapterActions.map(a => {return {...a}});
|
||||
actions.forEach(action => action.callback = callback);
|
||||
return actions;
|
||||
return this.applyCallbackToList(this.chapterActions, callback);
|
||||
}
|
||||
|
||||
getCollectionTagActions(callback: (action: Action, collectionTag: CollectionTag) => void) {
|
||||
const actions = this.collectionTagActions.map(a => {return {...a}});
|
||||
actions.forEach(action => action.callback = callback);
|
||||
return actions;
|
||||
return this.applyCallbackToList(this.collectionTagActions, callback);
|
||||
}
|
||||
|
||||
getReadingListActions(callback: (action: Action, readingList: ReadingList) => void) {
|
||||
const actions = this.readingListActions.map(a => {return {...a}});
|
||||
actions.forEach(action => action.callback = callback);
|
||||
return actions;
|
||||
return this.applyCallbackToList(this.readingListActions, callback);
|
||||
}
|
||||
|
||||
getBookmarkActions(callback: (action: Action, series: Series) => void) {
|
||||
const actions = this.bookmarkActions.map(a => {return {...a}});
|
||||
actions.forEach(action => action.callback = callback);
|
||||
return actions;
|
||||
return this.applyCallbackToList(this.bookmarkActions, callback);
|
||||
}
|
||||
|
||||
dummyCallback(action: Action, data: any) {}
|
||||
|
||||
_resetActions() {
|
||||
this.libraryActions = [];
|
||||
this.libraryActions = [
|
||||
{
|
||||
action: Action.Scan,
|
||||
title: 'Scan Library',
|
||||
callback: this.dummyCallback,
|
||||
requiresAdmin: false,
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
action: Action.Others,
|
||||
title: 'Others',
|
||||
callback: this.dummyCallback,
|
||||
requiresAdmin: true,
|
||||
children: [
|
||||
{
|
||||
action: Action.RefreshMetadata,
|
||||
title: 'Refresh Covers',
|
||||
callback: this.dummyCallback,
|
||||
requiresAdmin: true,
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
action: Action.AnalyzeFiles,
|
||||
title: 'Analyze Files',
|
||||
callback: this.dummyCallback,
|
||||
requiresAdmin: true,
|
||||
children: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
this.collectionTagActions = [
|
||||
{
|
||||
action: Action.Edit,
|
||||
title: 'Edit',
|
||||
callback: this.dummyCallback,
|
||||
requiresAdmin: true,
|
||||
children: [],
|
||||
},
|
||||
];
|
||||
|
||||
this.collectionTagActions = [];
|
||||
|
||||
this.seriesActions = [
|
||||
{
|
||||
action: Action.MarkAsRead,
|
||||
title: 'Mark as Read',
|
||||
callback: this.dummyCallback,
|
||||
requiresAdmin: false
|
||||
requiresAdmin: false,
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
action: Action.MarkAsUnread,
|
||||
title: 'Mark as Unread',
|
||||
callback: this.dummyCallback,
|
||||
requiresAdmin: false
|
||||
},
|
||||
{
|
||||
action: Action.AddToReadingList,
|
||||
title: 'Add to Reading List',
|
||||
callback: this.dummyCallback,
|
||||
requiresAdmin: false
|
||||
requiresAdmin: false,
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
action: Action.AddToWantToReadList,
|
||||
title: 'Add to Want To Read',
|
||||
action: Action.AddTo,
|
||||
title: 'Add to',
|
||||
callback: this.dummyCallback,
|
||||
requiresAdmin: false
|
||||
requiresAdmin: false,
|
||||
children: [
|
||||
{
|
||||
action: Action.AddToWantToReadList,
|
||||
title: 'Add to Want To Read',
|
||||
callback: this.dummyCallback,
|
||||
requiresAdmin: false,
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
action: Action.RemoveFromWantToReadList,
|
||||
title: 'Remove from Want To Read',
|
||||
callback: this.dummyCallback,
|
||||
requiresAdmin: false,
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
action: Action.AddToReadingList,
|
||||
title: 'Add to Reading List',
|
||||
callback: this.dummyCallback,
|
||||
requiresAdmin: false,
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
action: Action.AddToCollection,
|
||||
title: 'Add to Collection',
|
||||
callback: this.dummyCallback,
|
||||
requiresAdmin: true,
|
||||
children: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
action: Action.RemoveFromWantToReadList,
|
||||
title: 'Remove from Want To Read',
|
||||
action: Action.Scan,
|
||||
title: 'Scan Series',
|
||||
callback: this.dummyCallback,
|
||||
requiresAdmin: false
|
||||
}
|
||||
requiresAdmin: false,
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
action: Action.Edit,
|
||||
title: 'Edit',
|
||||
callback: this.dummyCallback,
|
||||
requiresAdmin: true,
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
action: Action.Others,
|
||||
title: 'Others',
|
||||
callback: this.dummyCallback,
|
||||
requiresAdmin: false,
|
||||
children: [
|
||||
{
|
||||
action: Action.RefreshMetadata,
|
||||
title: 'Refresh Covers',
|
||||
callback: this.dummyCallback,
|
||||
requiresAdmin: true,
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
action: Action.AnalyzeFiles,
|
||||
title: 'Analyze Files',
|
||||
callback: this.dummyCallback,
|
||||
requiresAdmin: true,
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
action: Action.Delete,
|
||||
title: 'Delete',
|
||||
callback: this.dummyCallback,
|
||||
requiresAdmin: true,
|
||||
children: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
this.volumeActions = [
|
||||
{
|
||||
action: Action.IncognitoRead,
|
||||
title: 'Read Incognito',
|
||||
callback: this.dummyCallback,
|
||||
requiresAdmin: false,
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
action: Action.MarkAsRead,
|
||||
title: 'Mark as Read',
|
||||
callback: this.dummyCallback,
|
||||
requiresAdmin: false
|
||||
requiresAdmin: false,
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
action: Action.MarkAsUnread,
|
||||
title: 'Mark as Unread',
|
||||
callback: this.dummyCallback,
|
||||
requiresAdmin: false
|
||||
},
|
||||
{
|
||||
action: Action.AddToReadingList,
|
||||
title: 'Add to Reading List',
|
||||
callback: this.dummyCallback,
|
||||
requiresAdmin: false
|
||||
},
|
||||
{
|
||||
action: Action.IncognitoRead,
|
||||
title: 'Read Incognito',
|
||||
callback: this.dummyCallback,
|
||||
requiresAdmin: false
|
||||
requiresAdmin: false,
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
action: Action.AddTo,
|
||||
title: 'Add to',
|
||||
callback: this.dummyCallback,
|
||||
requiresAdmin: false,
|
||||
children: [
|
||||
{
|
||||
action: Action.AddToReadingList,
|
||||
title: 'Add to Reading List',
|
||||
callback: this.dummyCallback,
|
||||
requiresAdmin: false,
|
||||
children: [],
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
action: Action.Edit,
|
||||
title: 'Details',
|
||||
callback: this.dummyCallback,
|
||||
requiresAdmin: false
|
||||
}
|
||||
requiresAdmin: false,
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
action: Action.Download,
|
||||
title: 'Download',
|
||||
callback: this.dummyCallback,
|
||||
requiresAdmin: false,
|
||||
children: [],
|
||||
},
|
||||
];
|
||||
|
||||
this.chapterActions = [
|
||||
{
|
||||
action: Action.IncognitoRead,
|
||||
title: 'Read Incognito',
|
||||
callback: this.dummyCallback,
|
||||
requiresAdmin: false,
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
action: Action.MarkAsRead,
|
||||
title: 'Mark as Read',
|
||||
callback: this.dummyCallback,
|
||||
requiresAdmin: false
|
||||
requiresAdmin: false,
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
action: Action.MarkAsUnread,
|
||||
title: 'Mark as Unread',
|
||||
callback: this.dummyCallback,
|
||||
requiresAdmin: false
|
||||
requiresAdmin: false,
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
action: Action.AddTo,
|
||||
title: 'Add to',
|
||||
callback: this.dummyCallback,
|
||||
requiresAdmin: false,
|
||||
children: [
|
||||
{
|
||||
action: Action.AddToReadingList,
|
||||
title: 'Add to Reading List',
|
||||
callback: this.dummyCallback,
|
||||
requiresAdmin: false,
|
||||
children: [],
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
action: Action.IncognitoRead,
|
||||
title: 'Read Incognito',
|
||||
action: Action.Edit,
|
||||
title: 'Details',
|
||||
callback: this.dummyCallback,
|
||||
requiresAdmin: false
|
||||
requiresAdmin: false,
|
||||
children: [],
|
||||
},
|
||||
// RBS will handle rendering this, so non-admins with download are appicable
|
||||
{
|
||||
action: Action.AddToReadingList,
|
||||
title: 'Add to Reading List',
|
||||
action: Action.Download,
|
||||
title: 'Download',
|
||||
callback: this.dummyCallback,
|
||||
requiresAdmin: false
|
||||
requiresAdmin: false,
|
||||
children: [],
|
||||
},
|
||||
];
|
||||
|
||||
@ -363,13 +404,15 @@ export class ActionFactoryService {
|
||||
action: Action.Edit,
|
||||
title: 'Edit',
|
||||
callback: this.dummyCallback,
|
||||
requiresAdmin: false
|
||||
requiresAdmin: false,
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
action: Action.Delete,
|
||||
title: 'Delete',
|
||||
callback: this.dummyCallback,
|
||||
requiresAdmin: false
|
||||
requiresAdmin: false,
|
||||
children: [],
|
||||
},
|
||||
];
|
||||
|
||||
@ -378,20 +421,41 @@ export class ActionFactoryService {
|
||||
action: Action.ViewSeries,
|
||||
title: 'View Series',
|
||||
callback: this.dummyCallback,
|
||||
requiresAdmin: false
|
||||
requiresAdmin: false,
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
action: Action.DownloadBookmark,
|
||||
title: 'Download',
|
||||
callback: this.dummyCallback,
|
||||
requiresAdmin: false
|
||||
requiresAdmin: false,
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
action: Action.Delete,
|
||||
title: 'Clear',
|
||||
callback: this.dummyCallback,
|
||||
requiresAdmin: false
|
||||
requiresAdmin: false,
|
||||
children: [],
|
||||
},
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
private applyCallback(action: ActionItem<any>, callback: (action: Action, data: any) => void) {
|
||||
action.callback = callback;
|
||||
|
||||
if (action.children === null || action.children?.length === 0) return;
|
||||
|
||||
action.children?.forEach((childAction) => {
|
||||
this.applyCallback(childAction, callback);
|
||||
});
|
||||
}
|
||||
|
||||
private applyCallbackToList(list: Array<ActionItem<any>>, callback: (action: Action, data: any) => void): Array<ActionItem<any>> {
|
||||
const actions = list.map((a) => {
|
||||
return { ...a };
|
||||
});
|
||||
actions.forEach((action) => this.applyCallback(action, callback));
|
||||
return actions;
|
||||
}
|
||||
}
|
||||
|
@ -130,7 +130,7 @@ export class CardDetailDrawerComponent implements OnInit, OnDestroy {
|
||||
|
||||
this.chapterActions = this.actionFactoryService.getChapterActions(this.handleChapterActionCallback.bind(this))
|
||||
.filter(item => item.action !== Action.Edit);
|
||||
this.chapterActions.push({title: 'Read', action: Action.Read, callback: this.handleChapterActionCallback.bind(this), requiresAdmin: false});
|
||||
this.chapterActions.push({title: 'Read', action: Action.Read, callback: this.handleChapterActionCallback.bind(this), requiresAdmin: false, children: []});
|
||||
|
||||
this.libraryService.getLibraryType(this.libraryId).subscribe(type => {
|
||||
this.libraryType = type;
|
||||
|
@ -2,10 +2,22 @@
|
||||
<div ngbDropdown container="body" class="d-inline-block">
|
||||
<button [disabled]="disabled" class="btn {{btnClass}}" id="actions-{{labelBy}}" ngbDropdownToggle (click)="preventClick($event)"><i class="fa {{iconClass}}" aria-hidden="true"></i></button>
|
||||
<div ngbDropdownMenu attr.aria-labelledby="actions-{{labelBy}}">
|
||||
<button ngbDropdownItem *ngFor="let action of nonAdminActions" (click)="performAction($event, action)">{{action.title}}</button>
|
||||
<div class="dropdown-divider" *ngIf="nonAdminActions.length > 1 && adminActions.length > 1"></div>
|
||||
<button ngbDropdownItem *ngFor="let action of adminActions" (click)="performAction($event, action)">{{action.title}}</button>
|
||||
<ng-container *ngTemplateOutlet="submenu; context: { list: actions }"></ng-container>
|
||||
</div>
|
||||
</div>
|
||||
<!-- IDEA: If we are not on desktop, then let's open a bottom drawer instead-->
|
||||
<ng-template #submenu let-list="list">
|
||||
<ng-container *ngFor="let action of list">
|
||||
<ng-container *ngIf="action.children === undefined || action?.children?.length === 0 else submenuDropdown">
|
||||
<button ngbDropdownItem *ngIf="willRenderAction(action)" (click)="performAction($event, action)">{{action.title}}</button>
|
||||
</ng-container>
|
||||
<ng-template #submenuDropdown>
|
||||
<div ngbDropdown #subMenuHover="ngbDropdown" placement="right" (mouseover)="preventClick($event); openSubmenu(action.title, subMenuHover)" (mouseleave)="preventClick($event)">
|
||||
<button id="actions-{{action.title}}" class="submenu-toggle" ngbDropdownToggle>{{action.title}} <i class="fa-solid fa-angle-right submenu-icon"></i></button>
|
||||
<div ngbDropdownMenu attr.aria-labelledby="actions-{{action.title}}">
|
||||
<ng-container *ngTemplateOutlet="submenu; context: { list: action.children }"></ng-container>
|
||||
</div>
|
||||
</div>
|
||||
</ng-template>
|
||||
</ng-container>
|
||||
</ng-template>
|
||||
</ng-container>
|
@ -1,3 +1,28 @@
|
||||
.dropdown-toggle:after {
|
||||
content: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
.submenu-toggle {
|
||||
display: block;
|
||||
width: 100%;
|
||||
padding: var(--bs-dropdown-item-padding-y) var(--bs-dropdown-item-padding-x);
|
||||
font-weight: 400;
|
||||
text-align: inherit;
|
||||
border: 0;
|
||||
color: var(--dropdown-item-text-color);
|
||||
background-color: var(--dropdown-item-bg-color);
|
||||
&:hover {
|
||||
color: var(--dropdown-item-text-color);
|
||||
background-color: var(--dropdown-item-hover-bg-color);
|
||||
cursor: pointer;
|
||||
}
|
||||
&:focus-visible {
|
||||
color: var(--dropdown-item-text-color);
|
||||
background-color: var(--dropdown-item-hover-bg-color);
|
||||
}
|
||||
}
|
||||
|
||||
.submenu-icon {
|
||||
float: right;
|
||||
padding: var(--bs-dropdown-item-padding-y) 0;
|
||||
}
|
||||
|
@ -1,5 +1,8 @@
|
||||
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
|
||||
import { ActionItem } from 'src/app/_services/action-factory.service';
|
||||
import { NgbDropdown } from '@ng-bootstrap/ng-bootstrap';
|
||||
import { take } from 'rxjs';
|
||||
import { AccountService } from 'src/app/_services/account.service';
|
||||
import { Action, ActionItem } from 'src/app/_services/action-factory.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-card-actionables',
|
||||
@ -16,16 +19,19 @@ export class CardActionablesComponent implements OnInit {
|
||||
@Input() disabled: boolean = false;
|
||||
@Output() actionHandler = new EventEmitter<ActionItem<any>>();
|
||||
|
||||
adminActions: ActionItem<any>[] = [];
|
||||
nonAdminActions: ActionItem<any>[] = [];
|
||||
isAdmin: boolean = false;
|
||||
canDownload: boolean = false;
|
||||
submenu: {[key: string]: NgbDropdown} = {};
|
||||
|
||||
|
||||
constructor(private readonly cdRef: ChangeDetectorRef) { }
|
||||
constructor(private readonly cdRef: ChangeDetectorRef, private accountService: AccountService) { }
|
||||
|
||||
ngOnInit(): void {
|
||||
this.nonAdminActions = this.actions.filter(item => !item.requiresAdmin);
|
||||
this.adminActions = this.actions.filter(item => item.requiresAdmin);
|
||||
this.cdRef.markForCheck();
|
||||
this.accountService.currentUser$.pipe(take(1)).subscribe((user) => {
|
||||
if (!user) return;
|
||||
this.isAdmin = this.accountService.hasAdminRole(user);
|
||||
this.canDownload = this.accountService.hasDownloadRole(user);
|
||||
this.cdRef.markForCheck();
|
||||
});
|
||||
}
|
||||
|
||||
preventClick(event: any) {
|
||||
@ -41,4 +47,23 @@ export class CardActionablesComponent implements OnInit {
|
||||
}
|
||||
}
|
||||
|
||||
willRenderAction(action: ActionItem<any>): boolean {
|
||||
return (action.requiresAdmin && this.isAdmin)
|
||||
|| (action.action === Action.Download && (this.canDownload || this.isAdmin))
|
||||
|| (!action.requiresAdmin && action.action !== Action.Download)
|
||||
}
|
||||
|
||||
openSubmenu(actionTitle: string, subMenu: NgbDropdown) {
|
||||
// We keep track when we open and when we get a request to open, if we have other keys, we close them and clear their keys
|
||||
if (Object.keys(this.submenu).length > 0) {
|
||||
const keys = Object.keys(this.submenu).filter(k => k !== actionTitle);
|
||||
keys.forEach(key => {
|
||||
this.submenu[key].close();
|
||||
delete this.submenu[key];
|
||||
});
|
||||
}
|
||||
this.submenu[actionTitle] = subMenu;
|
||||
subMenu.open();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -482,7 +482,6 @@ export class SeriesDetailComponent implements OnInit, OnDestroy, AfterContentChe
|
||||
|
||||
this.seriesActions = this.actionFactoryService.getSeriesActions(this.handleSeriesActionCallback.bind(this))
|
||||
.filter(action => action.action !== Action.Edit);
|
||||
this.seriesActions.push({action: Action.Download, callback: this.seriesActions[0].callback, requiresAdmin: false, title: 'Download'});
|
||||
|
||||
this.volumeActions = this.actionFactoryService.getVolumeActions(this.handleVolumeActionCallback.bind(this));
|
||||
this.chapterActions = this.actionFactoryService.getChapterActions(this.handleChapterActionCallback.bind(this));
|
||||
|
Loading…
x
Reference in New Issue
Block a user