diff --git a/src/frontend/src/CustomNodes/GenericNode/components/parameterComponent/index.tsx b/src/frontend/src/CustomNodes/GenericNode/components/parameterComponent/index.tsx index bf94fa43e..a2cecddc2 100644 --- a/src/frontend/src/CustomNodes/GenericNode/components/parameterComponent/index.tsx +++ b/src/frontend/src/CustomNodes/GenericNode/components/parameterComponent/index.tsx @@ -17,7 +17,10 @@ import { TOOLTIP_EMPTY } from "../../../../constants/constants"; import { TabsContext } from "../../../../contexts/tabsContext"; import { typesContext } from "../../../../contexts/typesContext"; import { ParameterComponentType } from "../../../../types/components"; -import { isValidConnection } from "../../../../utils/reactflowUtils"; +import { + isValidConnection, + scapedJSONStringfy, +} from "../../../../utils/reactflowUtils"; import { nodeColors, nodeIconsLucide, @@ -64,7 +67,7 @@ export default function ParameterComponent({ let disabled = reactFlowInstance ?.getEdges() - .some((e) => e.targetHandle === JSON.stringify(id)) ?? false; + .some((e) => e.targetHandle === scapedJSONStringfy(id)) ?? false; const { data: myData } = useContext(typesContext); @@ -207,7 +210,7 @@ export default function ParameterComponent({ isValidConnection(connection, reactFlowInstance) } diff --git a/src/frontend/src/CustomNodes/GenericNode/index.tsx b/src/frontend/src/CustomNodes/GenericNode/index.tsx index b476f7458..4244f84e8 100644 --- a/src/frontend/src/CustomNodes/GenericNode/index.tsx +++ b/src/frontend/src/CustomNodes/GenericNode/index.tsx @@ -9,7 +9,7 @@ import { TabsContext } from "../../contexts/tabsContext"; import { typesContext } from "../../contexts/typesContext"; import NodeToolbarComponent from "../../pages/FlowPage/components/nodeToolbarComponent"; import { NodeDataType } from "../../types/flow"; -import { cleanEdges } from "../../utils/reactflowUtils"; +import { cleanEdges, scapedJSONStringfy } from "../../utils/reactflowUtils"; import { nodeColors, nodeIconsLucide } from "../../utils/styleUtils"; import { classNames, toTitleCase } from "../../utils/utils"; import ParameterComponent from "./components/parameterComponent"; @@ -165,7 +165,7 @@ export default function GenericNode({ {data.node.template[t].show && !data.node.template[t].advanced ? ( { if (edge.source === node.id) { - let sourceHandleObject: sourceHandleType = JSON.parse( + let sourceHandleObject: sourceHandleType = scapeJSONParse( edge.sourceHandle ); sourceHandleObject.baseClasses = sourceHandleObject.baseClasses.concat( template["base_classes"] ); - edge.sourceHandle = JSON.stringify(sourceHandleObject); + edge.sourceHandle = scapedJSONStringfy(sourceHandleObject); } }); } @@ -411,13 +413,17 @@ export function TabsProvider({ children }: { children: ReactNode }) { selectionInstance.edges.forEach((e: Edge) => { let source = idsMap[e.source]; let target = idsMap[e.target]; - const sourceHandleObject: sourceHandleType = JSON.parse(e.sourceHandle); - let sourceHandle = JSON.stringify({ + const sourceHandleObject: sourceHandleType = scapeJSONParse( + e.sourceHandle + ); + let sourceHandle = scapedJSONStringfy({ ...sourceHandleObject, id: e.source, }); - const targetHandleObject: targetHandleType = JSON.parse(e.targetHandle); - let targetHandle = JSON.stringify({ + const targetHandleObject: targetHandleType = scapeJSONParse( + e.targetHandle + ); + let targetHandle = scapedJSONStringfy({ ...targetHandleObject, id: e.target, }); @@ -506,7 +512,7 @@ export function TabsProvider({ children }: { children: ReactNode }) { const updateEdges = (edges: Edge[]) => { edges.forEach((edge) => { - const targetHandleObject: targetHandleType = JSON.parse( + const targetHandleObject: targetHandleType = scapeJSONParse( edge.targetHandle ); edge.className = @@ -527,13 +533,13 @@ export function TabsProvider({ children }: { children: ReactNode }) { if (Object.keys(template["template"]).length > 0) { node.data.node.base_classes = template["base_classes"]; edges.forEach((edge) => { - let sourceHandleObject: sourceHandleType = JSON.parse( + let sourceHandleObject: sourceHandleType = scapeJSONParse( edge.sourceHandle ); if (edge.source === node.id) { let newSourceHandle = sourceHandleObject; newSourceHandle.baseClasses.concat(template["base_classes"]); - edge.sourceHandle = JSON.stringify(newSourceHandle); + edge.sourceHandle = scapedJSONStringfy(newSourceHandle); } }); node.data.node.description = template["description"]; diff --git a/src/frontend/src/pages/FlowPage/components/PageComponent/index.tsx b/src/frontend/src/pages/FlowPage/components/PageComponent/index.tsx index f2dde4e4b..3da13d019 100644 --- a/src/frontend/src/pages/FlowPage/components/PageComponent/index.tsx +++ b/src/frontend/src/pages/FlowPage/components/PageComponent/index.tsx @@ -26,7 +26,10 @@ import { typesContext } from "../../../../contexts/typesContext"; import { undoRedoContext } from "../../../../contexts/undoRedoContext"; import { APIClassType } from "../../../../types/api"; import { FlowType, NodeType, targetHandleType } from "../../../../types/flow"; -import { isValidConnection } from "../../../../utils/reactflowUtils"; +import { + isValidConnection, + scapeJSONParse, +} from "../../../../utils/reactflowUtils"; import { isWrappedWithClass } from "../../../../utils/utils"; import ConnectionLineComponent from "../ConnectionLineComponent"; import ExtraSidebar from "../extraSidebarComponent"; @@ -185,12 +188,12 @@ export default function Page({ flow }: { flow: FlowType }) { ...params, style: { stroke: "#555" }, className: - ((JSON.parse(params.targetHandle) as targetHandleType).type === - "Text" + ((scapeJSONParse(params.targetHandle) as targetHandleType) + .type === "Text" ? "stroke-foreground " : "stroke-foreground ") + " stroke-connection", animated: - (JSON.parse(params.targetHandle) as targetHandleType).type === + (scapeJSONParse(params.targetHandle) as targetHandleType).type === "Text", }, eds diff --git a/src/frontend/src/utils/reactflowUtils.ts b/src/frontend/src/utils/reactflowUtils.ts index 7658584f2..4e6e17f71 100644 --- a/src/frontend/src/utils/reactflowUtils.ts +++ b/src/frontend/src/utils/reactflowUtils.ts @@ -30,7 +30,8 @@ export function cleanEdges({ const sourceHandle = edge.sourceHandle; //right const targetHandle = edge.targetHandle; //left if (targetHandle) { - const targetHandleObject: targetHandleType = JSON.parse(targetHandle); + const targetHandleObject: targetHandleType = + scapeJSONParse(targetHandle); const field = targetHandleObject.fieldName; const id: targetHandleType = { type: targetNode.data.node.template[field]?.type, @@ -38,7 +39,7 @@ export function cleanEdges({ id: targetNode.data.id, inputTypes: targetNode.data.node.template[field]?.input_types, }; - if (JSON.stringify(id) !== targetHandle) { + if (scapedJSONStringfy(id) !== targetHandle) { newEdges = newEdges.filter((e) => e.id !== edge.id); } } @@ -48,7 +49,7 @@ export function cleanEdges({ baseClasses: sourceNode.data.node.base_classes, dataType: sourceNode.data.type, }; - if (JSON.stringify(id) !== sourceHandle) { + if (scapedJSONStringfy(id) !== sourceHandle) { newEdges = newEdges.filter((e) => e.id !== edge.id); } } @@ -62,14 +63,17 @@ export function isValidConnection( { source, target, sourceHandle, targetHandle }: Connection, reactFlowInstance: ReactFlowInstance ) { - const targetHandleObject: targetHandleType = JSON.parse(targetHandle); - const sourceHandleObject: sourceHandleType = JSON.parse(sourceHandle); + const targetHandleObject: targetHandleType = scapeJSONParse(targetHandle); + const sourceHandleObject: sourceHandleType = scapeJSONParse(sourceHandle); + console.log(sourceHandleObject, targetHandleObject); if ( targetHandleObject.inputTypes?.some( (n) => n === sourceHandleObject.dataType ) || - sourceHandleObject.baseClasses.some((t) => - targetHandleObject.inputTypes?.some((n) => n === t) + sourceHandleObject.baseClasses.some( + (t) => + targetHandleObject.inputTypes?.some((n) => n === t) || + t === targetHandleObject.type ) || targetHandleObject.type === "str" ) { @@ -145,10 +149,16 @@ export function updateIds(newFlow, getNodeId) { newFlow.edges.forEach((e: Edge) => { e.source = idsMap[e.source]; e.target = idsMap[e.target]; - const sourceHandleObject: sourceHandleType = JSON.parse(e.sourceHandle); - e.sourceHandle = JSON.stringify({ ...sourceHandleObject, id: e.source }); - const targetHandleObject: targetHandleType = JSON.parse(e.targetHandle); - e.targetHandle = JSON.stringify({ ...targetHandleObject, id: e.target }); + const sourceHandleObject: sourceHandleType = scapeJSONParse(e.sourceHandle); + e.sourceHandle = scapedJSONStringfy({ + ...sourceHandleObject, + id: e.source, + }); + const targetHandleObject: targetHandleType = scapeJSONParse(e.targetHandle); + e.targetHandle = scapedJSONStringfy({ + ...targetHandleObject, + id: e.target, + }); e.id = "reactflow__edge-" + e.source + @@ -193,9 +203,9 @@ export function validateNode( .getEdges() .some( (e) => - (JSON.parse(e.targetHandle) as targetHandleType).fieldName === - t && - (JSON.parse(e.targetHandle) as targetHandleType).id === n.id + (scapeJSONParse(e.targetHandle) as targetHandleType) + .fieldName === t && + (scapeJSONParse(e.targetHandle) as targetHandleType).id === n.id ) ? [ `${type} is missing ${ @@ -264,8 +274,8 @@ export function updateEdgesHandleIds({ baseClasses: sourceNode.data.node.base_classes, }; } - edge.sourceHandle = JSON.stringify(newSource); - edge.targetHandle = JSON.stringify(newTarget); + edge.sourceHandle = scapedJSONStringfy(newSource); + edge.targetHandle = scapedJSONStringfy(newTarget); }); return newEdges; } @@ -278,3 +288,10 @@ export function getConnectedNodes( const targetId = edge.target; return nodes.filter((node) => node.id === targetId || node.id === sourceId); } + +export function scapedJSONStringfy(json: object): string { + return JSON.stringify(json).replace(/"/g, '\\"'); +} +export function scapeJSONParse(json: string): any { + return JSON.parse(json.replace(/\\"/g, '"')); +}