This is an automated email from the ASF dual-hosted git repository.
tenthe pushed a commit to branch dev
in repository https://gitbox.apache.org/repos/asf/streampipes.git
The following commit(s) were added to refs/heads/dev by this push:
new 37a6e4b007 fix: Confirm changes dialog is shown twice when navigating
from asset edit mode to another page (#4688)
37a6e4b007 is described below
commit 37a6e4b00742e1e40af4066f26bcbd049ff5e992
Author: Jacqueline Höllig <[email protected]>
AuthorDate: Thu Jul 23 17:09:55 2026 +0200
fix: Confirm changes dialog is shown twice when navigating from asset edit
mode to another page (#4688)
---
.../edit-asset/asset-details.component.ts | 116 ++++++++++++++-------
1 file changed, 79 insertions(+), 37 deletions(-)
diff --git
a/ui/src/app/assets/components/asset-details/edit-asset/asset-details.component.ts
b/ui/src/app/assets/components/asset-details/edit-asset/asset-details.component.ts
index 49cd2d8cfc..c4c3fb55ec 100644
---
a/ui/src/app/assets/components/asset-details/edit-asset/asset-details.component.ts
+++
b/ui/src/app/assets/components/asset-details/edit-asset/asset-details.component.ts
@@ -51,7 +51,7 @@ import {
} from '@streampipes/platform-services';
import { MatDialog } from '@angular/material/dialog';
import { firstValueFrom, from, Observable, of } from 'rxjs';
-import { map, switchMap, tap } from 'rxjs/operators';
+import { finalize, map, shareReplay, switchMap, tap } from 'rxjs/operators';
import { SupportsUnsavedChangeDialog } from
'../../../../chart-shared/models/dataview-dashboard.model';
type ManageableAsset = SpAssetModel & {
@@ -91,6 +91,9 @@ export class SpAssetDetailsComponent
private pendingManageAssetResult?:
ObjectManageDialogResult<ManageableAsset>;
private originalAsset: SpAssetModel;
+ private initialGeneratedAssetId?: string;
+ private initialGeneratedElementId?: string;
+ private pendingConfirmLeaveDialog?: Observable<boolean>;
async saveAsset() {
await this.saveAssetChanges();
@@ -219,38 +222,42 @@ export class SpAssetDetailsComponent
_route: ActivatedRouteSnapshot,
_state: RouterStateSnapshot,
): Observable<boolean> {
- if (this.setShouldShowConfirm()) {
- const dialogRef = this.dialog.open(ConfirmDialogComponent, {
- width: '500px',
- data: {
- title: this.translateService.instant('Save changes?'),
- subtitle: this.translateService.instant(
- 'Update all changes to asset or discard current
changes.',
- ),
- neutralTitle: this.translateService.instant('Keep
editing'),
- cancelTitle:
- this.translateService.instant('Discard changes'),
- confirmTitle: this.translateService.instant('Update'),
- },
- });
- return dialogRef.afterClosed().pipe(
- switchMap((dialogResult: ConfirmDialogAction | undefined) => {
- if (dialogResult === 'confirm') {
- return from(this.saveAssetChanges()).pipe(
- map(() => true),
- );
- }
-
- if (dialogResult === 'cancel') {
- return of(true);
- }
-
- return of(false);
- }),
- );
- } else {
+ if (!this.setShouldShowConfirm()) {
return of(true);
}
+
+ if (this.pendingConfirmLeaveDialog) {
+ return this.pendingConfirmLeaveDialog;
+ }
+
+ const dialogRef = this.dialog.open(ConfirmDialogComponent, {
+ width: '500px',
+ data: {
+ title: this.translateService.instant('Save changes?'),
+ subtitle: this.translateService.instant(
+ 'Update all changes to asset or discard current changes.',
+ ),
+ neutralTitle: this.translateService.instant('Keep editing'),
+ cancelTitle: this.translateService.instant('Discard changes'),
+ confirmTitle: this.translateService.instant('Update'),
+ },
+ });
+ this.pendingConfirmLeaveDialog = dialogRef.afterClosed().pipe(
+ switchMap((dialogResult: ConfirmDialogAction | undefined) => {
+ if (dialogResult === 'confirm') {
+ return from(this.saveAssetChanges()).pipe(map(() => true));
+ }
+
+ if (dialogResult === 'cancel') {
+ return of(true);
+ }
+
+ return of(false);
+ }),
+ finalize(() => (this.pendingConfirmLeaveDialog = undefined)),
+ shareReplay({ bufferSize: 1, refCount: true }),
+ );
+ return this.pendingConfirmLeaveDialog;
}
setShouldShowConfirm(): boolean {
@@ -261,7 +268,11 @@ export class SpAssetDetailsComponent
}
onAssetAvailable() {
- this.originalAsset = this.cloneAsset(this.asset);
+ if (this.isNewAsset) {
+ this.initialGeneratedAssetId = this.asset.assetId;
+ this.initialGeneratedElementId = this.asset.elementId;
+ }
+ this.originalAsset = this.normalizeAssetForComparison(this.asset);
}
private makeManageableAsset(asset: SpAssetModel): ManageableAsset {
@@ -290,7 +301,7 @@ export class SpAssetDetailsComponent
await firstValueFrom(this.assetService.updateAsset(this.asset));
}
await this.savePendingManageAssetChanges();
- this.originalAsset = this.cloneAsset(this.asset);
+ this.originalAsset = this.normalizeAssetForComparison(this.asset);
}
private async savePendingManageAssetChanges(): Promise<void> {
@@ -312,14 +323,45 @@ export class SpAssetDetailsComponent
if (!this.originalAsset || !this.asset) {
return false;
}
-
return (
- JSON.stringify(this.originalAsset) !==
- JSON.stringify(this.cloneAsset(this.asset))
+ JSON.stringify(
+ this.normalizeAssetForComparison(this.originalAsset),
+ ) !== JSON.stringify(this.normalizeAssetForComparison(this.asset))
);
}
+ private normalizeAssetForComparison(asset: SpAssetModel): SpAssetModel {
+ const clonedAsset = this.cloneAsset(asset);
+ if (this.isNewAsset) {
+ if (clonedAsset.assetName === 'New Asset') {
+ clonedAsset.assetName = '';
+ }
+ if (clonedAsset.assetId === this.initialGeneratedAssetId) {
+ clonedAsset.assetId = '';
+ }
+ if (clonedAsset.elementId === this.initialGeneratedElementId) {
+ clonedAsset.elementId = '';
+ }
+ }
+ clonedAsset.additionalData ??= {};
+ clonedAsset.additionalData.customFields ??= [];
+ clonedAsset.assetSite ??= {
+ area: undefined,
+ siteId: undefined,
+ hasExactLocation: false,
+ location: undefined,
+ };
+ clonedAsset.assetType ??= {
+ assetIcon: undefined,
+ assetIconColor: undefined,
+ assetTypeCategory: undefined,
+ assetTypeLabel: undefined,
+ isa95AssetType: 'OTHER',
+ };
+ return clonedAsset;
+ }
+
private cloneAsset(asset: SpAssetModel): SpAssetModel {
- return JSON.parse(JSON.stringify(asset));
+ return SpAssetModel.fromData(asset);
}
}