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);
     }
 }

Reply via email to