diff --git a/console-webapp/src/app/app.module.ts b/console-webapp/src/app/app.module.ts index a649475e1..50776868b 100644 --- a/console-webapp/src/app/app.module.ts +++ b/console-webapp/src/app/app.module.ts @@ -46,6 +46,7 @@ import WhoisEditComponent from './settings/whois/whoisEdit.component'; import { NotificationsComponent } from './shared/components/notifications/notifications.component'; import { SelectedRegistrarWrapper } from './shared/components/selectedRegistrarWrapper/selectedRegistrarWrapper.component'; import { LocationBackDirective } from './shared/directives/locationBack.directive'; +import { UserLevelVisibility } from './shared/directives/userLevelVisiblity.directive'; import { BreakPointObserverService } from './shared/services/breakPoint.service'; import { GlobalLoaderService } from './shared/services/globalLoader.service'; import { UserDataService } from './shared/services/userData.service'; @@ -63,6 +64,7 @@ import { TldsComponent } from './tlds/tlds.component'; HeaderComponent, HomeComponent, LocationBackDirective, + UserLevelVisibility, NavigationComponent, NewRegistrarComponent, NotificationsComponent, diff --git a/console-webapp/src/app/navigation/navigation.component.html b/console-webapp/src/app/navigation/navigation.component.html index c157c42f9..59582655c 100644 --- a/console-webapp/src/app/navigation/navigation.component.html +++ b/console-webapp/src/app/navigation/navigation.component.html @@ -8,6 +8,7 @@ matTreeNodeToggle (click)="onClick(node)" [class.active]="router.url.includes(node.path)" + [elementId]="getElementId(node)" > {{ node.iconName }} diff --git a/console-webapp/src/app/navigation/navigation.component.ts b/console-webapp/src/app/navigation/navigation.component.ts index 55f7938e8..65601f6cb 100644 --- a/console-webapp/src/app/navigation/navigation.component.ts +++ b/console-webapp/src/app/navigation/navigation.component.ts @@ -18,6 +18,7 @@ import { MatTreeNestedDataSource } from '@angular/material/tree'; import { NavigationEnd, Router } from '@angular/router'; import { Subscription } from 'rxjs'; import { RouteWithIcon, routes } from '../app-routing.module'; +import { RESTRICTED_ELEMENTS } from '../shared/directives/userLevelVisiblity.directive'; interface NavMenuNode extends RouteWithIcon { parentRoute?: RouteWithIcon; @@ -37,6 +38,7 @@ export class NavigationComponent { treeControl = new NestedTreeControl((node) => node.children); dataSource = new MatTreeNestedDataSource(); private subscription!: Subscription; + hasChild = (_: number, node: RouteWithIcon) => !!node.children && node.children.length > 0; @@ -56,6 +58,12 @@ export class NavigationComponent { this.subscription.unsubscribe(); } + getElementId(node: RouteWithIcon) { + return node.path === 'registrars' + ? RESTRICTED_ELEMENTS.REGISTRAR_ELEMENT + : null; + } + syncExpandedNavigationWithRoute(url: string) { const maybeComponentWithChildren = this.dataSource.data.find((menuNode) => { return ( diff --git a/console-webapp/src/app/shared/directives/userLevelVisiblity.directive.ts b/console-webapp/src/app/shared/directives/userLevelVisiblity.directive.ts new file mode 100644 index 000000000..db3948cbd --- /dev/null +++ b/console-webapp/src/app/shared/directives/userLevelVisiblity.directive.ts @@ -0,0 +1,54 @@ +// Copyright 2024 The Nomulus Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { Directive, ElementRef, Input, OnChanges } from '@angular/core'; +import { UserDataService } from '../services/userData.service'; + +export enum RESTRICTED_ELEMENTS { + REGISTRAR_ELEMENT, +} + +export const DISABLED_ELEMENTS_PER_ROLE = { + NONE: [RESTRICTED_ELEMENTS.REGISTRAR_ELEMENT], +}; + +@Directive({ + selector: '[elementId]', +}) +export class UserLevelVisibility implements OnChanges { + @Input() elementId!: RESTRICTED_ELEMENTS | null; + + constructor( + private userDataService: UserDataService, + private el: ElementRef + ) {} + + ngOnChanges() { + this.processElement(); + } + + processElement() { + if (this.elementId === null) { + return; + } + + const globalRole = this.userDataService?.userData?.globalRole || 'NONE'; + if ( + // @ts-ignore + (DISABLED_ELEMENTS_PER_ROLE[globalRole] || []).includes(this.elementId) + ) { + this.el.nativeElement.style.display = 'none'; + } + } +}