🔨 refactor(flows.py): change response model of update_flow endpoint to FlowRead
🔨 refactor(parameterComponent): remove unused imports and refactor onChange function to handleOnNewValue ✨ feat(tabsContext): add tabsState and setTabsState to TabsContextType and TabsProvider 🔨 refactor(flowSettingsModal): refactor handleSaveFlow function to update flow and setTabsState with isPending false The update_flow endpoint now returns a FlowRead response model instead of FlowReadWithStyle. The parameterComponent file has been refactored to remove unused imports and to use a handleOnNewValue function to handle onChange events. The TabsContextType and TabsProvider have been updated to include tabsState and setTabsState. The flowSettingsModal has been refactored to update the flow and setTabsState with isPending false. 🔨 refactor(extraSidebarComponent): add tabsState and setTabsState to TabsContextType 🐛 fix(extraSidebarComponent): disable save button when flow is not pending 🐛 fix(extraSidebarComponent): update flow state after saving The TabsContextType now includes tabsState and setTabsState to allow for the management of the state of each tab. The save button is now disabled when the flow is not pending. The flow state is now updated after saving to reflect the changes made.
This commit is contained in:
parent
499d5238e3
commit
03076b3577
6 changed files with 78 additions and 59 deletions
|
|
@ -49,7 +49,7 @@ def read_flow(*, session: Session = Depends(get_session), flow_id: UUID):
|
||||||
raise HTTPException(status_code=404, detail="Flow not found")
|
raise HTTPException(status_code=404, detail="Flow not found")
|
||||||
|
|
||||||
|
|
||||||
@router.patch("/{flow_id}", response_model=FlowReadWithStyle, status_code=200)
|
@router.patch("/{flow_id}", response_model=FlowRead, status_code=200)
|
||||||
def update_flow(
|
def update_flow(
|
||||||
*, session: Session = Depends(get_session), flow_id: UUID, flow: FlowUpdate
|
*, session: Session = Depends(get_session), flow_id: UUID, flow: FlowUpdate
|
||||||
):
|
):
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,11 @@
|
||||||
import { Handle, Position, useUpdateNodeInternals } from "reactflow";
|
import { Handle, Position, useUpdateNodeInternals } from "reactflow";
|
||||||
import Tooltip from "../../../../components/TooltipComponent";
|
|
||||||
import {
|
import {
|
||||||
classNames,
|
classNames,
|
||||||
groupByFamily,
|
groupByFamily,
|
||||||
isValidConnection,
|
isValidConnection,
|
||||||
toFirstUpperCase,
|
|
||||||
} from "../../../../utils";
|
} from "../../../../utils";
|
||||||
import { useContext, useEffect, useRef, useState } from "react";
|
import { useContext, useEffect, useRef, useState } from "react";
|
||||||
import InputComponent from "../../../../components/inputComponent";
|
import InputComponent from "../../../../components/inputComponent";
|
||||||
import ToggleComponent from "../../../../components/toggleComponent";
|
|
||||||
import InputListComponent from "../../../../components/inputListComponent";
|
import InputListComponent from "../../../../components/inputListComponent";
|
||||||
import TextAreaComponent from "../../../../components/textAreaComponent";
|
import TextAreaComponent from "../../../../components/textAreaComponent";
|
||||||
import { typesContext } from "../../../../contexts/typesContext";
|
import { typesContext } from "../../../../contexts/typesContext";
|
||||||
|
|
@ -43,6 +40,7 @@ export default function ParameterComponent({
|
||||||
const updateNodeInternals = useUpdateNodeInternals();
|
const updateNodeInternals = useUpdateNodeInternals();
|
||||||
const [position, setPosition] = useState(0);
|
const [position, setPosition] = useState(0);
|
||||||
const { closePopUp } = useContext(PopUpContext);
|
const { closePopUp } = useContext(PopUpContext);
|
||||||
|
const { setTabsState, tabId } = useContext(TabsContext);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (ref.current && ref.current.offsetTop && ref.current.clientHeight) {
|
if (ref.current && ref.current.offsetTop && ref.current.clientHeight) {
|
||||||
|
|
@ -66,6 +64,19 @@ export default function ParameterComponent({
|
||||||
reactFlowInstance?.getEdges().some((e) => e.targetHandle === id) ?? false;
|
reactFlowInstance?.getEdges().some((e) => e.targetHandle === id) ?? false;
|
||||||
const [myData, setMyData] = useState(useContext(typesContext).data);
|
const [myData, setMyData] = useState(useContext(typesContext).data);
|
||||||
|
|
||||||
|
const handleOnNewValue = (newValue: any) => {
|
||||||
|
data.node.template[name].value = newValue;
|
||||||
|
// Set state to pending
|
||||||
|
setTabsState((prev) => {
|
||||||
|
return {
|
||||||
|
...prev,
|
||||||
|
[tabId]: {
|
||||||
|
isPending: true,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const groupedObj = groupByFamily(myData, tooltipTitle);
|
const groupedObj = groupByFamily(myData, tooltipTitle);
|
||||||
|
|
||||||
|
|
@ -165,17 +176,13 @@ export default function ParameterComponent({
|
||||||
? [""]
|
? [""]
|
||||||
: data.node.template[name].value
|
: data.node.template[name].value
|
||||||
}
|
}
|
||||||
onChange={(t: string[]) => {
|
onChange={handleOnNewValue}
|
||||||
data.node.template[name].value = t;
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
) : data.node.template[name].multiline ? (
|
) : data.node.template[name].multiline ? (
|
||||||
<TextAreaComponent
|
<TextAreaComponent
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
value={data.node.template[name].value ?? ""}
|
value={data.node.template[name].value ?? ""}
|
||||||
onChange={(t: string) => {
|
onChange={handleOnNewValue}
|
||||||
data.node.template[name].value = t;
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<InputComponent
|
<InputComponent
|
||||||
|
|
@ -183,9 +190,7 @@ export default function ParameterComponent({
|
||||||
disableCopyPaste={true}
|
disableCopyPaste={true}
|
||||||
password={data.node.template[name].password ?? false}
|
password={data.node.template[name].password ?? false}
|
||||||
value={data.node.template[name].value ?? ""}
|
value={data.node.template[name].value ?? ""}
|
||||||
onChange={(t) => {
|
onChange={handleOnNewValue}
|
||||||
data.node.template[name].value = t;
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -195,7 +200,7 @@ export default function ParameterComponent({
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
enabled={enabled}
|
enabled={enabled}
|
||||||
setEnabled={(t) => {
|
setEnabled={(t) => {
|
||||||
data.node.template[name].value = t;
|
handleOnNewValue(t);
|
||||||
setEnabled(t);
|
setEnabled(t);
|
||||||
}}
|
}}
|
||||||
size="large"
|
size="large"
|
||||||
|
|
@ -207,9 +212,7 @@ export default function ParameterComponent({
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
disableCopyPaste={true}
|
disableCopyPaste={true}
|
||||||
value={data.node.template[name].value ?? ""}
|
value={data.node.template[name].value ?? ""}
|
||||||
onChange={(t) => {
|
onChange={handleOnNewValue}
|
||||||
data.node.template[name].value = t;
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
) : left === true &&
|
) : left === true &&
|
||||||
|
|
@ -218,9 +221,7 @@ export default function ParameterComponent({
|
||||||
<div className="w-full">
|
<div className="w-full">
|
||||||
<Dropdown
|
<Dropdown
|
||||||
options={data.node.template[name].options}
|
options={data.node.template[name].options}
|
||||||
onSelect={(newValue) =>
|
onSelect={handleOnNewValue}
|
||||||
(data.node.template[name].value = newValue)
|
|
||||||
}
|
|
||||||
value={data.node.template[name].value ?? "Choose an option"}
|
value={data.node.template[name].value ?? "Choose an option"}
|
||||||
></Dropdown>
|
></Dropdown>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -228,17 +229,13 @@ export default function ParameterComponent({
|
||||||
<CodeAreaComponent
|
<CodeAreaComponent
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
value={data.node.template[name].value ?? ""}
|
value={data.node.template[name].value ?? ""}
|
||||||
onChange={(t: string) => {
|
onChange={handleOnNewValue}
|
||||||
data.node.template[name].value = t;
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
) : left === true && type === "file" ? (
|
) : left === true && type === "file" ? (
|
||||||
<InputFileComponent
|
<InputFileComponent
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
value={data.node.template[name].value ?? ""}
|
value={data.node.template[name].value ?? ""}
|
||||||
onChange={(t: string) => {
|
onChange={handleOnNewValue}
|
||||||
data.node.template[name].value = t;
|
|
||||||
}}
|
|
||||||
fileTypes={data.node.template[name].fileTypes}
|
fileTypes={data.node.template[name].fileTypes}
|
||||||
suffixes={data.node.template[name].suffixes}
|
suffixes={data.node.template[name].suffixes}
|
||||||
onFileChange={(t: string) => {
|
onFileChange={(t: string) => {
|
||||||
|
|
@ -251,18 +248,14 @@ export default function ParameterComponent({
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
disableCopyPaste={true}
|
disableCopyPaste={true}
|
||||||
value={data.node.template[name].value ?? ""}
|
value={data.node.template[name].value ?? ""}
|
||||||
onChange={(t) => {
|
onChange={handleOnNewValue}
|
||||||
data.node.template[name].value = t;
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
) : left === true && type === "prompt" ? (
|
) : left === true && type === "prompt" ? (
|
||||||
<PromptAreaComponent
|
<PromptAreaComponent
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
value={data.node.template[name].value ?? ""}
|
value={data.node.template[name].value ?? ""}
|
||||||
onChange={(t: string) => {
|
onChange={handleOnNewValue}
|
||||||
data.node.template[name].value = t;
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<></>
|
<></>
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ import {
|
||||||
useContext,
|
useContext,
|
||||||
} from "react";
|
} from "react";
|
||||||
import { FlowType, NodeType } from "../types/flow";
|
import { FlowType, NodeType } from "../types/flow";
|
||||||
import { TabsContextType } from "../types/tabs";
|
import { TabsContextType, TabsState } from "../types/tabs";
|
||||||
import { updateIds, updateTemplate } from "../utils";
|
import { updateIds, updateTemplate } from "../utils";
|
||||||
import { alertContext } from "./alertContext";
|
import { alertContext } from "./alertContext";
|
||||||
import { typesContext } from "./typesContext";
|
import { typesContext } from "./typesContext";
|
||||||
|
|
@ -43,7 +43,8 @@ const TabsContextInitialValue: TabsContextType = {
|
||||||
setDisableCopyPaste: (state: boolean) => {},
|
setDisableCopyPaste: (state: boolean) => {},
|
||||||
lastCopiedSelection: null,
|
lastCopiedSelection: null,
|
||||||
setLastCopiedSelection: (selection: any) => {},
|
setLastCopiedSelection: (selection: any) => {},
|
||||||
|
tabsState: {},
|
||||||
|
setTabsState: (state: TabsState) => {},
|
||||||
getNodeId: (nodeType: string) => "",
|
getNodeId: (nodeType: string) => "",
|
||||||
paste: (
|
paste: (
|
||||||
selection: { nodes: any; edges: any },
|
selection: { nodes: any; edges: any },
|
||||||
|
|
@ -64,6 +65,7 @@ export function TabsProvider({ children }: { children: ReactNode }) {
|
||||||
const [id, setId] = useState(uid());
|
const [id, setId] = useState(uid());
|
||||||
const { templates, reactFlowInstance } = useContext(typesContext);
|
const { templates, reactFlowInstance } = useContext(typesContext);
|
||||||
const [lastCopiedSelection, setLastCopiedSelection] = useState(null);
|
const [lastCopiedSelection, setLastCopiedSelection] = useState(null);
|
||||||
|
const [tabsState, setTabsState] = useState<TabsState>({});
|
||||||
|
|
||||||
const newNodeId = useRef(uid());
|
const newNodeId = useRef(uid());
|
||||||
function incrementNodeId() {
|
function incrementNodeId() {
|
||||||
|
|
@ -534,6 +536,7 @@ export function TabsProvider({ children }: { children: ReactNode }) {
|
||||||
description: flowData.description,
|
description: flowData.description,
|
||||||
name: flow?.name ?? "New Flow",
|
name: flow?.name ?? "New Flow",
|
||||||
data: flowData.data,
|
data: flowData.data,
|
||||||
|
id: "",
|
||||||
});
|
});
|
||||||
|
|
||||||
const addFlowToLocalState = (newFlow) => {
|
const addFlowToLocalState = (newFlow) => {
|
||||||
|
|
@ -582,6 +585,8 @@ export function TabsProvider({ children }: { children: ReactNode }) {
|
||||||
uploadFlows,
|
uploadFlows,
|
||||||
uploadFlow,
|
uploadFlow,
|
||||||
getNodeId,
|
getNodeId,
|
||||||
|
tabsState,
|
||||||
|
setTabsState,
|
||||||
paste,
|
paste,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
import { ArrowDownTrayIcon } from "@heroicons/react/24/outline";
|
|
||||||
import { useContext, useRef, useState } from "react";
|
import { useContext, useRef, useState } from "react";
|
||||||
import { alertContext } from "../../contexts/alertContext";
|
import { alertContext } from "../../contexts/alertContext";
|
||||||
import { PopUpContext } from "../../contexts/popUpContext";
|
import { PopUpContext } from "../../contexts/popUpContext";
|
||||||
|
|
@ -14,16 +13,16 @@ import {
|
||||||
} from "../../components/ui/dialog";
|
} from "../../components/ui/dialog";
|
||||||
import { Button } from "../../components/ui/button";
|
import { Button } from "../../components/ui/button";
|
||||||
import { SETTINGS_DIALOG_SUBTITLE } from "../../constants";
|
import { SETTINGS_DIALOG_SUBTITLE } from "../../constants";
|
||||||
import { updateFlowInDatabase } from "../../controllers/API";
|
|
||||||
import EditFlowSettings from "../../components/EditFlowSettingsComponent";
|
import EditFlowSettings from "../../components/EditFlowSettingsComponent";
|
||||||
import { Settings2 } from "lucide-react";
|
import { Settings2 } from "lucide-react";
|
||||||
|
import { updateFlowInDatabase } from "../../controllers/API";
|
||||||
|
|
||||||
export default function FlowSettingsModal() {
|
export default function FlowSettingsModal() {
|
||||||
const [open, setOpen] = useState(true);
|
const [open, setOpen] = useState(true);
|
||||||
const { closePopUp } = useContext(PopUpContext);
|
const { closePopUp } = useContext(PopUpContext);
|
||||||
const { setErrorData, setSuccessData } = useContext(alertContext);
|
const { setErrorData, setSuccessData } = useContext(alertContext);
|
||||||
const ref = useRef();
|
const ref = useRef();
|
||||||
const { flows, tabId, updateFlow } = useContext(TabsContext);
|
const { flows, tabId, updateFlow, setTabsState } = useContext(TabsContext);
|
||||||
const maxLength = 50;
|
const maxLength = 50;
|
||||||
function setModalOpen(x: boolean) {
|
function setModalOpen(x: boolean) {
|
||||||
setOpen(x);
|
setOpen(x);
|
||||||
|
|
@ -34,22 +33,26 @@ export default function FlowSettingsModal() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleSaveFlow(flow) {
|
async function handleSaveFlow(flow) {
|
||||||
if (name !== "") {
|
|
||||||
let newFlow = flows.find((f) => f.id === tabId);
|
|
||||||
if (newFlow) {
|
|
||||||
newFlow.name = name;
|
|
||||||
newFlow.description = description;
|
|
||||||
updateFlow(newFlow);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
try {
|
try {
|
||||||
updateFlowInDatabase(flow);
|
const updatedFlow = await updateFlowInDatabase(flow);
|
||||||
|
if (updatedFlow) {
|
||||||
|
updateFlow(updatedFlow);
|
||||||
|
setTabsState((prev) => {
|
||||||
|
return {
|
||||||
|
...prev,
|
||||||
|
[tabId]: {
|
||||||
|
isPending: false,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
// updateFlowStyleInDataBase(flow);
|
// updateFlowStyleInDataBase(flow);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
setErrorData(err);
|
setErrorData(err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const [name, setName] = useState(flows.find((f) => f.id === tabId).name);
|
const [name, setName] = useState(flows.find((f) => f.id === tabId).name);
|
||||||
const [description, setDescription] = useState(
|
const [description, setDescription] = useState(
|
||||||
flows.find((f) => f.id === tabId).description
|
flows.find((f) => f.id === tabId).description
|
||||||
|
|
|
||||||
|
|
@ -13,24 +13,23 @@ import { MagnifyingGlassIcon } from "@heroicons/react/24/outline";
|
||||||
import ShadTooltip from "../../../../components/ShadTooltipComponent";
|
import ShadTooltip from "../../../../components/ShadTooltipComponent";
|
||||||
import { Code2, FileDown, FileUp, Save } from "lucide-react";
|
import { Code2, FileDown, FileUp, Save } from "lucide-react";
|
||||||
import { PopUpContext } from "../../../../contexts/popUpContext";
|
import { PopUpContext } from "../../../../contexts/popUpContext";
|
||||||
import ImportModal from "../../../../modals/importModal";
|
|
||||||
import ExportModal from "../../../../modals/exportModal";
|
import ExportModal from "../../../../modals/exportModal";
|
||||||
import ApiModal from "../../../../modals/ApiModal";
|
import ApiModal from "../../../../modals/ApiModal";
|
||||||
import { TabsContext } from "../../../../contexts/tabsContext";
|
import { TabsContext } from "../../../../contexts/tabsContext";
|
||||||
import { alertContext } from "../../../../contexts/alertContext";
|
import { alertContext } from "../../../../contexts/alertContext";
|
||||||
import { updateFlowInDatabase } from "../../../../controllers/API";
|
import { updateFlowInDatabase } from "../../../../controllers/API";
|
||||||
import { INPUT_STYLE } from "../../../../constants";
|
import { INPUT_STYLE } from "../../../../constants";
|
||||||
import { Input } from "../../../../components/ui/input";
|
|
||||||
import { Separator } from "../../../../components/ui/separator";
|
import { Separator } from "../../../../components/ui/separator";
|
||||||
|
|
||||||
export default function ExtraSidebar() {
|
export default function ExtraSidebar() {
|
||||||
const { data } = useContext(typesContext);
|
const { data } = useContext(typesContext);
|
||||||
const { openPopUp } = useContext(PopUpContext);
|
const { openPopUp } = useContext(PopUpContext);
|
||||||
const { flows, tabId, uploadFlow } = useContext(TabsContext);
|
const { flows, tabId, uploadFlow, updateFlow, tabsState, setTabsState } =
|
||||||
|
useContext(TabsContext);
|
||||||
const { setSuccessData, setErrorData } = useContext(alertContext);
|
const { setSuccessData, setErrorData } = useContext(alertContext);
|
||||||
const [dataFilter, setFilterData] = useState(data);
|
const [dataFilter, setFilterData] = useState(data);
|
||||||
const [search, setSearch] = useState("");
|
const [search, setSearch] = useState("");
|
||||||
|
const isPending = tabsState[tabId]?.isPending;
|
||||||
function onDragStart(
|
function onDragStart(
|
||||||
event: React.DragEvent<any>,
|
event: React.DragEvent<any>,
|
||||||
data: { type: string; node?: APIClassType }
|
data: { type: string; node?: APIClassType }
|
||||||
|
|
@ -62,9 +61,21 @@ export default function ExtraSidebar() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleSaveFlow(flow) {
|
async function handleSaveFlow(flow) {
|
||||||
try {
|
try {
|
||||||
updateFlowInDatabase(flow);
|
const updatedFlow = await updateFlowInDatabase(flow);
|
||||||
|
if (updatedFlow) {
|
||||||
|
updateFlow(updatedFlow);
|
||||||
|
setTabsState((prev) => {
|
||||||
|
console.log(prev);
|
||||||
|
return {
|
||||||
|
...prev,
|
||||||
|
[tabId]: {
|
||||||
|
isPending: false,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
// updateFlowStyleInDataBase(flow);
|
// updateFlowStyleInDataBase(flow);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
setErrorData(err);
|
setErrorData(err);
|
||||||
|
|
@ -118,8 +129,13 @@ export default function ExtraSidebar() {
|
||||||
handleSaveFlow(flows.find((f) => f.id === tabId));
|
handleSaveFlow(flows.find((f) => f.id === tabId));
|
||||||
setSuccessData({ title: "Changes saved successfully" });
|
setSuccessData({ title: "Changes saved successfully" });
|
||||||
}}
|
}}
|
||||||
|
disabled={!isPending}
|
||||||
>
|
>
|
||||||
<Save className="w-5 h-5 dark:text-gray-300"></Save>
|
<Save
|
||||||
|
className={
|
||||||
|
"w-5 h-5" + (isPending ? " text-muted-foreground" : " ")
|
||||||
|
}
|
||||||
|
></Save>
|
||||||
</button>
|
</button>
|
||||||
</ShadTooltip>
|
</ShadTooltip>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
import { Dispatch, SetStateAction } from "react";
|
||||||
import { FlowType } from "../flow";
|
import { FlowType } from "../flow";
|
||||||
|
|
||||||
export type TabsContextType = {
|
export type TabsContextType = {
|
||||||
|
|
@ -18,6 +19,8 @@ export type TabsContextType = {
|
||||||
disableCopyPaste: boolean;
|
disableCopyPaste: boolean;
|
||||||
setDisableCopyPaste: (value: boolean) => void;
|
setDisableCopyPaste: (value: boolean) => void;
|
||||||
getNodeId: (nodeType: string) => string;
|
getNodeId: (nodeType: string) => string;
|
||||||
|
tabsState: TabsState;
|
||||||
|
setTabsState: Dispatch<SetStateAction<TabsState>>;
|
||||||
paste: (
|
paste: (
|
||||||
selection: { nodes: any; edges: any },
|
selection: { nodes: any; edges: any },
|
||||||
position: { x: number; y: number; paneX?: number; paneY?: number }
|
position: { x: number; y: number; paneX?: number; paneY?: number }
|
||||||
|
|
@ -26,9 +29,8 @@ export type TabsContextType = {
|
||||||
setLastCopiedSelection: (selection: { nodes: any; edges: any }) => void;
|
setLastCopiedSelection: (selection: { nodes: any; edges: any }) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type LangFlowState = {
|
export type TabsState = {
|
||||||
tabIndex: number;
|
[key: string]: {
|
||||||
flows: FlowType[];
|
isPending: boolean;
|
||||||
id: string;
|
};
|
||||||
nodeId: number;
|
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue