import and export inside flow
This commit is contained in:
parent
fa51eb3d3a
commit
7023a11f04
2 changed files with 171 additions and 149 deletions
|
|
@ -6,7 +6,8 @@ import { TabsContext } from "../../../../contexts/tabsContext";
|
||||||
var _ = require("lodash");
|
var _ = require("lodash");
|
||||||
|
|
||||||
export default function TabComponent({ selected, flow, onClick }) {
|
export default function TabComponent({ selected, flow, onClick }) {
|
||||||
const { removeFlow, updateFlow, flows, downloadFlow } = useContext(TabsContext);
|
const { removeFlow, updateFlow, flows, downloadFlow } =
|
||||||
|
useContext(TabsContext);
|
||||||
const [isRename, setIsRename] = useState(false);
|
const [isRename, setIsRename] = useState(false);
|
||||||
const [value, setValue] = useState("");
|
const [value, setValue] = useState("");
|
||||||
return (
|
return (
|
||||||
|
|
@ -57,7 +58,10 @@ export default function TabComponent({ selected, flow, onClick }) {
|
||||||
>
|
>
|
||||||
{flow.name}
|
{flow.name}
|
||||||
</span>
|
</span>
|
||||||
<ArrowDownTrayIcon onClick={()=>downloadFlow()} className="w-4 h-4 hover:text-blue-500 cursor-pointer"/>
|
{/* <ArrowDownTrayIcon
|
||||||
|
onClick={() => downloadFlow()}
|
||||||
|
className="w-4 h-4 hover:text-blue-500 cursor-pointer"
|
||||||
|
/> */}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<button
|
<button
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,13 @@
|
||||||
import { useCallback, useContext, useEffect, useRef, useState } from "react";
|
import { useCallback, useContext, useEffect, useRef, useState } from "react";
|
||||||
import ReactFlow, {
|
import ReactFlow, {
|
||||||
Background,
|
Background,
|
||||||
Controls,
|
Controls,
|
||||||
addEdge,
|
addEdge,
|
||||||
useEdgesState,
|
useEdgesState,
|
||||||
useNodesState,
|
useNodesState,
|
||||||
ReactFlowProvider,
|
ReactFlowProvider,
|
||||||
useReactFlow,
|
useReactFlow,
|
||||||
|
ControlButton,
|
||||||
} from "reactflow";
|
} from "reactflow";
|
||||||
import { locationContext } from "../../contexts/locationContext";
|
import { locationContext } from "../../contexts/locationContext";
|
||||||
import ExtraSidebar from "./components/extraSidebarComponent";
|
import ExtraSidebar from "./components/extraSidebarComponent";
|
||||||
|
|
@ -20,164 +21,181 @@ import BooleanNode from "../../CustomNodes/BooleanNode";
|
||||||
import { alertContext } from "../../contexts/alertContext";
|
import { alertContext } from "../../contexts/alertContext";
|
||||||
import { TabsContext } from "../../contexts/tabsContext";
|
import { TabsContext } from "../../contexts/tabsContext";
|
||||||
import { typesContext } from "../../contexts/typesContext";
|
import { typesContext } from "../../contexts/typesContext";
|
||||||
|
import {
|
||||||
|
ArrowDownTrayIcon,
|
||||||
|
ArrowUpTrayIcon,
|
||||||
|
} from "@heroicons/react/24/outline";
|
||||||
|
|
||||||
const nodeTypes = {
|
const nodeTypes = {
|
||||||
genericNode: GenericNode,
|
genericNode: GenericNode,
|
||||||
inputNode: InputNode,
|
inputNode: InputNode,
|
||||||
chatInputNode: ChatInputNode,
|
chatInputNode: ChatInputNode,
|
||||||
chatOutputNode: ChatOutputNode,
|
chatOutputNode: ChatOutputNode,
|
||||||
booleanNode: BooleanNode,
|
booleanNode: BooleanNode,
|
||||||
};
|
};
|
||||||
|
|
||||||
var _ = require("lodash");
|
var _ = require("lodash");
|
||||||
|
|
||||||
export default function FlowPage({ flow }) {
|
export default function FlowPage({ flow }) {
|
||||||
let { updateFlow, incrementNodeId } = useContext(TabsContext);
|
let { updateFlow, incrementNodeId, downloadFlow, uploadFlow } =
|
||||||
const { types, reactFlowInstance, setReactFlowInstance } =
|
useContext(TabsContext);
|
||||||
useContext(typesContext);
|
const { types, reactFlowInstance, setReactFlowInstance } =
|
||||||
const reactFlowWrapper = useRef(null);
|
useContext(typesContext);
|
||||||
|
const reactFlowWrapper = useRef(null);
|
||||||
|
|
||||||
function getId(){
|
function getId() {
|
||||||
return `dndnode_}`+incrementNodeId();
|
return `dndnode_}` + incrementNodeId();
|
||||||
};
|
}
|
||||||
|
|
||||||
const { setExtraComponent, setExtraNavigation } = useContext(locationContext);
|
const { setExtraComponent, setExtraNavigation } = useContext(locationContext);
|
||||||
const { setErrorData } = useContext(alertContext);
|
const { setErrorData } = useContext(alertContext);
|
||||||
|
|
||||||
const [nodes, setNodes, onNodesChange] = useNodesState(
|
const [nodes, setNodes, onNodesChange] = useNodesState(
|
||||||
flow.data?.nodes ?? []
|
flow.data?.nodes ?? []
|
||||||
);
|
);
|
||||||
const [edges, setEdges, onEdgesChange] = useEdgesState(
|
const [edges, setEdges, onEdgesChange] = useEdgesState(
|
||||||
flow.data?.edges ?? []
|
flow.data?.edges ?? []
|
||||||
);
|
);
|
||||||
const {setViewport} = useReactFlow()
|
const { setViewport } = useReactFlow();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (reactFlowInstance && flow) {
|
if (reactFlowInstance && flow) {
|
||||||
flow.data = reactFlowInstance.toObject();
|
flow.data = reactFlowInstance.toObject();
|
||||||
updateFlow(flow);
|
updateFlow(flow);
|
||||||
}
|
}
|
||||||
}, [nodes, edges]);
|
}, [nodes, edges]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setNodes(flow?.data?.nodes ?? []);
|
setNodes(flow?.data?.nodes ?? []);
|
||||||
setEdges(flow?.data?.edges ?? []);
|
setEdges(flow?.data?.edges ?? []);
|
||||||
if (reactFlowInstance) {
|
if (reactFlowInstance) {
|
||||||
setViewport(
|
setViewport(flow?.data?.viewport ?? { x: 1, y: 0, zoom: 1 });
|
||||||
flow?.data?.viewport ?? { x: 1, y: 0, zoom: 1 }
|
}
|
||||||
);
|
}, [flow, reactFlowInstance, setEdges, setNodes]);
|
||||||
}
|
|
||||||
}, [flow, reactFlowInstance, setEdges, setNodes]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setExtraComponent(<ExtraSidebar />);
|
setExtraComponent(<ExtraSidebar />);
|
||||||
setExtraNavigation({ title: "Nodes" });
|
setExtraNavigation({ title: "Nodes" });
|
||||||
}, [setExtraComponent, setExtraNavigation]);
|
}, [setExtraComponent, setExtraNavigation]);
|
||||||
|
|
||||||
const onEdgesChangeMod = useCallback(
|
const onEdgesChangeMod = useCallback(
|
||||||
(s) => {
|
(s) => {
|
||||||
onEdgesChange(s);
|
onEdgesChange(s);
|
||||||
setNodes((x) => {
|
setNodes((x) => {
|
||||||
let newX = _.cloneDeep(x);
|
let newX = _.cloneDeep(x);
|
||||||
return newX;
|
return newX;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
[onEdgesChange, setNodes]
|
[onEdgesChange, setNodes]
|
||||||
);
|
);
|
||||||
|
|
||||||
const onConnect = useCallback(
|
const onConnect = useCallback(
|
||||||
(params) => {
|
(params) => {
|
||||||
setEdges((eds) =>
|
setEdges((eds) =>
|
||||||
addEdge({ ...params, className: "animate-pulse" }, eds)
|
addEdge({ ...params, className: "animate-pulse" }, eds)
|
||||||
);
|
);
|
||||||
setNodes((x) => {
|
setNodes((x) => {
|
||||||
let newX = _.cloneDeep(x);
|
let newX = _.cloneDeep(x);
|
||||||
return newX;
|
return newX;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
[setEdges, setNodes]
|
[setEdges, setNodes]
|
||||||
);
|
);
|
||||||
|
|
||||||
const onDragOver = useCallback((event) => {
|
const onDragOver = useCallback((event) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
event.dataTransfer.dropEffect = "move";
|
event.dataTransfer.dropEffect = "move";
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const onDrop = useCallback(
|
const onDrop = useCallback(
|
||||||
(event) => {
|
(event) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
||||||
const reactflowBounds = reactFlowWrapper.current.getBoundingClientRect();
|
const reactflowBounds = reactFlowWrapper.current.getBoundingClientRect();
|
||||||
let data = JSON.parse(event.dataTransfer.getData("json"));
|
let data = JSON.parse(event.dataTransfer.getData("json"));
|
||||||
if (
|
if (
|
||||||
data.type !== "chatInput" ||
|
data.type !== "chatInput" ||
|
||||||
(data.type === "chatInput" &&
|
(data.type === "chatInput" &&
|
||||||
!reactFlowInstance.getNodes().some((n) => n.type === "chatInputNode"))
|
!reactFlowInstance.getNodes().some((n) => n.type === "chatInputNode"))
|
||||||
) {
|
) {
|
||||||
const position = reactFlowInstance.project({
|
const position = reactFlowInstance.project({
|
||||||
x: event.clientX - reactflowBounds.left,
|
x: event.clientX - reactflowBounds.left,
|
||||||
y: event.clientY - reactflowBounds.top,
|
y: event.clientY - reactflowBounds.top,
|
||||||
});
|
});
|
||||||
let newId = getId();
|
let newId = getId();
|
||||||
|
|
||||||
const newNode = {
|
const newNode = {
|
||||||
id: newId,
|
id: newId,
|
||||||
type:
|
type:
|
||||||
data.type === "str"
|
data.type === "str"
|
||||||
? "inputNode"
|
? "inputNode"
|
||||||
: data.type === "chatInput"
|
: data.type === "chatInput"
|
||||||
? "chatInputNode"
|
? "chatInputNode"
|
||||||
: data.type === "chatOutput"
|
: data.type === "chatOutput"
|
||||||
? "chatOutputNode"
|
? "chatOutputNode"
|
||||||
: data.type === "bool"
|
: data.type === "bool"
|
||||||
? "booleanNode"
|
? "booleanNode"
|
||||||
: "genericNode",
|
: "genericNode",
|
||||||
position,
|
position,
|
||||||
data: {
|
data: {
|
||||||
...data,
|
...data,
|
||||||
id: newId,
|
id: newId,
|
||||||
value: null,
|
value: null,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
setNodes((nds) => nds.concat(newNode));
|
setNodes((nds) => nds.concat(newNode));
|
||||||
} else {
|
} else {
|
||||||
setErrorData({
|
setErrorData({
|
||||||
title: "Error creating node",
|
title: "Error creating node",
|
||||||
list: ["There can't be more than one chat input."],
|
list: ["There can't be more than one chat input."],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[reactFlowInstance, setErrorData, setNodes]
|
[reactFlowInstance, setErrorData, setNodes]
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="w-full h-full" ref={reactFlowWrapper}>
|
<div className="w-full h-full" ref={reactFlowWrapper}>
|
||||||
{Object.keys(types).length > 0 ? (
|
{Object.keys(types).length > 0 ? (
|
||||||
<>
|
<>
|
||||||
<ReactFlow
|
<ReactFlow
|
||||||
nodes={nodes}
|
nodes={nodes}
|
||||||
onMove={() =>
|
onMove={() =>
|
||||||
updateFlow({ ...flow, data: reactFlowInstance.toObject() })
|
updateFlow({ ...flow, data: reactFlowInstance.toObject() })
|
||||||
}
|
}
|
||||||
edges={edges}
|
edges={edges}
|
||||||
onNodesChange={onNodesChange}
|
onNodesChange={onNodesChange}
|
||||||
onEdgesChange={onEdgesChangeMod}
|
onEdgesChange={onEdgesChangeMod}
|
||||||
onConnect={onConnect}
|
onConnect={onConnect}
|
||||||
onLoad={setReactFlowInstance}
|
onLoad={setReactFlowInstance}
|
||||||
onInit={setReactFlowInstance}
|
onInit={setReactFlowInstance}
|
||||||
nodeTypes={nodeTypes}
|
nodeTypes={nodeTypes}
|
||||||
connectionLineComponent={connection}
|
connectionLineComponent={connection}
|
||||||
onDragOver={onDragOver}
|
onDragOver={onDragOver}
|
||||||
onDrop={onDrop}
|
onDrop={onDrop}
|
||||||
>
|
>
|
||||||
<Background />
|
<Background />
|
||||||
<Controls></Controls>
|
<Controls>
|
||||||
</ReactFlow>
|
<ControlButton
|
||||||
<Chat flow={flow} reactFlowInstance={reactFlowInstance} />
|
className="text-black hover:text-blue-500"
|
||||||
</>
|
onClick={() => uploadFlow()}
|
||||||
) : (
|
>
|
||||||
<></>
|
<ArrowUpTrayIcon />
|
||||||
)}
|
</ControlButton>
|
||||||
</div>
|
|
||||||
);
|
<ControlButton
|
||||||
|
className="text-black hover:text-blue-500"
|
||||||
|
onClick={() => downloadFlow()}
|
||||||
|
>
|
||||||
|
<ArrowDownTrayIcon />
|
||||||
|
</ControlButton>
|
||||||
|
</Controls>
|
||||||
|
</ReactFlow>
|
||||||
|
<Chat flow={flow} reactFlowInstance={reactFlowInstance} />
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<></>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue