diff --git a/src/app/shared/nodes/generic-node/generic-node.spec.ts b/src/app/shared/nodes/generic-node/generic-node.spec.ts index 3f947e2..79ae6c9 100644 --- a/src/app/shared/nodes/generic-node/generic-node.spec.ts +++ b/src/app/shared/nodes/generic-node/generic-node.spec.ts @@ -1008,6 +1008,39 @@ describe('GenericNodeComponent', () => { })); }); + it('marks a resource parameter change dirty in the active flow data', () => { + const editorState = TestBed.inject(EditorStateHolder) as any; + editorState.activeFlowData.mockReturnValue({ + blocks: [], + containers: [], + resources: [{ + id: 'resource-1', + name: 'Storage', + typeName: 'S3Storage', + specificConfiguration: { name: 'Storage', source: 'CATALOG' } + }], + connections: [], + dependencies: [] + }); + component.data.data = { + ...component.data.data, + id: 'resource-1', + nodeFamily: 'resource', + typeName: 'S3Storage', + name: 'Storage', + specificConfiguration: { name: 'Storage', source: 'PERSONAL' } + }; + + (component as any).markFlowDirty(); + + expect(editorState.updateData).toHaveBeenCalledWith(expect.objectContaining({ + resources: [expect.objectContaining({ + id: 'resource-1', + specificConfiguration: { name: 'Storage', source: 'PERSONAL' } + })] + })); + }); + it('renders every input and output after the Rete node payload is updated', () => { fixture.componentRef.setInput('data', { ...component.data, diff --git a/src/app/shared/nodes/generic-node/generic-node.ts b/src/app/shared/nodes/generic-node/generic-node.ts index 7b4150c..e5cefc2 100644 --- a/src/app/shared/nodes/generic-node/generic-node.ts +++ b/src/app/shared/nodes/generic-node/generic-node.ts @@ -2362,16 +2362,24 @@ export class GenericNodeComponent implements OnDestroy { const blockId = typeof nodeData?.['id'] === 'string' ? nodeData['id'] : null; if (!blockId) return nextFlowData; - const block = nextFlowData.blocks.find((item) => item.id === blockId); - if (!block) return nextFlowData; - const configuredName = toStringOrNull(this.blockConfiguration?.['name']); - block.name = configuredName || this.name || block.name; - block.typeName = this.blockType ?? block.typeName; - block.specificConfiguration = this.cloneFlowData(this.blockConfiguration ?? {}); - (block as unknown as Record)[this.biasAnnotationsProperty] = this.cloneFlowData( - Array.isArray(nodeData?.[this.biasAnnotationsProperty]) ? nodeData[this.biasAnnotationsProperty] : [] - ); + const block = nextFlowData.blocks.find((item) => item.id === blockId); + if (block) { + block.name = configuredName || this.name || block.name; + block.typeName = this.blockType ?? block.typeName; + block.specificConfiguration = this.cloneFlowData(this.blockConfiguration ?? {}); + (block as unknown as Record)[this.biasAnnotationsProperty] = this.cloneFlowData( + Array.isArray(nodeData?.[this.biasAnnotationsProperty]) ? nodeData[this.biasAnnotationsProperty] : [] + ); + return nextFlowData; + } + + // Resources live beside blocks in FlowData, but share the generic settings editor. + const resource = nextFlowData.resources?.find((item) => item.id === blockId); + if (!resource) return nextFlowData; + resource.name = configuredName || this.name || resource.name; + resource.typeName = this.blockType ?? resource.typeName; + resource.specificConfiguration = this.cloneFlowData(this.blockConfiguration ?? {}); return nextFlowData; }