diff options
Diffstat (limited to 'src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/table-actions/table-actions.component.ts')
-rw-r--r-- | src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/table-actions/table-actions.component.ts | 161 |
1 files changed, 161 insertions, 0 deletions
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/table-actions/table-actions.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/table-actions/table-actions.component.ts new file mode 100644 index 000000000..0497f9301 --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/table-actions/table-actions.component.ts @@ -0,0 +1,161 @@ +import { Component, Input, OnChanges, OnInit, SimpleChanges } from '@angular/core'; + +import _ from 'lodash'; + +import { Icons } from '~/app/shared/enum/icons.enum'; +import { CdTableAction } from '~/app/shared/models/cd-table-action'; +import { CdTableSelection } from '~/app/shared/models/cd-table-selection'; +import { Permission } from '~/app/shared/models/permissions'; + +@Component({ + selector: 'cd-table-actions', + templateUrl: './table-actions.component.html', + styleUrls: ['./table-actions.component.scss'] +}) +export class TableActionsComponent implements OnChanges, OnInit { + @Input() + permission: Permission; + @Input() + selection: CdTableSelection; + @Input() + tableActions: CdTableAction[]; + @Input() + btnColor = 'accent'; + + // Use this if you just want to display a drop down button, + // labeled with the given text, with all actions in it. + // This disables the main action button. + @Input() + dropDownOnly?: string; + + currentAction?: CdTableAction; + // Array with all visible actions + dropDownActions: CdTableAction[] = []; + + icons = Icons; + + ngOnInit() { + this.removeActionsWithNoPermissions(); + this.onSelectionChange(); + } + + ngOnChanges(changes: SimpleChanges) { + if (changes.selection) { + this.onSelectionChange(); + } + } + + onSelectionChange(): void { + this.updateDropDownActions(); + this.updateCurrentAction(); + } + + toClassName(action: CdTableAction): string { + return action.name + .replace(/ /g, '-') + .replace(/[^a-z-]/gi, '') + .toLowerCase(); + } + + /** + * Removes all actions from 'tableActions' that need a permission the user doesn't have. + */ + private removeActionsWithNoPermissions() { + if (!this.permission) { + this.tableActions = []; + return; + } + const permissions = Object.keys(this.permission).filter((key) => this.permission[key]); + this.tableActions = this.tableActions.filter((action) => + permissions.includes(action.permission) + ); + } + + private updateDropDownActions(): void { + this.dropDownActions = this.tableActions.filter((action) => + action.visible ? action.visible(this.selection) : action + ); + } + + /** + * Finds the next action that is used as main action for the button + * + * The order of the list is crucial to get the right main action. + * + * Default button conditions of actions: + * - 'create' actions can be used with no or multiple selections + * - 'update' and 'delete' actions can be used with one selection + */ + private updateCurrentAction(): void { + if (this.dropDownOnly) { + this.currentAction = undefined; + return; + } + let buttonAction = this.dropDownActions.find((tableAction) => this.showableAction(tableAction)); + if (!buttonAction && this.dropDownActions.length > 0) { + buttonAction = this.dropDownActions[0]; + } + this.currentAction = buttonAction; + } + + /** + * Determines if action can be used for the button + * + * @param {CdTableAction} action + * @returns {boolean} + */ + private showableAction(action: CdTableAction): boolean { + const condition = action.canBePrimary; + const singleSelection = this.selection.hasSingleSelection; + const defaultCase = action.permission === 'create' ? !singleSelection : singleSelection; + return (condition && condition(this.selection)) || (!condition && defaultCase); + } + + useRouterLink(action: CdTableAction): string { + if (!action.routerLink || this.disableSelectionAction(action)) { + return undefined; + } + return _.isString(action.routerLink) ? action.routerLink : action.routerLink(); + } + + /** + * Determines if an action should be disabled + * + * Default disable conditions of 'update' and 'delete' actions: + * - If no or multiple selections are made + * - If one selection is made, but a task is executed on that item + * + * @param {CdTableAction} action + * @returns {Boolean} + */ + disableSelectionAction(action: CdTableAction): Boolean { + const disable = action.disable; + if (disable) { + return Boolean(disable(this.selection)); + } + const permission = action.permission; + const selected = this.selection.hasSingleSelection && this.selection.first(); + return Boolean( + ['update', 'delete'].includes(permission) && (!selected || selected.cdExecuting) + ); + } + + useClickAction(action: CdTableAction) { + /** + * In order to show tooltips for deactivated menu items, the class + * 'pointer-events: auto;' has been added to the .scss file which also + * re-activates the click-event. + * To prevent calling the click-event on deactivated elements we also have + * to check here if it's disabled. + */ + return !this.disableSelectionAction(action) && action.click && action.click(); + } + + useDisableDesc(action: CdTableAction) { + if (action.disable) { + const result = action.disable(this.selection); + return _.isString(result) ? result : undefined; + } + return undefined; + } +} |