From: Stephan Müller Date: Mon, 20 Aug 2018 12:01:08 +0000 (+0200) Subject: mgr/dashboard: Use table actions component for RBDs X-Git-Tag: v14.0.1~239^2~8 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=d173446bb8681ccb7642a90f90220643fe9219e6;p=ceph.git mgr/dashboard: Use table actions component for RBDs Signed-off-by: Stephan Müller --- diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-list/rbd-list.component.html b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-list/rbd-list.component.html index 76321cc3ec4b..686c749fa9a8 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-list/rbd-list.component.html +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-list/rbd-list.component.html @@ -10,87 +10,11 @@ forceIdentifier="true" selectionType="single" (updateSelection)="updateSelection($event)"> -
-
- - - - - -
-
+ + diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-list/rbd-list.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-list/rbd-list.component.spec.ts index 24b28a9dfcaa..7a985f61dc9e 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-list/rbd-list.component.spec.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-list/rbd-list.component.spec.ts @@ -1,5 +1,6 @@ import { HttpClientTestingModule } from '@angular/common/http/testing'; import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { By } from '@angular/platform-browser'; import { RouterTestingModule } from '@angular/router/testing'; import { ToastModule } from 'ng2-toastr'; @@ -12,9 +13,10 @@ import { } from 'ngx-bootstrap'; import { BehaviorSubject, of } from 'rxjs'; -import { configureTestBed } from '../../../../testing/unit-test-helper'; +import { configureTestBed, PermissionHelper } from '../../../../testing/unit-test-helper'; import { RbdService } from '../../../shared/api/rbd.service'; import { ComponentsModule } from '../../../shared/components/components.module'; +import { TableActionsComponent } from '../../../shared/datatable/table-actions/table-actions.component'; import { ViewCacheStatus } from '../../../shared/enum/view-cache-status.enum'; import { ExecutingTask } from '../../../shared/models/executing-task'; import { SummaryService } from '../../../shared/services/summary.service'; @@ -175,4 +177,169 @@ describe('RbdListComponent', () => { expectImageTasks(component.images[2], 'Flattening'); }); }); + + describe('show action buttons and drop down actions depending on permissions', () => { + let tableActions: TableActionsComponent; + let scenario: { fn; empty; single }; + let permissionHelper: PermissionHelper; + + const getTableActionComponent = (): TableActionsComponent => { + fixture.detectChanges(); + return fixture.debugElement.query(By.directive(TableActionsComponent)).componentInstance; + }; + + beforeEach(() => { + permissionHelper = new PermissionHelper(component.permission, () => + getTableActionComponent() + ); + scenario = { + fn: () => tableActions.getCurrentButton().name, + single: 'Edit', + empty: 'Add' + }; + }); + + describe('with all', () => { + beforeEach(() => { + tableActions = permissionHelper.setPermissionsAndGetActions(1, 1, 1); + }); + + it(`shows 'Edit' for single selection else 'Add' as main action`, () => + permissionHelper.testScenarios(scenario)); + + it('shows all actions', () => { + expect(tableActions.tableActions.length).toBe(5); + expect(tableActions.tableActions).toEqual(component.tableActions); + }); + }); + + describe('with read, create and update', () => { + beforeEach(() => { + tableActions = permissionHelper.setPermissionsAndGetActions(1, 1, 0); + }); + + it(`shows 'Edit' for single selection else 'Add' as main action`, () => + permissionHelper.testScenarios(scenario)); + + it(`shows all actions except for 'Delete'`, () => { + expect(tableActions.tableActions.length).toBe(4); + component.tableActions.pop(); + expect(tableActions.tableActions).toEqual(component.tableActions); + }); + }); + + describe('with read, create and delete', () => { + beforeEach(() => { + tableActions = permissionHelper.setPermissionsAndGetActions(1, 0, 1); + }); + + it(`shows 'Copy' for single selection else 'Add' as main action`, () => { + scenario.single = 'Copy'; + permissionHelper.testScenarios(scenario); + }); + + it(`shows 'Add', 'Copy' and 'Delete' action`, () => { + expect(tableActions.tableActions.length).toBe(3); + expect(tableActions.tableActions).toEqual([ + component.tableActions[0], + component.tableActions[2], + component.tableActions[4] + ]); + }); + }); + + describe('with read, edit and delete', () => { + beforeEach(() => { + tableActions = permissionHelper.setPermissionsAndGetActions(0, 1, 1); + }); + + it(`shows always 'Edit' as main action`, () => { + scenario.empty = 'Edit'; + permissionHelper.testScenarios(scenario); + }); + + it(`shows 'Edit', 'Flatten' and 'Delete' action`, () => { + expect(tableActions.tableActions.length).toBe(3); + expect(tableActions.tableActions).toEqual([ + component.tableActions[1], + component.tableActions[3], + component.tableActions[4] + ]); + }); + }); + + describe('with read and create', () => { + beforeEach(() => { + tableActions = permissionHelper.setPermissionsAndGetActions(1, 0, 0); + }); + + it(`shows 'Copy' for single selection else 'Add' as main action`, () => { + scenario.single = 'Copy'; + permissionHelper.testScenarios(scenario); + }); + + it(`shows 'Copy' and 'Add' actions`, () => { + expect(tableActions.tableActions.length).toBe(2); + expect(tableActions.tableActions).toEqual([ + component.tableActions[0], + component.tableActions[2] + ]); + }); + }); + + describe('with read and edit', () => { + beforeEach(() => { + tableActions = permissionHelper.setPermissionsAndGetActions(0, 1, 0); + }); + + it(`shows always 'Edit' as main action`, () => { + scenario.empty = 'Edit'; + permissionHelper.testScenarios(scenario); + }); + + it(`shows 'Edit' and 'Flatten' actions`, () => { + expect(tableActions.tableActions.length).toBe(2); + expect(tableActions.tableActions).toEqual([ + component.tableActions[1], + component.tableActions[3] + ]); + }); + }); + + describe('with read and delete', () => { + beforeEach(() => { + tableActions = permissionHelper.setPermissionsAndGetActions(0, 0, 1); + }); + + it(`shows always 'Delete' as main action`, () => { + scenario.single = 'Delete'; + scenario.empty = 'Delete'; + permissionHelper.testScenarios(scenario); + }); + + it(`shows only 'Delete' action`, () => { + expect(tableActions.tableActions.length).toBe(1); + expect(tableActions.tableActions).toEqual([component.tableActions[4]]); + }); + }); + + describe('with only read', () => { + beforeEach(() => { + tableActions = permissionHelper.setPermissionsAndGetActions(0, 0, 0); + }); + + it('shows no main action', () => { + permissionHelper.testScenarios({ + fn: () => tableActions.getCurrentButton(), + single: undefined, + empty: undefined + }); + }); + + it('shows no actions', () => { + expect(tableActions.tableActions.length).toBe(0); + expect(tableActions.tableActions).toEqual([]); + }); + }); + }); }); diff --git a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-list/rbd-list.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-list/rbd-list.component.ts index eafb9bda73fd..62a552f2d575 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-list/rbd-list.component.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-list/rbd-list.component.ts @@ -9,6 +9,7 @@ import { DeletionModalComponent } from '../../../shared/components/deletion-moda import { TableComponent } from '../../../shared/datatable/table/table.component'; import { CellTemplate } from '../../../shared/enum/cell-template.enum'; import { ViewCacheStatus } from '../../../shared/enum/view-cache-status.enum'; +import { CdTableAction } from '../../../shared/models/cd-table-action'; import { CdTableColumn } from '../../../shared/models/cd-table-column'; import { CdTableSelection } from '../../../shared/models/cd-table-selection'; import { FinishedTask } from '../../../shared/models/finished-task'; @@ -40,6 +41,7 @@ export class RbdListComponent implements OnInit { flattenTpl: TemplateRef; permission: Permission; + tableActions: CdTableAction[]; images: any; columns: CdTableColumn[]; retries: number; @@ -75,6 +77,45 @@ export class RbdListComponent implements OnInit { private taskListService: TaskListService ) { this.permission = this.authStorageService.getPermissions().rbdImage; + const getImageUri = () => + this.selection.first() && + `${encodeURI(this.selection.first().pool_name)}/${encodeURI(this.selection.first().name)}`; + const addAction: CdTableAction = { + permission: 'create', + icon: 'fa-plus', + routerLink: () => '/block/rbd/add', + buttonCondition: (selection: CdTableSelection) => !selection.hasSingleSelection, + name: 'Add' + }; + const editAction: CdTableAction = { + permission: 'update', + icon: 'fa-pencil', + routerLink: () => `/block/rbd/edit/${getImageUri()}`, + name: 'Edit' + }; + const deleteAction: CdTableAction = { + permission: 'delete', + icon: 'fa-trash-o', + click: () => this.deleteRbdModal(), + name: 'Delete' + }; + const copyAction: CdTableAction = { + permission: 'create', + buttonCondition: (selection: CdTableSelection) => selection.hasSingleSelection, + disable: (selection: CdTableSelection) => !selection.hasSingleSelection, + icon: 'fa-copy', + routerLink: () => `/block/rbd/copy/${getImageUri()}`, + name: 'Copy' + }; + const flattenAction: CdTableAction = { + permission: 'update', + disable: (selection: CdTableSelection) => + !selection.hasSingleSelection || selection.first().cdExecuting || !selection.first().parent, + icon: 'fa-chain-broken', + click: () => this.flattenRbdModal(), + name: 'Flatten' + }; + this.tableActions = [addAction, editAction, copyAction, flattenAction, deleteAction]; } ngOnInit() {