1 import { Component, Input, OnInit, TemplateRef, ViewChild } from '@angular/core';
2 import { CdTableColumn } from '../../models/cd-table-column';
3 import { CdFormGroup } from '../../forms/cd-form-group';
4 import _ from 'lodash';
7 selector: 'cd-checked-table-form',
8 templateUrl: './checked-table-form.component.html',
9 styleUrls: ['./checked-table-form.component.scss']
11 export class CheckedTableFormComponent implements OnInit {
12 @Input() data: Array<any>;
13 @Input() columns: CdTableColumn[];
14 @Input() form: CdFormGroup;
15 @Input() inputField: string;
16 @Input() scopes: Array<string> = [];
17 @Input() isTableForOctalMode = false;
18 @Input() initialValue: any = {
19 owner: ['read', 'write', 'execute'],
20 group: ['read', 'execute'],
21 others: ['read', 'execute']
24 @ViewChild('headerPermissionCheckboxTpl', { static: true })
25 headerPermissionCheckboxTpl: TemplateRef<any>;
26 @ViewChild('cellScopeCheckboxTpl', { static: true })
27 cellScopeCheckboxTpl: TemplateRef<any>;
28 @ViewChild('cellPermissionCheckboxTpl', { static: true })
29 cellPermissionCheckboxTpl: TemplateRef<any>;
34 this.columns.forEach((column) => {
35 if (column.name === 'All') {
36 column.cellTemplate = this.cellScopeCheckboxTpl;
37 column.headerTemplate = this.headerPermissionCheckboxTpl;
39 column.cellTemplate = this.cellPermissionCheckboxTpl;
40 column.headerTemplate = this.headerPermissionCheckboxTpl;
43 this.listenToChanges();
44 this.form.get(this.inputField).setValue(this.initialValue);
48 // Create/Update the data which is used by the data table to display the
49 // scopes/permissions every time the form field value has been changed.
50 this.form.get(this.inputField).valueChanges.subscribe((value) => {
51 const scopesPermissions: any[] = [];
52 _.each(this.scopes, (scope) => {
53 // Set the defaults values.
54 const scopePermission: any = { read: false, write: false, execute: false };
55 scopePermission['scope'] = scope;
56 // Apply settings from the given value if they exist.
58 _.each(value[scope], (permission) => {
59 scopePermission[permission] = true;
62 scopesPermissions.push(scopePermission);
64 this.data = scopesPermissions;
69 * Checks if the specified row checkbox needs to be rendered as checked.
70 * @param {string} scope The scope to be checked, e.g. 'cephfs', 'grafana',
72 * @return Returns true if all permissions (read, create, update, delete)
73 * are checked for the specified scope, otherwise false.
75 isRowChecked(scope: string) {
76 const scope_permission = _.find(this.data, (o) => {
77 return o['scope'] === scope;
79 if (_.isUndefined(scope_permission)) {
82 if (this.isTableForOctalMode) {
83 return scope_permission['read'] && scope_permission['write'] && scope_permission['execute'];
86 scope_permission['read'] &&
87 scope_permission['create'] &&
88 scope_permission['update'] &&
89 scope_permission['delete']
94 * Checks if the specified header checkbox needs to be rendered as checked.
95 * @param {string} property The property/permission (read, create,
96 * update, delete) to be checked. If 'scope' is given, all permissions
98 * @return Returns true if specified property/permission is selected
99 * for all scopes, otherwise false.
101 isHeaderChecked(property: string) {
102 let permissions = [property];
103 if ('scope' === property && this.isTableForOctalMode) {
104 permissions = ['read', 'write', 'execute'];
105 } else if ('scope' === property) {
106 permissions = ['read', 'create', 'update', 'delete'];
108 return permissions.every((permission) => {
109 return this.data.every((scope_permission) => {
110 return scope_permission[permission];
115 onClickCellCheckbox(scope: string, property: string, event: any = null) {
116 // Use a copy of the form field data to do not trigger the redrawing of the
117 // data table with every change.
118 const scopes_permissions = _.cloneDeep(this.form.getValue(this.inputField));
119 let permissions = [property];
120 if ('scope' === property && this.isTableForOctalMode) {
121 permissions = ['read', 'write', 'execute'];
122 } else if ('scope' === property) {
123 permissions = ['read', 'create', 'update', 'delete'];
125 if (!(scope in scopes_permissions)) {
126 scopes_permissions[scope] = [];
128 // Add or remove the given permission(s) depending on the click event or if no
129 // click event is given then add/remove them if they are absent/exist.
131 (event && event.target['checked']) ||
132 !_.isEqual(permissions.sort(), _.intersection(scopes_permissions[scope], permissions).sort())
134 scopes_permissions[scope] = _.union(scopes_permissions[scope], permissions);
136 scopes_permissions[scope] = _.difference(scopes_permissions[scope], permissions);
137 if (_.isEmpty(scopes_permissions[scope])) {
138 _.unset(scopes_permissions, scope);
141 this.form.get(this.inputField).setValue(scopes_permissions);
144 onClickHeaderCheckbox(property: string, event: any) {
145 // Use a copy of the form field data to do not trigger the redrawing of the
146 // data table with every change.
147 const scopes_permissions = _.cloneDeep(this.form.getValue(this.inputField));
148 let permissions = [property];
149 if ('scope' === property && this.isTableForOctalMode) {
150 permissions = ['read', 'write', 'execute'];
151 } else if ('scope' === property) {
152 permissions = ['read', 'create', 'update', 'delete'];
154 _.each(permissions, (permission) => {
155 _.each(this.scopes, (scope) => {
156 if (event.target['checked']) {
157 scopes_permissions[scope] = _.union(scopes_permissions[scope], [permission]);
159 scopes_permissions[scope] = _.difference(scopes_permissions[scope], [permission]);
160 if (_.isEmpty(scopes_permissions[scope])) {
161 _.unset(scopes_permissions, scope);
166 this.form.get(this.inputField).setValue(scopes_permissions);