Fixed Flows state not being updated always
This commit is contained in:
parent
154d77b579
commit
d6ea72cbea
9 changed files with 77 additions and 81 deletions
|
|
@ -1,4 +1,3 @@
|
|||
import { cloneDeep } from "lodash";
|
||||
import { useContext, useEffect, useState } from "react";
|
||||
import { NodeToolbar, useUpdateNodeInternals } from "reactflow";
|
||||
import ShadTooltip from "../../components/ShadTooltipComponent";
|
||||
|
|
@ -14,11 +13,7 @@ import { undoRedoContext } from "../../contexts/undoRedoContext";
|
|||
import NodeToolbarComponent from "../../pages/FlowPage/components/nodeToolbarComponent";
|
||||
import { validationStatusType } from "../../types/components";
|
||||
import { NodeDataType } from "../../types/flow";
|
||||
import {
|
||||
cleanEdges,
|
||||
handleKeyDown,
|
||||
scapedJSONStringfy,
|
||||
} from "../../utils/reactflowUtils";
|
||||
import { handleKeyDown, scapedJSONStringfy } from "../../utils/reactflowUtils";
|
||||
import { nodeColors, nodeIconsLucide } from "../../utils/styleUtils";
|
||||
import { classNames, getFieldTitle } from "../../utils/utils";
|
||||
import ParameterComponent from "./components/parameterComponent";
|
||||
|
|
@ -34,7 +29,8 @@ export default function GenericNode({
|
|||
xPos: number;
|
||||
yPos: number;
|
||||
}): JSX.Element {
|
||||
const { updateFlow, flows, tabId } = useContext(FlowsContext);
|
||||
const { updateFlow, flows, tabId, saveCurrentFlow } =
|
||||
useContext(FlowsContext);
|
||||
const updateNodeInternals = useUpdateNodeInternals();
|
||||
const { types, deleteNode, reactFlowInstance, setFilterEdge, getFilterEdge } =
|
||||
useContext(typesContext);
|
||||
|
|
@ -87,18 +83,15 @@ export default function GenericNode({
|
|||
|
||||
// State for outline color
|
||||
const { sseData, isBuilding } = useSSE();
|
||||
useEffect(() => {
|
||||
let myFlow = flows.find((flow) => flow.id === tabId);
|
||||
if (reactFlowInstance && myFlow) {
|
||||
let flow = cloneDeep(myFlow);
|
||||
flow.data = reactFlowInstance.toObject();
|
||||
/* useEffect(() => {
|
||||
let flow = flows.find((flow) => flow.id === tabId);
|
||||
if (reactFlowInstance && flow && flow.data) {
|
||||
cleanEdges({
|
||||
flow: {
|
||||
edges: flow.data.edges,
|
||||
nodes: flow.data.nodes,
|
||||
edges: flow.data!.edges,
|
||||
nodes: flow.data!.nodes,
|
||||
},
|
||||
updateEdge: (edge) => {
|
||||
flow.data!.edges = edge;
|
||||
reactFlowInstance.setEdges(edge);
|
||||
updateNodeInternals(data.id);
|
||||
},
|
||||
|
|
@ -106,7 +99,7 @@ export default function GenericNode({
|
|||
updateFlow(flow);
|
||||
}
|
||||
countHandles();
|
||||
}, [data]);
|
||||
}, [data]); */
|
||||
|
||||
useEffect(() => {
|
||||
setNodeDescription(data.node!.description);
|
||||
|
|
@ -138,6 +131,7 @@ export default function GenericNode({
|
|||
deleteNode={(id) => {
|
||||
takeSnapshot();
|
||||
deleteNode(id);
|
||||
saveCurrentFlow();
|
||||
}}
|
||||
setShowNode={(show: boolean) => {
|
||||
data.showNode = show;
|
||||
|
|
|
|||
|
|
@ -76,11 +76,8 @@ export default function BuildTrigger({
|
|||
}
|
||||
async function streamNodeData(flow: FlowType) {
|
||||
// Step 1: Make a POST request to send the flow data and receive a unique session ID
|
||||
const id = saveFlow({ ...flow, data: reactFlowInstance!.toObject() }, true);
|
||||
const response = await postBuildInit({
|
||||
...flow,
|
||||
data: reactFlowInstance!.toObject(),
|
||||
});
|
||||
const id = saveFlow(flow, true);
|
||||
const response = await postBuildInit(flow);
|
||||
const { flowId } = response.data;
|
||||
// Step 2: Use the session ID to establish an SSE connection using EventSource
|
||||
let validationResults: boolean[] = [];
|
||||
|
|
|
|||
|
|
@ -82,6 +82,7 @@ const FlowsContextInitialValue: FlowsContextType = {
|
|||
setLastCopiedSelection: (selection: any) => {},
|
||||
tabsState: {},
|
||||
setTabsState: (state: FlowsState) => {},
|
||||
saveCurrentFlow: () => {},
|
||||
getNodeId: (nodeType: string) => "",
|
||||
setTweak: (tweak: any) => {},
|
||||
getTweak: [],
|
||||
|
|
@ -638,8 +639,14 @@ export function FlowsProvider({ children }: { children: ReactNode }) {
|
|||
});
|
||||
}
|
||||
|
||||
function saveCurrentFlow() {
|
||||
const currentFlow = flows.find((flow) => flow.id === tabId);
|
||||
if (currentFlow && reactFlowInstance && currentFlow.data) {
|
||||
updateFlow({ ...currentFlow, data: reactFlowInstance?.toObject()! });
|
||||
}
|
||||
}
|
||||
|
||||
async function saveFlow(newFlow: FlowType, silent?: boolean) {
|
||||
console.log(newFlow);
|
||||
try {
|
||||
// updates flow in db
|
||||
const updatedFlow = await updateFlowInDatabase(newFlow);
|
||||
|
|
@ -668,8 +675,6 @@ export function FlowsProvider({ children }: { children: ReactNode }) {
|
|||
},
|
||||
};
|
||||
});
|
||||
|
||||
console.log(tabsState);
|
||||
}
|
||||
} catch (err) {
|
||||
setErrorData({
|
||||
|
|
@ -713,6 +718,7 @@ export function FlowsProvider({ children }: { children: ReactNode }) {
|
|||
setIsBuilt,
|
||||
lastCopiedSelection,
|
||||
setLastCopiedSelection,
|
||||
saveCurrentFlow,
|
||||
hardReset,
|
||||
tabId,
|
||||
setTabId,
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ const ExportModal = forwardRef(
|
|||
downloadFlow(
|
||||
{
|
||||
id: tabId,
|
||||
data: reactFlowInstance?.toObject()!,
|
||||
data: flow!.data!,
|
||||
description,
|
||||
name,
|
||||
last_tested_version: version,
|
||||
|
|
@ -85,7 +85,7 @@ const ExportModal = forwardRef(
|
|||
downloadFlow(
|
||||
removeApiKeys({
|
||||
id: tabId,
|
||||
data: reactFlowInstance?.toObject()!,
|
||||
data: flow!.data!,
|
||||
description,
|
||||
name,
|
||||
last_tested_version: version,
|
||||
|
|
|
|||
|
|
@ -393,7 +393,7 @@ export default function FormModal({
|
|||
const message = inputs;
|
||||
addChatHistory(message!, true, chatKey!, template.current);
|
||||
sendAll({
|
||||
...reactFlowInstance?.toObject()!,
|
||||
...flow.data!,
|
||||
inputs: inputs!,
|
||||
chatHistory,
|
||||
name: flow.name,
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import { Checkbox } from "../../components/ui/checkbox";
|
|||
import { alertContext } from "../../contexts/alertContext";
|
||||
import { FlowsContext } from "../../contexts/flowsContext";
|
||||
import { StoreContext } from "../../contexts/storeContext";
|
||||
import { typesContext } from "../../contexts/typesContext";
|
||||
import {
|
||||
getStoreComponents,
|
||||
getStoreTags,
|
||||
|
|
@ -41,6 +42,7 @@ export default function ShareModal({
|
|||
const { version, addFlow } = useContext(FlowsContext);
|
||||
const { hasApiKey, hasStore } = useContext(StoreContext);
|
||||
const { setSuccessData, setErrorData } = useContext(alertContext);
|
||||
const { reactFlowInstance } = useContext(typesContext);
|
||||
const [checked, setChecked] = useState(false);
|
||||
const [name, setName] = useState(component?.name ?? "");
|
||||
const [description, setDescription] = useState(component?.description ?? "");
|
||||
|
|
@ -127,7 +129,8 @@ export default function ShareModal({
|
|||
});
|
||||
}
|
||||
|
||||
await saveFlow(flows.find((flow) => flow.id === tabId)!, true);
|
||||
await saveFlow({ ...flows.find((flow) => flow.id === tabId)! }, true);
|
||||
|
||||
if (!update)
|
||||
saveFlowStore(flow!, getTagsIds(selectedTags, tags), sharePublic).then(
|
||||
successShare,
|
||||
|
|
|
|||
|
|
@ -60,7 +60,6 @@ export default function Page({
|
|||
let {
|
||||
updateFlow,
|
||||
uploadFlow,
|
||||
addFlow,
|
||||
getNodeId,
|
||||
paste,
|
||||
lastCopiedSelection,
|
||||
|
|
@ -69,7 +68,7 @@ export default function Page({
|
|||
saveFlow,
|
||||
setTabsState,
|
||||
tabId,
|
||||
flows,
|
||||
saveCurrentFlow,
|
||||
} = useContext(FlowsContext);
|
||||
const {
|
||||
types,
|
||||
|
|
@ -89,6 +88,12 @@ export default function Page({
|
|||
const [lastSelection, setLastSelection] =
|
||||
useState<OnSelectionChangeParams | null>(null);
|
||||
|
||||
const saveCurrentFlowTimeout = () => {
|
||||
setTimeout(() => {
|
||||
saveCurrentFlow();
|
||||
}, 500); // need to do this because ReactFlow is not asynchronous.
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const onKeyDown = (event: KeyboardEvent) => {
|
||||
if (
|
||||
|
|
@ -132,6 +137,7 @@ export default function Page({
|
|||
takeSnapshot();
|
||||
deleteNode(lastSelection.nodes.map((node) => node.id));
|
||||
deleteEdge(lastSelection.edges.map((edge) => edge.id));
|
||||
saveCurrentFlowTimeout();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
@ -147,7 +153,12 @@ export default function Page({
|
|||
document.removeEventListener("keydown", onKeyDown);
|
||||
document.removeEventListener("mousemove", handleMouseMove);
|
||||
};
|
||||
}, [lastCopiedSelection, lastSelection, takeSnapshot]);
|
||||
}, [
|
||||
lastCopiedSelection,
|
||||
lastSelection,
|
||||
takeSnapshot,
|
||||
saveCurrentFlowTimeout,
|
||||
]);
|
||||
|
||||
const [selectionMenuVisible, setSelectionMenuVisible] = useState(false);
|
||||
|
||||
|
|
@ -190,16 +201,8 @@ export default function Page({
|
|||
}, [flow, reactFlowInstance]);
|
||||
|
||||
useEffect(() => {
|
||||
const index = flows.findIndex((flowId) => flowId.id === flow.id);
|
||||
|
||||
const interval = setInterval(() => {
|
||||
saveFlow(
|
||||
{
|
||||
...flows[index]!,
|
||||
data: reactFlowInstance ? reactFlowInstance!.toObject() : flow!.data,
|
||||
},
|
||||
true
|
||||
);
|
||||
saveFlow(flow, true);
|
||||
}, 30000);
|
||||
|
||||
return () => {
|
||||
|
|
@ -209,10 +212,6 @@ export default function Page({
|
|||
|
||||
const onEdgesChangeMod = useCallback(
|
||||
(change: EdgeChange[]) => {
|
||||
updateFlow({
|
||||
...flow!,
|
||||
data: reactFlowInstance ? reactFlowInstance!.toObject() : flow!.data,
|
||||
});
|
||||
onEdgesChange(change);
|
||||
//@ts-ignore
|
||||
setTabsState((prev: FlowsState) => {
|
||||
|
|
@ -220,18 +219,18 @@ export default function Page({
|
|||
...prev,
|
||||
[tabId]: {
|
||||
...prev[tabId],
|
||||
isPending: false,
|
||||
isPending: true,
|
||||
},
|
||||
};
|
||||
});
|
||||
saveCurrentFlowTimeout();
|
||||
},
|
||||
[onEdgesChange, setNodes, setTabsState, tabId]
|
||||
[onEdgesChange, setNodes, setTabsState, saveCurrentFlowTimeout, tabId]
|
||||
);
|
||||
|
||||
const onNodesChangeMod = useCallback(
|
||||
(change: NodeChange[]) => {
|
||||
const changeString = JSON.stringify(change);
|
||||
|
||||
if (changeString !== nodesOnFlow) {
|
||||
onNodesChange(change);
|
||||
updateNodeFlow(changeString);
|
||||
|
|
@ -245,9 +244,10 @@ export default function Page({
|
|||
},
|
||||
};
|
||||
});
|
||||
saveCurrentFlowTimeout();
|
||||
}
|
||||
},
|
||||
[onNodesChange, setTabsState, tabId, updateNodeFlow]
|
||||
[onNodesChange, setTabsState, tabId, updateNodeFlow, saveCurrentFlowTimeout]
|
||||
);
|
||||
|
||||
function updateNodeFlow(changeString: string) {
|
||||
|
|
@ -283,7 +283,7 @@ export default function Page({
|
|||
return newX;
|
||||
});
|
||||
},
|
||||
[setEdges, setNodes, takeSnapshot]
|
||||
[setEdges, setNodes, takeSnapshot, addEdge]
|
||||
);
|
||||
|
||||
const onNodeDragStart: NodeDragHandler = useCallback(() => {
|
||||
|
|
@ -394,10 +394,7 @@ export default function Page({
|
|||
|
||||
return () => {
|
||||
if (tabsState && tabsState[flow.id]?.isPending) {
|
||||
saveFlow({
|
||||
...flow!,
|
||||
data: reactFlowInstance ? reactFlowInstance!.toObject() : flow!.data,
|
||||
});
|
||||
saveFlow(flow);
|
||||
}
|
||||
};
|
||||
}, []);
|
||||
|
|
@ -475,11 +472,7 @@ export default function Page({
|
|||
<ReactFlow
|
||||
nodes={nodes}
|
||||
onMove={() => {
|
||||
if (reactFlowInstance)
|
||||
updateFlow({
|
||||
...flow,
|
||||
data: reactFlowInstance.toObject(),
|
||||
});
|
||||
saveCurrentFlowTimeout();
|
||||
}}
|
||||
edges={edges}
|
||||
onNodesChange={onNodesChangeMod}
|
||||
|
|
|
|||
|
|
@ -289,32 +289,34 @@ export default function ExtraSidebar(): JSX.Element {
|
|||
</div>
|
||||
</ShadTooltip>
|
||||
<div className="side-bar-button">
|
||||
<ShadTooltip content="Save" side="top">
|
||||
<div>
|
||||
<button
|
||||
disabled={flow?.data?.nodes.length === 0}
|
||||
className={
|
||||
"extra-side-bar-buttons " +
|
||||
(isPending && flow!.data!.nodes?.length > 0
|
||||
? ""
|
||||
: "button-disable")
|
||||
}
|
||||
onClick={(event) => {
|
||||
saveFlow({ ...flow!, data: reactFlowInstance!.toObject() });
|
||||
}}
|
||||
>
|
||||
<IconComponent
|
||||
name="Save"
|
||||
{flow && flow.data && (
|
||||
<ShadTooltip content="Save" side="top">
|
||||
<div>
|
||||
<button
|
||||
disabled={flow?.data?.nodes.length === 0}
|
||||
className={
|
||||
"side-bar-button-size" +
|
||||
"extra-side-bar-buttons " +
|
||||
(isPending && flow!.data!.nodes?.length > 0
|
||||
? " "
|
||||
: " extra-side-bar-save-disable")
|
||||
? ""
|
||||
: "button-disable")
|
||||
}
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
</ShadTooltip>
|
||||
onClick={(event) => {
|
||||
saveFlow(flow!);
|
||||
}}
|
||||
>
|
||||
<IconComponent
|
||||
name="Save"
|
||||
className={
|
||||
"side-bar-button-size" +
|
||||
(isPending && flow!.data!.nodes?.length > 0
|
||||
? " "
|
||||
: " extra-side-bar-save-disable")
|
||||
}
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
</ShadTooltip>
|
||||
)}
|
||||
</div>
|
||||
<ShadTooltip content="Share" side="top" styleClasses="cursor-default">
|
||||
<div className="side-bar-button">{ModalMemo}</div>
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ export type FlowsContextType = {
|
|||
uploadFlows: () => void;
|
||||
isBuilt: boolean;
|
||||
setIsBuilt: (state: boolean) => void;
|
||||
saveCurrentFlow: () => void;
|
||||
uploadFlow: ({
|
||||
newProject,
|
||||
file,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue