From 04f2941a7d08791184ca4bd0395265e652b6e371 Mon Sep 17 00:00:00 2001 From: anovazzi1 Date: Wed, 13 Sep 2023 10:53:43 -0300 Subject: [PATCH] fix(GenericNode): import XYPosition from reactflow to fix type error feat(GenericNode): add position prop to GenericNode component to pass the position of the node fix(nodeToolbarComponent): import updateFlowPosition from reactflowUtils to fix reference error feat(nodeToolbarComponent): add position prop to NodeToolbarComponent to pass the position of the node fix(components): import XYPosition from reactflow to fix type error feat(components): add position prop to nodeToolbarPropsType to pass the position of the node feat(reactflowUtils): add expandGroupNode function to expand a group node and update the flow --- .../src/CustomNodes/GenericNode/index.tsx | 4 +- .../components/nodeToolbarComponent/index.tsx | 4 +- src/frontend/src/types/components/index.ts | 3 +- src/frontend/src/utils/reactflowUtils.ts | 82 +++++++++++++++++++ 4 files changed, 90 insertions(+), 3 deletions(-) diff --git a/src/frontend/src/CustomNodes/GenericNode/index.tsx b/src/frontend/src/CustomNodes/GenericNode/index.tsx index 50a275980..6a1c4fe59 100644 --- a/src/frontend/src/CustomNodes/GenericNode/index.tsx +++ b/src/frontend/src/CustomNodes/GenericNode/index.tsx @@ -1,6 +1,6 @@ import { cloneDeep } from "lodash"; import { useContext, useEffect, useState } from "react"; -import { NodeToolbar, useUpdateNodeInternals } from "reactflow"; +import { NodeToolbar, XYPosition, useUpdateNodeInternals } from "reactflow"; import ShadTooltip from "../../components/ShadTooltipComponent"; import Tooltip from "../../components/TooltipComponent"; import IconComponent from "../../components/genericIconComponent"; @@ -17,10 +17,12 @@ import ParameterComponent from "./components/parameterComponent"; export default function GenericNode({ data: olddata, + position, selected, }: { data: NodeDataType; selected: boolean; + position: XYPosition; }): JSX.Element { const [data, setData] = useState(olddata); const { updateFlow, flows, tabId } = useContext(TabsContext); diff --git a/src/frontend/src/pages/FlowPage/components/nodeToolbarComponent/index.tsx b/src/frontend/src/pages/FlowPage/components/nodeToolbarComponent/index.tsx index 8bd3f8d5b..e07482536 100644 --- a/src/frontend/src/pages/FlowPage/components/nodeToolbarComponent/index.tsx +++ b/src/frontend/src/pages/FlowPage/components/nodeToolbarComponent/index.tsx @@ -6,12 +6,13 @@ import { TabsContext } from "../../../../contexts/tabsContext"; import EditNodeModal from "../../../../modals/EditNodeModal"; import { nodeToolbarPropsType } from "../../../../types/components"; import { classNames } from "../../../../utils/utils"; -import { ungroupNode } from "../../../../utils/reactflowUtils"; +import { ungroupNode, updateFlowPosition } from "../../../../utils/reactflowUtils"; export default function NodeToolbarComponent({ data, setData, deleteNode, + position, }: nodeToolbarPropsType): JSX.Element { const [nodeLength, setNodeLength] = useState( Object.keys(data.node!.template).filter( @@ -127,6 +128,7 @@ export default function NodeToolbarComponent({ )} onClick={(event) => { event.preventDefault(); + updateFlowPosition(position,data.node?.flow!) ungroupNode(data, { edges: reactFlowInstance.getEdges(), nodes: reactFlowInstance.getNodes(), viewport: reactFlowInstance.getViewport() }) diff --git a/src/frontend/src/types/components/index.ts b/src/frontend/src/types/components/index.ts index c12219663..d7743692a 100644 --- a/src/frontend/src/types/components/index.ts +++ b/src/frontend/src/types/components/index.ts @@ -1,5 +1,5 @@ import { ReactElement, ReactNode } from "react"; -import { ReactFlowJsonObject } from "reactflow"; +import { ReactFlowJsonObject, XYPosition } from "reactflow"; import { APIClassType, APITemplateType, TemplateVariableType } from "../api"; import { ChatMessageType } from "../chat"; import { FlowStyleType, FlowType, NodeDataType, NodeType } from "../flow/index"; @@ -389,6 +389,7 @@ export type nodeToolbarPropsType = { data: NodeDataType; deleteNode: (idx: string) => void; setData: (newState: NodeDataType) => void; + position:XYPosition; }; export type parsedDataType = { diff --git a/src/frontend/src/utils/reactflowUtils.ts b/src/frontend/src/utils/reactflowUtils.ts index 5a1923b26..70af0b0b0 100644 --- a/src/frontend/src/utils/reactflowUtils.ts +++ b/src/frontend/src/utils/reactflowUtils.ts @@ -779,6 +779,88 @@ export function ungroupNode( BaseFlow.edges = edges; } +export function expandGroupNode( + groupNode: NodeDataType, + ReactFlowInstance: ReactFlowInstance, +) { + const {template} = groupNode.node + const {flow} = groupNode.node; + const gNodes = _.cloneDeep(flow.data.nodes); + const gEdges = flow.data.edges; + //redirect edges to correct proxy node + let updatedEdges: Edge[] = []; + ReactFlowInstance.getEdges().forEach((edge) => { + let newEdge = _.cloneDeep(edge); + if (newEdge.target === groupNode.id) { + if (newEdge.targetHandle.split("|").length > 3) { + let type = newEdge.targetHandle.split("|")[0]; + let field = newEdge.targetHandle.split("|")[4]; + let proxy = newEdge.targetHandle.split("|")[3]; + let node = gNodes.find((n) => n.id === proxy); + console.log(node); + if (node) { + newEdge.target = proxy; + if (node.type === "groupNode") { + newEdge.targetHandle = + type + + "|" + + field + + "|" + + proxy + + "|" + + node.data.node.template[field].proxy.id + + "|" + + node.data.node.template[field].proxy.field; + } else { + newEdge.targetHandle = type + "|" + field + "|" + proxy; + } + updatedEdges.push(newEdge); + } + } + } + if (newEdge.source === groupNode.id) { + const lastNode = _.cloneDeep(findLastNode(flow.data)); + newEdge.source = lastNode.id; + let sourceHandle = newEdge.sourceHandle.split("|"); + sourceHandle[1] = lastNode.id; + newEdge.sourceHandle = sourceHandle.join("|"); + updatedEdges.push(newEdge); + } + }); + + Object.keys(template).forEach((key) => { + let { field, id } = template[key].proxy; + let nodeIndex = gNodes.findIndex((n) => n.id === id); + if (nodeIndex !== -1) { + let display_name: string; + let show = gNodes[nodeIndex].data.node.template[field].show; + let advanced = gNodes[nodeIndex].data.node.template[field].advanced; + if (gNodes[nodeIndex].data.node.template[field].display_name) { + display_name = gNodes[nodeIndex].data.node.template[field].display_name; + } else { + display_name = gNodes[nodeIndex].data.node.template[field].name; + } + gNodes[nodeIndex].data.node.template[field] = template[key]; + gNodes[nodeIndex].data.node.template[field].show = show; + gNodes[nodeIndex].data.node.template[field].advanced = advanced; + gNodes[nodeIndex].data.node.template[field].display_name = display_name; + } + }); + + const nodes = [ + ...ReactFlowInstance.getNodes().filter((n) => n.id !== groupNode.id), + ...gNodes, + ]; + const edges = [ + ...ReactFlowInstance.getEdges().filter( + (e) => e.target !== groupNode.id && e.source !== groupNode.id + ), + ...gEdges, + ...updatedEdges, + ]; + ReactFlowInstance.setNodes(nodes); + ReactFlowInstance.setEdges(edges); +} export function processFLow(FlowObject: ReactFlowJsonObject) { let clonedFLow = _.cloneDeep(FlowObject); clonedFLow.nodes.forEach((node: NodeType) => {