From 59073957908ccbcdbca93cd11cce1e01e32b5366 Mon Sep 17 00:00:00 2001 From: Dmitriy Borzenko Date: Mon, 23 Sep 2024 18:52:27 +0300 Subject: [PATCH 1/9] added prototype for view service --- .../settings/account-settings.component.html | 10 ++++++ .../settings/account-settings.component.scss | 16 +++++++++ .../settings/account-settings.component.ts | 20 +++++++++++ src/app/common/app.values.ts | 2 ++ .../dataset-view-menu.component.html | 2 +- .../dataset-view-menu.component.ts | 13 +++++-- src/app/dataset-view/dataset.component.ts | 10 +++--- .../services/elements-view.service.spec.ts | 16 +++++++++ src/app/services/elements-view.service.ts | 35 +++++++++++++++++++ src/app/services/local-storage.service.ts | 11 ++++++ 10 files changed, 127 insertions(+), 8 deletions(-) create mode 100644 src/app/services/elements-view.service.spec.ts create mode 100644 src/app/services/elements-view.service.ts diff --git a/src/app/auth/settings/account-settings.component.html b/src/app/auth/settings/account-settings.component.html index eac7ba5e3..864732724 100644 --- a/src/app/auth/settings/account-settings.component.html +++ b/src/app/auth/settings/account-settings.component.html @@ -23,6 +23,16 @@ +
+ + Admin priveleges + +
>; + public adminPrivelegesOn: boolean = false; private router = inject(Router); private route = inject(ActivatedRoute); private loggedUserService = inject(LoggedUserService); + private localStorageService = inject(LocalStorageService); public ngOnInit(): void { + this.initAdminSlideToggle(); this.router.events .pipe( filter((event) => event instanceof NavigationEnd), @@ -46,6 +51,14 @@ export class AccountSettingsComponent extends BaseComponent implements OnInit { return `/${ProjectLinks.URL_SETTINGS}/${tab}`; } + public isAdmin(): boolean { + return this.loggedUserService.isAdmin; + } + + public adminSlideToggleChange(event: MatSlideToggleChange): void { + this.localStorageService.setAdminPriveleges(event.checked); + } + private extractActiveTabFromRoute(): void { const categoryParam: MaybeUndefined = this.route.snapshot.params[ ProjectLinks.URL_PARAM_CATEGORY @@ -61,4 +74,11 @@ export class AccountSettingsComponent extends BaseComponent implements OnInit { this.activeTab = AccountSettingsTabs.PROFILE; } + + private initAdminSlideToggle(): void { + const flag = this.localStorageService.adminPriveleges; + if (flag) { + this.adminPrivelegesOn = flag; + } + } } diff --git a/src/app/common/app.values.ts b/src/app/common/app.values.ts index baefba99c..ef0e6517d 100644 --- a/src/app/common/app.values.ts +++ b/src/app/common/app.values.ts @@ -7,6 +7,8 @@ export default class AppValues { public static readonly LOCAL_STORAGE_LOGIN_CALLBACK_URL = "login_callback_url"; public static readonly LOCAL_STORAGE_LOGIN_REDIRECT_URL = "login_redirect_url"; public static readonly LOCAL_STORAGE_ACCOUNT_ID = "account_id"; + public static readonly LOCAL_STORAGE_ADMIN_PRIVELEGES = "admin_priveleges"; + public static readonly SESSION_STORAGE_SIDE_PANEL_VISIBLE = "side_panel_visible"; public static readonly DEFAULT_USER_DISPLAY_NAME = "anonymous"; public static readonly DEFAULT_AVATAR_URL = "https://avatars.githubusercontent.com/u/11951648?v=4"; diff --git a/src/app/dataset-view/dataset-view-menu/dataset-view-menu.component.html b/src/app/dataset-view/dataset-view-menu/dataset-view-menu.component.html index 2ab71dc90..8e5b34796 100644 --- a/src/app/dataset-view/dataset-view-menu/dataset-view-menu.component.html +++ b/src/app/dataset-view/dataset-view-menu/dataset-view-menu.component.html @@ -72,7 +72,7 @@ data-test-id="navigateToFlows" value="flows" [class.active-link]="isDatasetViewTypeFlows" - *ngIf="shouldAllowSettingsTab" + *ngIf="shouldAllowFlowsTab" >
diff --git a/src/app/dataset-view/dataset-view-menu/dataset-view-menu.component.ts b/src/app/dataset-view/dataset-view-menu/dataset-view-menu.component.ts index 4f5f08420..bcccd71a6 100644 --- a/src/app/dataset-view/dataset-view-menu/dataset-view-menu.component.ts +++ b/src/app/dataset-view/dataset-view-menu/dataset-view-menu.component.ts @@ -15,7 +15,7 @@ import { DatasetViewTypeEnum } from "../dataset-view.interface"; import { SideNavHelper } from "../../common/sidenav.helper"; import { isMobileView, promiseWithCatch } from "src/app/common/app.helpers"; import { DatasetBasicsFragment, DatasetPermissionsFragment } from "src/app/api/kamu.graphql.interface"; -import { DatasetPermissionsService } from "../dataset.permissions.service"; +import { ElementsViewService, EnumViewActions } from "src/app/services/elements-view.service"; @Component({ selector: "app-dataset-view-menu", @@ -36,7 +36,7 @@ export class DatasetViewMenuComponent implements OnInit, AfterViewInit { private sideNavHelper: SideNavHelper; - private datasetPermissionsServices = inject(DatasetPermissionsService); + private elementsViewService = inject(ElementsViewService); private widgetHeightService = inject(WidgetHeightService); public ngAfterViewInit(): void { @@ -85,7 +85,14 @@ export class DatasetViewMenuComponent implements OnInit, AfterViewInit { } public get shouldAllowSettingsTab(): boolean { - return this.datasetPermissionsServices.shouldAllowSettingsTab(this.datasetPermissions); + return this.elementsViewService.executeAction( + EnumViewActions.SHOW_SETTINGS_TAB_ACTION, + this.datasetPermissions, + ); + } + + public get shouldAllowFlowsTab(): boolean { + return this.elementsViewService.executeAction(EnumViewActions.SHOW_FLOWS_TAB_ACTION, this.datasetPermissions); } public get datasetLink(): string { diff --git a/src/app/dataset-view/dataset.component.ts b/src/app/dataset-view/dataset.component.ts index b9d74d416..e8c437555 100644 --- a/src/app/dataset-view/dataset.component.ts +++ b/src/app/dataset-view/dataset.component.ts @@ -9,12 +9,12 @@ import { DatasetInfo } from "../interface/navigation.interface"; import { promiseWithCatch } from "../common/app.helpers"; import { DatasetRequestBySql } from "../interface/dataset.interface"; import { MaybeNull, MaybeUndefined } from "../common/app.types"; -import { DatasetPermissionsService } from "./dataset.permissions.service"; import { ReplaySubject, Subject, of } from "rxjs"; import { LineageGraphNodeData, LineageGraphNodeKind } from "./additional-components/lineage-component/lineage-model"; import _ from "lodash"; import { BaseDatasetDataComponent } from "../common/base-dataset-data.component"; import { takeUntilDestroyed } from "@angular/core/rxjs-interop"; +import { ElementsViewService, EnumViewActions } from "../services/elements-view.service"; @Component({ selector: "app-dataset", @@ -30,9 +30,9 @@ export class DatasetComponent extends BaseDatasetDataComponent implements OnInit private mainDatasetQueryComplete$: Subject = new ReplaySubject(1 /* bufferSize */); - private datasetPermissionsServices = inject(DatasetPermissionsService); private router = inject(Router); private cdr = inject(ChangeDetectorRef); + private elementsViewService = inject(ElementsViewService); public ngOnInit(): void { const urlDatasetInfo = this.getDatasetInfoFromUrl(); @@ -123,7 +123,7 @@ export class DatasetComponent extends BaseDatasetDataComponent implements OnInit takeUntilDestroyed(this.destroyRef), ) .subscribe((datasetPermissions: DatasetPermissionsFragment) => { - if (this.datasetPermissionsServices.shouldAllowFlowsTab(datasetPermissions)) { + if (this.elementsViewService.executeAction(EnumViewActions.SHOW_FLOWS_TAB_ACTION, datasetPermissions)) { this.datasetViewType = DatasetViewTypeEnum.Flows; } else { this.datasetViewType = DatasetViewTypeEnum.Overview; @@ -197,7 +197,9 @@ export class DatasetComponent extends BaseDatasetDataComponent implements OnInit takeUntilDestroyed(this.destroyRef), ) .subscribe((datasetPermissions: DatasetPermissionsFragment) => { - if (this.datasetPermissionsServices.shouldAllowSettingsTab(datasetPermissions)) { + if ( + this.elementsViewService.executeAction(EnumViewActions.SHOW_SETTINGS_TAB_ACTION, datasetPermissions) + ) { this.datasetViewType = DatasetViewTypeEnum.Settings; } else { this.datasetViewType = DatasetViewTypeEnum.Overview; diff --git a/src/app/services/elements-view.service.spec.ts b/src/app/services/elements-view.service.spec.ts new file mode 100644 index 000000000..5c50b1dca --- /dev/null +++ b/src/app/services/elements-view.service.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { ElementsViewService } from './elements-view.service'; + +describe('ElementsViewService', () => { + let service: ElementsViewService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(ElementsViewService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/src/app/services/elements-view.service.ts b/src/app/services/elements-view.service.ts new file mode 100644 index 000000000..3ab2d6e03 --- /dev/null +++ b/src/app/services/elements-view.service.ts @@ -0,0 +1,35 @@ +import { LocalStorageService } from "src/app/services/local-storage.service"; +import { inject, Injectable } from "@angular/core"; +import { DatasetPermissionsFragment } from "../api/kamu.graphql.interface"; +import { LoggedUserService } from "../auth/logged-user.service"; +import { DatasetPermissionsService } from "../dataset-view/dataset.permissions.service"; + +@Injectable({ + providedIn: "root", +}) +export class ElementsViewService { + private loggedUserService = inject(LoggedUserService); + private datasetPermissionsService = inject(DatasetPermissionsService); + private localStorageService = inject(LocalStorageService); + + private get isAdminPrivelegesOn(): boolean { + return this.loggedUserService.isAdmin && (this.localStorageService.adminPriveleges ?? false); + } + + public executeAction(action: EnumViewActions, datasetPermissions: DatasetPermissionsFragment | null): boolean { + if (action === EnumViewActions.SHOW_FLOWS_TAB_ACTION && datasetPermissions) { + return this.isAdminPrivelegesOn || this.datasetPermissionsService.shouldAllowFlowsTab(datasetPermissions); + } + if (action === EnumViewActions.SHOW_SETTINGS_TAB_ACTION && datasetPermissions) { + return ( + this.isAdminPrivelegesOn || this.datasetPermissionsService.shouldAllowSettingsTab(datasetPermissions) + ); + } + return false; + } +} + +export enum EnumViewActions { + SHOW_FLOWS_TAB_ACTION = "showFlowsTabAction", + SHOW_SETTINGS_TAB_ACTION = "showSettingsTabAction", +} diff --git a/src/app/services/local-storage.service.ts b/src/app/services/local-storage.service.ts index 7c4eb908c..d98f9cc75 100644 --- a/src/app/services/local-storage.service.ts +++ b/src/app/services/local-storage.service.ts @@ -15,6 +15,17 @@ export class LocalStorageService { return localStorage.getItem(AppValues.LOCAL_STORAGE_LOGIN_REDIRECT_URL); } + public get adminPriveleges(): boolean | null { + const flag = localStorage.getItem(AppValues.LOCAL_STORAGE_ADMIN_PRIVELEGES); + if (flag) { + return Boolean(JSON.parse(flag)); + } else return null; + } + + public setAdminPriveleges(flag: boolean) { + localStorage.setItem(AppValues.LOCAL_STORAGE_ADMIN_PRIVELEGES, JSON.stringify(flag)); + } + public setRedirectAfterLoginUrl(url: string | null) { if (url) { localStorage.setItem(AppValues.LOCAL_STORAGE_LOGIN_REDIRECT_URL, url); From b2c408b6e86df28293b69d4c3f57bf5f4a26e9f8 Mon Sep 17 00:00:00 2001 From: Dmitriy Borzenko Date: Thu, 3 Oct 2024 17:33:13 +0300 Subject: [PATCH 2/9] added new solution for ElementViewService --- src/app/app.component.ts | 7 ++ src/app/auth/logged-user.service.ts | 11 ++- .../settings/account-settings.component.html | 16 ++--- .../settings/account-settings.component.ts | 35 ++++++---- .../dataset-view-menu.component.html | 68 ++++++++++++------- .../dataset-view-menu.component.scss | 7 ++ .../dataset-view-menu.component.ts | 17 ++--- src/app/dataset-view/dataset.component.ts | 10 +-- src/app/services/elements-view.service.ts | 50 ++++++++------ 9 files changed, 135 insertions(+), 86 deletions(-) diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 047a3c7c4..a9980b564 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -91,6 +91,13 @@ export class AppComponent extends BaseComponent implements OnInit { this.loggedAccount = user ? _.cloneDeep(user) : AppComponent.ANONYMOUS_ACCOUNT_INFO; this.cdr.detectChanges(); }); + + this.initAdminSlideToggle(); + } + + private initAdminSlideToggle(): void { + const flag = this.localStorageService.adminPriveleges; + this.loggedUserService.emitAdminPrivelegesChanges(Boolean(flag)); } private setMomentOptions(): void { diff --git a/src/app/auth/logged-user.service.ts b/src/app/auth/logged-user.service.ts index 1e2348068..ab05c023c 100644 --- a/src/app/auth/logged-user.service.ts +++ b/src/app/auth/logged-user.service.ts @@ -1,6 +1,6 @@ import { Injectable } from "@angular/core"; import { catchError, first } from "rxjs/operators"; -import { Observable, ReplaySubject, Subject, of } from "rxjs"; +import { BehaviorSubject, Observable, ReplaySubject, Subject, of } from "rxjs"; import { NavigationService } from "../services/navigation.service"; import { MaybeNull } from "../common/app.types"; import { isNull } from "lodash"; @@ -20,6 +20,7 @@ import { takeUntilDestroyed } from "@angular/core/rxjs-interop"; export class LoggedUserService extends UnsubscribeDestroyRefAdapter { private loggedInUser: MaybeNull = null; private loggedInUser$: Subject> = new ReplaySubject>(1); + private adminPriveleges$: BehaviorSubject = new BehaviorSubject(false); constructor( private loginService: LoginService, @@ -38,6 +39,14 @@ export class LoggedUserService extends UnsubscribeDestroyRefAdapter { .subscribe((user: AccountFragment) => this.changeUser(user)); } + public get adminPrivelegesChanges(): Observable { + return this.adminPriveleges$.asObservable(); + } + + public emitAdminPrivelegesChanges(value: boolean): void { + return this.adminPriveleges$.next(value); + } + public initializeCompletes(): Observable { const loginInstructions: AppConfigLoginInstructions | null = this.appConfigService.loginInstructions; if (loginInstructions) { diff --git a/src/app/auth/settings/account-settings.component.html b/src/app/auth/settings/account-settings.component.html index 864732724..f35de63c9 100644 --- a/src/app/auth/settings/account-settings.component.html +++ b/src/app/auth/settings/account-settings.component.html @@ -1,9 +1,9 @@ -
+
-
+
@@ -294,7 +294,7 @@
- +
diff --git a/src/app/auth/settings/account-settings.component.ts b/src/app/auth/settings/account-settings.component.ts index 36a350eba..a7b3ae321 100644 --- a/src/app/auth/settings/account-settings.component.ts +++ b/src/app/auth/settings/account-settings.component.ts @@ -3,11 +3,11 @@ import { AccountFragment } from "src/app/api/kamu.graphql.interface"; import { AccountSettingsTabs } from "./account-settings.constants"; import { ChangeDetectionStrategy, Component, inject, OnInit } from "@angular/core"; import { ActivatedRoute, NavigationEnd, Router } from "@angular/router"; -import { filter } from "rxjs/operators"; +import { filter, map } from "rxjs/operators"; import { BaseComponent } from "src/app/common/base.component"; import AppValues from "src/app/common/app.values"; import { MaybeNull, MaybeUndefined } from "src/app/common/app.types"; -import { Observable } from "rxjs"; +import { combineLatest, Observable } from "rxjs"; import { LoggedUserService } from "../logged-user.service"; import { takeUntilDestroyed } from "@angular/core/rxjs-interop"; import { MatSlideToggleChange } from "@angular/material/slide-toggle"; @@ -25,15 +25,19 @@ export class AccountSettingsComponent extends BaseComponent implements OnInit { public activeTab: AccountSettingsTabs = AccountSettingsTabs.PROFILE; public user$: Observable>; - public adminPrivelegesOn: boolean = false; + public adminPriveleges$: Observable; private router = inject(Router); private route = inject(ActivatedRoute); private loggedUserService = inject(LoggedUserService); private localStorageService = inject(LocalStorageService); + public componentData$: Observable<{ + user: MaybeNull; + adminPriveleges: boolean; + }>; + public ngOnInit(): void { - this.initAdminSlideToggle(); this.router.events .pipe( filter((event) => event instanceof NavigationEnd), @@ -44,18 +48,30 @@ export class AccountSettingsComponent extends BaseComponent implements OnInit { }); this.extractActiveTabFromRoute(); - this.user$ = this.loggedUserService.loggedInUserChanges; + + this.componentData$ = combineLatest([ + this.loggedUserService.loggedInUserChanges, + this.loggedUserService.adminPrivelegesChanges, + ]).pipe( + map(([user, adminPriveleges]) => { + return { + user, + adminPriveleges, + }; + }), + ); } public getRouteLink(tab: AccountSettingsTabs): string { return `/${ProjectLinks.URL_SETTINGS}/${tab}`; } - public isAdmin(): boolean { + public get isAdmin(): boolean { return this.loggedUserService.isAdmin; } public adminSlideToggleChange(event: MatSlideToggleChange): void { + this.loggedUserService.emitAdminPrivelegesChanges(event.checked); this.localStorageService.setAdminPriveleges(event.checked); } @@ -74,11 +90,4 @@ export class AccountSettingsComponent extends BaseComponent implements OnInit { this.activeTab = AccountSettingsTabs.PROFILE; } - - private initAdminSlideToggle(): void { - const flag = this.localStorageService.adminPriveleges; - if (flag) { - this.adminPrivelegesOn = flag; - } - } } diff --git a/src/app/dataset-view/dataset-view-menu/dataset-view-menu.component.html b/src/app/dataset-view/dataset-view-menu/dataset-view-menu.component.html index 8e5b34796..643195d13 100644 --- a/src/app/dataset-view/dataset-view-menu/dataset-view-menu.component.html +++ b/src/app/dataset-view/dataset-view-menu/dataset-view-menu.component.html @@ -68,32 +68,48 @@ Discussions
- - -
- add_task - Flows -
-
-
- - -
- - Settings -
-
-
+ + + +
+ add_task + Flows + + admin_panel_settings +
+
+
+ + +
+ + Settings + + admin_panel_settings +
+
+
+
diff --git a/src/app/dataset-view/dataset-view-menu/dataset-view-menu.component.scss b/src/app/dataset-view/dataset-view-menu/dataset-view-menu.component.scss index 43c6ca3ab..9deb247f4 100644 --- a/src/app/dataset-view/dataset-view-menu/dataset-view-menu.component.scss +++ b/src/app/dataset-view/dataset-view-menu/dataset-view-menu.component.scss @@ -2,3 +2,10 @@ height: inherit; border-radius: inherit; } + +.admin-icon { + position: relative; + font-size: 16px; + bottom: 5px; + color: #378bb0; +} diff --git a/src/app/dataset-view/dataset-view-menu/dataset-view-menu.component.ts b/src/app/dataset-view/dataset-view-menu/dataset-view-menu.component.ts index bcccd71a6..8e8758748 100644 --- a/src/app/dataset-view/dataset-view-menu/dataset-view-menu.component.ts +++ b/src/app/dataset-view/dataset-view-menu/dataset-view-menu.component.ts @@ -15,7 +15,8 @@ import { DatasetViewTypeEnum } from "../dataset-view.interface"; import { SideNavHelper } from "../../common/sidenav.helper"; import { isMobileView, promiseWithCatch } from "src/app/common/app.helpers"; import { DatasetBasicsFragment, DatasetPermissionsFragment } from "src/app/api/kamu.graphql.interface"; -import { ElementsViewService, EnumViewActions } from "src/app/services/elements-view.service"; +import { ElementsViewService, ViewModeElement } from "src/app/services/elements-view.service"; +import { Observable } from "rxjs"; @Component({ selector: "app-dataset-view-menu", @@ -38,6 +39,8 @@ export class DatasetViewMenuComponent implements OnInit, AfterViewInit { private elementsViewService = inject(ElementsViewService); private widgetHeightService = inject(WidgetHeightService); + public viewModeElement$: Observable; + public readonly ViewModeElement: typeof ViewModeElement = ViewModeElement; public ngAfterViewInit(): void { this.widgetHeightService.setWidgetOffsetTop( @@ -50,6 +53,7 @@ export class DatasetViewMenuComponent implements OnInit, AfterViewInit { if (this.sidenav) { this.sideNavHelper = new SideNavHelper(this.sidenav); } + this.viewModeElement$ = this.elementsViewService.viewModeElement(); } public get isDatasetViewTypeOverview(): boolean { @@ -84,17 +88,6 @@ export class DatasetViewMenuComponent implements OnInit, AfterViewInit { return this.datasetViewType === DatasetViewTypeEnum.Settings; } - public get shouldAllowSettingsTab(): boolean { - return this.elementsViewService.executeAction( - EnumViewActions.SHOW_SETTINGS_TAB_ACTION, - this.datasetPermissions, - ); - } - - public get shouldAllowFlowsTab(): boolean { - return this.elementsViewService.executeAction(EnumViewActions.SHOW_FLOWS_TAB_ACTION, this.datasetPermissions); - } - public get datasetLink(): string { return `/${this.datasetBasics.owner.accountName}/${this.datasetBasics.name}/`; } diff --git a/src/app/dataset-view/dataset.component.ts b/src/app/dataset-view/dataset.component.ts index e8c437555..10256d8bf 100644 --- a/src/app/dataset-view/dataset.component.ts +++ b/src/app/dataset-view/dataset.component.ts @@ -14,7 +14,8 @@ import { LineageGraphNodeData, LineageGraphNodeKind } from "./additional-compone import _ from "lodash"; import { BaseDatasetDataComponent } from "../common/base-dataset-data.component"; import { takeUntilDestroyed } from "@angular/core/rxjs-interop"; -import { ElementsViewService, EnumViewActions } from "../services/elements-view.service"; +import { ElementsViewService } from "../services/elements-view.service"; +import { DatasetPermissionsService } from "./dataset.permissions.service"; @Component({ selector: "app-dataset", @@ -30,6 +31,7 @@ export class DatasetComponent extends BaseDatasetDataComponent implements OnInit private mainDatasetQueryComplete$: Subject = new ReplaySubject(1 /* bufferSize */); + private datasetPermissionsServices = inject(DatasetPermissionsService); private router = inject(Router); private cdr = inject(ChangeDetectorRef); private elementsViewService = inject(ElementsViewService); @@ -123,7 +125,7 @@ export class DatasetComponent extends BaseDatasetDataComponent implements OnInit takeUntilDestroyed(this.destroyRef), ) .subscribe((datasetPermissions: DatasetPermissionsFragment) => { - if (this.elementsViewService.executeAction(EnumViewActions.SHOW_FLOWS_TAB_ACTION, datasetPermissions)) { + if (this.datasetPermissionsServices.shouldAllowFlowsTab(datasetPermissions)) { this.datasetViewType = DatasetViewTypeEnum.Flows; } else { this.datasetViewType = DatasetViewTypeEnum.Overview; @@ -197,9 +199,7 @@ export class DatasetComponent extends BaseDatasetDataComponent implements OnInit takeUntilDestroyed(this.destroyRef), ) .subscribe((datasetPermissions: DatasetPermissionsFragment) => { - if ( - this.elementsViewService.executeAction(EnumViewActions.SHOW_SETTINGS_TAB_ACTION, datasetPermissions) - ) { + if (this.datasetPermissionsServices.shouldAllowSettingsTab(datasetPermissions)) { this.datasetViewType = DatasetViewTypeEnum.Settings; } else { this.datasetViewType = DatasetViewTypeEnum.Overview; diff --git a/src/app/services/elements-view.service.ts b/src/app/services/elements-view.service.ts index 3ab2d6e03..6a89e2a12 100644 --- a/src/app/services/elements-view.service.ts +++ b/src/app/services/elements-view.service.ts @@ -1,35 +1,43 @@ -import { LocalStorageService } from "src/app/services/local-storage.service"; +import { combineLatest, map, Observable } from "rxjs"; import { inject, Injectable } from "@angular/core"; -import { DatasetPermissionsFragment } from "../api/kamu.graphql.interface"; import { LoggedUserService } from "../auth/logged-user.service"; -import { DatasetPermissionsService } from "../dataset-view/dataset.permissions.service"; +import { DatasetSubscriptionsService } from "../dataset-view/dataset.subscriptions.service"; @Injectable({ providedIn: "root", }) export class ElementsViewService { private loggedUserService = inject(LoggedUserService); - private datasetPermissionsService = inject(DatasetPermissionsService); - private localStorageService = inject(LocalStorageService); + private datasetSubsService = inject(DatasetSubscriptionsService); - private get isAdminPrivelegesOn(): boolean { - return this.loggedUserService.isAdmin && (this.localStorageService.adminPriveleges ?? false); - } + public viewModeElement(): Observable { + return combineLatest([ + this.loggedUserService.adminPrivelegesChanges, + this.datasetSubsService.permissionsChanges, + ]).pipe( + map(([adminPriveleges, datasetPermissions]) => { + if (adminPriveleges) { + return ViewModeElement.ADMIN_MODE; + } + + const permissions = datasetPermissions.permissions; + if ( + permissions.canCommit || + permissions.canDelete || + permissions.canRename || + permissions.canSchedule + ) { + return ViewModeElement.PERMISSIONS_MODE; + } - public executeAction(action: EnumViewActions, datasetPermissions: DatasetPermissionsFragment | null): boolean { - if (action === EnumViewActions.SHOW_FLOWS_TAB_ACTION && datasetPermissions) { - return this.isAdminPrivelegesOn || this.datasetPermissionsService.shouldAllowFlowsTab(datasetPermissions); - } - if (action === EnumViewActions.SHOW_SETTINGS_TAB_ACTION && datasetPermissions) { - return ( - this.isAdminPrivelegesOn || this.datasetPermissionsService.shouldAllowSettingsTab(datasetPermissions) - ); - } - return false; + return ViewModeElement.NOT_AVAILABLE_MODE; + }), + ); } } -export enum EnumViewActions { - SHOW_FLOWS_TAB_ACTION = "showFlowsTabAction", - SHOW_SETTINGS_TAB_ACTION = "showSettingsTabAction", +export enum ViewModeElement { + NOT_AVAILABLE_MODE = "notAvailableMode", + PERMISSIONS_MODE = "permissionsMode", + ADMIN_MODE = "adminMode", } From bfa8d499aaabe4eea5715879121ab0095e4cb6bf Mon Sep 17 00:00:00 2001 From: Dmitriy Borzenko Date: Mon, 7 Oct 2024 14:33:09 +0300 Subject: [PATCH 3/9] Fixed minor PR comments --- src/app/app.component.ts | 4 +-- src/app/auth/logged-user.service.ts | 10 +++--- .../settings/account-settings.component.html | 12 +++---- .../settings/account-settings.component.ts | 28 ++++++++------- src/app/common/app.values.ts | 2 +- .../dataset-view-menu.component.html | 35 ++++++++++--------- .../dataset-view-menu.component.ts | 18 ++++++++-- src/app/services/elements-view.service.ts | 29 +++++++-------- src/app/services/local-storage.service.ts | 6 ++-- 9 files changed, 77 insertions(+), 67 deletions(-) diff --git a/src/app/app.component.ts b/src/app/app.component.ts index a9980b564..5023571b4 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -96,8 +96,8 @@ export class AppComponent extends BaseComponent implements OnInit { } private initAdminSlideToggle(): void { - const flag = this.localStorageService.adminPriveleges; - this.loggedUserService.emitAdminPrivelegesChanges(Boolean(flag)); + const flag = this.localStorageService.adminPrivileges; + this.loggedUserService.emitAdminPrivilegesChanges(Boolean(flag)); } private setMomentOptions(): void { diff --git a/src/app/auth/logged-user.service.ts b/src/app/auth/logged-user.service.ts index ab05c023c..428153d48 100644 --- a/src/app/auth/logged-user.service.ts +++ b/src/app/auth/logged-user.service.ts @@ -20,7 +20,7 @@ import { takeUntilDestroyed } from "@angular/core/rxjs-interop"; export class LoggedUserService extends UnsubscribeDestroyRefAdapter { private loggedInUser: MaybeNull = null; private loggedInUser$: Subject> = new ReplaySubject>(1); - private adminPriveleges$: BehaviorSubject = new BehaviorSubject(false); + private adminPrivileges$: BehaviorSubject = new BehaviorSubject(false); constructor( private loginService: LoginService, @@ -39,12 +39,12 @@ export class LoggedUserService extends UnsubscribeDestroyRefAdapter { .subscribe((user: AccountFragment) => this.changeUser(user)); } - public get adminPrivelegesChanges(): Observable { - return this.adminPriveleges$.asObservable(); + public get adminPrivilegesChanges(): Observable { + return this.adminPrivileges$.asObservable(); } - public emitAdminPrivelegesChanges(value: boolean): void { - return this.adminPriveleges$.next(value); + public emitAdminPrivilegesChanges(value: boolean): void { + return this.adminPrivileges$.next(value); } public initializeCompletes(): Observable { diff --git a/src/app/auth/settings/account-settings.component.html b/src/app/auth/settings/account-settings.component.html index f35de63c9..961a4348e 100644 --- a/src/app/auth/settings/account-settings.component.html +++ b/src/app/auth/settings/account-settings.component.html @@ -1,9 +1,9 @@ -
+
- {{ data.user?.displayName }} ({{ data.user?.accountName }}) + {{ data.user.displayName }} ({{ data.user.accountName }})

Your personal account

@@ -25,7 +25,7 @@
>; - public adminPriveleges$: Observable; + public adminPrivileges$: Observable; private router = inject(Router); private route = inject(ActivatedRoute); private loggedUserService = inject(LoggedUserService); private localStorageService = inject(LocalStorageService); - public componentData$: Observable<{ - user: MaybeNull; - adminPriveleges: boolean; - }>; + public userData$: Observable<{ + user: AccountFragment; + adminPrivileges: boolean; + } | null>; public ngOnInit(): void { this.router.events @@ -49,15 +49,17 @@ export class AccountSettingsComponent extends BaseComponent implements OnInit { this.extractActiveTabFromRoute(); - this.componentData$ = combineLatest([ + this.userData$ = combineLatest([ this.loggedUserService.loggedInUserChanges, - this.loggedUserService.adminPrivelegesChanges, + this.loggedUserService.adminPrivilegesChanges, ]).pipe( - map(([user, adminPriveleges]) => { - return { - user, - adminPriveleges, - }; + map(([user, adminPrivileges]) => { + return user + ? { + user, + adminPrivileges, + } + : null; }), ); } @@ -71,7 +73,7 @@ export class AccountSettingsComponent extends BaseComponent implements OnInit { } public adminSlideToggleChange(event: MatSlideToggleChange): void { - this.loggedUserService.emitAdminPrivelegesChanges(event.checked); + this.loggedUserService.emitAdminPrivilegesChanges(event.checked); this.localStorageService.setAdminPriveleges(event.checked); } diff --git a/src/app/common/app.values.ts b/src/app/common/app.values.ts index ef0e6517d..3b60f545f 100644 --- a/src/app/common/app.values.ts +++ b/src/app/common/app.values.ts @@ -7,7 +7,7 @@ export default class AppValues { public static readonly LOCAL_STORAGE_LOGIN_CALLBACK_URL = "login_callback_url"; public static readonly LOCAL_STORAGE_LOGIN_REDIRECT_URL = "login_redirect_url"; public static readonly LOCAL_STORAGE_ACCOUNT_ID = "account_id"; - public static readonly LOCAL_STORAGE_ADMIN_PRIVELEGES = "admin_priveleges"; + public static readonly LOCAL_STORAGE_ADMIN_PRIVILEGES = "admin_priveleges"; public static readonly SESSION_STORAGE_SIDE_PANEL_VISIBLE = "side_panel_visible"; public static readonly DEFAULT_USER_DISPLAY_NAME = "anonymous"; diff --git a/src/app/dataset-view/dataset-view-menu/dataset-view-menu.component.html b/src/app/dataset-view/dataset-view-menu/dataset-view-menu.component.html index 643195d13..29c2e2d27 100644 --- a/src/app/dataset-view/dataset-view-menu/dataset-view-menu.component.html +++ b/src/app/dataset-view/dataset-view-menu/dataset-view-menu.component.html @@ -6,18 +6,6 @@ >
- - -
- visibility - Overview -
-
-
@@ -93,7 +87,10 @@ data-test-id="navigateToSettings" value="settings" [class.active-link]="isDatasetViewTypeSettings" - *ngIf="viewMode === ViewModeElement.PERMISSIONS_MODE || viewMode === ViewModeElement.ADMIN_MODE" + *ngIf=" + viewMode === ElementVisibilityMode.AVAILABLE_VIA_PERMISSIONS || + viewMode === ElementVisibilityMode.AVAILABLE_VIA_ADMIN_PRIVILEGES + " >
- + settings + Settings - + admin_panel_settings
diff --git a/src/app/dataset-view/dataset-view-menu/dataset-view-menu.component.ts b/src/app/dataset-view/dataset-view-menu/dataset-view-menu.component.ts index 8e8758748..2eb613bef 100644 --- a/src/app/dataset-view/dataset-view-menu/dataset-view-menu.component.ts +++ b/src/app/dataset-view/dataset-view-menu/dataset-view-menu.component.ts @@ -15,7 +15,7 @@ import { DatasetViewTypeEnum } from "../dataset-view.interface"; import { SideNavHelper } from "../../common/sidenav.helper"; import { isMobileView, promiseWithCatch } from "src/app/common/app.helpers"; import { DatasetBasicsFragment, DatasetPermissionsFragment } from "src/app/api/kamu.graphql.interface"; -import { ElementsViewService, ViewModeElement } from "src/app/services/elements-view.service"; +import { ElementsViewService, ElementVisibilityMode } from "src/app/services/elements-view.service"; import { Observable } from "rxjs"; @Component({ @@ -39,8 +39,8 @@ export class DatasetViewMenuComponent implements OnInit, AfterViewInit { private elementsViewService = inject(ElementsViewService); private widgetHeightService = inject(WidgetHeightService); - public viewModeElement$: Observable; - public readonly ViewModeElement: typeof ViewModeElement = ViewModeElement; + public viewModeElement$: Observable; + public readonly ElementVisibilityMode: typeof ElementVisibilityMode = ElementVisibilityMode; public ngAfterViewInit(): void { this.widgetHeightService.setWidgetOffsetTop( @@ -49,6 +49,18 @@ export class DatasetViewMenuComponent implements OnInit, AfterViewInit { ); } + public datasetMenuItemDescriptors = [ + { + dataTestId: " navigateToOverview", + activeLink: true, + value: DatasetViewTypeEnum.Overview, + label: "", + icon: "", + tab: "", + pemissions: {}, + }, + ]; + public ngOnInit(): void { if (this.sidenav) { this.sideNavHelper = new SideNavHelper(this.sidenav); diff --git a/src/app/services/elements-view.service.ts b/src/app/services/elements-view.service.ts index 6a89e2a12..4a85eaf9a 100644 --- a/src/app/services/elements-view.service.ts +++ b/src/app/services/elements-view.service.ts @@ -10,34 +10,29 @@ export class ElementsViewService { private loggedUserService = inject(LoggedUserService); private datasetSubsService = inject(DatasetSubscriptionsService); - public viewModeElement(): Observable { + public viewModeElement(): Observable { return combineLatest([ - this.loggedUserService.adminPrivelegesChanges, + this.loggedUserService.adminPrivilegesChanges, this.datasetSubsService.permissionsChanges, ]).pipe( - map(([adminPriveleges, datasetPermissions]) => { - if (adminPriveleges) { - return ViewModeElement.ADMIN_MODE; + map(([adminPrivileges, datasetPermissions]) => { + if (adminPrivileges) { + return ElementVisibilityMode.AVAILABLE_VIA_ADMIN_PRIVILEGES; } const permissions = datasetPermissions.permissions; - if ( - permissions.canCommit || - permissions.canDelete || - permissions.canRename || - permissions.canSchedule - ) { - return ViewModeElement.PERMISSIONS_MODE; + if (permissions.canView) { + return ElementVisibilityMode.AVAILABLE_VIA_PERMISSIONS; } - return ViewModeElement.NOT_AVAILABLE_MODE; + return ElementVisibilityMode.UNAVAILABLE; }), ); } } -export enum ViewModeElement { - NOT_AVAILABLE_MODE = "notAvailableMode", - PERMISSIONS_MODE = "permissionsMode", - ADMIN_MODE = "adminMode", +export enum ElementVisibilityMode { + UNAVAILABLE, + AVAILABLE_VIA_PERMISSIONS, + AVAILABLE_VIA_ADMIN_PRIVILEGES, } diff --git a/src/app/services/local-storage.service.ts b/src/app/services/local-storage.service.ts index d98f9cc75..3682618df 100644 --- a/src/app/services/local-storage.service.ts +++ b/src/app/services/local-storage.service.ts @@ -15,15 +15,15 @@ export class LocalStorageService { return localStorage.getItem(AppValues.LOCAL_STORAGE_LOGIN_REDIRECT_URL); } - public get adminPriveleges(): boolean | null { - const flag = localStorage.getItem(AppValues.LOCAL_STORAGE_ADMIN_PRIVELEGES); + public get adminPrivileges(): boolean | null { + const flag = localStorage.getItem(AppValues.LOCAL_STORAGE_ADMIN_PRIVILEGES); if (flag) { return Boolean(JSON.parse(flag)); } else return null; } public setAdminPriveleges(flag: boolean) { - localStorage.setItem(AppValues.LOCAL_STORAGE_ADMIN_PRIVELEGES, JSON.stringify(flag)); + localStorage.setItem(AppValues.LOCAL_STORAGE_ADMIN_PRIVILEGES, JSON.stringify(flag)); } public setRedirectAfterLoginUrl(url: string | null) { From 73786af819365e4355a3390fb44615cd10cbcbe8 Mon Sep 17 00:00:00 2001 From: Dmitriy Borzenko Date: Mon, 7 Oct 2024 22:12:34 +0300 Subject: [PATCH 4/9] created dataset-view-menu-item component --- src/app/auth/logged-user.service.ts | 6 + .../dataset-view-menu-item.component.html | 20 +++ .../dataset-view-menu-item.component.scss | 42 +++++++ .../dataset-view-menu-item.component.spec.ts | 21 ++++ .../dataset-view-menu-item.component.ts | 31 +++++ .../dataset-view-menu.component.html | 118 +++--------------- .../dataset-view-menu.component.scss | 7 -- .../dataset-view-menu.component.ts | 54 +------- .../dataset-view-menu.model.ts | 99 +++++++++++++++ src/app/dataset-view/dataset.module.ts | 3 + src/app/services/local-storage.service.ts | 2 +- .../styles/components/_mat-toggle-group.scss | 2 +- src/styles.scss | 2 +- 13 files changed, 243 insertions(+), 164 deletions(-) create mode 100644 src/app/dataset-view/dataset-view-menu/components/dataset-view-menu-item/dataset-view-menu-item.component.html create mode 100644 src/app/dataset-view/dataset-view-menu/components/dataset-view-menu-item/dataset-view-menu-item.component.scss create mode 100644 src/app/dataset-view/dataset-view-menu/components/dataset-view-menu-item/dataset-view-menu-item.component.spec.ts create mode 100644 src/app/dataset-view/dataset-view-menu/components/dataset-view-menu-item/dataset-view-menu-item.component.ts create mode 100644 src/app/dataset-view/dataset-view-menu/dataset-view-menu.model.ts diff --git a/src/app/auth/logged-user.service.ts b/src/app/auth/logged-user.service.ts index 428153d48..ad52477d3 100644 --- a/src/app/auth/logged-user.service.ts +++ b/src/app/auth/logged-user.service.ts @@ -92,6 +92,7 @@ export class LoggedUserService extends UnsubscribeDestroyRefAdapter { this.changeUser(null); this.resetAccessToken(); this.clearGraphQLCache(); + this.resetAdminPrivileges(); } private attemptPreviousAuthenticationCompletes(): Observable { @@ -125,4 +126,9 @@ export class LoggedUserService extends UnsubscribeDestroyRefAdapter { private saveAccessToken(token: string): void { this.localStorageService.setAccessToken(token); } + + private resetAdminPrivileges(): void { + this.localStorageService.setAdminPriveleges(null); + this.emitAdminPrivilegesChanges(false); + } } diff --git a/src/app/dataset-view/dataset-view-menu/components/dataset-view-menu-item/dataset-view-menu-item.component.html b/src/app/dataset-view/dataset-view-menu/components/dataset-view-menu-item/dataset-view-menu-item.component.html new file mode 100644 index 000000000..1366b1e78 --- /dev/null +++ b/src/app/dataset-view/dataset-view-menu/components/dataset-view-menu-item/dataset-view-menu-item.component.html @@ -0,0 +1,20 @@ + +
+
+ {{ icon }} + {{ label }} + + admin_panel_settings +
+
+
diff --git a/src/app/dataset-view/dataset-view-menu/components/dataset-view-menu-item/dataset-view-menu-item.component.scss b/src/app/dataset-view/dataset-view-menu/components/dataset-view-menu-item/dataset-view-menu-item.component.scss new file mode 100644 index 000000000..f6040efce --- /dev/null +++ b/src/app/dataset-view/dataset-view-menu/components/dataset-view-menu-item/dataset-view-menu-item.component.scss @@ -0,0 +1,42 @@ +:host { + mat-button-toggle { + padding: 0 0 13px !important; + border: 2px transparent solid !important; + background: inherit !important; + + &.active-link { + border-bottom-color: #000 !important; + border-radius: 0; + } + + &:not(.active-link) { + &:hover { + padding: 0 0 14px !important; + box-shadow: none !important; + border-bottom: 1px solid !important; + border-radius: 0 !important; + } + } + } +} + +::ng-deep { + .mat-button-toggle-disabled { + .mat-button-toggle-button { + cursor: not-allowed; + color: rgb(0 0 0 / 51%); + + a { + cursor: not-allowed; + color: rgb(0 0 0 / 51%); + pointer-events: none; + } + } + } +} + +.admin-icon { + font-size: 16px; + bottom: 5px; + color: #378bb0; +} diff --git a/src/app/dataset-view/dataset-view-menu/components/dataset-view-menu-item/dataset-view-menu-item.component.spec.ts b/src/app/dataset-view/dataset-view-menu/components/dataset-view-menu-item/dataset-view-menu-item.component.spec.ts new file mode 100644 index 000000000..df5886056 --- /dev/null +++ b/src/app/dataset-view/dataset-view-menu/components/dataset-view-menu-item/dataset-view-menu-item.component.spec.ts @@ -0,0 +1,21 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { DatasetViewMenuItemComponent } from './dataset-view-menu-item.component'; + +describe('DatasetViewMenuItemComponent', () => { + let component: DatasetViewMenuItemComponent; + let fixture: ComponentFixture; + + beforeEach(() => { + TestBed.configureTestingModule({ + declarations: [DatasetViewMenuItemComponent] + }); + fixture = TestBed.createComponent(DatasetViewMenuItemComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/dataset-view/dataset-view-menu/components/dataset-view-menu-item/dataset-view-menu-item.component.ts b/src/app/dataset-view/dataset-view-menu/components/dataset-view-menu-item/dataset-view-menu-item.component.ts new file mode 100644 index 000000000..8acf3e21b --- /dev/null +++ b/src/app/dataset-view/dataset-view-menu/components/dataset-view-menu-item/dataset-view-menu-item.component.ts @@ -0,0 +1,31 @@ +import { ChangeDetectionStrategy, Component, Input } from "@angular/core"; +import { DatasetBasicsFragment } from "src/app/api/kamu.graphql.interface"; +import { MaybeNull, MaybeUndefined } from "src/app/common/app.types"; +import { DatasetViewTypeEnum } from "src/app/dataset-view/dataset-view.interface"; +import { ElementVisibilityMode } from "src/app/services/elements-view.service"; + +@Component({ + selector: "app-dataset-view-menu-item", + templateUrl: "./dataset-view-menu-item.component.html", + styleUrls: ["./dataset-view-menu-item.component.scss"], + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class DatasetViewMenuItemComponent { + @Input({ required: true }) public dataTestId: string; + @Input({ required: true }) public activeLink: boolean; + @Input({ required: true }) public value: DatasetViewTypeEnum; + @Input({ required: true }) public label: string; + @Input({ required: true }) public icon: string; + @Input({ required: true }) public tab: MaybeNull; + @Input({ required: true }) public viewMode: ElementVisibilityMode; + @Input({ required: true }) datasetBasics: DatasetBasicsFragment; + @Input({ required: true }) public visible: boolean; + @Input() public disabled: MaybeUndefined; + @Input() public showAdminIcon: MaybeUndefined; + + public readonly ElementVisibilityMode: typeof ElementVisibilityMode = ElementVisibilityMode; + + public get datasetLink(): string { + return `/${this.datasetBasics.owner.accountName}/${this.datasetBasics.name}/`; + } +} diff --git a/src/app/dataset-view/dataset-view-menu/dataset-view-menu.component.html b/src/app/dataset-view/dataset-view-menu/dataset-view-menu.component.html index 29c2e2d27..a17dc044a 100644 --- a/src/app/dataset-view/dataset-view-menu/dataset-view-menu.component.html +++ b/src/app/dataset-view/dataset-view-menu/dataset-view-menu.component.html @@ -3,113 +3,25 @@ [style]="isMinimizeSearchAdditionalButtons ? 'grid-template-columns: 1fr;' : ''" id="container-dataset-tabs" #datasetViewMenu + *ngIf="viewModeElement$ | async as viewMode" > diff --git a/src/app/dataset-view/dataset-view-menu/dataset-view-menu.component.scss b/src/app/dataset-view/dataset-view-menu/dataset-view-menu.component.scss index 9deb247f4..43c6ca3ab 100644 --- a/src/app/dataset-view/dataset-view-menu/dataset-view-menu.component.scss +++ b/src/app/dataset-view/dataset-view-menu/dataset-view-menu.component.scss @@ -2,10 +2,3 @@ height: inherit; border-radius: inherit; } - -.admin-icon { - position: relative; - font-size: 16px; - bottom: 5px; - color: #378bb0; -} diff --git a/src/app/dataset-view/dataset-view-menu/dataset-view-menu.component.ts b/src/app/dataset-view/dataset-view-menu/dataset-view-menu.component.ts index 2eb613bef..2920051a6 100644 --- a/src/app/dataset-view/dataset-view-menu/dataset-view-menu.component.ts +++ b/src/app/dataset-view/dataset-view-menu/dataset-view-menu.component.ts @@ -17,6 +17,7 @@ import { isMobileView, promiseWithCatch } from "src/app/common/app.helpers"; import { DatasetBasicsFragment, DatasetPermissionsFragment } from "src/app/api/kamu.graphql.interface"; import { ElementsViewService, ElementVisibilityMode } from "src/app/services/elements-view.service"; import { Observable } from "rxjs"; +import { DatasetMenuItemOptions, DatasetViewMenuItems } from "./dataset-view-menu.model"; @Component({ selector: "app-dataset-view-menu", @@ -33,14 +34,13 @@ export class DatasetViewMenuComponent implements OnInit, AfterViewInit { @Input({ required: true }) datasetPermissions: DatasetPermissionsFragment; @Input({ required: true }) datasetViewType: DatasetViewTypeEnum; @Input() isMinimizeSearchAdditionalButtons: boolean; - public readonly DatasetViewTypeEnum: typeof DatasetViewTypeEnum = DatasetViewTypeEnum; - + public datasetMenuItemDescriptors: DatasetMenuItemOptions[] = DatasetViewMenuItems; private sideNavHelper: SideNavHelper; + public readonly DatasetViewTypeEnum: typeof DatasetViewTypeEnum = DatasetViewTypeEnum; private elementsViewService = inject(ElementsViewService); private widgetHeightService = inject(WidgetHeightService); public viewModeElement$: Observable; - public readonly ElementVisibilityMode: typeof ElementVisibilityMode = ElementVisibilityMode; public ngAfterViewInit(): void { this.widgetHeightService.setWidgetOffsetTop( @@ -49,18 +49,6 @@ export class DatasetViewMenuComponent implements OnInit, AfterViewInit { ); } - public datasetMenuItemDescriptors = [ - { - dataTestId: " navigateToOverview", - activeLink: true, - value: DatasetViewTypeEnum.Overview, - label: "", - icon: "", - tab: "", - pemissions: {}, - }, - ]; - public ngOnInit(): void { if (this.sidenav) { this.sideNavHelper = new SideNavHelper(this.sidenav); @@ -68,42 +56,6 @@ export class DatasetViewMenuComponent implements OnInit, AfterViewInit { this.viewModeElement$ = this.elementsViewService.viewModeElement(); } - public get isDatasetViewTypeOverview(): boolean { - return this.datasetViewType === DatasetViewTypeEnum.Overview; - } - - public get isDatasetViewTypeData(): boolean { - return this.datasetViewType === DatasetViewTypeEnum.Data; - } - - public get isDatasetViewTypeMetadata(): boolean { - return this.datasetViewType === DatasetViewTypeEnum.Metadata; - } - - public get isDatasetViewTypeHistory(): boolean { - return this.datasetViewType === DatasetViewTypeEnum.History; - } - - public get isDatasetViewTypeLineage(): boolean { - return this.datasetViewType === DatasetViewTypeEnum.Lineage; - } - - public get isDatasetViewTypeDiscussions(): boolean { - return this.datasetViewType === DatasetViewTypeEnum.Discussions; - } - - public get isDatasetViewTypeFlows(): boolean { - return this.datasetViewType === DatasetViewTypeEnum.Flows; - } - - public get isDatasetViewTypeSettings(): boolean { - return this.datasetViewType === DatasetViewTypeEnum.Settings; - } - - public get datasetLink(): string { - return `/${this.datasetBasics.owner.accountName}/${this.datasetBasics.name}/`; - } - @HostListener("window:resize") private checkWindowSize(): void { this.isMinimizeSearchAdditionalButtons = isMobileView(); diff --git a/src/app/dataset-view/dataset-view-menu/dataset-view-menu.model.ts b/src/app/dataset-view/dataset-view-menu/dataset-view-menu.model.ts new file mode 100644 index 000000000..81f83cfae --- /dev/null +++ b/src/app/dataset-view/dataset-view-menu/dataset-view-menu.model.ts @@ -0,0 +1,99 @@ +import { DatasetPermissionsFragment } from "src/app/api/kamu.graphql.interface"; +import { DatasetViewTypeEnum } from "../dataset-view.interface"; + +export interface DatasetMenuItemOptions { + dataTestId: string; + value: DatasetViewTypeEnum; + label: string; + icon: string; + tab: DatasetViewTypeEnum | null; + disabled?: boolean; + showAdminIcon?: boolean; + shouldAllowTab: (data: DatasetPermissionsFragment) => boolean; +} + +export const DatasetViewMenuItems = [ + { + dataTestId: "navigateToOverview", + value: DatasetViewTypeEnum.Overview, + label: "Overview", + icon: "visibility", + tab: null, + shouldAllowTab: (data: DatasetPermissionsFragment) => { + return data.permissions.canView; + }, + }, + { + dataTestId: "navigateToData", + value: DatasetViewTypeEnum.Data, + label: "Data", + icon: "dataset", + tab: DatasetViewTypeEnum.Data, + shouldAllowTab: (data: DatasetPermissionsFragment) => { + return data.permissions.canView; + }, + }, + { + dataTestId: "navigateToMetadata", + value: DatasetViewTypeEnum.Metadata, + label: "Metadata", + icon: "dataset_linked", + tab: DatasetViewTypeEnum.Metadata, + shouldAllowTab: (data: DatasetPermissionsFragment) => { + return data.permissions.canView; + }, + }, + { + dataTestId: "navigateToHistory", + value: DatasetViewTypeEnum.History, + label: "History", + icon: "manage_history", + tab: DatasetViewTypeEnum.History, + shouldAllowTab: (data: DatasetPermissionsFragment) => { + return data.permissions.canView; + }, + }, + { + dataTestId: "navigateToLineage", + value: DatasetViewTypeEnum.Lineage, + label: "Lineage", + icon: "account_tree", + tab: DatasetViewTypeEnum.Lineage, + shouldAllowTab: (data: DatasetPermissionsFragment) => { + return data.permissions.canView; + }, + }, + { + dataTestId: "navigateToDiscussion", + value: DatasetViewTypeEnum.Discussions, + label: "Discussions", + icon: "message", + tab: DatasetViewTypeEnum.Discussions, + disabled: true, + shouldAllowTab: (data: DatasetPermissionsFragment) => { + return data.permissions.canView; + }, + }, + { + dataTestId: "navigateToFlows", + value: DatasetViewTypeEnum.Flows, + label: "Flows", + icon: "add_task", + tab: DatasetViewTypeEnum.Flows, + showAdminIcon: true, + shouldAllowTab: (data: DatasetPermissionsFragment) => { + return data.permissions.canSchedule; + }, + }, + { + dataTestId: "navigateToSettings", + value: DatasetViewTypeEnum.Settings, + label: "Settings", + icon: "settings", + tab: DatasetViewTypeEnum.Settings, + showAdminIcon: true, + shouldAllowTab: (data: DatasetPermissionsFragment) => { + return data.permissions.canDelete || data.permissions.canRename; + }, + }, +]; diff --git a/src/app/dataset-view/dataset.module.ts b/src/app/dataset-view/dataset.module.ts index 71fd9ece4..07be23bc7 100644 --- a/src/app/dataset-view/dataset.module.ts +++ b/src/app/dataset-view/dataset.module.ts @@ -86,6 +86,7 @@ import { FlowsComponent } from "./additional-components/flows-component/flows.co import { AngularMultiSelectModule } from "angular2-multiselect-dropdown"; import { MatTabsModule } from "@angular/material/tabs"; import { MatChipsModule } from "@angular/material/chips"; +import { DatasetViewMenuItemComponent } from "./dataset-view-menu/components/dataset-view-menu-item/dataset-view-menu-item.component"; @NgModule({ imports: [ @@ -165,6 +166,7 @@ import { MatChipsModule } from "@angular/material/chips"; FlowsTableComponent, AngularMultiSelectModule, MatChipsModule, + DatasetViewMenuItemComponent, ], declarations: [ DatasetViewHeaderComponent, @@ -208,6 +210,7 @@ import { MatChipsModule } from "@angular/material/chips"; RequestTimerComponent, AddDataModalComponent, FileFromUrlModalComponent, + DatasetViewMenuItemComponent, ], }) export class DatasetModule { diff --git a/src/app/services/local-storage.service.ts b/src/app/services/local-storage.service.ts index 3682618df..0547eff1d 100644 --- a/src/app/services/local-storage.service.ts +++ b/src/app/services/local-storage.service.ts @@ -22,7 +22,7 @@ export class LocalStorageService { } else return null; } - public setAdminPriveleges(flag: boolean) { + public setAdminPriveleges(flag: boolean | null) { localStorage.setItem(AppValues.LOCAL_STORAGE_ADMIN_PRIVILEGES, JSON.stringify(flag)); } diff --git a/src/assets/styles/components/_mat-toggle-group.scss b/src/assets/styles/components/_mat-toggle-group.scss index 8223085cd..101878239 100644 --- a/src/assets/styles/components/_mat-toggle-group.scss +++ b/src/assets/styles/components/_mat-toggle-group.scss @@ -53,6 +53,6 @@ mat-button-toggle { .mat-button-toggle-appearance-standard { .mat-button-toggle-label-content { - padding: 0 !important; + padding: 3px !important; } } diff --git a/src/styles.scss b/src/styles.scss index d2108317f..3f2c2a3ed 100644 --- a/src/styles.scss +++ b/src/styles.scss @@ -1524,7 +1524,7 @@ input { color: black; div { - padding: 0 12px; + padding: 0 14px; } &:hover { From 2c753f413639c234b589a31476fe03ab9d324145 Mon Sep 17 00:00:00 2001 From: Dmitriy Borzenko Date: Tue, 8 Oct 2024 13:55:58 +0300 Subject: [PATCH 5/9] Fixed PR comments and refactoring --- .../dataset-view-menu-item.component.html | 2 +- .../dataset-view-menu-item.component.ts | 15 +--- .../dataset-view-menu.component.html | 5 +- .../dataset-view-menu.component.ts | 14 ++-- .../dataset-view-menu.model.ts | 73 +++++++++---------- .../visibility-mode.service.spec.ts | 15 ++++ .../visibility-mode.service.ts} | 6 +- src/app/dataset-view/dataset.component.ts | 2 - .../services/elements-view.service.spec.ts | 16 ---- 9 files changed, 70 insertions(+), 78 deletions(-) create mode 100644 src/app/dataset-view/dataset-view-menu/visibility-mode.service.spec.ts rename src/app/{services/elements-view.service.ts => dataset-view/dataset-view-menu/visibility-mode.service.ts} (85%) delete mode 100644 src/app/services/elements-view.service.spec.ts diff --git a/src/app/dataset-view/dataset-view-menu/components/dataset-view-menu-item/dataset-view-menu-item.component.html b/src/app/dataset-view/dataset-view-menu/components/dataset-view-menu-item/dataset-view-menu-item.component.html index 1366b1e78..04abffee2 100644 --- a/src/app/dataset-view/dataset-view-menu/components/dataset-view-menu-item/dataset-view-menu-item.component.html +++ b/src/app/dataset-view/dataset-view-menu/components/dataset-view-menu-item/dataset-view-menu-item.component.html @@ -5,7 +5,7 @@ [value]="value" *ngIf="visible" > - +
{{ icon }} {{ label }} diff --git a/src/app/dataset-view/dataset-view-menu/components/dataset-view-menu-item/dataset-view-menu-item.component.ts b/src/app/dataset-view/dataset-view-menu/components/dataset-view-menu-item/dataset-view-menu-item.component.ts index 8acf3e21b..cd2a78a96 100644 --- a/src/app/dataset-view/dataset-view-menu/components/dataset-view-menu-item/dataset-view-menu-item.component.ts +++ b/src/app/dataset-view/dataset-view-menu/components/dataset-view-menu-item/dataset-view-menu-item.component.ts @@ -1,8 +1,6 @@ import { ChangeDetectionStrategy, Component, Input } from "@angular/core"; -import { DatasetBasicsFragment } from "src/app/api/kamu.graphql.interface"; -import { MaybeNull, MaybeUndefined } from "src/app/common/app.types"; -import { DatasetViewTypeEnum } from "src/app/dataset-view/dataset-view.interface"; -import { ElementVisibilityMode } from "src/app/services/elements-view.service"; +import { MaybeUndefined } from "src/app/common/app.types"; +import { ElementVisibilityMode } from "../../visibility-mode.service"; @Component({ selector: "app-dataset-view-menu-item", @@ -13,19 +11,14 @@ import { ElementVisibilityMode } from "src/app/services/elements-view.service"; export class DatasetViewMenuItemComponent { @Input({ required: true }) public dataTestId: string; @Input({ required: true }) public activeLink: boolean; - @Input({ required: true }) public value: DatasetViewTypeEnum; + @Input({ required: true }) public value: string; @Input({ required: true }) public label: string; @Input({ required: true }) public icon: string; - @Input({ required: true }) public tab: MaybeNull; + @Input({ required: true }) public datasetLink: string; @Input({ required: true }) public viewMode: ElementVisibilityMode; - @Input({ required: true }) datasetBasics: DatasetBasicsFragment; @Input({ required: true }) public visible: boolean; @Input() public disabled: MaybeUndefined; @Input() public showAdminIcon: MaybeUndefined; public readonly ElementVisibilityMode: typeof ElementVisibilityMode = ElementVisibilityMode; - - public get datasetLink(): string { - return `/${this.datasetBasics.owner.accountName}/${this.datasetBasics.name}/`; - } } diff --git a/src/app/dataset-view/dataset-view-menu/dataset-view-menu.component.html b/src/app/dataset-view/dataset-view-menu/dataset-view-menu.component.html index a17dc044a..84a417912 100644 --- a/src/app/dataset-view/dataset-view-menu/dataset-view-menu.component.html +++ b/src/app/dataset-view/dataset-view-menu/dataset-view-menu.component.html @@ -14,12 +14,11 @@ [value]="menuItem.value" [label]="menuItem.label" [icon]="menuItem.icon" - [tab]="menuItem.tab" [viewMode]="viewMode" - [datasetBasics]="datasetBasics" [disabled]="menuItem.disabled" [showAdminIcon]="menuItem.showAdminIcon" - [visible]="menuItem.shouldAllowTab(datasetPermissions)" + [visible]="menuItem.shouldAllowTab(viewMode, datasetPermissions)" + [datasetLink]="datasetLink" > diff --git a/src/app/dataset-view/dataset-view-menu/dataset-view-menu.component.ts b/src/app/dataset-view/dataset-view-menu/dataset-view-menu.component.ts index 2920051a6..29f567a7f 100644 --- a/src/app/dataset-view/dataset-view-menu/dataset-view-menu.component.ts +++ b/src/app/dataset-view/dataset-view-menu/dataset-view-menu.component.ts @@ -15,9 +15,9 @@ import { DatasetViewTypeEnum } from "../dataset-view.interface"; import { SideNavHelper } from "../../common/sidenav.helper"; import { isMobileView, promiseWithCatch } from "src/app/common/app.helpers"; import { DatasetBasicsFragment, DatasetPermissionsFragment } from "src/app/api/kamu.graphql.interface"; -import { ElementsViewService, ElementVisibilityMode } from "src/app/services/elements-view.service"; import { Observable } from "rxjs"; -import { DatasetMenuItemOptions, DatasetViewMenuItems } from "./dataset-view-menu.model"; +import { DatasetViewMenuItems } from "./dataset-view-menu.model"; +import { ElementVisibilityMode, VisibilityModeService } from "./visibility-mode.service"; @Component({ selector: "app-dataset-view-menu", @@ -34,11 +34,11 @@ export class DatasetViewMenuComponent implements OnInit, AfterViewInit { @Input({ required: true }) datasetPermissions: DatasetPermissionsFragment; @Input({ required: true }) datasetViewType: DatasetViewTypeEnum; @Input() isMinimizeSearchAdditionalButtons: boolean; - public datasetMenuItemDescriptors: DatasetMenuItemOptions[] = DatasetViewMenuItems; + public datasetMenuItemDescriptors = DatasetViewMenuItems; private sideNavHelper: SideNavHelper; public readonly DatasetViewTypeEnum: typeof DatasetViewTypeEnum = DatasetViewTypeEnum; - private elementsViewService = inject(ElementsViewService); + private visibilityModeService = inject(VisibilityModeService); private widgetHeightService = inject(WidgetHeightService); public viewModeElement$: Observable; @@ -53,7 +53,11 @@ export class DatasetViewMenuComponent implements OnInit, AfterViewInit { if (this.sidenav) { this.sideNavHelper = new SideNavHelper(this.sidenav); } - this.viewModeElement$ = this.elementsViewService.viewModeElement(); + this.viewModeElement$ = this.visibilityModeService.viewModeElement(); + } + + public get datasetLink(): string { + return `/${this.datasetBasics.owner.accountName}/${this.datasetBasics.name}`; } @HostListener("window:resize") diff --git a/src/app/dataset-view/dataset-view-menu/dataset-view-menu.model.ts b/src/app/dataset-view/dataset-view-menu/dataset-view-menu.model.ts index 81f83cfae..1a38bb9e8 100644 --- a/src/app/dataset-view/dataset-view-menu/dataset-view-menu.model.ts +++ b/src/app/dataset-view/dataset-view-menu/dataset-view-menu.model.ts @@ -1,99 +1,98 @@ import { DatasetPermissionsFragment } from "src/app/api/kamu.graphql.interface"; -import { DatasetViewTypeEnum } from "../dataset-view.interface"; +import { ElementVisibilityMode } from "./visibility-mode.service"; export interface DatasetMenuItemOptions { dataTestId: string; - value: DatasetViewTypeEnum; + value: string; label: string; icon: string; - tab: DatasetViewTypeEnum | null; disabled?: boolean; showAdminIcon?: boolean; - shouldAllowTab: (data: DatasetPermissionsFragment) => boolean; + shouldAllowTab: (viewMode: ElementVisibilityMode, permissions: DatasetPermissionsFragment | null) => boolean; } -export const DatasetViewMenuItems = [ +export const DatasetViewMenuItems: DatasetMenuItemOptions[] = [ { dataTestId: "navigateToOverview", - value: DatasetViewTypeEnum.Overview, + value: "overview", label: "Overview", icon: "visibility", - tab: null, - shouldAllowTab: (data: DatasetPermissionsFragment) => { - return data.permissions.canView; + shouldAllowTab: (viewMode: ElementVisibilityMode) => { + return viewMode !== ElementVisibilityMode.UNAVAILABLE; }, }, { dataTestId: "navigateToData", - value: DatasetViewTypeEnum.Data, + value: "data", label: "Data", icon: "dataset", - tab: DatasetViewTypeEnum.Data, - shouldAllowTab: (data: DatasetPermissionsFragment) => { - return data.permissions.canView; + shouldAllowTab: (viewMode: ElementVisibilityMode) => { + return viewMode !== ElementVisibilityMode.UNAVAILABLE; }, }, { dataTestId: "navigateToMetadata", - value: DatasetViewTypeEnum.Metadata, + value: "metadata", label: "Metadata", icon: "dataset_linked", - tab: DatasetViewTypeEnum.Metadata, - shouldAllowTab: (data: DatasetPermissionsFragment) => { - return data.permissions.canView; + shouldAllowTab: (viewMode: ElementVisibilityMode) => { + return viewMode !== ElementVisibilityMode.UNAVAILABLE; }, }, { dataTestId: "navigateToHistory", - value: DatasetViewTypeEnum.History, + value: "history", label: "History", icon: "manage_history", - tab: DatasetViewTypeEnum.History, - shouldAllowTab: (data: DatasetPermissionsFragment) => { - return data.permissions.canView; + shouldAllowTab: (viewMode: ElementVisibilityMode) => { + return viewMode !== ElementVisibilityMode.UNAVAILABLE; }, }, { dataTestId: "navigateToLineage", - value: DatasetViewTypeEnum.Lineage, + value: "lineage", label: "Lineage", icon: "account_tree", - tab: DatasetViewTypeEnum.Lineage, - shouldAllowTab: (data: DatasetPermissionsFragment) => { - return data.permissions.canView; + shouldAllowTab: (viewMode: ElementVisibilityMode) => { + return viewMode !== ElementVisibilityMode.UNAVAILABLE; }, }, + { dataTestId: "navigateToDiscussion", - value: DatasetViewTypeEnum.Discussions, + value: "discussions", label: "Discussions", icon: "message", - tab: DatasetViewTypeEnum.Discussions, disabled: true, - shouldAllowTab: (data: DatasetPermissionsFragment) => { - return data.permissions.canView; + shouldAllowTab: (viewMode: ElementVisibilityMode) => { + return viewMode !== ElementVisibilityMode.UNAVAILABLE; }, }, { dataTestId: "navigateToFlows", - value: DatasetViewTypeEnum.Flows, + value: "flows", label: "Flows", icon: "add_task", - tab: DatasetViewTypeEnum.Flows, showAdminIcon: true, - shouldAllowTab: (data: DatasetPermissionsFragment) => { - return data.permissions.canSchedule; + shouldAllowTab: (viewMode: ElementVisibilityMode, permissions: DatasetPermissionsFragment | null) => { + return ( + viewMode === ElementVisibilityMode.AVAILABLE_VIA_ADMIN_PRIVILEGES || + Boolean(permissions?.permissions.canSchedule) + ); }, }, { dataTestId: "navigateToSettings", - value: DatasetViewTypeEnum.Settings, + value: "settings", label: "Settings", icon: "settings", - tab: DatasetViewTypeEnum.Settings, showAdminIcon: true, - shouldAllowTab: (data: DatasetPermissionsFragment) => { - return data.permissions.canDelete || data.permissions.canRename; + shouldAllowTab: (viewMode: ElementVisibilityMode, permissions: DatasetPermissionsFragment | null) => { + return ( + viewMode === ElementVisibilityMode.AVAILABLE_VIA_ADMIN_PRIVILEGES || + Boolean(permissions?.permissions.canDelete) || + Boolean(permissions?.permissions.canRename) + ); }, }, ]; diff --git a/src/app/dataset-view/dataset-view-menu/visibility-mode.service.spec.ts b/src/app/dataset-view/dataset-view-menu/visibility-mode.service.spec.ts new file mode 100644 index 000000000..78059453c --- /dev/null +++ b/src/app/dataset-view/dataset-view-menu/visibility-mode.service.spec.ts @@ -0,0 +1,15 @@ +import { TestBed } from "@angular/core/testing"; +import { VisibilityModeService } from "./visibility-mode.service"; + +describe("VisibilityModeService", () => { + let service: VisibilityModeService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(VisibilityModeService); + }); + + it("should be created", () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/src/app/services/elements-view.service.ts b/src/app/dataset-view/dataset-view-menu/visibility-mode.service.ts similarity index 85% rename from src/app/services/elements-view.service.ts rename to src/app/dataset-view/dataset-view-menu/visibility-mode.service.ts index 4a85eaf9a..7130ff229 100644 --- a/src/app/services/elements-view.service.ts +++ b/src/app/dataset-view/dataset-view-menu/visibility-mode.service.ts @@ -1,12 +1,12 @@ import { combineLatest, map, Observable } from "rxjs"; import { inject, Injectable } from "@angular/core"; -import { LoggedUserService } from "../auth/logged-user.service"; -import { DatasetSubscriptionsService } from "../dataset-view/dataset.subscriptions.service"; +import { LoggedUserService } from "../../auth/logged-user.service"; +import { DatasetSubscriptionsService } from "../dataset.subscriptions.service"; @Injectable({ providedIn: "root", }) -export class ElementsViewService { +export class VisibilityModeService { private loggedUserService = inject(LoggedUserService); private datasetSubsService = inject(DatasetSubscriptionsService); diff --git a/src/app/dataset-view/dataset.component.ts b/src/app/dataset-view/dataset.component.ts index 10256d8bf..977b3d520 100644 --- a/src/app/dataset-view/dataset.component.ts +++ b/src/app/dataset-view/dataset.component.ts @@ -14,7 +14,6 @@ import { LineageGraphNodeData, LineageGraphNodeKind } from "./additional-compone import _ from "lodash"; import { BaseDatasetDataComponent } from "../common/base-dataset-data.component"; import { takeUntilDestroyed } from "@angular/core/rxjs-interop"; -import { ElementsViewService } from "../services/elements-view.service"; import { DatasetPermissionsService } from "./dataset.permissions.service"; @Component({ @@ -34,7 +33,6 @@ export class DatasetComponent extends BaseDatasetDataComponent implements OnInit private datasetPermissionsServices = inject(DatasetPermissionsService); private router = inject(Router); private cdr = inject(ChangeDetectorRef); - private elementsViewService = inject(ElementsViewService); public ngOnInit(): void { const urlDatasetInfo = this.getDatasetInfoFromUrl(); diff --git a/src/app/services/elements-view.service.spec.ts b/src/app/services/elements-view.service.spec.ts deleted file mode 100644 index 5c50b1dca..000000000 --- a/src/app/services/elements-view.service.spec.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { TestBed } from '@angular/core/testing'; - -import { ElementsViewService } from './elements-view.service'; - -describe('ElementsViewService', () => { - let service: ElementsViewService; - - beforeEach(() => { - TestBed.configureTestingModule({}); - service = TestBed.inject(ElementsViewService); - }); - - it('should be created', () => { - expect(service).toBeTruthy(); - }); -}); From 31162b81b9bbd27558798b34f5acad24783c05f8 Mon Sep 17 00:00:00 2001 From: Dmitriy Borzenko Date: Tue, 8 Oct 2024 15:56:15 +0300 Subject: [PATCH 6/9] removed unused service --- src/app/auth/logged-user.service.ts | 8 ++-- .../settings/account-settings.component.ts | 2 +- .../dataset-view-menu-item.component.html | 5 +-- .../dataset-view-menu-item.component.ts | 5 +-- .../dataset-view-menu.component.html | 6 +-- .../dataset-view-menu.component.ts | 8 ++-- .../dataset-view-menu.model.ts | 42 +++++++++---------- .../visibility-mode.service.spec.ts | 15 ------- .../visibility-mode.service.ts | 38 ----------------- 9 files changed, 34 insertions(+), 95 deletions(-) delete mode 100644 src/app/dataset-view/dataset-view-menu/visibility-mode.service.spec.ts delete mode 100644 src/app/dataset-view/dataset-view-menu/visibility-mode.service.ts diff --git a/src/app/auth/logged-user.service.ts b/src/app/auth/logged-user.service.ts index ad52477d3..895b84a31 100644 --- a/src/app/auth/logged-user.service.ts +++ b/src/app/auth/logged-user.service.ts @@ -20,7 +20,9 @@ import { takeUntilDestroyed } from "@angular/core/rxjs-interop"; export class LoggedUserService extends UnsubscribeDestroyRefAdapter { private loggedInUser: MaybeNull = null; private loggedInUser$: Subject> = new ReplaySubject>(1); - private adminPrivileges$: BehaviorSubject = new BehaviorSubject(false); + private adminPrivileges$: BehaviorSubject<{ value: boolean }> = new BehaviorSubject<{ value: boolean }>({ + value: false, + }); constructor( private loginService: LoginService, @@ -39,12 +41,12 @@ export class LoggedUserService extends UnsubscribeDestroyRefAdapter { .subscribe((user: AccountFragment) => this.changeUser(user)); } - public get adminPrivilegesChanges(): Observable { + public get adminPrivilegesChanges(): Observable<{ value: boolean }> { return this.adminPrivileges$.asObservable(); } public emitAdminPrivilegesChanges(value: boolean): void { - return this.adminPrivileges$.next(value); + return this.adminPrivileges$.next({ value }); } public initializeCompletes(): Observable { diff --git a/src/app/auth/settings/account-settings.component.ts b/src/app/auth/settings/account-settings.component.ts index 7d568b237..3a6068f46 100644 --- a/src/app/auth/settings/account-settings.component.ts +++ b/src/app/auth/settings/account-settings.component.ts @@ -57,7 +57,7 @@ export class AccountSettingsComponent extends BaseComponent implements OnInit { return user ? { user, - adminPrivileges, + adminPrivileges: adminPrivileges.value, } : null; }), diff --git a/src/app/dataset-view/dataset-view-menu/components/dataset-view-menu-item/dataset-view-menu-item.component.html b/src/app/dataset-view/dataset-view-menu/components/dataset-view-menu-item/dataset-view-menu-item.component.html index 04abffee2..2a2008eee 100644 --- a/src/app/dataset-view/dataset-view-menu/components/dataset-view-menu-item/dataset-view-menu-item.component.html +++ b/src/app/dataset-view/dataset-view-menu/components/dataset-view-menu-item/dataset-view-menu-item.component.html @@ -9,10 +9,7 @@
{{ icon }} {{ label }} - + admin_panel_settings
diff --git a/src/app/dataset-view/dataset-view-menu/components/dataset-view-menu-item/dataset-view-menu-item.component.ts b/src/app/dataset-view/dataset-view-menu/components/dataset-view-menu-item/dataset-view-menu-item.component.ts index cd2a78a96..696ffbc5b 100644 --- a/src/app/dataset-view/dataset-view-menu/components/dataset-view-menu-item/dataset-view-menu-item.component.ts +++ b/src/app/dataset-view/dataset-view-menu/components/dataset-view-menu-item/dataset-view-menu-item.component.ts @@ -1,6 +1,5 @@ import { ChangeDetectionStrategy, Component, Input } from "@angular/core"; import { MaybeUndefined } from "src/app/common/app.types"; -import { ElementVisibilityMode } from "../../visibility-mode.service"; @Component({ selector: "app-dataset-view-menu-item", @@ -15,10 +14,8 @@ export class DatasetViewMenuItemComponent { @Input({ required: true }) public label: string; @Input({ required: true }) public icon: string; @Input({ required: true }) public datasetLink: string; - @Input({ required: true }) public viewMode: ElementVisibilityMode; + @Input({ required: true }) public adminPrivileges: boolean | null; @Input({ required: true }) public visible: boolean; @Input() public disabled: MaybeUndefined; @Input() public showAdminIcon: MaybeUndefined; - - public readonly ElementVisibilityMode: typeof ElementVisibilityMode = ElementVisibilityMode; } diff --git a/src/app/dataset-view/dataset-view-menu/dataset-view-menu.component.html b/src/app/dataset-view/dataset-view-menu/dataset-view-menu.component.html index 84a417912..0eb5cd2f9 100644 --- a/src/app/dataset-view/dataset-view-menu/dataset-view-menu.component.html +++ b/src/app/dataset-view/dataset-view-menu/dataset-view-menu.component.html @@ -3,7 +3,7 @@ [style]="isMinimizeSearchAdditionalButtons ? 'grid-template-columns: 1fr;' : ''" id="container-dataset-tabs" #datasetViewMenu - *ngIf="viewModeElement$ | async as viewMode" + *ngIf="adminPrivileges$ | async as adminPrivileges" >
@@ -14,10 +14,10 @@ [value]="menuItem.value" [label]="menuItem.label" [icon]="menuItem.icon" - [viewMode]="viewMode" + [adminPrivileges]="adminPrivileges.value" [disabled]="menuItem.disabled" [showAdminIcon]="menuItem.showAdminIcon" - [visible]="menuItem.shouldAllowTab(viewMode, datasetPermissions)" + [visible]="menuItem.shouldAllowTab(datasetPermissions, adminPrivileges.value)" [datasetLink]="datasetLink" > diff --git a/src/app/dataset-view/dataset-view-menu/dataset-view-menu.component.ts b/src/app/dataset-view/dataset-view-menu/dataset-view-menu.component.ts index 29f567a7f..12694c3d9 100644 --- a/src/app/dataset-view/dataset-view-menu/dataset-view-menu.component.ts +++ b/src/app/dataset-view/dataset-view-menu/dataset-view-menu.component.ts @@ -17,7 +17,7 @@ import { isMobileView, promiseWithCatch } from "src/app/common/app.helpers"; import { DatasetBasicsFragment, DatasetPermissionsFragment } from "src/app/api/kamu.graphql.interface"; import { Observable } from "rxjs"; import { DatasetViewMenuItems } from "./dataset-view-menu.model"; -import { ElementVisibilityMode, VisibilityModeService } from "./visibility-mode.service"; +import { LoggedUserService } from "src/app/auth/logged-user.service"; @Component({ selector: "app-dataset-view-menu", @@ -35,12 +35,12 @@ export class DatasetViewMenuComponent implements OnInit, AfterViewInit { @Input({ required: true }) datasetViewType: DatasetViewTypeEnum; @Input() isMinimizeSearchAdditionalButtons: boolean; public datasetMenuItemDescriptors = DatasetViewMenuItems; + public adminPrivileges$: Observable<{ value: boolean }>; private sideNavHelper: SideNavHelper; public readonly DatasetViewTypeEnum: typeof DatasetViewTypeEnum = DatasetViewTypeEnum; - private visibilityModeService = inject(VisibilityModeService); private widgetHeightService = inject(WidgetHeightService); - public viewModeElement$: Observable; + private loggedUserService = inject(LoggedUserService); public ngAfterViewInit(): void { this.widgetHeightService.setWidgetOffsetTop( @@ -53,7 +53,7 @@ export class DatasetViewMenuComponent implements OnInit, AfterViewInit { if (this.sidenav) { this.sideNavHelper = new SideNavHelper(this.sidenav); } - this.viewModeElement$ = this.visibilityModeService.viewModeElement(); + this.adminPrivileges$ = this.loggedUserService.adminPrivilegesChanges; } public get datasetLink(): string { diff --git a/src/app/dataset-view/dataset-view-menu/dataset-view-menu.model.ts b/src/app/dataset-view/dataset-view-menu/dataset-view-menu.model.ts index 1a38bb9e8..bcee100ae 100644 --- a/src/app/dataset-view/dataset-view-menu/dataset-view-menu.model.ts +++ b/src/app/dataset-view/dataset-view-menu/dataset-view-menu.model.ts @@ -1,5 +1,4 @@ import { DatasetPermissionsFragment } from "src/app/api/kamu.graphql.interface"; -import { ElementVisibilityMode } from "./visibility-mode.service"; export interface DatasetMenuItemOptions { dataTestId: string; @@ -8,7 +7,7 @@ export interface DatasetMenuItemOptions { icon: string; disabled?: boolean; showAdminIcon?: boolean; - shouldAllowTab: (viewMode: ElementVisibilityMode, permissions: DatasetPermissionsFragment | null) => boolean; + shouldAllowTab: (datasetPermissions: DatasetPermissionsFragment, adminPrivileges?: boolean) => boolean; } export const DatasetViewMenuItems: DatasetMenuItemOptions[] = [ @@ -17,8 +16,8 @@ export const DatasetViewMenuItems: DatasetMenuItemOptions[] = [ value: "overview", label: "Overview", icon: "visibility", - shouldAllowTab: (viewMode: ElementVisibilityMode) => { - return viewMode !== ElementVisibilityMode.UNAVAILABLE; + shouldAllowTab: (datasetPermissions: DatasetPermissionsFragment) => { + return datasetPermissions.permissions.canView; }, }, { @@ -26,8 +25,8 @@ export const DatasetViewMenuItems: DatasetMenuItemOptions[] = [ value: "data", label: "Data", icon: "dataset", - shouldAllowTab: (viewMode: ElementVisibilityMode) => { - return viewMode !== ElementVisibilityMode.UNAVAILABLE; + shouldAllowTab: (datasetPermissions: DatasetPermissionsFragment) => { + return datasetPermissions.permissions.canView; }, }, { @@ -35,8 +34,8 @@ export const DatasetViewMenuItems: DatasetMenuItemOptions[] = [ value: "metadata", label: "Metadata", icon: "dataset_linked", - shouldAllowTab: (viewMode: ElementVisibilityMode) => { - return viewMode !== ElementVisibilityMode.UNAVAILABLE; + shouldAllowTab: (datasetPermissions: DatasetPermissionsFragment) => { + return datasetPermissions.permissions.canView; }, }, { @@ -44,8 +43,8 @@ export const DatasetViewMenuItems: DatasetMenuItemOptions[] = [ value: "history", label: "History", icon: "manage_history", - shouldAllowTab: (viewMode: ElementVisibilityMode) => { - return viewMode !== ElementVisibilityMode.UNAVAILABLE; + shouldAllowTab: (datasetPermissions: DatasetPermissionsFragment) => { + return datasetPermissions.permissions.canView; }, }, { @@ -53,8 +52,8 @@ export const DatasetViewMenuItems: DatasetMenuItemOptions[] = [ value: "lineage", label: "Lineage", icon: "account_tree", - shouldAllowTab: (viewMode: ElementVisibilityMode) => { - return viewMode !== ElementVisibilityMode.UNAVAILABLE; + shouldAllowTab: (datasetPermissions: DatasetPermissionsFragment) => { + return datasetPermissions.permissions.canView; }, }, @@ -64,8 +63,8 @@ export const DatasetViewMenuItems: DatasetMenuItemOptions[] = [ label: "Discussions", icon: "message", disabled: true, - shouldAllowTab: (viewMode: ElementVisibilityMode) => { - return viewMode !== ElementVisibilityMode.UNAVAILABLE; + shouldAllowTab: (datasetPermissions: DatasetPermissionsFragment) => { + return datasetPermissions.permissions.canView; }, }, { @@ -74,11 +73,8 @@ export const DatasetViewMenuItems: DatasetMenuItemOptions[] = [ label: "Flows", icon: "add_task", showAdminIcon: true, - shouldAllowTab: (viewMode: ElementVisibilityMode, permissions: DatasetPermissionsFragment | null) => { - return ( - viewMode === ElementVisibilityMode.AVAILABLE_VIA_ADMIN_PRIVILEGES || - Boolean(permissions?.permissions.canSchedule) - ); + shouldAllowTab: (datasetPermissions: DatasetPermissionsFragment, adminPrivileges?: boolean) => { + return Boolean(adminPrivileges) || datasetPermissions?.permissions.canSchedule; }, }, { @@ -87,11 +83,11 @@ export const DatasetViewMenuItems: DatasetMenuItemOptions[] = [ label: "Settings", icon: "settings", showAdminIcon: true, - shouldAllowTab: (viewMode: ElementVisibilityMode, permissions: DatasetPermissionsFragment | null) => { + shouldAllowTab: (datasetPermissions: DatasetPermissionsFragment, adminPrivileges?: boolean) => { return ( - viewMode === ElementVisibilityMode.AVAILABLE_VIA_ADMIN_PRIVILEGES || - Boolean(permissions?.permissions.canDelete) || - Boolean(permissions?.permissions.canRename) + Boolean(adminPrivileges) || + datasetPermissions.permissions.canDelete || + datasetPermissions.permissions.canRename ); }, }, diff --git a/src/app/dataset-view/dataset-view-menu/visibility-mode.service.spec.ts b/src/app/dataset-view/dataset-view-menu/visibility-mode.service.spec.ts deleted file mode 100644 index 78059453c..000000000 --- a/src/app/dataset-view/dataset-view-menu/visibility-mode.service.spec.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { TestBed } from "@angular/core/testing"; -import { VisibilityModeService } from "./visibility-mode.service"; - -describe("VisibilityModeService", () => { - let service: VisibilityModeService; - - beforeEach(() => { - TestBed.configureTestingModule({}); - service = TestBed.inject(VisibilityModeService); - }); - - it("should be created", () => { - expect(service).toBeTruthy(); - }); -}); diff --git a/src/app/dataset-view/dataset-view-menu/visibility-mode.service.ts b/src/app/dataset-view/dataset-view-menu/visibility-mode.service.ts deleted file mode 100644 index 7130ff229..000000000 --- a/src/app/dataset-view/dataset-view-menu/visibility-mode.service.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { combineLatest, map, Observable } from "rxjs"; -import { inject, Injectable } from "@angular/core"; -import { LoggedUserService } from "../../auth/logged-user.service"; -import { DatasetSubscriptionsService } from "../dataset.subscriptions.service"; - -@Injectable({ - providedIn: "root", -}) -export class VisibilityModeService { - private loggedUserService = inject(LoggedUserService); - private datasetSubsService = inject(DatasetSubscriptionsService); - - public viewModeElement(): Observable { - return combineLatest([ - this.loggedUserService.adminPrivilegesChanges, - this.datasetSubsService.permissionsChanges, - ]).pipe( - map(([adminPrivileges, datasetPermissions]) => { - if (adminPrivileges) { - return ElementVisibilityMode.AVAILABLE_VIA_ADMIN_PRIVILEGES; - } - - const permissions = datasetPermissions.permissions; - if (permissions.canView) { - return ElementVisibilityMode.AVAILABLE_VIA_PERMISSIONS; - } - - return ElementVisibilityMode.UNAVAILABLE; - }), - ); - } -} - -export enum ElementVisibilityMode { - UNAVAILABLE, - AVAILABLE_VIA_PERMISSIONS, - AVAILABLE_VIA_ADMIN_PRIVILEGES, -} From 878e97d37f6545d25f8000f4782ef1da19dabd3a Mon Sep 17 00:00:00 2001 From: Dmitriy Borzenko Date: Wed, 9 Oct 2024 16:47:39 +0300 Subject: [PATCH 7/9] Changed admin guard --- src/app/account/account.component.ts | 2 -- src/app/app-routing.module.ts | 4 +-- src/app/app.component.ts | 6 ++-- src/app/auth/guards/admin.guard.ts | 36 +++++++++---------- .../settings/account-settings.component.ts | 3 -- src/app/common/base.component.ts | 3 ++ .../app-header/app-header.component.html | 19 ++++++---- .../app-header/app-header.component.scss | 12 +++++++ .../app-header/app-header.component.ts | 2 ++ .../dataset-create.component.ts | 2 -- .../final-yaml-modal.component.ts | 2 -- .../edit-details-modal.component.ts | 2 -- .../edit-license-modal.component.ts | 2 -- .../edit-watermark-modal.component.ts | 2 -- .../readme-section.component.ts | 2 -- .../overview-component/overview.component.ts | 2 -- 16 files changed, 50 insertions(+), 51 deletions(-) diff --git a/src/app/account/account.component.ts b/src/app/account/account.component.ts index e01b5f8ce..d8789059b 100644 --- a/src/app/account/account.component.ts +++ b/src/app/account/account.component.ts @@ -14,7 +14,6 @@ import { MaybeNull } from "src/app/common/app.types"; import { AccountNotFoundError } from "src/app/common/errors"; import { AccountPageQueryParams } from "./account.component.model"; import { ModalService } from "../components/modal/modal.service"; -import { LoggedUserService } from "../auth/logged-user.service"; @Component({ selector: "app-account", @@ -35,7 +34,6 @@ export class AccountComponent extends BaseComponent implements OnInit { private route = inject(ActivatedRoute); private modalService = inject(ModalService); private accountService = inject(AccountService); - private loggedUserService = inject(LoggedUserService); public ngOnInit(): void { const accountName$ = this.route.params.pipe( diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts index c72c7ae8e..1f635718d 100644 --- a/src/app/app-routing.module.ts +++ b/src/app/app-routing.module.ts @@ -15,7 +15,7 @@ import { SetTransformComponent } from "./dataset-view/additional-components/meta import { LoginGuard } from "./auth/guards/login.guard"; import { ReturnToCliComponent } from "./components/return-to-cli/return-to-cli.component"; import { AddPushSourceComponent } from "./dataset-view/additional-components/metadata-component/components/source-events/add-push-source/add-push-source.component"; -import { AdminGuard } from "./auth/guards/admin.guard"; +import { adminGuard } from "./auth/guards/admin.guard"; import { AdminDashboardComponent } from "./admin-view/admin-dashboard/admin-dashboard.component"; import { DatasetFlowDetailsComponent } from "./dataset-flow/dataset-flow-details/dataset-flow-details.component"; import { AccountComponent } from "./account/account.component"; @@ -42,7 +42,7 @@ export const routes: Routes = [ component: DatasetCreateComponent, }, { - canActivate: [AdminGuard], + canActivate: [adminGuard], path: ProjectLinks.URL_ADMIN_DASHBOARD, component: AdminDashboardComponent, }, diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 5023571b4..1ab9affe9 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -17,7 +17,6 @@ import { LoginService } from "./auth/login/login.service"; import { loadErrorMessages } from "@apollo/client/dev"; import { isDevMode } from "@angular/core"; import moment from "moment"; -import { LoggedUserService } from "./auth/logged-user.service"; import packageFile from "../../package.json"; import { LocalStorageService } from "./services/local-storage.service"; import { takeUntilDestroyed } from "@angular/core/rxjs-interop"; @@ -63,7 +62,6 @@ export class AppComponent extends BaseComponent implements OnInit { private navigationService = inject(NavigationService); private appConfigService = inject(AppConfigService); private cdr = inject(ChangeDetectorRef); - private loggedUserService = inject(LoggedUserService); private localStorageService = inject(LocalStorageService); public ngOnInit(): void { @@ -182,7 +180,7 @@ export class AppComponent extends BaseComponent implements OnInit { yesButtonText: "Ok", }), ); - //TODO: Implement AdminDashBoardComponent - // this.navigationService.navigateToAdminDashBoard(); + // TODO: Implement AdminDashBoardComponent + // this.navigationService.navigateToAdminDashBoard(); } } diff --git a/src/app/auth/guards/admin.guard.ts b/src/app/auth/guards/admin.guard.ts index 7d0d1a580..685f4ebea 100644 --- a/src/app/auth/guards/admin.guard.ts +++ b/src/app/auth/guards/admin.guard.ts @@ -1,23 +1,21 @@ -import { inject, Injectable } from "@angular/core"; +import { inject } from "@angular/core"; import { NavigationService } from "src/app/services/navigation.service"; import { LoggedUserService } from "../logged-user.service"; +import { CanActivateFn } from "@angular/router"; +import { combineLatest, map, of } from "rxjs"; -@Injectable({ - providedIn: "root", -}) -export class AdminGuard { - private navigationService = inject(NavigationService); - private loggedUserService = inject(LoggedUserService); +export const adminGuard: CanActivateFn = () => { + const navigationService = inject(NavigationService); + const loggedUserService = inject(LoggedUserService); - public canActivate(): boolean { - if (!this.isAdmin()) { - this.navigationService.navigateToHome(); - return false; - } - return true; - } - - private isAdmin(): boolean { - return this.loggedUserService.isAdmin; - } -} + return combineLatest([of(loggedUserService.isAdmin), loggedUserService.adminPrivilegesChanges]).pipe( + map(([isAdmin, adminPrivileges]) => { + if (isAdmin && adminPrivileges.value) { + return true; + } else { + navigationService.navigateToHome(); + return false; + } + }), + ); +}; diff --git a/src/app/auth/settings/account-settings.component.ts b/src/app/auth/settings/account-settings.component.ts index 3a6068f46..b7c3f27b3 100644 --- a/src/app/auth/settings/account-settings.component.ts +++ b/src/app/auth/settings/account-settings.component.ts @@ -8,7 +8,6 @@ import { BaseComponent } from "src/app/common/base.component"; import AppValues from "src/app/common/app.values"; import { MaybeNull, MaybeUndefined } from "src/app/common/app.types"; import { combineLatest, Observable } from "rxjs"; -import { LoggedUserService } from "../logged-user.service"; import { takeUntilDestroyed } from "@angular/core/rxjs-interop"; import { MatSlideToggleChange } from "@angular/material/slide-toggle"; import { LocalStorageService } from "src/app/services/local-storage.service"; @@ -25,11 +24,9 @@ export class AccountSettingsComponent extends BaseComponent implements OnInit { public activeTab: AccountSettingsTabs = AccountSettingsTabs.PROFILE; public user$: Observable>; - public adminPrivileges$: Observable; private router = inject(Router); private route = inject(ActivatedRoute); - private loggedUserService = inject(LoggedUserService); private localStorageService = inject(LocalStorageService); public userData$: Observable<{ diff --git a/src/app/common/base.component.ts b/src/app/common/base.component.ts index 964617044..3027747d2 100644 --- a/src/app/common/base.component.ts +++ b/src/app/common/base.component.ts @@ -5,9 +5,12 @@ import ProjectLinks from "../project-links"; import { requireValue } from "./app.helpers"; import { UnsubscribeDestroyRefAdapter } from "./unsubscribe.ondestroy.adapter"; import { Observable, map } from "rxjs"; +import { LoggedUserService } from "../auth/logged-user.service"; export abstract class BaseComponent extends UnsubscribeDestroyRefAdapter { + public adminPrivileges$: Observable<{ value: boolean }>; protected activatedRoute = inject(ActivatedRoute); + protected loggedUserService = inject(LoggedUserService); public get searchString(): string { return window.location.search; diff --git a/src/app/components/app-header/app-header.component.html b/src/app/components/app-header/app-header.component.html index fc9023425..30b044f5a 100644 --- a/src/app/components/app-header/app-header.component.html +++ b/src/app/components/app-header/app-header.component.html @@ -119,13 +119,18 @@ Your Datasets - - Dashboard - + + + Dashboard + + + admin_panel_settings + = { root: DatasetKind.Root, diff --git a/src/app/dataset-view/additional-components/metadata-component/components/final-yaml-modal/final-yaml-modal.component.ts b/src/app/dataset-view/additional-components/metadata-component/components/final-yaml-modal/final-yaml-modal.component.ts index 21e10d0e1..0ad73619d 100644 --- a/src/app/dataset-view/additional-components/metadata-component/components/final-yaml-modal/final-yaml-modal.component.ts +++ b/src/app/dataset-view/additional-components/metadata-component/components/final-yaml-modal/final-yaml-modal.component.ts @@ -3,7 +3,6 @@ import { ChangeDetectionStrategy, Component, inject, Input } from "@angular/core import { NgbActiveModal } from "@ng-bootstrap/ng-bootstrap"; import { DatasetInfo } from "src/app/interface/navigation.interface"; import { DatasetCommitService } from "../../../overview-component/services/dataset-commit.service"; -import { LoggedUserService } from "src/app/auth/logged-user.service"; import { takeUntilDestroyed } from "@angular/core/rxjs-interop"; @Component({ @@ -18,7 +17,6 @@ export class FinalYamlModalComponent extends BaseComponent { public activeModal = inject(NgbActiveModal); private datasetCommitService = inject(DatasetCommitService); - private loggedUserService = inject(LoggedUserService); public saveEvent(): void { this.datasetCommitService diff --git a/src/app/dataset-view/additional-components/overview-component/components/edit-details-modal/edit-details-modal.component.ts b/src/app/dataset-view/additional-components/overview-component/components/edit-details-modal/edit-details-modal.component.ts index da391b6f3..152e38cd6 100644 --- a/src/app/dataset-view/additional-components/overview-component/components/edit-details-modal/edit-details-modal.component.ts +++ b/src/app/dataset-view/additional-components/overview-component/components/edit-details-modal/edit-details-modal.component.ts @@ -12,7 +12,6 @@ import { BaseComponent } from "src/app/common/base.component"; import { DatasetSchema, DataRow } from "src/app/interface/dataset.interface"; import { TemplatesYamlEventsService } from "src/app/services/templates-yaml-events.service"; import { DatasetCommitService } from "../../services/dataset-commit.service"; -import { LoggedUserService } from "src/app/auth/logged-user.service"; import { finalize } from "rxjs"; import { takeUntilDestroyed } from "@angular/core/rxjs-interop"; @@ -36,7 +35,6 @@ export class EditDetailsModalComponent extends BaseComponent implements OnInit { private datasetCommitService = inject(DatasetCommitService); private yamlEventService = inject(TemplatesYamlEventsService); public activeModal = inject(NgbActiveModal); - private loggedUserService = inject(LoggedUserService); public get keywords(): string[] { return Array.from(this.keywordsSet); diff --git a/src/app/dataset-view/additional-components/overview-component/components/edit-license-modal/edit-license-modal.component.ts b/src/app/dataset-view/additional-components/overview-component/components/edit-license-modal/edit-license-modal.component.ts index be343cf77..c2b57e9d4 100644 --- a/src/app/dataset-view/additional-components/overview-component/components/edit-license-modal/edit-license-modal.component.ts +++ b/src/app/dataset-view/additional-components/overview-component/components/edit-license-modal/edit-license-modal.component.ts @@ -13,7 +13,6 @@ import { MaybeNull } from "src/app/common/app.types"; import { DatasetSchema, DataRow } from "src/app/interface/dataset.interface"; import { TemplatesYamlEventsService } from "src/app/services/templates-yaml-events.service"; import { DatasetCommitService } from "../../services/dataset-commit.service"; -import { LoggedUserService } from "src/app/auth/logged-user.service"; import { finalize } from "rxjs"; import { LicenseFormType } from "./edit-license-modal.types"; import { takeUntilDestroyed } from "@angular/core/rxjs-interop"; @@ -27,7 +26,6 @@ export class EditLicenseModalComponent extends BaseComponent implements OnInit { private fb = inject(FormBuilder); private datasetCommitService = inject(DatasetCommitService); private yamlEventService = inject(TemplatesYamlEventsService); - private loggedUserService = inject(LoggedUserService); @Input({ required: true }) public datasetBasics: DatasetBasicsFragment; @Input({ required: true }) public currentState?: { diff --git a/src/app/dataset-view/additional-components/overview-component/components/edit-watermark-modal/edit-watermark-modal.component.ts b/src/app/dataset-view/additional-components/overview-component/components/edit-watermark-modal/edit-watermark-modal.component.ts index db6316bc9..f57163f91 100644 --- a/src/app/dataset-view/additional-components/overview-component/components/edit-watermark-modal/edit-watermark-modal.component.ts +++ b/src/app/dataset-view/additional-components/overview-component/components/edit-watermark-modal/edit-watermark-modal.component.ts @@ -7,7 +7,6 @@ import { DatasetBasicsFragment } from "src/app/api/kamu.graphql.interface"; import { BaseComponent } from "src/app/common/base.component"; import { MY_MOMENT_FORMATS } from "src/app/common/data.helpers"; import { DatasetCommitService } from "../../services/dataset-commit.service"; -import { LoggedUserService } from "src/app/auth/logged-user.service"; import { finalize } from "rxjs"; import { takeUntilDestroyed } from "@angular/core/rxjs-interop"; @@ -26,7 +25,6 @@ export class EditWatermarkModalComponent extends BaseComponent implements OnInit public activeModal = inject(NgbActiveModal); private datasetCommitService = inject(DatasetCommitService); - private loggedUserService = inject(LoggedUserService); ngOnInit(): void { this.date = new Date(); diff --git a/src/app/dataset-view/additional-components/overview-component/components/readme-section/readme-section.component.ts b/src/app/dataset-view/additional-components/overview-component/components/readme-section/readme-section.component.ts index cb852108b..f3bd57c70 100644 --- a/src/app/dataset-view/additional-components/overview-component/components/readme-section/readme-section.component.ts +++ b/src/app/dataset-view/additional-components/overview-component/components/readme-section/readme-section.component.ts @@ -4,7 +4,6 @@ import { MaybeNull } from "src/app/common/app.types"; import { BaseComponent } from "src/app/common/base.component"; import { EditMode } from "./readme-section.types"; import { DatasetCommitService } from "../../services/dataset-commit.service"; -import { LoggedUserService } from "src/app/auth/logged-user.service"; import { takeUntilDestroyed } from "@angular/core/rxjs-interop"; @Component({ @@ -29,7 +28,6 @@ export class ReadmeSectionComponent extends BaseComponent implements OnInit { } private datasetCommitService = inject(DatasetCommitService); - private loggedUserService = inject(LoggedUserService); public ngOnInit(): void { if (this.currentReadme) { diff --git a/src/app/dataset-view/additional-components/overview-component/overview.component.ts b/src/app/dataset-view/additional-components/overview-component/overview.component.ts index 41de007f2..a47d71162 100644 --- a/src/app/dataset-view/additional-components/overview-component/overview.component.ts +++ b/src/app/dataset-view/additional-components/overview-component/overview.component.ts @@ -32,7 +32,6 @@ import { promiseWithCatch } from "src/app/common/app.helpers"; import { ModalService } from "src/app/components/modal/modal.service"; import AppValues from "src/app/common/app.values"; import { FileUploadService } from "src/app/services/file-upload.service"; -import { LoggedUserService } from "src/app/auth/logged-user.service"; import ProjectLinks from "src/app/project-links"; import { takeUntilDestroyed } from "@angular/core/rxjs-interop"; @@ -69,7 +68,6 @@ export class OverviewComponent extends BaseComponent implements OnInit { private fileUploadService = inject(FileUploadService); private configService = inject(AppConfigService); private modalService = inject(ModalService); - private loggedUserService = inject(LoggedUserService); public ngOnInit(): void { this.uploadFileLoading$ = this.fileUploadService.isUploadFile; From b9ed47d2a731a0114ca478b5d4e8b672a8338a15 Mon Sep 17 00:00:00 2001 From: Dmitriy Borzenko Date: Wed, 9 Oct 2024 22:03:32 +0300 Subject: [PATCH 8/9] added component wrapper for admin links --- .../admin-link/admin-link.component.html | 2 ++ .../admin-link/admin-link.component.scss | 25 +++++++++++++++++++ .../admin-link/admin-link.component.spec.ts | 21 ++++++++++++++++ .../admin-link/admin-link.component.ts | 12 +++++++++ src/app/app.module.ts | 2 ++ .../app-header/app-header.component.html | 17 ++++++------- .../app-header/app-header.component.scss | 12 --------- 7 files changed, 69 insertions(+), 22 deletions(-) create mode 100644 src/app/admin-view/admin-link/admin-link.component.html create mode 100644 src/app/admin-view/admin-link/admin-link.component.scss create mode 100644 src/app/admin-view/admin-link/admin-link.component.spec.ts create mode 100644 src/app/admin-view/admin-link/admin-link.component.ts diff --git a/src/app/admin-view/admin-link/admin-link.component.html b/src/app/admin-view/admin-link/admin-link.component.html new file mode 100644 index 000000000..5abfed52c --- /dev/null +++ b/src/app/admin-view/admin-link/admin-link.component.html @@ -0,0 +1,2 @@ + + admin_panel_settings diff --git a/src/app/admin-view/admin-link/admin-link.component.scss b/src/app/admin-view/admin-link/admin-link.component.scss new file mode 100644 index 000000000..07d6da3f0 --- /dev/null +++ b/src/app/admin-view/admin-link/admin-link.component.scss @@ -0,0 +1,25 @@ +:host { + position: relative; +} + +.admin-privileges-icon { + font-size: 16px; + position: absolute; + top: -4px; + right: -27px; + display: block; +} + +.light-theme { + color: #f1f1f1 !important; +} + +.dark-theme { + color: #378bb0 !important; +} + +@media (width <=768px) { + .admin-privileges-icon { + display: none; + } +} diff --git a/src/app/admin-view/admin-link/admin-link.component.spec.ts b/src/app/admin-view/admin-link/admin-link.component.spec.ts new file mode 100644 index 000000000..a0d747274 --- /dev/null +++ b/src/app/admin-view/admin-link/admin-link.component.spec.ts @@ -0,0 +1,21 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { AdminLinkComponent } from './admin-link.component'; + +describe('AdminLinkComponent', () => { + let component: AdminLinkComponent; + let fixture: ComponentFixture; + + beforeEach(() => { + TestBed.configureTestingModule({ + declarations: [AdminLinkComponent] + }); + fixture = TestBed.createComponent(AdminLinkComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/admin-view/admin-link/admin-link.component.ts b/src/app/admin-view/admin-link/admin-link.component.ts new file mode 100644 index 000000000..19c85c72f --- /dev/null +++ b/src/app/admin-view/admin-link/admin-link.component.ts @@ -0,0 +1,12 @@ +import { ChangeDetectionStrategy, Component, Input } from "@angular/core"; + +@Component({ + selector: "app-admin-link", + templateUrl: "./admin-link.component.html", + styleUrls: ["./admin-link.component.scss"], + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class AdminLinkComponent { + @Input({ required: true }) adminPrivileges: boolean; + @Input() theme: string = "light-theme"; +} diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 946a90110..7842b0bef 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -73,6 +73,7 @@ import { AccountComponent } from "./account/account.component"; import { DatasetsTabComponent } from "./account/additional-components/datasets-tab/datasets-tab.component"; import { AccessTokensTabComponent } from "./auth/settings/tabs/access-tokens-tab/access-tokens-tab.component"; import { MatSlideToggleModule } from "@angular/material/slide-toggle"; +import { AdminLinkComponent } from "./admin-view/admin-link/admin-link.component"; const Services = [ { @@ -204,6 +205,7 @@ const MatModules = [ AdminDashboardComponent, AccessTokensTabComponent, AccountFlowsTabComponent, + AdminLinkComponent, ], imports: [ AppRoutingModule, diff --git a/src/app/components/app-header/app-header.component.html b/src/app/components/app-header/app-header.component.html index 30b044f5a..83e289ed0 100644 --- a/src/app/components/app-header/app-header.component.html +++ b/src/app/components/app-header/app-header.component.html @@ -120,16 +120,13 @@ - - Dashboard - - - admin_panel_settings + + + + Dashboard + + + Date: Mon, 28 Oct 2024 16:05:21 +0200 Subject: [PATCH 9/9] added prototype for button --- src/app/common/app.types.ts | 11 +++++++++ .../admin-available-button.component.html | 5 ++++ .../admin-available-button.component.scss | 7 ++++++ .../admin-available-button.component.spec.ts | 21 +++++++++++++++++ .../admin-available-button.component.ts | 23 +++++++++++++++++++ .../flow-details-logs-tab.component.ts | 2 -- .../data-component/data.component.ts | 2 -- .../overview.component.html | 23 +++++++++++-------- .../overview.component.model.ts | 8 +++++++ .../overview-component/overview.component.ts | 8 +++++++ src/app/shared/shared/shared.module.ts | 3 +++ 11 files changed, 99 insertions(+), 14 deletions(-) create mode 100644 src/app/common/components/admin-available-button/admin-available-button.component.html create mode 100644 src/app/common/components/admin-available-button/admin-available-button.component.scss create mode 100644 src/app/common/components/admin-available-button/admin-available-button.component.spec.ts create mode 100644 src/app/common/components/admin-available-button/admin-available-button.component.ts create mode 100644 src/app/dataset-view/additional-components/overview-component/overview.component.model.ts diff --git a/src/app/common/app.types.ts b/src/app/common/app.types.ts index a43eec10a..c03b27e34 100644 --- a/src/app/common/app.types.ts +++ b/src/app/common/app.types.ts @@ -1,3 +1,14 @@ export type MaybeNull = T | null; export type MaybeUndefined = T | undefined; export type MaybeNullOrUndefined = T | null | undefined; + +export interface AdminAvailableButtonType { + label: string; + icon: string; + datasetId: string; + visible?: boolean; + showAdminIcon?: boolean; + adminPrivileges?: boolean; + disabled?: boolean; + class?: string; +} diff --git a/src/app/common/components/admin-available-button/admin-available-button.component.html b/src/app/common/components/admin-available-button/admin-available-button.component.html new file mode 100644 index 000000000..5e7cdbbc1 --- /dev/null +++ b/src/app/common/components/admin-available-button/admin-available-button.component.html @@ -0,0 +1,5 @@ + diff --git a/src/app/common/components/admin-available-button/admin-available-button.component.scss b/src/app/common/components/admin-available-button/admin-available-button.component.scss new file mode 100644 index 000000000..d7f8faa6c --- /dev/null +++ b/src/app/common/components/admin-available-button/admin-available-button.component.scss @@ -0,0 +1,7 @@ +mat-icon.admin-icon { + color: #378bb0; + transform: scale(0.65); + position: relative; + bottom: 4px; + right: 6px; +} diff --git a/src/app/common/components/admin-available-button/admin-available-button.component.spec.ts b/src/app/common/components/admin-available-button/admin-available-button.component.spec.ts new file mode 100644 index 000000000..4a5369373 --- /dev/null +++ b/src/app/common/components/admin-available-button/admin-available-button.component.spec.ts @@ -0,0 +1,21 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { AdminAvailableButtonComponent } from './admin-available-button.component'; + +describe('AdminAvailableButtonComponent', () => { + let component: AdminAvailableButtonComponent; + let fixture: ComponentFixture; + + beforeEach(() => { + TestBed.configureTestingModule({ + declarations: [AdminAvailableButtonComponent] + }); + fixture = TestBed.createComponent(AdminAvailableButtonComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/common/components/admin-available-button/admin-available-button.component.ts b/src/app/common/components/admin-available-button/admin-available-button.component.ts new file mode 100644 index 000000000..ab9e81283 --- /dev/null +++ b/src/app/common/components/admin-available-button/admin-available-button.component.ts @@ -0,0 +1,23 @@ +import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output } from "@angular/core"; + +@Component({ + selector: "app-admin-available-button", + templateUrl: "./admin-available-button.component.html", + styleUrls: ["./admin-available-button.component.scss"], + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class AdminAvailableButtonComponent { + @Input() public visible: boolean = true; + @Input() public icon: string = ""; + @Input({ required: true }) public label: string; + @Input() public class?: string; + @Input() public disabled: boolean; + @Input() public datasetId: string; + @Input() public showAdwinIcon: boolean; + @Input() public adminPrivileges: boolean; + @Output() public onClick = new EventEmitter(); + + public click(): void { + this.onClick.emit(); + } +} diff --git a/src/app/dataset-flow/dataset-flow-details/tabs/flow-details-logs-tab/flow-details-logs-tab.component.ts b/src/app/dataset-flow/dataset-flow-details/tabs/flow-details-logs-tab/flow-details-logs-tab.component.ts index 5140aefc3..840788bd6 100644 --- a/src/app/dataset-flow/dataset-flow-details/tabs/flow-details-logs-tab/flow-details-logs-tab.component.ts +++ b/src/app/dataset-flow/dataset-flow-details/tabs/flow-details-logs-tab/flow-details-logs-tab.component.ts @@ -1,5 +1,4 @@ import { ChangeDetectionStrategy, Component, inject, Input } from "@angular/core"; -import { LoggedUserService } from "src/app/auth/logged-user.service"; import { BaseComponent } from "src/app/common/base.component"; import { GrafanaLogsService } from "../../grafana-logs.service"; import { DatasetFlowByIdResponse } from "../../dataset-flow-details.types"; @@ -13,7 +12,6 @@ import { AppConfigService } from "src/app/app-config.service"; }) export class FlowDetailsLogsTabComponent extends BaseComponent { @Input({ required: true }) flowDetails: DatasetFlowByIdResponse; - private loggedUserService = inject(LoggedUserService); private grafanaLogsService = inject(GrafanaLogsService); private appConfigService = inject(AppConfigService); diff --git a/src/app/dataset-view/additional-components/data-component/data.component.ts b/src/app/dataset-view/additional-components/data-component/data.component.ts index d8d0d852d..90a5c5719 100644 --- a/src/app/dataset-view/additional-components/data-component/data.component.ts +++ b/src/app/dataset-view/additional-components/data-component/data.component.ts @@ -28,7 +28,6 @@ import { takeUntilDestroyed } from "@angular/core/rxjs-interop"; import { Clipboard } from "@angular/cdk/clipboard"; import ProjectLinks from "src/app/project-links"; import { ToastrService } from "ngx-toastr"; -import { LoggedUserService } from "src/app/auth/logged-user.service"; import { AppConfigService } from "src/app/app-config.service"; import { UploadPrepareData, UploadPrepareResponse } from "src/app/common/ingest-via-file-upload.types"; import { FileUploadService } from "src/app/services/file-upload.service"; @@ -68,7 +67,6 @@ export class DataComponent extends BaseComponent implements OnInit { private cdr = inject(ChangeDetectorRef); private clipboard = inject(Clipboard); private toastService = inject(ToastrService); - private loggedUserService = inject(LoggedUserService); private appConfigService = inject(AppConfigService); private queryExplainerService = inject(QueryExplainerService); private fileUploadService = inject(FileUploadService); diff --git a/src/app/dataset-view/additional-components/overview-component/overview.component.html b/src/app/dataset-view/additional-components/overview-component/overview.component.html index e4692902b..bed2043d3 100644 --- a/src/app/dataset-view/additional-components/overview-component/overview.component.html +++ b/src/app/dataset-view/additional-components/overview-component/overview.component.html @@ -114,16 +114,19 @@

Keywords

add Add data - + + + +
; + public adminPrivileges$: Observable<{ value: boolean }>; public readonly UPLOAD_FILE_IMAGE = AppValues.UPLOAD_FILE_IMAGE; public readonly URL_PARAM_ADD_POLLING_SOURCE = ProjectLinks.URL_PARAM_ADD_POLLING_SOURCE; public readonly URL_PARAM_SET_TRANSFORM = ProjectLinks.URL_PARAM_SET_TRANSFORM; public readonly URL_PARAM_ADD_PUSH_SOURCE = ProjectLinks.URL_PARAM_ADD_PUSH_SOURCE; + public readonly UPDATE_BUTTON_DESCRIPTOR = updateButtonDescriptor; public currentState?: { schema: MaybeNull; @@ -81,6 +84,7 @@ export class OverviewComponent extends BaseComponent implements OnInit { overview: overviewUpdate.overview, }; }); + this.adminPrivileges$ = this.loggedUserService.adminPrivilegesChanges; } public showWebsite(url: string): void { @@ -91,6 +95,10 @@ export class OverviewComponent extends BaseComponent implements OnInit { this.selectTopicEmit.emit(topicName); } + public get isOwnerDataset(): boolean { + return this.datasetBasics.owner.accountName === this.loggedUserService.currentlyLoggedInUser.accountName; + } + public get metadataFragmentBlock(): MaybeUndefined { return this.currentState ? this.currentState.overview.metadata.chain.blocks.nodes[0] : undefined; } diff --git a/src/app/shared/shared/shared.module.ts b/src/app/shared/shared/shared.module.ts index af34510e2..4aa48b5cf 100644 --- a/src/app/shared/shared/shared.module.ts +++ b/src/app/shared/shared/shared.module.ts @@ -20,6 +20,7 @@ import { SafeHtmlPipe } from "src/app/common/pipes/safe-html.pipe"; import { DragAndDropDirective } from "src/app/common/directives/drag-and-drop.directive"; import { YamlEventViewerComponent } from "src/app/dataset-block/metadata-block/components/event-details/components/common/yaml-event-viewer/yaml-event-viewer.component"; import { RouterModule } from "@angular/router"; +import { AdminAvailableButtonComponent } from "src/app/common/components/admin-available-button/admin-available-button.component"; @NgModule({ declarations: [ @@ -36,6 +37,7 @@ import { RouterModule } from "@angular/router"; SafeHtmlPipe, DragAndDropDirective, YamlEventViewerComponent, + AdminAvailableButtonComponent, ], imports: [ CommonModule, @@ -64,6 +66,7 @@ import { RouterModule } from "@angular/router"; SafeHtmlPipe, DragAndDropDirective, YamlEventViewerComponent, + AdminAvailableButtonComponent, ], }) export class SharedModule {}