From: Nizamudeen A Date: Fri, 4 Aug 2023 12:48:50 +0000 (+0530) Subject: mgr/dashboard: create/generalize checked table scope_permission table X-Git-Tag: v18.2.1~378^2~7 X-Git-Url: http://git.apps.os.sepia.ceph.com/?a=commitdiff_plain;h=a1363f81420e8ec82f741c31a6124baccd5447ff;p=ceph-ci.git mgr/dashboard: create/generalize checked table scope_permission table Fixes: https://tracker.ceph.com/issues/62345 Signed-off-by: Nizamudeen A (cherry picked from commit 6241530960df147ae7323f5675021695dd4f4610) --- diff --git a/src/pybind/mgr/dashboard/frontend/src/app/core/auth/role-form/role-form.component.html b/src/pybind/mgr/dashboard/frontend/src/app/core/auth/role-form/role-form.component.html index 08904c1c2b3..9b792d127f1 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/core/auth/role-form/role-form.component.html +++ b/src/pybind/mgr/dashboard/frontend/src/app/core/auth/role-form/role-form.component.html @@ -54,15 +54,12 @@
- - +
@@ -76,46 +73,3 @@ - - -
- - -
-
- - -
- - -
-
- - -
- - -
-
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/core/auth/role-form/role-form.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/core/auth/role-form/role-form.component.spec.ts index 7552f594bf3..f4e8e1d0bce 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/core/auth/role-form/role-form.component.spec.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/core/auth/role-form/role-form.component.spec.ts @@ -101,72 +101,11 @@ describe('RoleFormComponent', () => { roleReq.flush({}); expect(router.navigate).toHaveBeenCalledWith(['/user-management/roles']); }); - - it('should check all perms for a scope', () => { - formHelper.setValue('scopes_permissions', { cephfs: ['read'] }); - component.onClickCellCheckbox('grafana', 'scope'); - const scopes_permissions = form.getValue('scopes_permissions'); - expect(Object.keys(scopes_permissions)).toContain('grafana'); - expect(scopes_permissions['grafana']).toEqual(['create', 'delete', 'read', 'update']); - }); - - it('should uncheck all perms for a scope', () => { - formHelper.setValue('scopes_permissions', { cephfs: ['read', 'create', 'update', 'delete'] }); - component.onClickCellCheckbox('cephfs', 'scope'); - const scopes_permissions = form.getValue('scopes_permissions'); - expect(Object.keys(scopes_permissions)).not.toContain('cephfs'); - }); - - it('should uncheck all scopes and perms', () => { - component.scopes = ['cephfs', 'grafana']; - formHelper.setValue('scopes_permissions', { - cephfs: ['read', 'delete'], - grafana: ['update'] - }); - component.onClickHeaderCheckbox('scope', ({ - target: { checked: false } - } as unknown) as Event); - const scopes_permissions = form.getValue('scopes_permissions'); - expect(scopes_permissions).toEqual({}); - }); - - it('should check all scopes and perms', () => { - component.scopes = ['cephfs', 'grafana']; - formHelper.setValue('scopes_permissions', { - cephfs: ['create', 'update'], - grafana: ['delete'] - }); - component.onClickHeaderCheckbox('scope', ({ target: { checked: true } } as unknown) as Event); - const scopes_permissions = form.getValue('scopes_permissions'); - const keys = Object.keys(scopes_permissions); - expect(keys).toEqual(['cephfs', 'grafana']); - keys.forEach((key) => { - expect(scopes_permissions[key].sort()).toEqual(['create', 'delete', 'read', 'update']); - }); - }); - - it('should check if column is checked', () => { - component.scopes_permissions = [ - { scope: 'a', read: true, create: true, update: true, delete: true }, - { scope: 'b', read: false, create: true, update: false, delete: true } - ]; - expect(component.isRowChecked('a')).toBeTruthy(); - expect(component.isRowChecked('b')).toBeFalsy(); - expect(component.isRowChecked('c')).toBeFalsy(); - }); - - it('should check if header is checked', () => { - component.scopes_permissions = [ - { scope: 'a', read: true, create: true, update: false, delete: true }, - { scope: 'b', read: false, create: true, update: false, delete: true } - ]; - expect(component.isHeaderChecked('read')).toBeFalsy(); - expect(component.isHeaderChecked('create')).toBeTruthy(); - expect(component.isHeaderChecked('update')).toBeFalsy(); - }); }); describe('edit mode', () => { + let formHelper: FormHelper; + const role: RoleFormModel = { name: 'role1', description: 'Role 1', @@ -174,6 +113,7 @@ describe('RoleFormComponent', () => { }; const scopes = ['osd', 'user']; beforeEach(() => { + formHelper = new FormHelper(form); spyOn(roleService, 'get').and.callFake(() => of(role)); spyOn(TestBed.inject(ScopeService), 'list').and.callFake(() => of(scopes)); setUrl('/user-management/roles/edit/role1'); @@ -204,9 +144,10 @@ describe('RoleFormComponent', () => { }); it('should submit', () => { - component.onClickCellCheckbox('osd', 'update'); - component.onClickCellCheckbox('osd', 'create'); - component.onClickCellCheckbox('user', 'read'); + formHelper.setValue('scopes_permissions', { + osd: ['read', 'update'], + user: ['read'] + }); component.submit(); const roleReq = httpTesting.expectOne(`api/role/${role.name}`); expect(roleReq.request.method).toBe('PUT'); diff --git a/src/pybind/mgr/dashboard/frontend/src/app/core/auth/role-form/role-form.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/core/auth/role-form/role-form.component.ts index 21dff1c85af..e7876d29464 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/core/auth/role-form/role-form.component.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/core/auth/role-form/role-form.component.ts @@ -1,4 +1,4 @@ -import { Component, OnInit, TemplateRef, ViewChild } from '@angular/core'; +import { Component, OnInit } from '@angular/core'; import { FormControl, Validators } from '@angular/forms'; import { ActivatedRoute, Router } from '@angular/router'; @@ -23,12 +23,6 @@ import { RoleFormModel } from './role-form.model'; styleUrls: ['./role-form.component.scss'] }) export class RoleFormComponent extends CdForm implements OnInit { - @ViewChild('headerPermissionCheckboxTpl', { static: true }) - headerPermissionCheckboxTpl: TemplateRef; - @ViewChild('cellScopeCheckboxTpl', { static: true }) - cellScopeCheckboxTpl: TemplateRef; - @ViewChild('cellPermissionCheckboxTpl', { static: true }) - cellPermissionCheckboxTpl: TemplateRef; roleForm: CdFormGroup; response: RoleFormModel; @@ -36,6 +30,7 @@ export class RoleFormComponent extends CdForm implements OnInit { columns: CdTableColumn[]; scopes: Array = []; scopes_permissions: Array = []; + initialValue = {}; roleFormMode = RoleFormMode; mode: RoleFormMode; @@ -54,7 +49,7 @@ export class RoleFormComponent extends CdForm implements OnInit { super(); this.resource = $localize`role`; this.createForm(); - this.listenToChanges(); + // this.listenToChanges(); } createForm() { @@ -73,41 +68,31 @@ export class RoleFormComponent extends CdForm implements OnInit { { prop: 'scope', name: $localize`All`, - flexGrow: 2, - cellTemplate: this.cellScopeCheckboxTpl, - headerTemplate: this.headerPermissionCheckboxTpl + flexGrow: 2 }, { prop: 'read', name: $localize`Read`, flexGrow: 1, - cellClass: 'text-center', - cellTemplate: this.cellPermissionCheckboxTpl, - headerTemplate: this.headerPermissionCheckboxTpl + cellClass: 'text-center' }, { prop: 'create', name: $localize`Create`, flexGrow: 1, - cellClass: 'text-center', - cellTemplate: this.cellPermissionCheckboxTpl, - headerTemplate: this.headerPermissionCheckboxTpl + cellClass: 'text-center' }, { prop: 'update', name: $localize`Update`, flexGrow: 1, - cellClass: 'text-center', - cellTemplate: this.cellPermissionCheckboxTpl, - headerTemplate: this.headerPermissionCheckboxTpl + cellClass: 'text-center' }, { prop: 'delete', name: $localize`Delete`, flexGrow: 1, - cellClass: 'text-center', - cellTemplate: this.cellPermissionCheckboxTpl, - headerTemplate: this.headerPermissionCheckboxTpl + cellClass: 'text-center' } ]; if (this.router.url.startsWith('/user-management/roles/edit')) { @@ -127,7 +112,6 @@ export class RoleFormComponent extends CdForm implements OnInit { // Load the scopes and initialize the default scopes/permissions data. this.scopeService.list().subscribe((scopes: Array) => { this.scopes = scopes; - this.roleForm.get('scopes_permissions').setValue({}); this.loadingReady(); }); @@ -146,125 +130,13 @@ export class RoleFormComponent extends CdForm implements OnInit { ['name', 'description', 'scopes_permissions'].forEach((key) => this.roleForm.get(key).setValue(resp[1][key]) ); + this.initialValue = resp[1]['scopes_permissions']; this.loadingReady(); }); }); } - listenToChanges() { - // Create/Update the data which is used by the data table to display the - // scopes/permissions every time the form field value has been changed. - this.roleForm.get('scopes_permissions').valueChanges.subscribe((value) => { - const scopes_permissions: any[] = []; - _.each(this.scopes, (scope) => { - // Set the defaults values. - const scope_permission: any = { read: false, create: false, update: false, delete: false }; - scope_permission['scope'] = scope; - // Apply settings from the given value if they exist. - if (scope in value) { - _.each(value[scope], (permission) => { - scope_permission[permission] = true; - }); - } - scopes_permissions.push(scope_permission); - }); - this.scopes_permissions = scopes_permissions; - }); - } - - /** - * Checks if the specified row checkbox needs to be rendered as checked. - * @param {string} scope The scope to be checked, e.g. 'cephfs', 'grafana', - * 'osd', 'pool' ... - * @return Returns true if all permissions (read, create, update, delete) - * are checked for the specified scope, otherwise false. - */ - isRowChecked(scope: string) { - const scope_permission = _.find(this.scopes_permissions, (o) => { - return o['scope'] === scope; - }); - if (_.isUndefined(scope_permission)) { - return false; - } - return ( - scope_permission['read'] && - scope_permission['create'] && - scope_permission['update'] && - scope_permission['delete'] - ); - } - - /** - * Checks if the specified header checkbox needs to be rendered as checked. - * @param {string} property The property/permission (read, create, - * update, delete) to be checked. If 'scope' is given, all permissions - * are checked. - * @return Returns true if specified property/permission is selected - * for all scopes, otherwise false. - */ - isHeaderChecked(property: string) { - let permissions = [property]; - if ('scope' === property) { - permissions = ['read', 'create', 'update', 'delete']; - } - return permissions.every((permission) => { - return this.scopes_permissions.every((scope_permission) => { - return scope_permission[permission]; - }); - }); - } - - onClickCellCheckbox(scope: string, property: string, event: any = null) { - // Use a copy of the form field data to do not trigger the redrawing of the - // data table with every change. - const scopes_permissions = _.cloneDeep(this.roleForm.getValue('scopes_permissions')); - let permissions = [property]; - if ('scope' === property) { - permissions = ['read', 'create', 'update', 'delete']; - } - if (!(scope in scopes_permissions)) { - scopes_permissions[scope] = []; - } - // Add or remove the given permission(s) depending on the click event or if no - // click event is given then add/remove them if they are absent/exist. - if ( - (event && event.target['checked']) || - !_.isEqual(permissions.sort(), _.intersection(scopes_permissions[scope], permissions).sort()) - ) { - scopes_permissions[scope] = _.union(scopes_permissions[scope], permissions); - } else { - scopes_permissions[scope] = _.difference(scopes_permissions[scope], permissions); - if (_.isEmpty(scopes_permissions[scope])) { - _.unset(scopes_permissions, scope); - } - } - this.roleForm.get('scopes_permissions').setValue(scopes_permissions); - } - - onClickHeaderCheckbox(property: 'scope' | 'read' | 'create' | 'update' | 'delete', event: any) { - // Use a copy of the form field data to do not trigger the redrawing of the - // data table with every change. - const scopes_permissions = _.cloneDeep(this.roleForm.getValue('scopes_permissions')); - let permissions = [property]; - if ('scope' === property) { - permissions = ['read', 'create', 'update', 'delete']; - } - _.each(permissions, (permission) => { - _.each(this.scopes, (scope) => { - if (event.target['checked']) { - scopes_permissions[scope] = _.union(scopes_permissions[scope], [permission]); - } else { - scopes_permissions[scope] = _.difference(scopes_permissions[scope], [permission]); - if (_.isEmpty(scopes_permissions[scope])) { - _.unset(scopes_permissions, scope); - } - } - }); - }); - this.roleForm.get('scopes_permissions').setValue(scopes_permissions); - } - getRequest(): RoleFormModel { const roleFormModel = new RoleFormModel(); ['name', 'description', 'scopes_permissions'].forEach( diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/checked-table-form/checked-table-form.component.html b/src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/checked-table-form/checked-table-form.component.html new file mode 100644 index 00000000000..7d96239e93d --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/checked-table-form/checked-table-form.component.html @@ -0,0 +1,52 @@ + + + + +
+ + +
+
+ + +
+ + +
+
+ + +
+ + +
+
diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/checked-table-form/checked-table-form.component.scss b/src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/checked-table-form/checked-table-form.component.scss new file mode 100644 index 00000000000..e69de29bb2d diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/checked-table-form/checked-table-form.component.spec.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/checked-table-form/checked-table-form.component.spec.ts new file mode 100644 index 00000000000..b4c756a16c3 --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/checked-table-form/checked-table-form.component.spec.ts @@ -0,0 +1,140 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { CheckedTableFormComponent } from './checked-table-form.component'; +import { TableComponent } from '../table/table.component'; +import { TableKeyValueComponent } from '../table-key-value/table-key-value.component'; +import { TablePaginationComponent } from '../table-pagination/table-pagination.component'; +import { NgxDatatableModule } from '@swimlane/ngx-datatable'; +import { FormHelper } from '~/testing/unit-test-helper'; +import { CdFormGroup } from '../../forms/cd-form-group'; +import { FormControl } from '@angular/forms'; + +describe('CheckedTableFormComponent', () => { + let component: CheckedTableFormComponent; + let fixture: ComponentFixture; + let formHelper: FormHelper; + let form: CdFormGroup; + + let fakeColumns = [ + { + prop: 'scope', + name: $localize`All`, + flexGrow: 1 + }, + { + prop: 'read', + name: $localize`Read`, + flexGrow: 1 + }, + { + prop: 'write', + name: $localize`Write`, + flexGrow: 1 + }, + { + prop: 'execute', + name: $localize`Execute`, + flexGrow: 1 + } + ]; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + CheckedTableFormComponent, + TableComponent, + TableKeyValueComponent, + TablePaginationComponent + ], + imports: [NgxDatatableModule] + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(CheckedTableFormComponent); + component = fixture.componentInstance; + component.columns = fakeColumns; + component.data = [ + { scope: 'owner', read: true, write: true, execute: true }, + { scope: 'group', read: true, write: true, execute: true }, + { scope: 'other', read: true, write: true, execute: true } + ]; + component.scopes = ['owner', 'group', 'others']; + component.form = new CdFormGroup({ + scopes_permissions: new FormControl({}) + }); + component.inputField = 'scopes_permissions'; + component.isTableForOctalMode = true; + form = component.form; + formHelper = new FormHelper(form); + component.ngOnInit(); + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + it('should check all perms for a scope', () => { + formHelper.setValue('scopes_permissions', { owner: ['read'] }); + component.onClickCellCheckbox('group', 'scope'); + const scopes_permissions = form.getValue('scopes_permissions'); + expect(Object.keys(scopes_permissions)).toContain('group'); + expect(scopes_permissions['group']).toEqual(['read', 'write', 'execute'].sort()); + }); + + it('should uncheck all perms for a scope', () => { + formHelper.setValue('scopes_permissions', { owner: ['read', 'write', 'execute'] }); + component.onClickCellCheckbox('owner', 'scope'); + const scopes_permissions = form.getValue('scopes_permissions'); + expect(Object.keys(scopes_permissions)).not.toContain('owner'); + }); + + it('should uncheck all scopes and perms', () => { + component.scopes = ['owner', 'group']; + formHelper.setValue('scopes_permissions', { + owner: ['read', 'execute'], + group: ['write'] + }); + component.onClickHeaderCheckbox('scope', ({ + target: { checked: false } + } as unknown) as Event); + const scopes_permissions = form.getValue('scopes_permissions'); + expect(scopes_permissions).toEqual({}); + }); + + it('should check all scopes and perms', () => { + component.scopes = ['owner', 'group']; + formHelper.setValue('scopes_permissions', { + owner: ['read', 'write'], + group: ['execute'] + }); + component.onClickHeaderCheckbox('scope', ({ target: { checked: true } } as unknown) as Event); + const scopes_permissions = form.getValue('scopes_permissions'); + const keys = Object.keys(scopes_permissions); + expect(keys).toEqual(['owner', 'group']); + keys.forEach((key) => { + expect(scopes_permissions[key].sort()).toEqual(['execute', 'read', 'write']); + }); + }); + + it('should check if column is checked', () => { + component.data = [ + { scope: 'a', read: true, write: true, execute: true }, + { scope: 'b', read: false, write: true, execute: false } + ]; + expect(component.isRowChecked('a')).toBeTruthy(); + expect(component.isRowChecked('b')).toBeFalsy(); + expect(component.isRowChecked('c')).toBeFalsy(); + }); + + it('should check if header is checked', () => { + component.data = [ + { scope: 'a', read: true, write: true, execute: true }, + { scope: 'b', read: false, write: true, execute: false } + ]; + expect(component.isHeaderChecked('read')).toBeFalsy(); + expect(component.isHeaderChecked('write')).toBeTruthy(); + expect(component.isHeaderChecked('execute')).toBeFalsy(); + }); +}); diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/checked-table-form/checked-table-form.component.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/checked-table-form/checked-table-form.component.ts new file mode 100644 index 00000000000..27ff4bbc650 --- /dev/null +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/checked-table-form/checked-table-form.component.ts @@ -0,0 +1,168 @@ +import { Component, Input, OnInit, TemplateRef, ViewChild } from '@angular/core'; +import { CdTableColumn } from '../../models/cd-table-column'; +import { CdFormGroup } from '../../forms/cd-form-group'; +import _ from 'lodash'; + +@Component({ + selector: 'cd-checked-table-form', + templateUrl: './checked-table-form.component.html', + styleUrls: ['./checked-table-form.component.scss'] +}) +export class CheckedTableFormComponent implements OnInit { + @Input() data: Array; + @Input() columns: CdTableColumn[]; + @Input() form: CdFormGroup; + @Input() inputField: string; + @Input() scopes: Array = []; + @Input() isTableForOctalMode = false; + @Input() initialValue: any = { + owner: ['read', 'write', 'execute'], + group: ['read', 'execute'], + others: ['read', 'execute'] + }; + + @ViewChild('headerPermissionCheckboxTpl', { static: true }) + headerPermissionCheckboxTpl: TemplateRef; + @ViewChild('cellScopeCheckboxTpl', { static: true }) + cellScopeCheckboxTpl: TemplateRef; + @ViewChild('cellPermissionCheckboxTpl', { static: true }) + cellPermissionCheckboxTpl: TemplateRef; + + constructor() {} + + ngOnInit(): void { + this.columns.forEach((column) => { + if (column.name === 'All') { + column.cellTemplate = this.cellScopeCheckboxTpl; + column.headerTemplate = this.headerPermissionCheckboxTpl; + } else { + column.cellTemplate = this.cellPermissionCheckboxTpl; + column.headerTemplate = this.headerPermissionCheckboxTpl; + } + }); + this.listenToChanges(); + this.form.get(this.inputField).setValue(this.initialValue); + } + + listenToChanges() { + // Create/Update the data which is used by the data table to display the + // scopes/permissions every time the form field value has been changed. + this.form.get(this.inputField).valueChanges.subscribe((value) => { + const scopesPermissions: any[] = []; + _.each(this.scopes, (scope) => { + // Set the defaults values. + const scopePermission: any = { read: false, write: false, execute: false }; + scopePermission['scope'] = scope; + // Apply settings from the given value if they exist. + if (scope in value) { + _.each(value[scope], (permission) => { + scopePermission[permission] = true; + }); + } + scopesPermissions.push(scopePermission); + }); + this.data = scopesPermissions; + }); + } + + /** + * Checks if the specified row checkbox needs to be rendered as checked. + * @param {string} scope The scope to be checked, e.g. 'cephfs', 'grafana', + * 'osd', 'pool' ... + * @return Returns true if all permissions (read, create, update, delete) + * are checked for the specified scope, otherwise false. + */ + isRowChecked(scope: string) { + const scope_permission = _.find(this.data, (o) => { + return o['scope'] === scope; + }); + if (_.isUndefined(scope_permission)) { + return false; + } + if (this.isTableForOctalMode) { + return scope_permission['read'] && scope_permission['write'] && scope_permission['execute']; + } + return ( + scope_permission['read'] && + scope_permission['create'] && + scope_permission['update'] && + scope_permission['delete'] + ); + } + + /** + * Checks if the specified header checkbox needs to be rendered as checked. + * @param {string} property The property/permission (read, create, + * update, delete) to be checked. If 'scope' is given, all permissions + * are checked. + * @return Returns true if specified property/permission is selected + * for all scopes, otherwise false. + */ + isHeaderChecked(property: string) { + let permissions = [property]; + if ('scope' === property && this.isTableForOctalMode) { + permissions = ['read', 'write', 'execute']; + } else if ('scope' === property) { + permissions = ['read', 'create', 'update', 'delete']; + } + return permissions.every((permission) => { + return this.data.every((scope_permission) => { + return scope_permission[permission]; + }); + }); + } + + onClickCellCheckbox(scope: string, property: string, event: any = null) { + // Use a copy of the form field data to do not trigger the redrawing of the + // data table with every change. + const scopes_permissions = _.cloneDeep(this.form.getValue(this.inputField)); + let permissions = [property]; + if ('scope' === property && this.isTableForOctalMode) { + permissions = ['read', 'write', 'execute']; + } else if ('scope' === property) { + permissions = ['read', 'create', 'update', 'delete']; + } + if (!(scope in scopes_permissions)) { + scopes_permissions[scope] = []; + } + // Add or remove the given permission(s) depending on the click event or if no + // click event is given then add/remove them if they are absent/exist. + if ( + (event && event.target['checked']) || + !_.isEqual(permissions.sort(), _.intersection(scopes_permissions[scope], permissions).sort()) + ) { + scopes_permissions[scope] = _.union(scopes_permissions[scope], permissions); + } else { + scopes_permissions[scope] = _.difference(scopes_permissions[scope], permissions); + if (_.isEmpty(scopes_permissions[scope])) { + _.unset(scopes_permissions, scope); + } + } + this.form.get(this.inputField).setValue(scopes_permissions); + } + + onClickHeaderCheckbox(property: string, event: any) { + // Use a copy of the form field data to do not trigger the redrawing of the + // data table with every change. + const scopes_permissions = _.cloneDeep(this.form.getValue(this.inputField)); + let permissions = [property]; + if ('scope' === property && this.isTableForOctalMode) { + permissions = ['read', 'write', 'execute']; + } else if ('scope' === property) { + permissions = ['read', 'create', 'update', 'delete']; + } + _.each(permissions, (permission) => { + _.each(this.scopes, (scope) => { + if (event.target['checked']) { + scopes_permissions[scope] = _.union(scopes_permissions[scope], [permission]); + } else { + scopes_permissions[scope] = _.difference(scopes_permissions[scope], [permission]); + if (_.isEmpty(scopes_permissions[scope])) { + _.unset(scopes_permissions, scope); + } + } + }); + }); + this.form.get(this.inputField).setValue(scopes_permissions); + } +} diff --git a/src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/datatable.module.ts b/src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/datatable.module.ts index 71c5d8f72e1..37e94f236be 100644 --- a/src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/datatable.module.ts +++ b/src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/datatable.module.ts @@ -24,6 +24,7 @@ import { FormlyTextareaTypeComponent } from '../forms/crud-form/formly-textarea- import { FormlyInputWrapperComponent } from '../forms/crud-form/formly-input-wrapper/formly-input-wrapper.component'; import { FormlyFileTypeComponent } from '../forms/crud-form/formly-file-type/formly-file-type.component'; import { FormlyFileValueAccessorDirective } from '../forms/crud-form/formly-file-type/formly-file-type-accessor'; +import { CheckedTableFormComponent } from './checked-table-form/checked-table-form.component'; @NgModule({ imports: [ @@ -78,7 +79,8 @@ import { FormlyFileValueAccessorDirective } from '../forms/crud-form/formly-file FormlyObjectTypeComponent, FormlyInputWrapperComponent, FormlyFileTypeComponent, - FormlyFileValueAccessorDirective + FormlyFileValueAccessorDirective, + CheckedTableFormComponent ], exports: [ TableComponent, @@ -86,7 +88,8 @@ import { FormlyFileValueAccessorDirective } from '../forms/crud-form/formly-file TableKeyValueComponent, TableActionsComponent, CRUDTableComponent, - TablePaginationComponent + TablePaginationComponent, + CheckedTableFormComponent ] }) export class DataTableModule {}