This is an automated email from the ASF dual-hosted git repository. riemer pushed a commit to branch fix-permission-management-dashboard in repository https://gitbox.apache.org/repos/asf/streampipes.git
commit 1a6612233a495b67f589f9fa3cc14846b3d6dccc Author: Dominik Riemer <[email protected]> AuthorDate: Tue Nov 25 10:45:08 2025 +0100 fix: Align UI views with dashboard and data explorer permissions --- .../panel/dashboard-panel.component.html | 4 +-- .../components/panel/dashboard-panel.component.ts | 8 +++--- .../dashboard-toolbar.component.html | 4 +-- .../dashboard-toolbar.component.ts | 2 +- .../data-explorer-chart-container.component.html | 32 ++++++++++++---------- .../data-explorer-chart-container.component.ts | 4 +++ .../data-explorer-chart-view.component.ts | 26 +++++++++++++++--- .../data-explorer-overview-table.component.ts | 5 +++- .../pipeline-details-toolbar.component.html | 26 ++++++++++-------- .../pipeline-details-toolbar.component.ts | 3 ++ .../pipeline-details.component.html | 1 + .../pipeline-details/pipeline-details.component.ts | 12 ++++---- 12 files changed, 79 insertions(+), 48 deletions(-) diff --git a/ui/src/app/dashboard/components/panel/dashboard-panel.component.html b/ui/src/app/dashboard/components/panel/dashboard-panel.component.html index a2aca9c431..e7daf7b908 100644 --- a/ui/src/app/dashboard/components/panel/dashboard-panel.component.html +++ b/ui/src/app/dashboard/components/panel/dashboard-panel.component.html @@ -31,9 +31,7 @@ [dashboard]="dashboard" [editMode]="editMode" [(viewMode)]="viewMode" - [hasDataExplorerWritePrivileges]=" - hasDataExplorerWritePrivileges - " + [hasDashboardWritePrivileges]="hasDashboardWritePrivileges" [timeRangeVisible]="timeRangeVisible" [timeSettings]="timeSettings" (saveDashboardEmitter)="persistDashboardChanges()" diff --git a/ui/src/app/dashboard/components/panel/dashboard-panel.component.ts b/ui/src/app/dashboard/components/panel/dashboard-panel.component.ts index 0946164609..93ca7bb5fc 100644 --- a/ui/src/app/dashboard/components/panel/dashboard-panel.component.ts +++ b/ui/src/app/dashboard/components/panel/dashboard-panel.component.ts @@ -80,7 +80,7 @@ export class DashboardPanelComponent _dashboardGrid: DashboardGridViewComponent; _dashboardSlide: DashboardSlideViewComponent; - hasDataExplorerWritePrivileges = false; + hasDashboardWritePrivileges = false; public items: Dashboard[]; @@ -114,10 +114,10 @@ export class DashboardPanelComponent this.getDashboard(params.id, startTime, endTime); this.authSubscription = this.currentUserService.user$.subscribe(_ => { - this.hasDataExplorerWritePrivileges = this.authService.hasRole( - UserPrivilege.PRIVILEGE_WRITE_DATA_EXPLORER_VIEW, + this.hasDashboardWritePrivileges = this.authService.hasRole( + UserPrivilege.PRIVILEGE_WRITE_DASHBOARD, ); - if (queryParams.editMode && this.hasDataExplorerWritePrivileges) { + if (queryParams.editMode && this.hasDashboardWritePrivileges) { this.editMode = true; } }); diff --git a/ui/src/app/dashboard/components/panel/dashboard-toolbar/dashboard-toolbar.component.html b/ui/src/app/dashboard/components/panel/dashboard-toolbar/dashboard-toolbar.component.html index 22f0e0fcfb..0d85549398 100644 --- a/ui/src/app/dashboard/components/panel/dashboard-toolbar/dashboard-toolbar.component.html +++ b/ui/src/app/dashboard/components/panel/dashboard-toolbar/dashboard-toolbar.component.html @@ -100,7 +100,7 @@ <mat-icon>more_vert</mat-icon> </button> <mat-menu #optMenu="matMenu"> - @if (!editMode && hasDataExplorerWritePrivileges) { + @if (!editMode && hasDashboardWritePrivileges) { <button mat-menu-item (click)="triggerEditModeEmitter.emit()" @@ -122,7 +122,7 @@ <span>{{ 'Hide time range selector' | translate }}</span> </button> } - @if (hasDataExplorerWritePrivileges) { + @if (hasDashboardWritePrivileges) { <button mat-menu-item (click)="deleteDashboardEmitter.emit()"> <mat-icon>clear</mat-icon> <span>{{ 'Delete dashboard' | translate }}</span> diff --git a/ui/src/app/dashboard/components/panel/dashboard-toolbar/dashboard-toolbar.component.ts b/ui/src/app/dashboard/components/panel/dashboard-toolbar/dashboard-toolbar.component.ts index 21664ed1aa..9f979d9100 100644 --- a/ui/src/app/dashboard/components/panel/dashboard-toolbar/dashboard-toolbar.component.ts +++ b/ui/src/app/dashboard/components/panel/dashboard-toolbar/dashboard-toolbar.component.ts @@ -43,7 +43,7 @@ export class DashboardToolbarComponent { timeRangeVisible: boolean; @Input() - hasDataExplorerWritePrivileges: boolean; + hasDashboardWritePrivileges: boolean; @Input() timeSettings: TimeSettings; diff --git a/ui/src/app/data-explorer-shared/components/chart-container/data-explorer-chart-container.component.html b/ui/src/app/data-explorer-shared/components/chart-container/data-explorer-chart-container.component.html index 6928d45086..f0fb79ee9e 100644 --- a/ui/src/app/data-explorer-shared/components/chart-container/data-explorer-chart-container.component.html +++ b/ui/src/app/data-explorer-shared/components/chart-container/data-explorer-chart-container.component.html @@ -146,21 +146,23 @@ </sp-time-selector-menu> } </mat-menu> - @if (!dataViewMode) { - @if (editMode && hasDataExplorerWritePrivileges) { - <button - mat-icon-button - (click)="removeWidget()" - [matTooltip]="'Delete Chart' | translate" - [attr.data-cy]=" - 'remove-' + - configuredWidget.baseAppearanceConfig - .widgetTitle - " - > - <mat-icon>clear</mat-icon> - </button> - } + @if ( + !dataViewMode && + editMode && + hasDashboardWritePrivileges + ) { + <button + mat-icon-button + (click)="removeWidget()" + [matTooltip]="'Delete Chart' | translate" + [attr.data-cy]=" + 'remove-' + + configuredWidget.baseAppearanceConfig + .widgetTitle + " + > + <mat-icon>clear</mat-icon> + </button> } </div> } diff --git a/ui/src/app/data-explorer-shared/components/chart-container/data-explorer-chart-container.component.ts b/ui/src/app/data-explorer-shared/components/chart-container/data-explorer-chart-container.component.ts index de5144a8c3..4fb1bb090e 100644 --- a/ui/src/app/data-explorer-shared/components/chart-container/data-explorer-chart-container.component.ts +++ b/ui/src/app/data-explorer-shared/components/chart-container/data-explorer-chart-container.component.ts @@ -138,6 +138,7 @@ export class DataExplorerChartContainerComponent }; hasDataExplorerWritePrivileges = false; + hasDashboardWritePrivileges = false; authSubscription: Subscription; widgetTypeChangedSubscription: Subscription; @@ -175,6 +176,9 @@ export class DataExplorerChartContainerComponent this.hasDataExplorerWritePrivileges = this.authService.hasRole( UserPrivilege.PRIVILEGE_WRITE_DATA_EXPLORER_VIEW, ); + this.hasDashboardWritePrivileges = this.authService.hasRole( + UserPrivilege.PRIVILEGE_WRITE_DASHBOARD, + ); }, ); this.widgetLoaded = true; diff --git a/ui/src/app/data-explorer/components/chart-view/data-explorer-chart-view.component.ts b/ui/src/app/data-explorer/components/chart-view/data-explorer-chart-view.component.ts index 4935fab6c6..0489ead3bc 100644 --- a/ui/src/app/data-explorer/components/chart-view/data-explorer-chart-view.component.ts +++ b/ui/src/app/data-explorer/components/chart-view/data-explorer-chart-view.component.ts @@ -20,6 +20,7 @@ import { Component, ElementRef, inject, + OnDestroy, OnInit, ViewChild, } from '@angular/core'; @@ -40,6 +41,7 @@ import { import { AssetSaveService, ConfirmDialogComponent, + CurrentUserService, DialogService, PanelType, TimeSelectionService, @@ -48,12 +50,14 @@ import { DataExplorerRoutingService } from '../../../data-explorer-shared/servic import { DataExplorerSharedService } from '../../../data-explorer-shared/services/data-explorer-shared.service'; import { DataExplorerDetectChangesService } from '../../services/data-explorer-detect-changes.service'; import { SupportsUnsavedChangeDialog } from '../../../data-explorer-shared/models/dataview-dashboard.model'; -import { Observable, of } from 'rxjs'; +import { Observable, of, Subscription } from 'rxjs'; import { MatDialog } from '@angular/material/dialog'; import { catchError, map } from 'rxjs/operators'; import { TranslateService } from '@ngx-translate/core'; import { ResizeEchartsService } from '../../../data-explorer-shared/services/resize-echarts.service'; import { AssetDialogComponent } from '../../dialog/asset-dialog.component'; +import { AuthService } from '../../../services/auth.service'; +import { UserRole } from '../../../_enums/user-role.enum'; @Component({ selector: 'sp-data-explorer-data-view', @@ -62,7 +66,7 @@ import { AssetDialogComponent } from '../../dialog/asset-dialog.component'; standalone: false, }) export class DataExplorerChartViewComponent - implements OnInit, SupportsUnsavedChangeDialog + implements OnInit, OnDestroy, SupportsUnsavedChangeDialog { dataViewLoaded = false; timeSettings: TimeSettings; @@ -91,9 +95,13 @@ export class DataExplorerChartViewComponent private timeSelectionService = inject(TimeSelectionService); private translateService = inject(TranslateService); private dialogService = inject(DialogService); + private currentUserService = inject(CurrentUserService); + private authService = inject(AuthService); private assetSaveService = inject(AssetSaveService); + currentUser$: Subscription; + chartNotFound = false; observableGenerator = @@ -103,7 +111,14 @@ export class DataExplorerChartViewComponent ngOnInit() { const dataViewId = this.route.snapshot.params.id; - this.editMode = this.route.snapshot.queryParams.editMode; + + this.currentUser$ = this.currentUserService.user$.subscribe(user => { + if (!this.authService.hasRole(UserRole.ROLE_DATA_EXPLORER_ADMIN)) { + this.editMode = false; + } else { + this.editMode = this.route.snapshot.queryParams.editMode; + } + }); if (dataViewId) { this.loadDataView(dataViewId); @@ -342,7 +357,6 @@ export class DataExplorerChartViewComponent this.deselectedAssets, this.originalAssets, ); - //this.dialogRef.close(true); } saveToAssets(data: DataExplorerWidgetModel): void { @@ -364,4 +378,8 @@ export class DataExplorerChartViewComponent }, ]; } + + ngOnDestroy() { + this.currentUser$?.unsubscribe(); + } } diff --git a/ui/src/app/data-explorer/components/overview/data-explorer-overview-table/data-explorer-overview-table.component.ts b/ui/src/app/data-explorer/components/overview/data-explorer-overview-table/data-explorer-overview-table.component.ts index e28ddf8c81..0edf6c1cbf 100644 --- a/ui/src/app/data-explorer/components/overview/data-explorer-overview-table/data-explorer-overview-table.component.ts +++ b/ui/src/app/data-explorer/components/overview/data-explorer-overview-table/data-explorer-overview-table.component.ts @@ -87,7 +87,10 @@ export class SpDataExplorerDataViewOverviewComponent implements OnInit { } openDataView(dataView: DataExplorerWidgetModel, editMode: boolean): void { - this.routingService.navigateToDataView(editMode, dataView.elementId); + this.routingService.navigateToDataView( + editMode && this.hasDataExplorerWritePrivileges, + dataView.elementId, + ); } showPermissionsDialog(chart: DataExplorerWidgetModel) { diff --git a/ui/src/app/pipeline-details/components/pipeline-details-toolbar/pipeline-details-toolbar.component.html b/ui/src/app/pipeline-details/components/pipeline-details-toolbar/pipeline-details-toolbar.component.html index 1df6b32768..7acfa2659c 100644 --- a/ui/src/app/pipeline-details/components/pipeline-details-toolbar/pipeline-details-toolbar.component.html +++ b/ui/src/app/pipeline-details/components/pipeline-details-toolbar/pipeline-details-toolbar.component.html @@ -34,18 +34,20 @@ > </div> </button> - <button - mat-button - color="accent" - [matTooltip]="'Pipeline as code' | translate" - [matTooltipPosition]="'above'" - (click)="openCodeDialogEmitter.emit()" - > - <div fxLayoutAlign="start center" fxLayout="row"> - <i class="material-icons">code</i> - <span> {{ 'View pipeline as code' | translate }}</span> - </div> - </button> + @if (hasPipelineWritePrivileges) { + <button + mat-button + color="accent" + [matTooltip]="'Pipeline as code' | translate" + [matTooltipPosition]="'above'" + (click)="openCodeDialogEmitter.emit()" + > + <div fxLayoutAlign="start center" fxLayout="row"> + <i class="material-icons">code</i> + <span> {{ 'View pipeline as code' | translate }}</span> + </div> + </button> + } <div fxFlex></div> <div fxLayoutAlign="end center"> <button diff --git a/ui/src/app/pipeline-details/components/pipeline-details-toolbar/pipeline-details-toolbar.component.ts b/ui/src/app/pipeline-details/components/pipeline-details-toolbar/pipeline-details-toolbar.component.ts index ede7f4eab4..c08ba9108a 100644 --- a/ui/src/app/pipeline-details/components/pipeline-details-toolbar/pipeline-details-toolbar.component.ts +++ b/ui/src/app/pipeline-details/components/pipeline-details-toolbar/pipeline-details-toolbar.component.ts @@ -27,6 +27,9 @@ export class PipelineDetailsToolbarComponent { @Input() autoRefresh: boolean; + @Input() + hasPipelineWritePrivileges: boolean; + @Input() previewModeActive: boolean; diff --git a/ui/src/app/pipeline-details/pipeline-details.component.html b/ui/src/app/pipeline-details/pipeline-details.component.html index e024d3d147..277b64b496 100644 --- a/ui/src/app/pipeline-details/pipeline-details.component.html +++ b/ui/src/app/pipeline-details/pipeline-details.component.html @@ -24,6 +24,7 @@ <div nav fxFlex="100" fxLayoutAlign="start center" class="mr-5"> <sp-pipeline-details-toolbar fxFlex="100" + [hasPipelineWritePrivileges]="hasPipelineWritePrivileges" [autoRefresh]="autoRefresh" [previewModeActive]="previewModeActive" (togglePreviewEmitter)="toggleLivePreview()" diff --git a/ui/src/app/pipeline-details/pipeline-details.component.ts b/ui/src/app/pipeline-details/pipeline-details.component.ts index 1cf208269c..b6edcbaaa8 100644 --- a/ui/src/app/pipeline-details/pipeline-details.component.ts +++ b/ui/src/app/pipeline-details/pipeline-details.component.ts @@ -66,8 +66,8 @@ export class SpPipelineDetailsComponent implements OnInit, OnDestroy { previewModeActive = false; pipelineNotFound = false; - currentUserSub: Subscription; - autoRefreshSub: Subscription; + currentUser$: Subscription; + autoRefresh$: Subscription; @ViewChild('pipelinePreviewComponent') pipelinePreviewComponent: PipelinePreviewComponent; @@ -84,7 +84,7 @@ export class SpPipelineDetailsComponent implements OnInit, OnDestroy { ) {} ngOnInit(): void { - this.currentUserSub = this.currentUserService.user$.subscribe(user => { + this.currentUser$ = this.currentUserService.user$.subscribe(user => { this.hasPipelineWritePrivileges = this.authService.hasRole( UserPrivilege.PRIVILEGE_WRITE_PIPELINE, ); @@ -147,7 +147,7 @@ export class SpPipelineDetailsComponent implements OnInit, OnDestroy { } setupAutoRefresh(): void { - this.autoRefreshSub = interval(5000) + this.autoRefresh$ = interval(5000) .pipe( filter(() => this.autoRefresh), switchMap(() => this.getMonitoringObservables(true)), @@ -212,7 +212,7 @@ export class SpPipelineDetailsComponent implements OnInit, OnDestroy { } ngOnDestroy() { - this.currentUserSub?.unsubscribe(); - this.autoRefreshSub?.unsubscribe(); + this.currentUser$?.unsubscribe(); + this.autoRefresh$?.unsubscribe(); } }
