11import type { Node , XYPosition } from "@xyflow/react" ;
22
3+ import {
4+ getFlexNodeAnnotations ,
5+ serializeFlexNodes ,
6+ } from "@/components/shared/ReactFlow/FlowCanvas/FlexNode/interface" ;
7+ import type { FlexNodeData } from "@/components/shared/ReactFlow/FlowCanvas/FlexNode/types" ;
38import {
49 type Bounds ,
510 calculateNodesCenter ,
@@ -23,7 +28,10 @@ import {
2328 isTaskOutputArgument ,
2429} from "@/utils/componentSpec" ;
2530
26- import { EDITOR_POSITION_ANNOTATION } from "../annotations" ;
31+ import {
32+ EDITOR_POSITION_ANNOTATION ,
33+ FLEX_NODES_ANNOTATION ,
34+ } from "../annotations" ;
2735import { extractPositionFromAnnotations } from "../annotations" ;
2836import { generateDigest } from "../componentStore" ;
2937import { getUniqueName , getUniqueTaskName } from "../unique" ;
@@ -67,12 +75,14 @@ export const createSubgraphFromNodes = async (
6775 const taskNodes = selectedNodes . filter ( ( node ) => node . type === "task" ) ;
6876 const inputNodes = selectedNodes . filter ( ( node ) => node . type === "input" ) ;
6977 const outputNodes = selectedNodes . filter ( ( node ) => node . type === "output" ) ;
78+ const flexNodes = selectedNodes . filter ( ( node ) => node . type === "flex" ) ;
7079
7180 const subgraphTasks : Record < string , TaskSpec > = { } ;
7281 const subgraphInputs : InputSpec [ ] = [ ] ;
7382 const subgraphArguments : Record < string , ArgumentType > = { } ;
7483 const subgraphOutputs : OutputSpec [ ] = [ ] ;
7584 const subgraphOutputValues : Record < string , TaskOutputArgument > = { } ;
85+ const subgraphAnnotations : Record < string , string > = { } ;
7686
7787 const bounds = getNodesBounds ( selectedNodes ) ;
7888
@@ -145,6 +155,13 @@ export const createSubgraphFromNodes = async (
145155 currentGraphSpec ,
146156 ) ;
147157
158+ processSelectedFlexNodes (
159+ flexNodes ,
160+ bounds ,
161+ subgraphAnnotations ,
162+ currentComponentSpec ,
163+ ) ;
164+
148165 // Create the replacement task that represents the subgraph
149166 const subgraphPosition = calculateNodesCenter ( selectedNodes ) ;
150167
@@ -159,6 +176,7 @@ export const createSubgraphFromNodes = async (
159176 subgraphOutputValues ,
160177 subgraphPosition ,
161178 subgraphArguments ,
179+ subgraphAnnotations ,
162180 ) ;
163181
164182 const text = await getComponentText ( subgraphTask . componentRef ) ;
@@ -179,6 +197,7 @@ const createSubgraphTask = async (
179197 outputValues : Record < string , TaskOutputArgument > ,
180198 position : XYPosition ,
181199 args : Record < string , ArgumentType > ,
200+ annotations : Record < string , string > = { } ,
182201) => {
183202 let author : string = "Unknown" ;
184203 try {
@@ -205,6 +224,7 @@ const createSubgraphTask = async (
205224 sdk : "https://cloud-pipelines.net/pipeline-editor/" ,
206225 "editor.flow-direction" : "left-to-right" ,
207226 author,
227+ ...annotations ,
208228 } ,
209229 } ,
210230 } ;
@@ -309,6 +329,38 @@ const processSelectedOutputNodes = (
309329 } ) ;
310330} ;
311331
332+ const processSelectedFlexNodes = (
333+ flexNodes : Node [ ] ,
334+ bounds : Bounds ,
335+ annotations : Record < string , string > ,
336+ currentComponentSpec : ComponentSpec ,
337+ ) : void => {
338+ const existingFlexNodes = getFlexNodeAnnotations ( currentComponentSpec ) ;
339+ const newFlexNodes : FlexNodeData [ ] = [ ] ;
340+
341+ flexNodes . forEach ( ( node ) => {
342+ const flexNodeId = node . id ;
343+
344+ const existingFlexNode = existingFlexNodes . find (
345+ ( flex ) => flex . id === flexNodeId ,
346+ ) ;
347+
348+ if ( existingFlexNode ) {
349+ const newFlexNode = { ...existingFlexNode } ;
350+ const normalizedPosition = normalizeNodePosition ( node , bounds ) ;
351+ newFlexNode . position = normalizedPosition ;
352+
353+ newFlexNodes . push ( newFlexNode ) ;
354+ }
355+ } ) ;
356+
357+ if ( newFlexNodes . length === 0 ) {
358+ return ;
359+ }
360+
361+ annotations [ FLEX_NODES_ANNOTATION ] = serializeFlexNodes ( newFlexNodes ) ;
362+ } ;
363+
312364const processTaskInputConnections = (
313365 taskSpec : TaskSpec ,
314366 taskPosition : XYPosition ,
0 commit comments