This is an automated email from the ASF dual-hosted git repository.
zehnder 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 5f235e2ff0 Edit Assets links for adapter while editing (#3817)
5f235e2ff0 is described below
commit 5f235e2ff0883c6253b0d5c3c9dcf27bd5527705
Author: Jacqueline Höllig <[email protected]>
AuthorDate: Mon Oct 13 14:02:23 2025 +0200
Edit Assets links for adapter while editing (#3817)
Co-authored-by: Philipp Zehnder <[email protected]>
Co-authored-by: Dominik Riemer <[email protected]>
---
.../src/lib/model/assets/asset.model.ts | 1 +
.../adapter-asset-configuration.component.ts | 78 +++++++-
.../start-adapter-configuration.component.html | 7 +
.../start-adapter-configuration.component.ts | 31 ++--
.../adapter-started-dialog.component.html | 1 +
.../adapter-started-dialog.component.ts | 96 +++++++---
.../adapter-started-success.component.html | 22 +++
.../adapter-started-success.component.ts | 3 +
.../adapter-asset-configuration.service.ts | 205 +++++++++++++++++++--
9 files changed, 394 insertions(+), 50 deletions(-)
diff --git
a/ui/projects/streampipes/platform-services/src/lib/model/assets/asset.model.ts
b/ui/projects/streampipes/platform-services/src/lib/model/assets/asset.model.ts
index b64f794ec6..e78b42fbb4 100644
---
a/ui/projects/streampipes/platform-services/src/lib/model/assets/asset.model.ts
+++
b/ui/projects/streampipes/platform-services/src/lib/model/assets/asset.model.ts
@@ -105,6 +105,7 @@ export interface SpAssetModel extends SpAsset {
export interface SpAssetTreeNode {
assetId: string;
assetName: string;
+ assetLinks: AssetLink[];
assets?: SpAssetTreeNode[];
spAssetModelId: string;
flattenPath: any[];
diff --git
a/ui/src/app/connect/components/adapter-configuration/adapter-asset-configuration/adapter-asset-configuration.component.ts
b/ui/src/app/connect/components/adapter-configuration/adapter-asset-configuration/adapter-asset-configuration.component.ts
index f48e53c270..8666dc0958 100644
---
a/ui/src/app/connect/components/adapter-configuration/adapter-asset-configuration/adapter-asset-configuration.component.ts
+++
b/ui/src/app/connect/components/adapter-configuration/adapter-asset-configuration/adapter-asset-configuration.component.ts
@@ -26,6 +26,7 @@ import {
AssetLinkType,
SpAsset,
SpAssetTreeNode,
+ AdapterDescription,
} from '@streampipes/platform-services';
import { MatStepper } from '@angular/material/stepper';
import { Observable } from 'rxjs';
@@ -39,11 +40,15 @@ import { Observable } from 'rxjs';
export class AdapterAssetConfigurationComponent implements OnInit {
@Input() linkageData: LinkageData[] = [];
@Input() stepper: MatStepper;
+ @Input() isEdit: boolean;
+ @Input() adapter: AdapterDescription;
@Output() adapterStartedEmitter: EventEmitter<void> =
new EventEmitter<void>();
@Output() selectedAssetsChange = new EventEmitter<SpAssetTreeNode[]>();
+ @Output() deselectedAssetsChange = new EventEmitter<SpAssetTreeNode[]>();
+ @Output() originalAssetsEmitter = new EventEmitter<SpAssetTreeNode[]>();
treeControl: NestedTreeControl<SpAssetTreeNode>;
dataSource: MatTreeNestedDataSource<SpAssetTreeNode>;
@@ -56,6 +61,8 @@ export class AdapterAssetConfigurationComponent implements
OnInit {
assetLinksLoaded = false;
updateObservable: Observable<SpAssetModel>;
selectedAssets: SpAssetTreeNode[] = [];
+ deselectedAssets: SpAssetTreeNode[] = [];
+ originalAssets: SpAssetTreeNode[] = [];
constructor(private assetService: AssetManagementService) {
this.treeControl = new NestedTreeControl<SpAssetTreeNode>(
@@ -76,13 +83,40 @@ export class AdapterAssetConfigurationComponent implements
OnInit {
asset => asset.assetId === node.assetId,
);
+ const index_deselected = this.deselectedAssets.findIndex(
+ asset => asset.assetId === node.assetId,
+ );
+
if (index > -1) {
this.selectedAssets.splice(index, 1);
+ if (this.isNodeInOriginalData(node)) {
+ this.deselectedAssets.push(node);
+ }
} else {
this.selectedAssets.push(node);
+ if (index_deselected > -1) {
+ this.deselectedAssets.splice(index_deselected, 1);
+ }
}
- this.selectedAssetsChange.emit(this.selectedAssets);
+ const selectEmit = this.selectedAssets.filter(
+ node => !this.isNodeInOriginalData(node),
+ );
+
+ this.selectedAssetsChange.emit(selectEmit);
+ this.deselectedAssetsChange.emit(this.deselectedAssets);
+ }
+
+ private isNodeInOriginalData(node: SpAssetTreeNode): boolean {
+ for (const asset of this.originalAssets) {
+ if (
+ asset.assetId === node.assetId &&
+ asset.spAssetModelId === node.spAssetModelId
+ ) {
+ return true;
+ }
+ }
+ return false;
}
isSelected(node: SpAssetTreeNode): boolean {
@@ -100,9 +134,50 @@ export class AdapterAssetConfigurationComponent implements
OnInit {
next: assets => {
this.assetsData = this.mapAssets(assets);
this.dataSource.data = this.assetsData;
+ if (this.isEdit) {
+ this.setSelect();
+ }
},
});
}
+
+ private setSelect() {
+ if (!this.adapter || !this.adapter.elementId) {
+ return;
+ }
+
+ this.assetsData.forEach(node => {
+ this.selectNodeIfMatch(node);
+ });
+ }
+
+ private selectNodeIfMatch(
+ node: SpAssetTreeNode,
+ path: SpAssetTreeNode[] = [],
+ ) {
+ const currentPath = [...path, node];
+
+ if (
+ node.assetLinks &&
+ node.assetLinks.some(
+ link => link.resourceId === this.adapter.elementId,
+ )
+ ) {
+ if (!this.isSelected(node)) {
+ this.selectedAssets.push(node);
+ this.originalAssets.push(node);
+ this.originalAssetsEmitter.emit(this.originalAssets);
+ currentPath.forEach(n => this.treeControl.expand(n));
+ }
+ }
+
+ if (node.assets) {
+ node.assets.forEach(child =>
+ this.selectNodeIfMatch(child, currentPath),
+ );
+ }
+ }
+
private mapAssets(
apiAssets: SpAsset[],
parentId: string = '',
@@ -124,6 +199,7 @@ export class AdapterAssetConfigurationComponent implements
OnInit {
assetId: asset.assetId,
assetName: asset.assetName,
flattenPath: flattenedPath,
+ assetLinks: asset.assetLinks,
assets: asset.assets
? this.mapAssets(asset.assets, parentId, flattenedPathCopy)
: [],
diff --git
a/ui/src/app/connect/components/adapter-configuration/start-adapter-configuration/start-adapter-configuration.component.html
b/ui/src/app/connect/components/adapter-configuration/start-adapter-configuration/start-adapter-configuration.component.html
index fe2fd92658..4f9c96965e 100644
---
a/ui/src/app/connect/components/adapter-configuration/start-adapter-configuration/start-adapter-configuration.component.html
+++
b/ui/src/app/connect/components/adapter-configuration/start-adapter-configuration/start-adapter-configuration.component.html
@@ -108,11 +108,18 @@
[optionDescription]="'Add Adapter to an existing Asset' |
translate"
optionIcon="precision_manufacturing"
dataCy="show-asset-checkbox"
+ [isChecked]="
+ showAsset && (!isEditMode || originalAssets.length > 0)
+ "
(optionSelectedEmitter)="showAsset = $event"
>
<sp-adapter-asset-configuration
*ngIf="showAsset"
+ [isEdit]="isEditMode"
+ [adapter]="adapterDescription"
(selectedAssetsChange)="onSelectedAssetsChange($event)"
+ (deselectedAssetsChange)="onDeselectedAssetsChange($event)"
+ (originalAssetsEmitter)="onOriginalAssetsEmitted($event)"
>
</sp-adapter-asset-configuration>
</sp-adapter-options-panel>
diff --git
a/ui/src/app/connect/components/adapter-configuration/start-adapter-configuration/start-adapter-configuration.component.ts
b/ui/src/app/connect/components/adapter-configuration/start-adapter-configuration/start-adapter-configuration.component.ts
index 476877c11c..5d2ccbaf39 100644
---
a/ui/src/app/connect/components/adapter-configuration/start-adapter-configuration/start-adapter-configuration.component.ts
+++
b/ui/src/app/connect/components/adapter-configuration/start-adapter-configuration/start-adapter-configuration.component.ts
@@ -16,20 +16,12 @@
*
*/
-import {
- Component,
- EventEmitter,
- Input,
- OnInit,
- Output,
- SimpleChanges,
- OnChanges,
-} from '@angular/core';
+import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
import {
AdapterDescription,
- SpAssetTreeNode,
EventRateTransformationRuleDescription,
EventSchema,
+ SpAssetTreeNode,
RemoveDuplicatesTransformationRuleDescription,
} from '@streampipes/platform-services';
import {
@@ -67,8 +59,6 @@ export class StartAdapterConfigurationComponent implements
OnInit {
@Input() isEditMode: boolean;
- @Input() stepper: MatStepper;
-
/**
* Cancels the adapter configuration process
*/
@@ -110,6 +100,8 @@ export class StartAdapterConfigurationComponent implements
OnInit {
showCode = false;
showAsset = false;
selectedAssets = [];
+ deselectedAssets = [];
+ originalAssets = [];
constructor(
private dialogService: DialogService,
@@ -120,6 +112,7 @@ export class StartAdapterConfigurationComponent implements
OnInit {
) {}
ngOnInit(): void {
+ this.showAsset = this.isEditMode;
this.startAdapterForm = this._formBuilder.group({});
this.startAdapterForm.addControl(
'adapterName',
@@ -189,6 +182,9 @@ export class StartAdapterConfigurationComponent implements
OnInit {
data: {
adapter: this.adapterDescription,
editMode: true,
+ selectedAssets: this.selectedAssets,
+ deselectedAssets: this.deselectedAssets,
+ originalAssets: this.originalAssets,
},
});
@@ -213,8 +209,7 @@ export class StartAdapterConfigurationComponent implements
OnInit {
selectedAssets: this.selectedAssets,
},
});
- const dialogInstance =
- dialogRef.componentInstance as unknown as AdapterStartedDialog;
+
dialogRef.afterClosed().subscribe(() => {
this.adapterStartedEmitter.emit();
});
@@ -224,6 +219,14 @@ export class StartAdapterConfigurationComponent implements
OnInit {
this.selectedAssets = updatedAssets;
}
+ onDeselectedAssetsChange(updatedAssets: SpAssetTreeNode[]): void {
+ this.deselectedAssets = updatedAssets;
+ }
+
+ onOriginalAssetsEmitted(updatedAssets: SpAssetTreeNode[]): void {
+ this.originalAssets = updatedAssets;
+ }
+
private checkAndApplyStreamRules(): void {
if (this.removeDuplicates) {
const removeDuplicates:
RemoveDuplicatesTransformationRuleDescription =
diff --git
a/ui/src/app/connect/dialog/adapter-started/adapter-started-dialog.component.html
b/ui/src/app/connect/dialog/adapter-started/adapter-started-dialog.component.html
index 0f01497bc3..8d0560d4e7 100644
---
a/ui/src/app/connect/dialog/adapter-started/adapter-started-dialog.component.html
+++
b/ui/src/app/connect/dialog/adapter-started/adapter-started-dialog.component.html
@@ -45,6 +45,7 @@
[pipelineOperationStatus]="pipelineOperationStatus"
[saveInDataLake]="saveInDataLake"
[saveInAsset]="addToAssetText"
+ [deletedFromAsset]="deletedFromAssetText"
[templateErrorMessage]="templateErrorMessage"
[adapterErrorMessage]="adapterErrorMessage"
></sp-adapter-started-success>
diff --git
a/ui/src/app/connect/dialog/adapter-started/adapter-started-dialog.component.ts
b/ui/src/app/connect/dialog/adapter-started/adapter-started-dialog.component.ts
index 7193931339..8f16df7572 100644
---
a/ui/src/app/connect/dialog/adapter-started/adapter-started-dialog.component.ts
+++
b/ui/src/app/connect/dialog/adapter-started/adapter-started-dialog.component.ts
@@ -24,6 +24,7 @@ import {
Output,
inject,
} from '@angular/core';
+
import { ShepherdService } from '../../../services/tour/shepherd.service';
import {
AdapterDescription,
@@ -38,16 +39,14 @@ import {
PipelineTemplateService,
PipelineUpdateInfo,
SpLogMessage,
-} from '@streampipes/platform-services';
-import { DialogRef } from '@streampipes/shared-ui';
-import {
- CompactPipelineService,
LinkageData,
+ CompactPipelineService,
} from '@streampipes/platform-services';
-import { AssetSaveService } from
'../../services/adapter-asset-configuration.service';
+import { DialogRef } from '@streampipes/shared-ui';
-import { firstValueFrom } from 'rxjs';
import { TranslateService } from '@ngx-translate/core';
+import { AssetSaveService } from
'../../services/adapter-asset-configuration.service';
+import { firstValueFrom } from 'rxjs';
@Component({
selector: 'sp-dialog-adapter-started-dialog',
@@ -70,6 +69,8 @@ export class AdapterStartedDialog implements OnInit {
* Assets selectedAsset to link the adapter tp
*/
@Input() selectedAssets: SpAssetTreeNode[];
+ @Input() deselectedAssets: SpAssetTreeNode[];
+ @Input() originalAssets: SpAssetTreeNode[];
/**
* Indicates if a pipeline to store the adapter events should be started
@@ -107,6 +108,7 @@ export class AdapterStartedDialog implements OnInit {
adapterElementId = '';
adapterErrorMessage: SpLogMessage;
addToAssetText = '';
+ deletedFromAssetText = '';
constructor(
public dialogRef: DialogRef<AdapterStartedDialog>,
@@ -150,6 +152,13 @@ export class AdapterStartedDialog implements OnInit {
},
);
+ this.loadingText = this.translateService.instant(
+ 'Updating adapter {{adapterName}}',
+ {
+ adapterName: this.adapter.name,
+ },
+ );
+
this.loading = true;
this.adapterService.updateAdapter(this.adapter).subscribe({
next: status => {
@@ -162,6 +171,8 @@ export class AdapterStartedDialog implements OnInit {
this.onAdapterFailure(errorLogMessage);
}
+
+ this.addToAsset();
},
error: error => {
this.onAdapterFailure(error.error);
@@ -170,6 +181,12 @@ export class AdapterStartedDialog implements OnInit {
}
addAdapter() {
+ this.loadingText = this.translateService.instant(
+ 'Creating adapter {{adapterName}}',
+ {
+ adapterName: this.adapter.name,
+ },
+ );
this.loadingText = this.translateService.instant(
'Creating adapter {{adapterName}}',
{
@@ -182,11 +199,13 @@ export class AdapterStartedDialog implements OnInit {
if (status.success) {
const adapterElementId = status.notifications[0].title;
this.adapterElementId = adapterElementId;
+ this.adapterElementId = adapterElementId;
if (this.saveInDataLake) {
this.startSaveInDataLakePipeline(adapterElementId);
} else {
this.startAdapter(adapterElementId, true);
this.addToAsset();
+ this.addToAsset();
}
} else {
const errorMsg: SpLogMessage =
@@ -226,10 +245,16 @@ export class AdapterStartedDialog implements OnInit {
adapterName: this.adapter.name,
},
);
+ this.loadingText = this.translateService.instant(
+ 'Starting adapter {{adapterName}}',
+ {
+ adapterName: this.adapter.name,
+ },
+ );
this.adapterService
.startAdapterByElementId(adapterElementId)
.subscribe(
- startStatus => {
+ () => {
this.onAdapterReady(successMessage, showPreview);
},
error => {
@@ -264,15 +289,21 @@ export class AdapterStartedDialog implements OnInit {
}
async addToAsset(): Promise<void> {
+ let linkageData: LinkageData[];
try {
- const adapter = await this.getAdapter();
- const linkageData: LinkageData[] = this.createLinkageData(adapter);
+ if (!this.editMode) {
+ const adapter = await this.getAdapter();
+ linkageData = this.createLinkageData(adapter);
- if (this.saveInDataLake) {
- await this.addDataLakeLinkageData(adapter, linkageData);
+ if (this.saveInDataLake) {
+ await this.addDataLakeLinkageData(adapter, linkageData);
+ }
+ } else {
+ linkageData = this.createLinkageData(this.adapter);
}
await this.saveAssets(linkageData);
+
this.setSuccessMessage(linkageData);
} catch (err) {
console.error('Error in addToAsset:', err);
@@ -289,7 +320,10 @@ export class AdapterStartedDialog implements OnInit {
return [
{
type: 'adapter',
- id: this.adapterElementId,
+ id:
+ this.adapterElementId !== ''
+ ? this.adapterElementId
+ : adapter.elementId,
name: adapter.name,
},
{
@@ -326,6 +360,8 @@ export class AdapterStartedDialog implements OnInit {
await this.assetSaveService.saveSelectedAssets(
this.selectedAssets,
linkageData,
+ this.deselectedAssets,
+ this.originalAssets,
);
}
@@ -333,18 +369,31 @@ export class AdapterStartedDialog implements OnInit {
const assetTypesList = this.formatWithAnd(
linkageData.map(data => data.type),
);
+ if (this.selectedAssets.length > 0) {
+ const assetIdsList = this.formatWithAnd(
+ this.selectedAssets.map(asset => asset.assetName),
+ );
- const assetIdsList = this.formatWithAnd(
- this.selectedAssets.map(asset => asset.assetName),
- );
-
- this.addToAssetText = this.translateService.instant(
- 'Your {{assetTypes}} were successfully added to {{assetIds}}.',
- {
- assetTypes: assetTypesList,
- assetIds: assetIdsList,
- },
- );
+ this.addToAssetText = this.translateService.instant(
+ 'Your {{assetTypes}} were successfully added to {{assetIds}}.',
+ {
+ assetTypes: assetTypesList,
+ assetIds: assetIdsList,
+ },
+ );
+ }
+ if (this.deselectedAssets && this.deselectedAssets.length > 0) {
+ const assetIdsRemovedList = this.formatWithAnd(
+ this.deselectedAssets.map(asset => asset.assetName),
+ );
+ this.deletedFromAssetText = this.translateService.instant(
+ 'Your {{assetTypes}} were successfully deleted from
{{assetIds}}.',
+ {
+ assetTypes: assetTypesList,
+ assetIds: assetIdsRemovedList,
+ },
+ );
+ }
}
private formatWithAnd(list: string[]): string {
@@ -381,6 +430,7 @@ export class AdapterStartedDialog implements OnInit {
pipelineOperationStatus;
this.startAdapter(adapterElementId, true);
this.addToAsset();
+ this.addToAsset();
},
error => {
this.onAdapterFailure(error.error);
diff --git
a/ui/src/app/connect/dialog/adapter-started/adapter-started-success/adapter-started-success.component.html
b/ui/src/app/connect/dialog/adapter-started/adapter-started-success/adapter-started-success.component.html
index 1e3dd059d5..eacf8df178 100644
---
a/ui/src/app/connect/dialog/adapter-started/adapter-started-success/adapter-started-success.component.html
+++
b/ui/src/app/connect/dialog/adapter-started/adapter-started-success/adapter-started-success.component.html
@@ -87,6 +87,28 @@
</div>
<mat-divider fxFlex="100"></mat-divider>
</div>
+
+ <div
+ fxLayout="column"
+ fxLayoutAlign="center center"
+ fxFlex="100"
+ *ngIf="deletedFromAsset !== ''"
+ >
+ <div>
+ <div
+ class="info-message"
+ fxFlex="100"
+ fxLayoutAlign="center center"
+ fxLayout="row"
+ >
+ <i class="material-icons">done</i>
+ <span data-cy="sp-connect-adapter-success-added"
+ > {{ deletedFromAsset }}</span
+ >
+ </div>
+ </div>
+ <mat-divider fxFlex="100"></mat-divider>
+ </div>
<sp-exception-details
*ngIf="adapterErrorMessage"
[message]="adapterErrorMessage"
diff --git
a/ui/src/app/connect/dialog/adapter-started/adapter-started-success/adapter-started-success.component.ts
b/ui/src/app/connect/dialog/adapter-started/adapter-started-success/adapter-started-success.component.ts
index 51fd017df1..2609cc670c 100644
---
a/ui/src/app/connect/dialog/adapter-started/adapter-started-success/adapter-started-success.component.ts
+++
b/ui/src/app/connect/dialog/adapter-started/adapter-started-success/adapter-started-success.component.ts
@@ -39,6 +39,9 @@ export class SpAdapterStartedSuccessComponent {
@Input()
saveInAsset = '';
+ @Input()
+ deletedFromAsset = '';
+
@Input()
pipelineOperationStatus: PipelineOperationStatus;
diff --git a/ui/src/app/connect/services/adapter-asset-configuration.service.ts
b/ui/src/app/connect/services/adapter-asset-configuration.service.ts
index 67d374b730..c7dbe9ef9a 100644
--- a/ui/src/app/connect/services/adapter-asset-configuration.service.ts
+++ b/ui/src/app/connect/services/adapter-asset-configuration.service.ts
@@ -27,6 +27,7 @@ import {
GenericStorageService,
SpAssetTreeNode,
} from '@streampipes/platform-services';
+import { firstValueFrom } from 'rxjs';
@Injectable({
providedIn: 'root',
@@ -44,11 +45,55 @@ export class AssetSaveService {
@Output() adapterStartedEmitter: EventEmitter<void> =
new EventEmitter<void>();
- saveSelectedAssets(
+ async saveSelectedAssets(
selectedAssets: SpAssetTreeNode[],
linkageData: LinkageData[],
- ): void {
- const uniqueAssetIDsDict = this.getAssetPaths(selectedAssets);
+ deselectedAssets: SpAssetTreeNode[] = [],
+ originalAssets: SpAssetTreeNode[] = [],
+ ): Promise<void> {
+ const links = this.buildLinks(linkageData);
+
+ if (deselectedAssets.length > 0) {
+ await this.deleteLinkOnDeselectAssets(deselectedAssets, links);
+ }
+ if (selectedAssets.length > 0) {
+ await this.setLinkOnSelectAssets(selectedAssets, links);
+ }
+
+ if (originalAssets.length > 0) {
+ //filter is necessary, otherwise conflicting database instances
are produced
+ const filteredOriginal = this.filterAssets(
+ originalAssets,
+ deselectedAssets,
+ selectedAssets,
+ );
+
+ if (filteredOriginal.length > 0) {
+ this.renameLinkage(filteredOriginal, links);
+ }
+ }
+ }
+ private filterAssets(
+ originalAssets: SpAssetTreeNode[],
+ deselectedAssets: SpAssetTreeNode[],
+ selectedAssets: SpAssetTreeNode[],
+ ): SpAssetTreeNode[] {
+ const deselectedAssetIds = new Set(
+ deselectedAssets.map(asset => asset.assetId),
+ );
+ const selectedAssetIds = new Set(
+ selectedAssets.map(asset => asset.assetId),
+ );
+
+ return originalAssets.filter(
+ asset =>
+ !deselectedAssetIds.has(asset.assetId) &&
+ !selectedAssetIds.has(asset.assetId),
+ );
+ }
+
+ renameLinkage(originalAssets, links) {
+ const uniqueAssetIDsDict = this.getAssetPaths(originalAssets);
const uniqueAssetIDs = Object.keys(uniqueAssetIDsDict);
uniqueAssetIDs.forEach(spAssetModelId => {
@@ -56,24 +101,37 @@ export class AssetSaveService {
next: current => {
this.currentAsset = current;
- const links = this.buildLinks(linkageData);
-
uniqueAssetIDsDict[spAssetModelId].forEach(path => {
if (path.length === 2) {
- current.assetLinks = [
- ...(current.assetLinks ?? []),
- ...links,
- ];
+ current.assetLinks = (current.assetLinks ??
[]).map(
+ (link: any) => {
+ const matchedLink = links.find(
+ l => l.resourceId === link.resourceId,
+ );
+ if (matchedLink) {
+ link.linkLabel = matchedLink.linkLabel;
+ }
+ return link;
+ },
+ );
}
+
if (path.length > 2) {
- this.updateDictValue(current, path, links);
+ links.forEach(linkToUpdate => {
+ this.updateLinkLabelInDict(
+ current,
+ path,
+ linkToUpdate,
+ );
+ });
}
});
const updateObservable =
this.assetService.updateAsset(current);
+
updateObservable?.subscribe({
- next: updated => {
+ next: () => {
this.adapterStartedEmitter.emit();
},
});
@@ -82,6 +140,130 @@ export class AssetSaveService {
});
}
+ private updateLinkLabelInDict(
+ dict: SpAssetTreeNode,
+ path: (string | number)[],
+ linkToUpdate: any,
+ ) {
+ let current = dict;
+
+ for (let i = 2; i < path.length; i++) {
+ const key = path[i];
+ if (i === path.length - 1) {
+ if (current.assets?.[key]?.assetLinks) {
+ current.assets[key].assetLinks = current.assets[
+ key
+ ].assetLinks.map((link: any) => {
+ if (link.resourceId === linkToUpdate.resourceId) {
+ link.linkLabel = linkToUpdate.linkLabel;
+ }
+ return link;
+ });
+ }
+ } else {
+ if (Array.isArray(current.assets)) {
+ current = current.assets[key as number];
+ }
+ }
+ }
+
+ return current;
+ }
+ async setLinkOnSelectAssets(
+ selectedAssets: SpAssetTreeNode[],
+ links: AssetLink[],
+ ): Promise<void> {
+ const uniqueAssetIDsDict = this.getAssetPaths(selectedAssets);
+ const uniqueAssetIDs = Object.keys(uniqueAssetIDsDict);
+
+ for (const spAssetModelId of uniqueAssetIDs) {
+ const current = await firstValueFrom(
+ this.assetService.getAsset(spAssetModelId),
+ );
+
+ uniqueAssetIDsDict[spAssetModelId].forEach(path => {
+ if (path.length === 2) {
+ current.assetLinks = [
+ ...(current.assetLinks ?? []),
+ ...links,
+ ];
+ }
+
+ if (path.length > 2) {
+ this.updateDictValue(current, path, links);
+ }
+ });
+
+ const updateObservable = this.assetService.updateAsset(current);
+ await firstValueFrom(updateObservable); // Ensure this completes
before continuing
+ }
+ }
+
+ async deleteLinkOnDeselectAssets(
+ deselectedAssets: SpAssetTreeNode[],
+ links: AssetLink[],
+ ): Promise<void> {
+ const uniqueAssetIDsDict = this.getAssetPaths(deselectedAssets);
+ const uniqueAssetIDs = Object.keys(uniqueAssetIDsDict);
+
+ for (const spAssetModelId of uniqueAssetIDs) {
+ const current = await firstValueFrom(
+ this.assetService.getAsset(spAssetModelId),
+ );
+
+ uniqueAssetIDsDict[spAssetModelId].forEach(path => {
+ if (path.length === 2) {
+ current.assetLinks = (current.assetLinks ?? []).filter(
+ (link: any) =>
+ !links.some(
+ l =>
+ JSON.stringify(l.resourceId) ===
+ JSON.stringify(link.resourceId),
+ ),
+ );
+ }
+
+ if (path.length > 2) {
+ links.forEach(linkToRemove => {
+ this.deleteDictValue(current, path, linkToRemove);
+ });
+ }
+ });
+
+ const updateObservable = this.assetService.updateAsset(current);
+ await firstValueFrom(updateObservable); // Ensure this completes
before continuing
+ }
+ }
+
+ private deleteDictValue(
+ dict: SpAssetTreeNode,
+ path: (string | number)[],
+ linkToRemove: any,
+ ) {
+ let current = dict;
+
+ for (let i = 2; i < path.length; i++) {
+ const key = path[i];
+ if (i === path.length - 1) {
+ if (current.assets?.[key]?.assetLinks) {
+ current.assets[key].assetLinks = current.assets[
+ key
+ ].assetLinks.filter(
+ (link: any) =>
+ JSON.stringify(link.resourceId) !==
+ JSON.stringify(linkToRemove.resourceId),
+ );
+ }
+ } else {
+ if (Array.isArray(current.assets)) {
+ current = current.assets[key as number];
+ }
+ }
+ }
+
+ return current;
+ }
+
private updateDictValue(
dict: SpAssetModel,
path: (string | number)[],
@@ -89,7 +271,6 @@ export class AssetSaveService {
) {
const result: any = { ...dict };
let current = result;
- let parent: any = null;
for (let i = 2; i < path.length; i++) {
const key = path[i];