Removed reactFlowInstance and changed to the interceptor function, validate connection not working

This commit is contained in:
Lucas Oliveira 2023-12-29 23:21:53 -03:00
commit 5c1c613c76
17 changed files with 149 additions and 141 deletions

View file

@ -71,7 +71,7 @@ export default function ParameterComponent({
const { setErrorData, modalContextOpen } = useContext(alertContext); const { setErrorData, modalContextOpen } = useContext(alertContext);
const updateNodeInternals = useUpdateNodeInternals(); const updateNodeInternals = useUpdateNodeInternals();
const [position, setPosition] = useState(0); const [position, setPosition] = useState(0);
const { setTabsState, tabId, flows, tabsState, updateFlow } = const { setTabsState, tabId, flows, tabsState, updateFlow, nodes, edges, setEdges } =
useContext(FlowsContext); useContext(FlowsContext);
const [dataRef, setDataRef] = useState(data); const [dataRef, setDataRef] = useState(data);
@ -96,10 +96,9 @@ export default function ParameterComponent({
setDataRef(data); setDataRef(data);
}, [modalContextOpen]); }, [modalContextOpen]);
const { reactFlowInstance, setFilterEdge } = useContext(typesContext); const { setFilterEdge } = useContext(typesContext);
let disabled = let disabled =
reactFlowInstance edges
?.getEdges()
.some( .some(
(edge) => (edge) =>
edge.targetHandle === edge.targetHandle ===
@ -181,14 +180,14 @@ export default function ParameterComponent({
let flow = flows.find((flow) => flow.id === tabId); let flow = flows.find((flow) => flow.id === tabId);
setTimeout(() => { setTimeout(() => {
//timeout necessary because ReactFlow updates are not async //timeout necessary because ReactFlow updates are not async
if (reactFlowInstance && flow && flow.data) { if (flow && flow.data) {
cleanEdges({ cleanEdges({
flow: { flow: {
edges: flow.data!.edges, edges: flow.data!.edges,
nodes: flow.data!.nodes, nodes: flow.data!.nodes,
}, },
updateEdge: (edge) => { updateEdge: (edge) => {
reactFlowInstance.setEdges(edge); setEdges(edge);
updateNodeInternals(data.id); updateNodeInternals(data.id);
}, },
}); });
@ -323,7 +322,7 @@ export default function ParameterComponent({
: scapedJSONStringfy(id) : scapedJSONStringfy(id)
} }
isValidConnection={(connection) => isValidConnection={(connection) =>
isValidConnection(connection, reactFlowInstance!) isValidConnection(connection, nodes, edges)
} }
className={classNames( className={classNames(
left ? "my-12 -ml-0.5 " : " my-12 -mr-0.5 ", left ? "my-12 -ml-0.5 " : " my-12 -mr-0.5 ",
@ -396,7 +395,7 @@ export default function ParameterComponent({
: scapedJSONStringfy(id) : scapedJSONStringfy(id)
} }
isValidConnection={(connection) => isValidConnection={(connection) =>
isValidConnection(connection, reactFlowInstance!) isValidConnection(connection, nodes, edges)
} }
className={classNames( className={classNames(
left ? "-ml-0.5 " : "-mr-0.5 ", left ? "-ml-0.5 " : "-mr-0.5 ",

View file

@ -33,7 +33,7 @@ export default function GenericNode({
const { updateFlow, flows, tabId, saveCurrentFlow } = const { updateFlow, flows, tabId, saveCurrentFlow } =
useContext(FlowsContext); useContext(FlowsContext);
const updateNodeInternals = useUpdateNodeInternals(); const updateNodeInternals = useUpdateNodeInternals();
const { types, deleteNode, reactFlowInstance, setFilterEdge, getFilterEdge } = const { types, deleteNode } =
useContext(typesContext); useContext(typesContext);
const name = nodeIconsLucide[data.type] ? data.type : types[data.type]; const name = nodeIconsLucide[data.type] ? data.type : types[data.type];
const [inputName, setInputName] = useState(false); const [inputName, setInputName] = useState(false);

View file

@ -25,8 +25,7 @@ export default function BuildTrigger({
isBuilt: boolean; isBuilt: boolean;
}): JSX.Element { }): JSX.Element {
const { updateSSEData, isBuilding, setIsBuilding, sseData } = useSSE(); const { updateSSEData, isBuilding, setIsBuilding, sseData } = useSSE();
const { reactFlowInstance } = useContext(typesContext); const { setTabsState, saveFlow, nodes, edges } = useContext(FlowsContext);
const { setTabsState, saveFlow } = useContext(FlowsContext);
const { setErrorData, setSuccessData } = useContext(alertContext); const { setErrorData, setSuccessData } = useContext(alertContext);
const [isIconTouched, setIsIconTouched] = useState(false); const [isIconTouched, setIsIconTouched] = useState(false);
const eventClick = isBuilding ? "pointer-events-none" : ""; const eventClick = isBuilding ? "pointer-events-none" : "";
@ -38,8 +37,8 @@ export default function BuildTrigger({
return; return;
} }
const errors = validateNodes( const errors = validateNodes(
reactFlowInstance!.getNodes(), nodes,
reactFlowInstance!.getEdges() edges
); );
if (errors.length > 0) { if (errors.length > 0) {
setErrorData({ setErrorData({

View file

@ -41,6 +41,7 @@ import { classNames } from "../../utils/utils";
import DictComponent from "../dictComponent"; import DictComponent from "../dictComponent";
import IconComponent from "../genericIconComponent"; import IconComponent from "../genericIconComponent";
import KeypairListComponent from "../keypairListComponent"; import KeypairListComponent from "../keypairListComponent";
import { FlowsContext } from "../../contexts/flowsContext";
export default function CodeTabsComponent({ export default function CodeTabsComponent({
flow, flow,
@ -54,7 +55,7 @@ export default function CodeTabsComponent({
const [data, setData] = useState(flow ? flow["data"]!["nodes"] : null); const [data, setData] = useState(flow ? flow["data"]!["nodes"] : null);
const [openAccordion, setOpenAccordion] = useState<string[]>([]); const [openAccordion, setOpenAccordion] = useState<string[]>([]);
const { dark } = useContext(darkContext); const { dark } = useContext(darkContext);
const { reactFlowInstance } = useContext(typesContext); const {setNodes} = useContext(FlowsContext);
const [errorDuplicateKey, setErrorDuplicateKey] = useState(false); const [errorDuplicateKey, setErrorDuplicateKey] = useState(false);
useEffect(() => { useEffect(() => {
@ -68,7 +69,7 @@ export default function CodeTabsComponent({
unselectAllNodes({ unselectAllNodes({
data, data,
updateNodes: (nodes) => { updateNodes: (nodes) => {
reactFlowInstance?.setNodes(nodes); setNodes(nodes);
}, },
}); });
} }

View file

@ -3,6 +3,7 @@ import _, { cloneDeep } from "lodash";
import { import {
ReactNode, ReactNode,
createContext, createContext,
useCallback,
useContext, useContext,
useEffect, useEffect,
useRef, useRef,
@ -10,10 +11,14 @@ import {
} from "react"; } from "react";
import { import {
Edge, Edge,
EdgeChange,
Node, Node,
NodeChange,
ReactFlowJsonObject, ReactFlowJsonObject,
XYPosition, XYPosition,
addEdge, addEdge,
useEdgesState,
useNodesState,
} from "reactflow"; } from "reactflow";
import ShortUniqueId from "short-unique-id"; import ShortUniqueId from "short-unique-id";
import { import {
@ -93,8 +98,12 @@ const FlowsContextInitialValue: FlowsContextType = {
saveComponent: async (component: NodeDataType, override: boolean) => "", saveComponent: async (component: NodeDataType, override: boolean) => "",
deleteComponent: (key: string) => {}, deleteComponent: (key: string) => {},
version: "", version: "",
nodesOnFlow: "", nodes: [],
setNodesOnFlow: (nodes: string) => "", setNodes: () => {},
onNodesChange: () => {},
edges: [],
setEdges: () => {},
onEdgesChange: () => {},
}; };
export const FlowsContext = createContext<FlowsContextType>( export const FlowsContext = createContext<FlowsContextType>(
@ -102,18 +111,15 @@ export const FlowsContext = createContext<FlowsContextType>(
); );
export function FlowsProvider({ children }: { children: ReactNode }) { export function FlowsProvider({ children }: { children: ReactNode }) {
const { setErrorData, setNoticeData, setSuccessData } = const { setErrorData, setSuccessData } =
useContext(alertContext); useContext(alertContext);
const { getAuthentication, isAuthenticated } = useContext(AuthContext); const { getAuthentication, isAuthenticated } = useContext(AuthContext);
const [tabId, setTabId] = useState(""); const [tabId, setTabId] = useState("");
const [isLoading, setIsLoading] = useState(false); const [isLoading, setIsLoading] = useState(false);
const [nodesOnFlow, setNodesOnFlow] = useState("");
const [flows, setFlows] = useState<Array<FlowType>>([]); const [flows, setFlows] = useState<Array<FlowType>>([]);
const [id, setId] = useState(uid()); const [id, setId] = useState(uid());
const { reactFlowInstance, setData, data } = useContext(typesContext); const { reactFlowInstance, setData } = useContext(typesContext);
const [lastCopiedSelection, setLastCopiedSelection] = useState<{ const [lastCopiedSelection, setLastCopiedSelection] = useState<{
nodes: any; nodes: any;
edges: any; edges: any;
@ -121,6 +127,50 @@ export function FlowsProvider({ children }: { children: ReactNode }) {
const [tabsState, setTabsState] = useState<FlowsState>({}); const [tabsState, setTabsState] = useState<FlowsState>({});
const [getTweak, setTweak] = useState<tweakType>([]); const [getTweak, setTweak] = useState<tweakType>([]);
const [nodes, setNodesInternal, onNodesChangeInternal] = useNodesState([]);
const [edges, setEdgesInternal, onEdgesChangeInternal] = useEdgesState([]);
const onNodesChange = useCallback((nodes: NodeChange[]) => {
onNodesChangeInternal(nodes);
//@ts-ignore
setTabsState((prev: FlowsState) => {
return {
...prev,
[tabId]: {
...prev[tabId],
isPending: true,
},
};
});
//SAVE FLOW IN FLOWS
}, [onNodesChangeInternal, setTabsState, tabId]);
const onEdgesChange = useCallback(
(edges: EdgeChange[]) => {
onEdgesChangeInternal(edges);
//@ts-ignore
setTabsState((prev: FlowsState) => {
return {
...prev,
[tabId]: {
...prev[tabId],
isPending: true,
},
};
});
},
[onEdgesChangeInternal, setTabsState, tabId]
);
const setNodes = (nodes: Node[] | ((oldState: Node[]) => Node[])) => {
setNodesInternal(nodes)
}
const setEdges = (edges: Edge[] | ((oldState: Edge[]) => Edge[])) => {
setEdgesInternal(edges);
};
useEffect(() => { useEffect(() => {
if (!isAuthenticated) { if (!isAuthenticated) {
hardReset(); hardReset();
@ -128,6 +178,7 @@ export function FlowsProvider({ children }: { children: ReactNode }) {
}, [isAuthenticated]); }, [isAuthenticated]);
const newNodeId = useRef(uid()); const newNodeId = useRef(uid());
function incrementNodeId() { function incrementNodeId() {
newNodeId.current = uid(); newNodeId.current = uid();
return newNodeId.current; return newNodeId.current;
@ -425,8 +476,8 @@ export function FlowsProvider({ children }: { children: ReactNode }) {
let minimumX = Infinity; let minimumX = Infinity;
let minimumY = Infinity; let minimumY = Infinity;
let idsMap = {}; let idsMap = {};
let nodes: Node<NodeDataType>[] = reactFlowInstance!.getNodes(); let newNodes: Node<NodeDataType>[] = nodes;
let edges = reactFlowInstance!.getEdges(); let newEdges = edges;
selectionInstance.nodes.forEach((node: Node) => { selectionInstance.nodes.forEach((node: Node) => {
if (node.position.y < minimumY) { if (node.position.y < minimumY) {
minimumY = node.position.y; minimumY = node.position.y;
@ -463,11 +514,11 @@ export function FlowsProvider({ children }: { children: ReactNode }) {
}; };
// Add the new node to the list of nodes in state // Add the new node to the list of nodes in state
nodes = nodes newNodes = nodes
.map((node) => ({ ...node, selected: false })) .map((node) => ({ ...node, selected: false }))
.concat({ ...newNode, selected: false }); .concat({ ...newNode, selected: false });
}); });
reactFlowInstance!.setNodes(nodes); setNodes(newNodes);
selectionInstance.edges.forEach((edge: Edge) => { selectionInstance.edges.forEach((edge: Edge) => {
let source = idsMap[edge.source]; let source = idsMap[edge.source];
@ -498,7 +549,7 @@ export function FlowsProvider({ children }: { children: ReactNode }) {
"-" + "-" +
target + target +
targetHandle; targetHandle;
edges = addEdge( newEdges = addEdge(
{ {
source, source,
target, target,
@ -514,10 +565,10 @@ export function FlowsProvider({ children }: { children: ReactNode }) {
animated: targetHandleObject.type === "Text", animated: targetHandleObject.type === "Text",
selected: false, selected: false,
}, },
edges.map((edge) => ({ ...edge, selected: false })) newEdges.map((edge) => ({ ...edge, selected: false }))
); );
}); });
reactFlowInstance!.setEdges(edges); setEdges(newEdges);
} }
const addFlow = async ( const addFlow = async (
@ -744,8 +795,12 @@ export function FlowsProvider({ children }: { children: ReactNode }) {
isLoading, isLoading,
saveComponent, saveComponent,
deleteComponent, deleteComponent,
nodesOnFlow, nodes,
setNodesOnFlow, setNodes,
onNodesChange,
edges,
setEdges,
onEdgesChange,
}} }}
> >
{children} {children}

View file

@ -29,7 +29,7 @@ const defaultOptions: UseUndoRedoOptions = {
export const undoRedoContext = createContext<undoRedoContextType>(initialValue); export const undoRedoContext = createContext<undoRedoContextType>(initialValue);
export function UndoRedoProvider({ children }) { export function UndoRedoProvider({ children }) {
const { tabId, flows } = useContext(FlowsContext); const { tabId, flows, setNodes, setEdges, nodes, edges } = useContext(FlowsContext);
const [past, setPast] = useState<HistoryItem[][]>(flows.map(() => [])); const [past, setPast] = useState<HistoryItem[][]>(flows.map(() => []));
const [future, setFuture] = useState<HistoryItem[][]>(flows.map(() => [])); const [future, setFuture] = useState<HistoryItem[][]>(flows.map(() => []));
@ -48,14 +48,12 @@ export function UndoRedoProvider({ children }) {
setTabIndex(flows.findIndex((flow) => flow.id === tabId)); setTabIndex(flows.findIndex((flow) => flow.id === tabId));
}, [flows, tabId]); }, [flows, tabId]);
const { setNodes, setEdges, getNodes, getEdges } = useReactFlow();
const takeSnapshot = useCallback(() => { const takeSnapshot = useCallback(() => {
// push the current graph to the past state // push the current graph to the past state
let newPast = cloneDeep(past); let newPast = cloneDeep(past);
let newState = { let newState = {
nodes: cloneDeep(getNodes()), nodes: cloneDeep(nodes),
edges: cloneDeep(getEdges()), edges: cloneDeep(edges),
}; };
if ( if (
past[tabIndex] && past[tabIndex] &&
@ -76,7 +74,7 @@ export function UndoRedoProvider({ children }) {
newFuture[tabIndex] = []; newFuture[tabIndex] = [];
return newFuture; return newFuture;
}); });
}, [getNodes, getEdges, past, future, flows, tabId, setPast, setFuture]); }, [nodes, edges, past, future, flows, tabId, setPast, setFuture]);
const undo = useCallback(() => { const undo = useCallback(() => {
// get the last state that we want to go back to // get the last state that we want to go back to
@ -93,7 +91,7 @@ export function UndoRedoProvider({ children }) {
setFuture((old) => { setFuture((old) => {
let newFuture = cloneDeep(old); let newFuture = cloneDeep(old);
newFuture[tabIndex] = old[tabIndex]; newFuture[tabIndex] = old[tabIndex];
newFuture[tabIndex].push({ nodes: getNodes(), edges: getEdges() }); newFuture[tabIndex].push({ nodes: nodes, edges: edges });
return newFuture; return newFuture;
}); });
// now we can set the graph to the past state // now we can set the graph to the past state
@ -103,8 +101,8 @@ export function UndoRedoProvider({ children }) {
}, [ }, [
setNodes, setNodes,
setEdges, setEdges,
getNodes, nodes,
getEdges, edges,
future, future,
past, past,
setFuture, setFuture,
@ -124,7 +122,7 @@ export function UndoRedoProvider({ children }) {
setPast((old) => { setPast((old) => {
let newPast = cloneDeep(old); let newPast = cloneDeep(old);
newPast[tabIndex] = old[tabIndex]; newPast[tabIndex] = old[tabIndex];
newPast[tabIndex].push({ nodes: getNodes(), edges: getEdges() }); newPast[tabIndex].push({ nodes: nodes, edges: edges });
return newPast; return newPast;
}); });
setNodes(futureState.nodes); setNodes(futureState.nodes);
@ -137,8 +135,8 @@ export function UndoRedoProvider({ children }) {
setPast, setPast,
setNodes, setNodes,
setEdges, setEdges,
getNodes, nodes,
getEdges, edges,
future, future,
tabIndex, tabIndex,
]); ]);

View file

@ -62,8 +62,7 @@ const EditNodeModal = forwardRef(
const [myData, setMyData] = useState(data); const [myData, setMyData] = useState(data);
const { setTabsState, tabId } = useContext(FlowsContext); const { setTabsState, tabId, edges } = useContext(FlowsContext);
const { reactFlowInstance } = useContext(typesContext);
const { setModalContextOpen } = useContext(alertContext); const { setModalContextOpen } = useContext(alertContext);
function changeAdvanced(n) { function changeAdvanced(n) {
@ -159,7 +158,7 @@ const EditNodeModal = forwardRef(
fieldName: templateParam, fieldName: templateParam,
}; };
let disabled = let disabled =
reactFlowInstance?.getEdges().some( edges.some(
(edge) => (edge) =>
edge.targetHandle === edge.targetHandle ===
scapedJSONStringfy( scapedJSONStringfy(

View file

@ -28,7 +28,6 @@ export default function CodeAreaModal({
}: codeAreaModalPropsType): JSX.Element { }: codeAreaModalPropsType): JSX.Element {
const [code, setCode] = useState(value); const [code, setCode] = useState(value);
const { dark } = useContext(darkContext); const { dark } = useContext(darkContext);
const { reactFlowInstance } = useContext(typesContext);
const [height, setHeight] = useState<string | null>(null); const [height, setHeight] = useState<string | null>(null);
const { setErrorData, setSuccessData } = useContext(alertContext); const { setErrorData, setSuccessData } = useContext(alertContext);
const [error, setError] = useState<{ const [error, setError] = useState<{

View file

@ -13,7 +13,6 @@ import BaseModal from "../baseModal";
const ExportModal = forwardRef( const ExportModal = forwardRef(
(props: { children: ReactNode }, ref): JSX.Element => { (props: { children: ReactNode }, ref): JSX.Element => {
const { flows, tabId, downloadFlow, version } = useContext(FlowsContext); const { flows, tabId, downloadFlow, version } = useContext(FlowsContext);
const { reactFlowInstance } = useContext(typesContext);
const { setNoticeData } = useContext(alertContext); const { setNoticeData } = useContext(alertContext);
const [checked, setChecked] = useState(true); const [checked, setChecked] = useState(true);
const flow = flows.find((f) => f.id === tabId); const flow = flows.find((f) => f.id === tabId);

View file

@ -38,7 +38,7 @@ export default function FormModal({
setOpen: (open: boolean) => void; setOpen: (open: boolean) => void;
flow: FlowType; flow: FlowType;
}): JSX.Element { }): JSX.Element {
const { tabsState, setTabsState } = useContext(FlowsContext); const { tabsState, setTabsState, nodes, edges } = useContext(FlowsContext);
const [chatValue, setChatValue] = useState(() => { const [chatValue, setChatValue] = useState(() => {
try { try {
const { formKeysData } = tabsState[flow.id]; const { formKeysData } = tabsState[flow.id];
@ -62,7 +62,6 @@ export default function FormModal({
const [chatHistory, setChatHistory] = useState<ChatMessageType[]>([]); const [chatHistory, setChatHistory] = useState<ChatMessageType[]>([]);
const template = useRef(tabsState[flow.id].formKeysData.template); const template = useRef(tabsState[flow.id].formKeysData.template);
const { reactFlowInstance } = useContext(typesContext);
const { accessToken } = useContext(AuthContext); const { accessToken } = useContext(AuthContext);
const { setErrorData } = useContext(alertContext); const { setErrorData } = useContext(alertContext);
const ws = useRef<WebSocket | null>(null); const ws = useRef<WebSocket | null>(null);
@ -385,8 +384,8 @@ export default function FormModal({
function sendMessage(): void { function sendMessage(): void {
let nodeValidationErrors = validateNodes( let nodeValidationErrors = validateNodes(
reactFlowInstance!.getNodes(), nodes,
reactFlowInstance!.getEdges() edges
); );
if (nodeValidationErrors.length === 0) { if (nodeValidationErrors.length === 0) {
setLockChat(true); setLockChat(true);

View file

@ -40,10 +40,9 @@ export default function ShareModal({
setOpen?: (open: boolean) => void; setOpen?: (open: boolean) => void;
disabled?: boolean; disabled?: boolean;
}): JSX.Element { }): JSX.Element {
const { version, addFlow, downloadFlow } = useContext(FlowsContext); const { version } = useContext(FlowsContext);
const { hasApiKey, hasStore } = useContext(StoreContext); const { hasApiKey, hasStore } = useContext(StoreContext);
const { setSuccessData, setErrorData } = useContext(alertContext); const { setSuccessData, setErrorData } = useContext(alertContext);
const { reactFlowInstance } = useContext(typesContext);
const [internalOpen, internalSetOpen] = useState(children ? false : true); const [internalOpen, internalSetOpen] = useState(children ? false : true);
const [openConfirmationModal, setOpenConfirmationModal] = useState(false); const [openConfirmationModal, setOpenConfirmationModal] = useState(false);
const nameComponent = is_component ? "component" : "flow"; const nameComponent = is_component ? "component" : "flow";

View file

@ -82,7 +82,7 @@ export default function Page({
const reactFlowWrapper = useRef<HTMLDivElement>(null); const reactFlowWrapper = useRef<HTMLDivElement>(null);
const { takeSnapshot } = useContext(undoRedoContext); const { takeSnapshot } = useContext(undoRedoContext);
const { nodesOnFlow, setNodesOnFlow } = useContext(FlowsContext); const { nodes, edges, setNodes, setEdges, onNodesChange, onEdgesChange } = useContext(FlowsContext);
const position = useRef({ x: 0, y: 0 }); const position = useRef({ x: 0, y: 0 });
const [lastSelection, setLastSelection] = const [lastSelection, setLastSelection] =
@ -164,13 +164,7 @@ export default function Page({
const { setExtraComponent, setExtraNavigation } = useContext(locationContext); const { setExtraComponent, setExtraNavigation } = useContext(locationContext);
const { setErrorData } = useContext(alertContext); const { setErrorData } = useContext(alertContext);
const [nodes, setNodes, onNodesChange] = useNodesState(
flow.data?.nodes ?? []
);
const [edges, setEdges, onEdgesChange] = useEdgesState(
flow.data?.edges ?? []
);
const { setViewport } = useReactFlow(); const { setViewport } = useReactFlow();
const edgeUpdateSuccessful = useRef(true); const edgeUpdateSuccessful = useRef(true);
@ -210,50 +204,6 @@ export default function Page({
}; };
}, [flow, flow.data]); }, [flow, flow.data]);
const onEdgesChangeMod = useCallback(
(change: EdgeChange[]) => {
onEdgesChange(change);
//@ts-ignore
setTabsState((prev: FlowsState) => {
return {
...prev,
[tabId]: {
...prev[tabId],
isPending: true,
},
};
});
saveCurrentFlowTimeout();
},
[onEdgesChange, setNodes, setTabsState, saveCurrentFlowTimeout, tabId]
);
const onNodesChangeMod = useCallback(
(change: NodeChange[]) => {
const changeString = JSON.stringify(change);
if (changeString !== nodesOnFlow) {
onNodesChange(change);
updateNodeFlow(changeString);
//@ts-ignore
setTabsState((prev: FlowsState) => {
return {
...prev,
[tabId]: {
...prev[tabId],
isPending: true,
},
};
});
saveCurrentFlowTimeout();
}
},
[onNodesChange, setTabsState, tabId, updateNodeFlow, saveCurrentFlowTimeout]
);
function updateNodeFlow(changeString: string) {
setNodesOnFlow(changeString);
}
const onConnect = useCallback( const onConnect = useCallback(
(params: Connection) => { (params: Connection) => {
takeSnapshot(); takeSnapshot();
@ -416,7 +366,7 @@ export default function Page({
const onEdgeUpdate = useCallback( const onEdgeUpdate = useCallback(
(oldEdge: Edge, newConnection: Connection) => { (oldEdge: Edge, newConnection: Connection) => {
if (isValidConnection(newConnection, reactFlowInstance!)) { if (isValidConnection(newConnection, nodes, edges)) {
edgeUpdateSuccessful.current = true; edgeUpdateSuccessful.current = true;
setEdges((els) => updateEdge(oldEdge, newConnection, els)); setEdges((els) => updateEdge(oldEdge, newConnection, els));
} }
@ -498,8 +448,8 @@ export default function Page({
nodes={nodes} nodes={nodes}
onMove={onMove} onMove={onMove}
edges={edges} edges={edges}
onNodesChange={onNodesChangeMod} onNodesChange={onNodesChange}
onEdgesChange={onEdgesChangeMod} onEdgesChange={onEdgesChange}
onConnect={onConnect} onConnect={onConnect}
disableKeyboardA11y={true} disableKeyboardA11y={true}
onInit={setReactFlowInstance} onInit={setReactFlowInstance}
@ -579,7 +529,7 @@ export default function Page({
/> />
</ReactFlow> </ReactFlow>
{!view && ( {!view && (
<Chat flow={flow} reactFlowInstance={reactFlowInstance!} /> <Chat flow={flow} />
)} )}
</div> </div>
) : ( ) : (

View file

@ -26,7 +26,7 @@ import DisclosureComponent from "../DisclosureComponent";
import SidebarDraggableComponent from "./sideBarDraggableComponent"; import SidebarDraggableComponent from "./sideBarDraggableComponent";
export default function ExtraSidebar(): JSX.Element { export default function ExtraSidebar(): JSX.Element {
const { data, templates, getFilterEdge, setFilterEdge, reactFlowInstance } = const { data, templates, getFilterEdge, setFilterEdge } =
useContext(typesContext); useContext(typesContext);
const { flows, tabId, uploadFlow, tabsState, saveFlow, isBuilt, version } = const { flows, tabId, uploadFlow, tabsState, saveFlow, isBuilt, version } =
useContext(FlowsContext); useContext(FlowsContext);

View file

@ -65,9 +65,8 @@ export default function NodeToolbarComponent({
const isMinimal = canMinimize(); const isMinimal = canMinimize();
const isGroup = data.node?.flow ? true : false; const isGroup = data.node?.flow ? true : false;
const { paste, saveComponent, version, flows } = useContext(FlowsContext); const { paste, saveComponent, version, flows, nodes, edges, setNodes, setEdges } = useContext(FlowsContext);
const { takeSnapshot } = useContext(undoRedoContext); const { takeSnapshot } = useContext(undoRedoContext);
const reactFlowInstance = useReactFlow();
const [showModalAdvanced, setShowModalAdvanced] = useState(false); const [showModalAdvanced, setShowModalAdvanced] = useState(false);
const [showconfirmShare, setShowconfirmShare] = useState(false); const [showconfirmShare, setShowconfirmShare] = useState(false);
const [selectedValue, setSelectedValue] = useState(""); const [selectedValue, setSelectedValue] = useState("");
@ -115,7 +114,7 @@ export default function NodeToolbarComponent({
case "ungroup": case "ungroup":
takeSnapshot(); takeSnapshot();
updateFlowPosition(position, data.node?.flow!); updateFlowPosition(position, data.node?.flow!);
expandGroupNode(data, reactFlowInstance, getNodeId); expandGroupNode(data, getNodeId, nodes, edges, setNodes, setEdges);
break; break;
case "override": case "override":
setShowOverrideModal(true); setShowOverrideModal(true);
@ -152,14 +151,14 @@ export default function NodeToolbarComponent({
event.preventDefault(); event.preventDefault();
paste( paste(
{ {
nodes: [reactFlowInstance.getNode(data.id)], nodes: [nodes.find((node) => node.id === data.id)!],
edges: [], edges: [],
}, },
{ {
x: 50, x: 50,
y: 10, y: 10,
paneX: reactFlowInstance.getNode(data.id)?.position.x, paneX: nodes.find((node) => node.id === data.id)?.position.x,
paneY: reactFlowInstance.getNode(data.id)?.position.y, paneY: nodes.find((node) => node.id === data.id)?.position.y,
} }
); );
}} }}

View file

@ -1,7 +1,7 @@
import { ReactFlowInstance } from "reactflow"; import { ReactFlowInstance } from "reactflow";
import { FlowType } from "../flow"; import { FlowType } from "../flow";
export type ChatType = { flow: FlowType; reactFlowInstance: ReactFlowInstance }; export type ChatType = { flow: FlowType; };
export type ChatMessageType = { export type ChatMessageType = {
message: string | Object; message: string | Object;
template?: string; template?: string;

View file

@ -1,6 +1,9 @@
import { XYPosition } from "reactflow"; import { XYPosition, Node, NodeChange, Edge, EdgeChange } from "reactflow";
import { tweakType } from "../components"; import { tweakType } from "../components";
import { FlowType, NodeDataType } from "../flow"; import { FlowType, NodeDataType } from "../flow";
import { Dispatch, SetStateAction } from "react";
type OnChange<ChangesType> = (changes: ChangesType[]) => void;
export type FlowsContextType = { export type FlowsContextType = {
saveFlow: (flow: FlowType, silent?: boolean) => Promise<void>; saveFlow: (flow: FlowType, silent?: boolean) => Promise<void>;
@ -56,8 +59,12 @@ export type FlowsContextType = {
) => Promise<String | undefined>; ) => Promise<String | undefined>;
deleteComponent: (key: string) => void; deleteComponent: (key: string) => void;
version: string; version: string;
nodesOnFlow: string; nodes: Array<Node>;
setNodesOnFlow: (nodes: string) => void; setNodes: (update: Node[] | ((oldState: Node[]) => Node[])) => void;
onNodesChange: OnChange<NodeChange>;
edges: Array<Edge>;
setEdges: (update: Edge[] | ((oldState: Edge[]) => Edge[])) => void;
onEdgesChange: OnChange<EdgeChange>;
}; };
export type FlowsState = { export type FlowsState = {

View file

@ -86,8 +86,10 @@ export function unselectAllNodes({ updateNodes, data }: unselectAllNodesType) {
export function isValidConnection( export function isValidConnection(
{ source, target, sourceHandle, targetHandle }: Connection, { source, target, sourceHandle, targetHandle }: Connection,
reactFlowInstance: ReactFlowInstance nodes: Node[],
edges: Edge[],
) { ) {
debugger
const targetHandleObject: targetHandleType = scapeJSONParse(targetHandle!); const targetHandleObject: targetHandleType = scapeJSONParse(targetHandle!);
const sourceHandleObject: sourceHandleType = scapeJSONParse(sourceHandle!); const sourceHandleObject: sourceHandleType = scapeJSONParse(sourceHandle!);
if ( if (
@ -100,19 +102,17 @@ export function isValidConnection(
t === targetHandleObject.type t === targetHandleObject.type
) )
) { ) {
let targetNode = reactFlowInstance?.getNode(target!)?.data?.node; let targetNode = nodes.find((node) => node.id === target!)?.data?.node;
if (!targetNode) { if (!targetNode) {
if ( if (
!reactFlowInstance edges
.getEdges()
.find((e) => e.targetHandle === targetHandle) .find((e) => e.targetHandle === targetHandle)
) { ) {
return true; return true;
} }
} else if ( } else if (
(!targetNode.template[targetHandleObject.fieldName].list && (!targetNode.template[targetHandleObject.fieldName].list &&
!reactFlowInstance edges
.getEdges()
.find((e) => e.targetHandle === targetHandle)) || .find((e) => e.targetHandle === targetHandle)) ||
targetNode.template[targetHandleObject.fieldName].list targetNode.template[targetHandleObject.fieldName].list
) { ) {
@ -543,12 +543,13 @@ export function generateFlow(
export function filterFlow( export function filterFlow(
selection: OnSelectionChangeParams, selection: OnSelectionChangeParams,
reactFlowInstance: ReactFlowInstance setNodes: (update: Node[] | ((oldState: Node[]) => Node[])) => void,
setEdges: (update: Edge[] | ((oldState: Edge[]) => Edge[])) => void,
) { ) {
reactFlowInstance.setNodes((nodes) => setNodes((nodes) =>
nodes.filter((node) => !selection.nodes.includes(node)) nodes.filter((node) => !selection.nodes.includes(node))
); );
reactFlowInstance.setEdges((edges) => setEdges((edges) =>
edges.filter((edge) => !selection.edges.includes(edge)) edges.filter((edge) => !selection.edges.includes(edge))
); );
} }
@ -575,11 +576,12 @@ export function updateFlowPosition(NewPosition: XYPosition, flow: FlowType) {
export function concatFlows( export function concatFlows(
flow: FlowType, flow: FlowType,
ReactFlowInstance: ReactFlowInstance setNodes: (update: Node[] | ((oldState: Node[]) => Node[])) => void,
setEdges: (update: Edge[] | ((oldState: Edge[]) => Edge[])) => void,
) { ) {
const { nodes, edges } = flow.data!; const { nodes, edges } = flow.data!;
ReactFlowInstance.addNodes(nodes); setNodes((old) => [...old, ...nodes]);
ReactFlowInstance.addEdges(edges); setEdges((old) => [...old, ...edges]);
} }
export function validateSelection( export function validateSelection(
@ -921,13 +923,16 @@ function updateEdgesIds(edges: Edge[], idsMap: { [key: string]: string }) {
export function expandGroupNode( export function expandGroupNode(
groupNode: NodeDataType, groupNode: NodeDataType,
ReactFlowInstance: ReactFlowInstance, getNodeId: (type: string) => string,
getNodeId: (type: string) => string nodes: Node[],
edges: Edge[],
setNodes: (update: Node[] | ((oldState: Node[]) => Node[])) => void,
setEdges: (update: Edge[] | ((oldState: Edge[]) => Edge[])) => void
) { ) {
const { template, flow } = _.cloneDeep(groupNode.node!); const { template, flow } = _.cloneDeep(groupNode.node!);
const idsMap = updateIds(flow!.data!, getNodeId); const idsMap = updateIds(flow!.data!, getNodeId);
updateProxyIdsOnTemplate(template, idsMap); updateProxyIdsOnTemplate(template, idsMap);
let flowEdges = ReactFlowInstance.getEdges(); let flowEdges = edges;
updateEdgesIds(flowEdges, idsMap); updateEdgesIds(flowEdges, idsMap);
const gNodes: NodeType[] = flow?.data?.nodes!; const gNodes: NodeType[] = flow?.data?.nodes!;
const gEdges = flow!.data!.edges; const gEdges = flow!.data!.edges;
@ -1008,19 +1013,19 @@ export function expandGroupNode(
} }
}); });
const nodes = [ const filteredNodes = [
...ReactFlowInstance.getNodes().filter((n) => n.id !== groupNode.id), ...nodes.filter((n) => n.id !== groupNode.id),
...gNodes, ...gNodes,
]; ];
const edges = [ const filteredEdges = [
...ReactFlowInstance.getEdges().filter( ...edges.filter(
(e) => e.target !== groupNode.id && e.source !== groupNode.id (e) => e.target !== groupNode.id && e.source !== groupNode.id
), ),
...gEdges, ...gEdges,
...updatedEdges, ...updatedEdges,
]; ];
ReactFlowInstance.setNodes(nodes); setNodes(filteredNodes);
ReactFlowInstance.setEdges(edges); setEdges(filteredEdges);
} }
export function processFlow(FlowObject: ReactFlowJsonObject) { export function processFlow(FlowObject: ReactFlowJsonObject) {