From 5230e1642aa8adddedbac08b12999ac8a9d8eff9 Mon Sep 17 00:00:00 2001 From: RehanY147 Date: Tue, 19 Dec 2023 22:14:48 +0500 Subject: [PATCH] NAS-125354 / 24.04 / Added ixRequiresRoles directive (#9340) --- .../common/common-directives.module.ts | 10 ++++ .../requires-roles-wrapper.component.scss | 20 ++++++++ .../requires-roles-wrapper.component.ts | 15 ++++++ .../requires-roles.directive.ts | 47 +++++++++++++++++++ .../icon-action-config.interface.ts | 2 + .../ix-cell-actions.component.html | 42 +++++++++++++---- .../ix-cell-actions.component.ts | 2 + src/app/modules/ix-table2/ix-table2.module.ts | 2 + .../docker-images-list.component.html | 1 + .../docker-images-list.component.spec.ts | 2 + .../docker-images-list.component.ts | 2 + .../nfs-card/nfs-card.component.spec.ts | 2 + .../nfs-card/nfs-card.component.ts | 2 + .../nfs/nfs-form/nfs-form.component.html | 1 + .../nfs/nfs-form/nfs-form.component.spec.ts | 2 + .../nfs/nfs-form/nfs-form.component.ts | 3 ++ src/assets/i18n/af.json | 1 + src/assets/i18n/ar.json | 1 + src/assets/i18n/ast.json | 1 + src/assets/i18n/az.json | 1 + src/assets/i18n/be.json | 1 + src/assets/i18n/bg.json | 1 + src/assets/i18n/bn.json | 1 + src/assets/i18n/br.json | 1 + src/assets/i18n/bs.json | 1 + src/assets/i18n/ca.json | 1 + src/assets/i18n/cs.json | 1 + src/assets/i18n/cy.json | 1 + src/assets/i18n/da.json | 1 + src/assets/i18n/de.json | 1 + src/assets/i18n/dsb.json | 1 + src/assets/i18n/el.json | 1 + src/assets/i18n/en-au.json | 1 + src/assets/i18n/en-gb.json | 1 + src/assets/i18n/en.json | 1 + src/assets/i18n/eo.json | 1 + src/assets/i18n/es-ar.json | 1 + src/assets/i18n/es-co.json | 1 + src/assets/i18n/es-mx.json | 1 + src/assets/i18n/es-ni.json | 1 + src/assets/i18n/es-ve.json | 1 + src/assets/i18n/es.json | 1 + src/assets/i18n/et.json | 1 + src/assets/i18n/eu.json | 1 + src/assets/i18n/fa.json | 1 + src/assets/i18n/fi.json | 1 + src/assets/i18n/fr.json | 1 + src/assets/i18n/fy.json | 1 + src/assets/i18n/ga.json | 1 + src/assets/i18n/gd.json | 1 + src/assets/i18n/gl.json | 1 + src/assets/i18n/he.json | 1 + src/assets/i18n/hi.json | 1 + src/assets/i18n/hr.json | 1 + src/assets/i18n/hsb.json | 1 + src/assets/i18n/hu.json | 1 + src/assets/i18n/ia.json | 1 + src/assets/i18n/id.json | 1 + src/assets/i18n/io.json | 1 + src/assets/i18n/is.json | 1 + src/assets/i18n/it.json | 1 + src/assets/i18n/ja.json | 1 + src/assets/i18n/ka.json | 1 + src/assets/i18n/kk.json | 1 + src/assets/i18n/km.json | 1 + src/assets/i18n/kn.json | 1 + src/assets/i18n/ko.json | 1 + src/assets/i18n/lb.json | 1 + src/assets/i18n/lt.json | 1 + src/assets/i18n/lv.json | 1 + src/assets/i18n/mk.json | 1 + src/assets/i18n/ml.json | 1 + src/assets/i18n/mn.json | 1 + src/assets/i18n/mr.json | 1 + src/assets/i18n/my.json | 1 + src/assets/i18n/nb.json | 1 + src/assets/i18n/ne.json | 1 + src/assets/i18n/nl.json | 1 + src/assets/i18n/nn.json | 1 + src/assets/i18n/os.json | 1 + src/assets/i18n/pa.json | 1 + src/assets/i18n/pl.json | 1 + src/assets/i18n/pt-br.json | 1 + src/assets/i18n/pt.json | 1 + src/assets/i18n/ro.json | 1 + src/assets/i18n/ru.json | 1 + src/assets/i18n/sk.json | 1 + src/assets/i18n/sl.json | 1 + src/assets/i18n/sq.json | 1 + src/assets/i18n/sr-latn.json | 1 + src/assets/i18n/sr.json | 1 + src/assets/i18n/strings.json | 1 + src/assets/i18n/sv.json | 1 + src/assets/i18n/sw.json | 1 + src/assets/i18n/ta.json | 1 + src/assets/i18n/te.json | 1 + src/assets/i18n/th.json | 1 + src/assets/i18n/tr.json | 1 + src/assets/i18n/tt.json | 1 + src/assets/i18n/udm.json | 1 + src/assets/i18n/uk.json | 1 + src/assets/i18n/vi.json | 1 + src/assets/i18n/zh-hans.json | 1 + src/assets/i18n/zh-hant.json | 1 + 104 files changed, 233 insertions(+), 10 deletions(-) create mode 100644 src/app/directives/common/requires-roles/requires-roles-wrapper.component.scss create mode 100644 src/app/directives/common/requires-roles/requires-roles-wrapper.component.ts create mode 100644 src/app/directives/common/requires-roles/requires-roles.directive.ts diff --git a/src/app/directives/common/common-directives.module.ts b/src/app/directives/common/common-directives.module.ts index ac935ca4f9c..7d4d711894e 100644 --- a/src/app/directives/common/common-directives.module.ts +++ b/src/app/directives/common/common-directives.module.ts @@ -1,19 +1,27 @@ import { CommonModule } from '@angular/common'; import { NgModule } from '@angular/core'; +import { MatTooltipModule } from '@angular/material/tooltip'; +import { TranslateModule } from '@ngx-translate/core'; import { AutofocusDirective } from 'app/directives/common/autofocus/autofocus.directive'; import { HasRoleDirective } from 'app/directives/common/has-role/has-role.directive'; import { IfNightlyDirective } from 'app/directives/common/if-nightly/if-nightly.directive'; +import { RequiresRolesWrapperComponent } from 'app/directives/common/requires-roles/requires-roles-wrapper.component'; +import { RequiresRolesDirective } from 'app/directives/common/requires-roles/requires-roles.directive'; import { StepActivationDirective } from 'app/directives/common/step-activation.directive'; import { LetDirective } from './app-let.directive'; @NgModule({ imports: [ CommonModule, + MatTooltipModule, + TranslateModule, ], declarations: [ LetDirective, IfNightlyDirective, HasRoleDirective, + RequiresRolesWrapperComponent, + RequiresRolesDirective, AutofocusDirective, StepActivationDirective, ], @@ -21,6 +29,8 @@ import { LetDirective } from './app-let.directive'; LetDirective, IfNightlyDirective, HasRoleDirective, + RequiresRolesWrapperComponent, + RequiresRolesDirective, AutofocusDirective, StepActivationDirective, ], diff --git a/src/app/directives/common/requires-roles/requires-roles-wrapper.component.scss b/src/app/directives/common/requires-roles/requires-roles-wrapper.component.scss new file mode 100644 index 00000000000..149ed6d176c --- /dev/null +++ b/src/app/directives/common/requires-roles/requires-roles-wrapper.component.scss @@ -0,0 +1,20 @@ + +:host ::ng-deep .role-missing { + button { + cursor: none; + pointer-events: none; + } + + .mat-mdc-button, + .mdc-button { + margin-right: 8px; + } + + .mdc-button__label, + .mat-icon, + .mat-mdc-menu-item-text { + opacity: 0.5; + text-decoration: line-through; + } +} + diff --git a/src/app/directives/common/requires-roles/requires-roles-wrapper.component.ts b/src/app/directives/common/requires-roles/requires-roles-wrapper.component.ts new file mode 100644 index 00000000000..3ae24bf23b3 --- /dev/null +++ b/src/app/directives/common/requires-roles/requires-roles-wrapper.component.ts @@ -0,0 +1,15 @@ +import { Component, Input, TemplateRef } from '@angular/core'; + +@Component({ + selector: 'ix-requires-roles-wrapper', + template: ` + + + +`, + styleUrls: ['./requires-roles-wrapper.component.scss'], +}) +export class RequiresRolesWrapperComponent { + @Input() template: TemplateRef; + @Input() class: string; +} diff --git a/src/app/directives/common/requires-roles/requires-roles.directive.ts b/src/app/directives/common/requires-roles/requires-roles.directive.ts new file mode 100644 index 00000000000..004ae93c367 --- /dev/null +++ b/src/app/directives/common/requires-roles/requires-roles.directive.ts @@ -0,0 +1,47 @@ +import { + ComponentRef, Directive, HostBinding, Input, TemplateRef, ViewContainerRef, +} from '@angular/core'; +import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy'; +import { RequiresRolesWrapperComponent } from 'app/directives/common/requires-roles/requires-roles-wrapper.component'; +import { Role } from 'app/enums/role.enum'; +import { AuthService } from 'app/services/auth/auth.service'; + +@UntilDestroy() +@Directive({ + selector: '[ixRequiresRoles]', +}) +export class RequiresRolesDirective { + private wrapperContainer: ComponentRef; + + @Input() + set ixRequiresRoles(roles: Role[]) { + this.authService.hasRole(roles).pipe(untilDestroyed(this)).subscribe({ + next: (hasRole) => { + if (!hasRole) { + this.wrapperContainer = this.viewContainerRef.createComponent(RequiresRolesWrapperComponent); + this.wrapperContainer.instance.template = this.templateRef; + this.wrapperContainer.instance.class = this.elementClass; + } else { + this.viewContainerRef.createEmbeddedView(this.templateRef); + } + }, + }); + } + + protected cssClassList: string[] = []; + + @Input('class') + @HostBinding('class') + get elementClass(): string { + return this.cssClassList.join(' '); + } + set(val: string): void { + this.cssClassList = val.split(' '); + } + + constructor( + private templateRef: TemplateRef, + private viewContainerRef: ViewContainerRef, + private authService: AuthService, + ) { } +} diff --git a/src/app/modules/ix-table2/components/ix-table-body/cells/ix-cell-actions/icon-action-config.interface.ts b/src/app/modules/ix-table2/components/ix-table-body/cells/ix-cell-actions/icon-action-config.interface.ts index 45c38fff4f3..81063dc8ef4 100644 --- a/src/app/modules/ix-table2/components/ix-table-body/cells/ix-cell-actions/icon-action-config.interface.ts +++ b/src/app/modules/ix-table2/components/ix-table-body/cells/ix-cell-actions/icon-action-config.interface.ts @@ -1,4 +1,5 @@ import { Observable } from 'rxjs'; +import { Role } from 'app/enums/role.enum'; export interface IconActionConfig { iconName: string; @@ -7,4 +8,5 @@ export interface IconActionConfig { dynamicTooltip?: (row: T) => Observable; hidden?: (row: T) => Observable; disabled?: (row: T) => Observable; + requiresRoles?: Role[]; } diff --git a/src/app/modules/ix-table2/components/ix-table-body/cells/ix-cell-actions/ix-cell-actions.component.html b/src/app/modules/ix-table2/components/ix-table-body/cells/ix-cell-actions/ix-cell-actions.component.html index 578aae8d10f..e443ff18d28 100644 --- a/src/app/modules/ix-table2/components/ix-table-body/cells/ix-cell-actions/ix-cell-actions.component.html +++ b/src/app/modules/ix-table2/components/ix-table-body/cells/ix-cell-actions/ix-cell-actions.component.html @@ -2,16 +2,38 @@ -
- -
+ + +
+ + +
+ +
+
+ diff --git a/src/app/modules/ix-table2/components/ix-table-body/cells/ix-cell-actions/ix-cell-actions.component.ts b/src/app/modules/ix-table2/components/ix-table-body/cells/ix-cell-actions/ix-cell-actions.component.ts index 5eb9e26e826..5ca2c2e465b 100644 --- a/src/app/modules/ix-table2/components/ix-table-body/cells/ix-cell-actions/ix-cell-actions.component.ts +++ b/src/app/modules/ix-table2/components/ix-table-body/cells/ix-cell-actions/ix-cell-actions.component.ts @@ -1,4 +1,5 @@ import { ChangeDetectionStrategy, Component } from '@angular/core'; +import { Role } from 'app/enums/role.enum'; import { IconActionConfig } from 'app/modules/ix-table2/components/ix-table-body/cells/ix-cell-actions/icon-action-config.interface'; import { Column, ColumnComponent } from 'app/modules/ix-table2/interfaces/table-column.interface'; @@ -10,6 +11,7 @@ import { Column, ColumnComponent } from 'app/modules/ix-table2/interfaces/table- }) export class IxCellActionsComponent extends ColumnComponent { actions: IconActionConfig[]; + Role = Role; } export function actionsColumn( diff --git a/src/app/modules/ix-table2/ix-table2.module.ts b/src/app/modules/ix-table2/ix-table2.module.ts index 63dd6cb5b18..da643f92f20 100644 --- a/src/app/modules/ix-table2/ix-table2.module.ts +++ b/src/app/modules/ix-table2/ix-table2.module.ts @@ -12,6 +12,7 @@ import { TranslateModule } from '@ngx-translate/core'; import { NgxFilesizeModule } from 'ngx-filesize'; import { CoreComponents } from 'app/core/core-components.module'; import { FormatDateTimePipe } from 'app/core/pipes/format-datetime.pipe'; +import { CommonDirectivesModule } from 'app/directives/common/common-directives.module'; import { IxIconModule } from 'app/modules/ix-icon/ix-icon.module'; import { IxTable2EmptyRowComponent } from 'app/modules/ix-table2/components/ix-empty-row/ix-empty-row.component'; import { IxCellActionsComponent } from 'app/modules/ix-table2/components/ix-table-body/cells/ix-cell-actions/ix-cell-actions.component'; @@ -53,6 +54,7 @@ import { IxTableColumnsSelectorComponent } from './components/ix-table-columns-s MatSlideToggleModule, TranslateModule, NgxFilesizeModule, + CommonDirectivesModule, TestIdModule, CoreComponents, MatMenuModule, diff --git a/src/app/pages/apps/components/docker-images/docker-images-list/docker-images-list.component.html b/src/app/pages/apps/components/docker-images/docker-images-list/docker-images-list.component.html index 7f8a83897be..cd12297ea6e 100644 --- a/src/app/pages/apps/components/docker-images/docker-images-list/docker-images-list.component.html +++ b/src/app/pages/apps/components/docker-images/docker-images-list/docker-images-list.component.html @@ -109,6 +109,7 @@ {{ image.update_available ? ('Update available' | translate) : ('Up to date' | translate) }}