Merge branch 'cz/bug/state/zustand' of personal:logspace-ai/langflow into cz/bug/state/zustand
This commit is contained in:
commit
2f91fc0b8f
21 changed files with 250 additions and 474 deletions
|
|
@ -16,17 +16,19 @@ import {
|
||||||
FETCH_ERROR_MESSAGE,
|
FETCH_ERROR_MESSAGE,
|
||||||
} from "./constants/constants";
|
} from "./constants/constants";
|
||||||
import { AuthContext } from "./contexts/authContext";
|
import { AuthContext } from "./contexts/authContext";
|
||||||
import { locationContext } from "./contexts/locationContext";
|
|
||||||
import { getHealth, getRepoStars, getVersion } from "./controllers/API";
|
import { getHealth, getRepoStars, getVersion } from "./controllers/API";
|
||||||
import Router from "./routes";
|
import Router from "./routes";
|
||||||
import useAlertStore from "./stores/alertStore";
|
import useAlertStore from "./stores/alertStore";
|
||||||
import { useTypesStore } from "./stores/typesStore";
|
import { useTypesStore } from "./stores/typesStore";
|
||||||
import { useDarkStore } from "./stores/darkStore";
|
import { useDarkStore } from "./stores/darkStore";
|
||||||
import useFlowsManagerStore from "./stores/flowsManagerStore";
|
import useFlowsManagerStore from "./stores/flowsManagerStore";
|
||||||
|
import { useLocationStore } from "./stores/locationStore";
|
||||||
|
|
||||||
export default function App() {
|
export default function App() {
|
||||||
let { setCurrent, setShowSideBar, setIsStackedOpen } =
|
const setCurrent = useLocationStore((state) => state.setCurrent);
|
||||||
useContext(locationContext);
|
const setShowSideBar = useLocationStore((state) => state.setShowSideBar);
|
||||||
|
const setIsStackedOpen = useLocationStore((state) => state.setIsStackedOpen);
|
||||||
|
|
||||||
let location = useLocation();
|
let location = useLocation();
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setCurrent(location.pathname.replace(/\/$/g, "").split("/"));
|
setCurrent(location.pathname.replace(/\/$/g, "").split("/"));
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,6 @@ import IconComponent from "../../components/genericIconComponent";
|
||||||
import InputComponent from "../../components/inputComponent";
|
import InputComponent from "../../components/inputComponent";
|
||||||
import { Textarea } from "../../components/ui/textarea";
|
import { Textarea } from "../../components/ui/textarea";
|
||||||
import { priorityFields } from "../../constants/constants";
|
import { priorityFields } from "../../constants/constants";
|
||||||
import { useSSE } from "../../contexts/SSEContext";
|
|
||||||
import NodeToolbarComponent from "../../pages/FlowPage/components/nodeToolbarComponent";
|
import NodeToolbarComponent from "../../pages/FlowPage/components/nodeToolbarComponent";
|
||||||
import useFlowStore from "../../stores/flowStore";
|
import useFlowStore from "../../stores/flowStore";
|
||||||
import { validationStatusType } from "../../types/components";
|
import { validationStatusType } from "../../types/components";
|
||||||
|
|
@ -80,7 +79,8 @@ export default function GenericNode({
|
||||||
}, [data, data.node]);
|
}, [data, data.node]);
|
||||||
|
|
||||||
// State for outline color
|
// State for outline color
|
||||||
const { sseData, isBuilding } = useSSE();
|
const sseData = useFlowStore((state) => state.sseData);
|
||||||
|
const isBuilding = useFlowStore((state) => state.isBuilding);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setNodeDescription(data.node!.description);
|
setNodeDescription(data.node!.description);
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,16 @@
|
||||||
import { Transition } from "@headlessui/react";
|
import { Transition } from "@headlessui/react";
|
||||||
import { useContext, useState } from "react";
|
import { useState } from "react";
|
||||||
import Loading from "../../../components/ui/loading";
|
import Loading from "../../../components/ui/loading";
|
||||||
import { useSSE } from "../../../contexts/SSEContext";
|
|
||||||
import { postBuildInit } from "../../../controllers/API";
|
import { postBuildInit } from "../../../controllers/API";
|
||||||
import { FlowType } from "../../../types/flow";
|
import { FlowType } from "../../../types/flow";
|
||||||
|
|
||||||
import useAlertStore from "../../../stores/alertStore";
|
import useAlertStore from "../../../stores/alertStore";
|
||||||
import useFlowStore from "../../../stores/flowStore";
|
import useFlowStore from "../../../stores/flowStore";
|
||||||
import useFlowsManagerStore from "../../../stores/flowsManagerStore";
|
|
||||||
import { parsedDataType } from "../../../types/components";
|
import { parsedDataType } from "../../../types/components";
|
||||||
import { FlowState } from "../../../types/tabs";
|
|
||||||
import { validateNodes } from "../../../utils/reactflowUtils";
|
import { validateNodes } from "../../../utils/reactflowUtils";
|
||||||
import RadialProgressComponent from "../../RadialProgress";
|
import RadialProgressComponent from "../../RadialProgress";
|
||||||
import IconComponent from "../../genericIconComponent";
|
import IconComponent from "../../genericIconComponent";
|
||||||
|
import { stat } from "fs";
|
||||||
|
|
||||||
export default function BuildTrigger({
|
export default function BuildTrigger({
|
||||||
open,
|
open,
|
||||||
|
|
@ -24,17 +22,17 @@ export default function BuildTrigger({
|
||||||
setIsBuilt: any;
|
setIsBuilt: any;
|
||||||
isBuilt: boolean;
|
isBuilt: boolean;
|
||||||
}): JSX.Element {
|
}): JSX.Element {
|
||||||
const { updateSSEData, isBuilding, setIsBuilding, sseData } = useSSE();
|
const updateSSEData = useFlowStore((state) => state.updateSSEData);
|
||||||
|
const isBuilding = useFlowStore((state) => state.isBuilding);
|
||||||
|
const setIsBuilding = useFlowStore((state) => state.setIsBuilding);
|
||||||
const nodes = useFlowStore((state) => state.nodes);
|
const nodes = useFlowStore((state) => state.nodes);
|
||||||
const edges = useFlowStore((state) => state.edges);
|
const edges = useFlowStore((state) => state.edges);
|
||||||
const setErrorData = useAlertStore((state) => state.setErrorData);
|
const setErrorData = useAlertStore((state) => state.setErrorData);
|
||||||
const setSuccessData = useAlertStore((state) => state.setSuccessData);
|
const setSuccessData = useAlertStore((state) => state.setSuccessData);
|
||||||
const setCurrentFlowState = useFlowsManagerStore(
|
const setFlowState = useFlowStore(
|
||||||
(state) => state.setCurrentFlowState
|
(state) => state.setFlowState
|
||||||
);
|
);
|
||||||
const saveFlow = useFlowsManagerStore((state) => state.saveFlow);
|
|
||||||
|
|
||||||
const [isIconTouched, setIsIconTouched] = useState(false);
|
|
||||||
const eventClick = isBuilding ? "pointer-events-none" : "";
|
const eventClick = isBuilding ? "pointer-events-none" : "";
|
||||||
const [progress, setProgress] = useState(0);
|
const [progress, setProgress] = useState(0);
|
||||||
|
|
||||||
|
|
@ -79,7 +77,6 @@ export default function BuildTrigger({
|
||||||
}
|
}
|
||||||
async function streamNodeData(flow: FlowType) {
|
async function streamNodeData(flow: FlowType) {
|
||||||
// Step 1: Make a POST request to send the flow data and receive a unique session ID
|
// Step 1: Make a POST request to send the flow data and receive a unique session ID
|
||||||
const id = saveFlow(flow, true);
|
|
||||||
const response = await postBuildInit(flow);
|
const response = await postBuildInit(flow);
|
||||||
const { flowId } = response.data;
|
const { flowId } = response.data;
|
||||||
// Step 2: Use the session ID to establish an SSE connection using EventSource
|
// Step 2: Use the session ID to establish an SSE connection using EventSource
|
||||||
|
|
@ -102,7 +99,7 @@ export default function BuildTrigger({
|
||||||
// If the event is a log, log it
|
// If the event is a log, log it
|
||||||
setSuccessData({ title: parsedData.log });
|
setSuccessData({ title: parsedData.log });
|
||||||
} else if (parsedData.input_keys !== undefined) {
|
} else if (parsedData.input_keys !== undefined) {
|
||||||
setCurrentFlowState(parsedData);
|
setFlowState(parsedData);
|
||||||
} else {
|
} else {
|
||||||
// Otherwise, process the data
|
// Otherwise, process the data
|
||||||
const isValid = processStreamResult(parsedData);
|
const isValid = processStreamResult(parsedData);
|
||||||
|
|
@ -148,14 +145,6 @@ export default function BuildTrigger({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleMouseEnter = () => {
|
|
||||||
setIsIconTouched(true);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleMouseLeave = () => {
|
|
||||||
setIsIconTouched(false);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Transition
|
<Transition
|
||||||
show={!open}
|
show={!open}
|
||||||
|
|
@ -173,8 +162,6 @@ export default function BuildTrigger({
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
handleBuild(flow);
|
handleBuild(flow);
|
||||||
}}
|
}}
|
||||||
onMouseEnter={handleMouseEnter}
|
|
||||||
onMouseLeave={handleMouseLeave}
|
|
||||||
>
|
>
|
||||||
<button>
|
<button>
|
||||||
<div className="round-button-div">
|
<div className="round-button-div">
|
||||||
|
|
|
||||||
|
|
@ -13,11 +13,9 @@ import useFlowsManagerStore from "../../stores/flowsManagerStore";
|
||||||
|
|
||||||
export default function Chat({ flow }: ChatType): JSX.Element {
|
export default function Chat({ flow }: ChatType): JSX.Element {
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
const [canOpen, setCanOpen] = useState(false);
|
|
||||||
const isBuilt = useFlowStore((state) => state.isBuilt);
|
const isBuilt = useFlowStore((state) => state.isBuilt);
|
||||||
const setIsBuilt = useFlowStore((state) => state.setIsBuilt);
|
const setIsBuilt = useFlowStore((state) => state.setIsBuilt);
|
||||||
const currentFlowState = useFlowsManagerStore((state) => state.currentFlowState);
|
const flowState = useFlowStore((state) => state.flowState);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const handleKeyDown = (event: KeyboardEvent) => {
|
const handleKeyDown = (event: KeyboardEvent) => {
|
||||||
if (
|
if (
|
||||||
|
|
@ -58,18 +56,8 @@ export default function Chat({ flow }: ChatType): JSX.Element {
|
||||||
) {
|
) {
|
||||||
setIsBuilt(false);
|
setIsBuilt(false);
|
||||||
}
|
}
|
||||||
if (
|
|
||||||
currentFlowState &&
|
|
||||||
currentFlowState.formKeysData &&
|
|
||||||
currentFlowState.formKeysData.input_keys !== null
|
|
||||||
) {
|
|
||||||
setCanOpen(true);
|
|
||||||
} else {
|
|
||||||
setCanOpen(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
prevNodesRef.current = currentNodes;
|
prevNodesRef.current = currentNodes;
|
||||||
}, [currentFlowState, flow.id]);
|
}, [flowState, flow.id]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|
@ -81,9 +69,8 @@ export default function Chat({ flow }: ChatType): JSX.Element {
|
||||||
isBuilt={isBuilt}
|
isBuilt={isBuilt}
|
||||||
/>
|
/>
|
||||||
{isBuilt &&
|
{isBuilt &&
|
||||||
currentFlowState &&
|
flowState &&
|
||||||
currentFlowState.formKeysData &&
|
!!flowState?.input_keys && (
|
||||||
canOpen && (
|
|
||||||
<FormModal
|
<FormModal
|
||||||
key={flow.id}
|
key={flow.id}
|
||||||
flow={flow}
|
flow={flow}
|
||||||
|
|
@ -92,7 +79,7 @@ export default function Chat({ flow }: ChatType): JSX.Element {
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<ChatTrigger
|
<ChatTrigger
|
||||||
canOpen={canOpen}
|
canOpen={!!flowState?.input_keys}
|
||||||
open={open}
|
open={open}
|
||||||
setOpen={setOpen}
|
setOpen={setOpen}
|
||||||
isBuilt={isBuilt}
|
isBuilt={isBuilt}
|
||||||
|
|
|
||||||
|
|
@ -24,16 +24,16 @@ const AccordionTrigger = React.forwardRef<
|
||||||
React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Trigger>
|
React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Trigger>
|
||||||
>(({ className, children, ...props }, ref) => (
|
>(({ className, children, ...props }, ref) => (
|
||||||
<AccordionPrimitive.Header className="flex">
|
<AccordionPrimitive.Header className="flex">
|
||||||
<AccordionPrimitive.Trigger
|
<AccordionPrimitive.Trigger asChild ref={ref} {...props}>
|
||||||
ref={ref}
|
<div
|
||||||
className={cn(
|
className={cn(
|
||||||
"flex flex-1 items-center justify-between py-4 text-sm font-medium transition-all [&[data-state=open]>svg]:rotate-180",
|
"cursor-pointer flex flex-1 items-center justify-between py-4 text-sm font-medium transition-all [&[data-state=open]>svg]:rotate-180",
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
{...props}
|
>
|
||||||
>
|
{children}
|
||||||
{children}
|
<ChevronDownIcon className="h-4 w-4 text-muted-foreground transition-transform duration-200" />
|
||||||
<ChevronDownIcon className="h-4 w-4 text-muted-foreground transition-transform duration-200" />
|
</div>
|
||||||
</AccordionPrimitive.Trigger>
|
</AccordionPrimitive.Trigger>
|
||||||
</AccordionPrimitive.Header>
|
</AccordionPrimitive.Header>
|
||||||
));
|
));
|
||||||
|
|
|
||||||
|
|
@ -1,34 +0,0 @@
|
||||||
import { createContext, useCallback, useContext, useState } from "react";
|
|
||||||
|
|
||||||
const initialValue = {
|
|
||||||
updateSSEData: ({}) => {},
|
|
||||||
sseData: {},
|
|
||||||
isBuilding: false,
|
|
||||||
setIsBuilding: (isBuilding: boolean) => {},
|
|
||||||
};
|
|
||||||
|
|
||||||
const SSEContext = createContext(initialValue);
|
|
||||||
|
|
||||||
export function useSSE() {
|
|
||||||
return useContext(SSEContext);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function SSEProvider({ children }) {
|
|
||||||
const [sseData, setSSEData] = useState({});
|
|
||||||
const [isBuilding, setIsBuilding] = useState(false);
|
|
||||||
|
|
||||||
const updateSSEData = useCallback((newData: any) => {
|
|
||||||
setSSEData((prevData) => ({
|
|
||||||
...prevData,
|
|
||||||
...newData,
|
|
||||||
}));
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<SSEContext.Provider
|
|
||||||
value={{ sseData, updateSSEData, isBuilding, setIsBuilding }}
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
</SSEContext.Provider>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
@ -3,9 +3,7 @@ import { BrowserRouter } from "react-router-dom";
|
||||||
import { ReactFlowProvider } from "reactflow";
|
import { ReactFlowProvider } from "reactflow";
|
||||||
import { TooltipProvider } from "../components/ui/tooltip";
|
import { TooltipProvider } from "../components/ui/tooltip";
|
||||||
import { ApiInterceptor } from "../controllers/API/api";
|
import { ApiInterceptor } from "../controllers/API/api";
|
||||||
import { SSEProvider } from "./SSEContext";
|
|
||||||
import { AuthProvider } from "./authContext";
|
import { AuthProvider } from "./authContext";
|
||||||
import { LocationProvider } from "./locationContext";
|
|
||||||
|
|
||||||
export default function ContextWrapper({ children }: { children: ReactNode }) {
|
export default function ContextWrapper({ children }: { children: ReactNode }) {
|
||||||
//element to wrap all context
|
//element to wrap all context
|
||||||
|
|
@ -15,12 +13,8 @@ export default function ContextWrapper({ children }: { children: ReactNode }) {
|
||||||
<AuthProvider>
|
<AuthProvider>
|
||||||
<TooltipProvider>
|
<TooltipProvider>
|
||||||
<ReactFlowProvider>
|
<ReactFlowProvider>
|
||||||
<LocationProvider>
|
|
||||||
<ApiInterceptor />
|
<ApiInterceptor />
|
||||||
<SSEProvider>
|
|
||||||
{children}
|
{children}
|
||||||
</SSEProvider>
|
|
||||||
</LocationProvider>
|
|
||||||
</ReactFlowProvider>
|
</ReactFlowProvider>
|
||||||
</TooltipProvider>
|
</TooltipProvider>
|
||||||
</AuthProvider>
|
</AuthProvider>
|
||||||
|
|
|
||||||
|
|
@ -1,50 +0,0 @@
|
||||||
import { createContext, ReactNode, useState } from "react";
|
|
||||||
import { locationContextType } from "../types/typesContext";
|
|
||||||
|
|
||||||
//initial value for location context
|
|
||||||
const initialValue = {
|
|
||||||
//actual
|
|
||||||
current: window.location.pathname.replace(/\/$/g, "").split("/"),
|
|
||||||
isStackedOpen:
|
|
||||||
window.innerWidth > 1024 && window.location.pathname.split("/")[1]
|
|
||||||
? true
|
|
||||||
: false,
|
|
||||||
setCurrent: () => {},
|
|
||||||
setIsStackedOpen: () => {},
|
|
||||||
showSideBar: window.location.pathname.split("/")[1] ? true : false,
|
|
||||||
setShowSideBar: () => {},
|
|
||||||
extraNavigation: { title: "" },
|
|
||||||
setExtraNavigation: () => {},
|
|
||||||
extraComponent: <></>,
|
|
||||||
setExtraComponent: () => {},
|
|
||||||
};
|
|
||||||
|
|
||||||
export const locationContext = createContext<locationContextType>(initialValue);
|
|
||||||
|
|
||||||
export function LocationProvider({ children }: { children: ReactNode }) {
|
|
||||||
const [current, setCurrent] = useState(initialValue.current);
|
|
||||||
const [isStackedOpen, setIsStackedOpen] = useState(
|
|
||||||
initialValue.isStackedOpen
|
|
||||||
);
|
|
||||||
const [showSideBar, setShowSideBar] = useState(initialValue.showSideBar);
|
|
||||||
const [extraNavigation, setExtraNavigation] = useState({ title: "" });
|
|
||||||
const [extraComponent, setExtraComponent] = useState(<></>);
|
|
||||||
return (
|
|
||||||
<locationContext.Provider
|
|
||||||
value={{
|
|
||||||
isStackedOpen,
|
|
||||||
setIsStackedOpen,
|
|
||||||
current,
|
|
||||||
setCurrent,
|
|
||||||
showSideBar,
|
|
||||||
setShowSideBar,
|
|
||||||
extraNavigation,
|
|
||||||
setExtraNavigation,
|
|
||||||
extraComponent,
|
|
||||||
setExtraComponent,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
</locationContext.Provider>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
@ -1,105 +0,0 @@
|
||||||
import _ from "lodash";
|
|
||||||
import {
|
|
||||||
createContext,
|
|
||||||
ReactNode,
|
|
||||||
useContext,
|
|
||||||
useEffect,
|
|
||||||
useState,
|
|
||||||
} from "react";
|
|
||||||
import { getAll, getHealth } from "../controllers/API";
|
|
||||||
import useAlertStore from "../stores/alertStore";
|
|
||||||
import { APIKindType } from "../types/api";
|
|
||||||
import { typesContextType } from "../types/typesContext";
|
|
||||||
import { AuthContext } from "./authContext";
|
|
||||||
|
|
||||||
//context to share types adn functions from nodes to flow
|
|
||||||
|
|
||||||
const initialValue: typesContextType = {
|
|
||||||
types: {},
|
|
||||||
setTypes: () => {},
|
|
||||||
templates: {},
|
|
||||||
setTemplates: () => {},
|
|
||||||
data: {},
|
|
||||||
setData: () => {},
|
|
||||||
getTypes: () => {},
|
|
||||||
setFetchError: () => {},
|
|
||||||
fetchError: false,
|
|
||||||
setFilterEdge: (filter) => {},
|
|
||||||
getFilterEdge: [],
|
|
||||||
};
|
|
||||||
|
|
||||||
export const typesContext = createContext<typesContextType>(initialValue);
|
|
||||||
|
|
||||||
export function TypesProvider({ children }: { children: ReactNode }) {
|
|
||||||
const [types, setTypes] = useState({});
|
|
||||||
const [templates, setTemplates] = useState({});
|
|
||||||
const [data, setData] = useState({});
|
|
||||||
const [fetchError, setFetchError] = useState(false);
|
|
||||||
const setLoading = useAlertStore((state) => state.setLoading);
|
|
||||||
const [getFilterEdge, setFilterEdge] = useState([]);
|
|
||||||
|
|
||||||
async function getTypes(): Promise<void> {
|
|
||||||
// We will keep a flag to handle the case where the component is unmounted before the API call resolves.
|
|
||||||
let isMounted = true;
|
|
||||||
try {
|
|
||||||
const result = await getAll();
|
|
||||||
// Make sure to only update the state if the component is still mounted.
|
|
||||||
if (isMounted && result?.status === 200) {
|
|
||||||
setLoading(false);
|
|
||||||
let { data } = _.cloneDeep(result);
|
|
||||||
setData((old) => ({ ...old, ...data }));
|
|
||||||
setTemplates(
|
|
||||||
Object.keys(data).reduce((acc, curr) => {
|
|
||||||
Object.keys(data[curr]).forEach((c: keyof APIKindType) => {
|
|
||||||
//prevent wrong overwriting of the component template by a group of the same type
|
|
||||||
if (!data[curr][c].flow) acc[c] = data[curr][c];
|
|
||||||
});
|
|
||||||
return acc;
|
|
||||||
}, {})
|
|
||||||
);
|
|
||||||
// Set the types by reducing over the keys of the result data and updating the accumulator.
|
|
||||||
setTypes(
|
|
||||||
// Reverse the keys so the tool world does not overlap
|
|
||||||
Object.keys(data)
|
|
||||||
.reverse()
|
|
||||||
.reduce((acc, curr) => {
|
|
||||||
Object.keys(data[curr]).forEach((c: keyof APIKindType) => {
|
|
||||||
acc[c] = curr;
|
|
||||||
// Add the base classes to the accumulator as well.
|
|
||||||
data[curr][c].base_classes?.forEach((b) => {
|
|
||||||
acc[b] = curr;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
return acc;
|
|
||||||
}, {})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error("An error has occurred while fetching types.");
|
|
||||||
console.log(error);
|
|
||||||
await getHealth().catch((e) => {
|
|
||||||
setFetchError(true);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<typesContext.Provider
|
|
||||||
value={{
|
|
||||||
types,
|
|
||||||
setTypes,
|
|
||||||
setTemplates,
|
|
||||||
templates,
|
|
||||||
data,
|
|
||||||
setData,
|
|
||||||
getTypes,
|
|
||||||
fetchError,
|
|
||||||
setFetchError,
|
|
||||||
setFilterEdge,
|
|
||||||
getFilterEdge,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
</typesContext.Provider>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
@ -31,6 +31,7 @@ import {
|
||||||
tabsArray,
|
tabsArray,
|
||||||
} from "../../utils/utils";
|
} from "../../utils/utils";
|
||||||
import BaseModal from "../baseModal";
|
import BaseModal from "../baseModal";
|
||||||
|
import useFlowStore from "../../stores/flowStore";
|
||||||
|
|
||||||
const ApiModal = forwardRef(
|
const ApiModal = forwardRef(
|
||||||
(
|
(
|
||||||
|
|
@ -49,18 +50,18 @@ const ApiModal = forwardRef(
|
||||||
const tweak = useRef<tweakType>([]);
|
const tweak = useRef<tweakType>([]);
|
||||||
const tweaksList = useRef<string[]>([]);
|
const tweaksList = useRef<string[]>([]);
|
||||||
const [getTweak, setTweak] = useState<tweakType>([]);
|
const [getTweak, setTweak] = useState<tweakType>([]);
|
||||||
const currentFlowState = useFlowsManagerStore(
|
const flowState = useFlowStore(
|
||||||
(state) => state.currentFlowState
|
(state) => state.flowState
|
||||||
);
|
);
|
||||||
const pythonApiCode = getPythonApiCode(
|
const pythonApiCode = getPythonApiCode(
|
||||||
flow,
|
flow,
|
||||||
autoLogin,
|
autoLogin,
|
||||||
tweak.current,
|
tweak.current,
|
||||||
currentFlowState
|
flowState
|
||||||
);
|
);
|
||||||
const curl_code = getCurlCode(flow, autoLogin, tweak.current, currentFlowState);
|
const curl_code = getCurlCode(flow, autoLogin, tweak.current, flowState);
|
||||||
const pythonCode = getPythonCode(flow, tweak.current, currentFlowState);
|
const pythonCode = getPythonCode(flow, tweak.current, flowState);
|
||||||
const widgetCode = getWidgetCode(flow, autoLogin, currentFlowState);
|
const widgetCode = getWidgetCode(flow, autoLogin, flowState);
|
||||||
const tweaksCode = buildTweaks(flow);
|
const tweaksCode = buildTweaks(flow);
|
||||||
const codesArray = [
|
const codesArray = [
|
||||||
curl_code,
|
curl_code,
|
||||||
|
|
@ -171,11 +172,11 @@ const ApiModal = forwardRef(
|
||||||
flow,
|
flow,
|
||||||
autoLogin,
|
autoLogin,
|
||||||
tweak.current,
|
tweak.current,
|
||||||
currentFlowState
|
flowState
|
||||||
);
|
);
|
||||||
const curl_code = getCurlCode(flow, autoLogin, tweak.current, currentFlowState);
|
const curl_code = getCurlCode(flow, autoLogin, tweak.current, flowState);
|
||||||
const pythonCode = getPythonCode(flow, tweak.current, currentFlowState);
|
const pythonCode = getPythonCode(flow, tweak.current, flowState);
|
||||||
const widgetCode = getWidgetCode(flow, autoLogin, currentFlowState);
|
const widgetCode = getWidgetCode(flow, autoLogin, flowState);
|
||||||
|
|
||||||
tabs![0].code = curl_code;
|
tabs![0].code = curl_code;
|
||||||
tabs![1].code = pythonApiCode;
|
tabs![1].code = pythonApiCode;
|
||||||
|
|
|
||||||
|
|
@ -40,20 +40,19 @@ export default function FormModal({
|
||||||
}): JSX.Element {
|
}): JSX.Element {
|
||||||
const nodes = useFlowStore((state) => state.nodes);
|
const nodes = useFlowStore((state) => state.nodes);
|
||||||
const edges = useFlowStore((state) => state.edges);
|
const edges = useFlowStore((state) => state.edges);
|
||||||
const currentFlowState = useFlowsManagerStore(
|
const flowState = useFlowStore(
|
||||||
(state) => state.currentFlowState
|
(state) => state.flowState
|
||||||
);
|
);
|
||||||
const setCurrentFlowState = useFlowsManagerStore(
|
const setFlowState = useFlowStore(
|
||||||
(state) => state.setCurrentFlowState
|
(state) => state.setFlowState
|
||||||
);
|
);
|
||||||
const [chatValue, setChatValue] = useState(() => {
|
const [chatValue, setChatValue] = useState(() => {
|
||||||
try {
|
try {
|
||||||
const formKeysData = currentFlowState?.formKeysData;
|
if (!flowState) {
|
||||||
if (!formKeysData) {
|
throw new Error("flowState is undefined");
|
||||||
throw new Error("formKeysData is undefined");
|
|
||||||
}
|
}
|
||||||
const inputKeys = formKeysData.input_keys;
|
const inputKeys = flowState.input_keys;
|
||||||
const handleKeys = formKeysData.handle_keys;
|
const handleKeys = flowState.handle_keys;
|
||||||
|
|
||||||
const keyToUse = Object.keys(inputKeys!).find(
|
const keyToUse = Object.keys(inputKeys!).find(
|
||||||
(key) => !handleKeys?.some((j) => j === key) && inputKeys![key] === ""
|
(key) => !handleKeys?.some((j) => j === key) && inputKeys![key] === ""
|
||||||
|
|
@ -68,7 +67,7 @@ export default function FormModal({
|
||||||
});
|
});
|
||||||
|
|
||||||
const [chatHistory, setChatHistory] = useState<ChatMessageType[]>([]);
|
const [chatHistory, setChatHistory] = useState<ChatMessageType[]>([]);
|
||||||
const template = useRef(currentFlowState?.formKeysData.template ?? undefined);
|
const template = useRef(flowState?.template ?? undefined);
|
||||||
const { accessToken } = useContext(AuthContext);
|
const { accessToken } = useContext(AuthContext);
|
||||||
const setErrorData = useAlertStore((state) => state.setErrorData);
|
const setErrorData = useAlertStore((state) => state.setErrorData);
|
||||||
const ws = useRef<WebSocket | null>(null);
|
const ws = useRef<WebSocket | null>(null);
|
||||||
|
|
@ -77,11 +76,11 @@ export default function FormModal({
|
||||||
const messagesRef = useRef<HTMLDivElement | null>(null);
|
const messagesRef = useRef<HTMLDivElement | null>(null);
|
||||||
|
|
||||||
const [chatKey, setChatKey] = useState(() => {
|
const [chatKey, setChatKey] = useState(() => {
|
||||||
if (currentFlowState?.formKeysData?.input_keys) {
|
if (flowState?.input_keys) {
|
||||||
return Object.keys(currentFlowState.formKeysData.input_keys!).find(
|
return Object.keys(flowState.input_keys!).find(
|
||||||
(key) =>
|
(key) =>
|
||||||
!currentFlowState.formKeysData.handle_keys!.some((j) => j === key) &&
|
!flowState.handle_keys!.some((j) => j === key) &&
|
||||||
currentFlowState.formKeysData.input_keys![key] === ""
|
flowState.input_keys![key] === ""
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
// TODO: return a sensible default
|
// TODO: return a sensible default
|
||||||
|
|
@ -387,7 +386,7 @@ export default function FormModal({
|
||||||
let nodeValidationErrors = validateNodes(nodes, edges);
|
let nodeValidationErrors = validateNodes(nodes, edges);
|
||||||
if (nodeValidationErrors.length === 0) {
|
if (nodeValidationErrors.length === 0) {
|
||||||
setLockChat(true);
|
setLockChat(true);
|
||||||
let inputs = currentFlowState?.formKeysData.input_keys;
|
let inputs = flowState?.input_keys;
|
||||||
setChatValue("");
|
setChatValue("");
|
||||||
const message = inputs;
|
const message = inputs;
|
||||||
addChatHistory(message!, true, chatKey!, template.current);
|
addChatHistory(message!, true, chatKey!, template.current);
|
||||||
|
|
@ -399,10 +398,10 @@ export default function FormModal({
|
||||||
description: flow.description,
|
description: flow.description,
|
||||||
chatKey: chatKey!,
|
chatKey: chatKey!,
|
||||||
});
|
});
|
||||||
if (currentFlowState && chatKey) {
|
if (flowState && chatKey) {
|
||||||
setCurrentFlowState((old: FlowState | undefined) => {
|
setFlowState((old: FlowState | undefined) => {
|
||||||
let newFlowState = cloneDeep(old!);
|
let newFlowState = cloneDeep(old!);
|
||||||
newFlowState.formKeysData.input_keys![chatKey] = "";
|
newFlowState.input_keys![chatKey] = "";
|
||||||
return newFlowState;
|
return newFlowState;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -415,7 +414,7 @@ export default function FormModal({
|
||||||
}
|
}
|
||||||
function clearChat(): void {
|
function clearChat(): void {
|
||||||
setChatHistory([]);
|
setChatHistory([]);
|
||||||
template.current = currentFlowState?.formKeysData.template;
|
template.current = flowState?.template;
|
||||||
ws.current?.send(JSON.stringify({ clear_history: true }));
|
ws.current?.send(JSON.stringify({ clear_history: true }));
|
||||||
if (lockChat) setLockChat(false);
|
if (lockChat) setLockChat(false);
|
||||||
}
|
}
|
||||||
|
|
@ -423,7 +422,7 @@ export default function FormModal({
|
||||||
function handleOnCheckedChange(checked: boolean, i: string) {
|
function handleOnCheckedChange(checked: boolean, i: string) {
|
||||||
if (checked === true) {
|
if (checked === true) {
|
||||||
setChatKey(i);
|
setChatKey(i);
|
||||||
setChatValue(currentFlowState?.formKeysData.input_keys![i] ?? "");
|
setChatValue(flowState?.input_keys![i] ?? "");
|
||||||
} else {
|
} else {
|
||||||
setChatKey(null!);
|
setChatKey(null!);
|
||||||
setChatValue("");
|
setChatValue("");
|
||||||
|
|
@ -432,7 +431,7 @@ export default function FormModal({
|
||||||
return (
|
return (
|
||||||
<Dialog open={open} onOpenChange={setOpen}>
|
<Dialog open={open} onOpenChange={setOpen}>
|
||||||
<DialogTrigger hidden></DialogTrigger>
|
<DialogTrigger hidden></DialogTrigger>
|
||||||
{currentFlowState && currentFlowState.formKeysData && (
|
{flowState && flowState && (
|
||||||
<DialogContent className="min-w-[80vw]">
|
<DialogContent className="min-w-[80vw]">
|
||||||
<DialogHeader>
|
<DialogHeader>
|
||||||
<DialogTitle className="flex items-center">
|
<DialogTitle className="flex items-center">
|
||||||
|
|
@ -468,8 +467,8 @@ export default function FormModal({
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{currentFlowState?.formKeysData?.input_keys
|
{flowState?.input_keys
|
||||||
? Object.keys(currentFlowState?.formKeysData.input_keys!).map(
|
? Object.keys(flowState?.input_keys!).map(
|
||||||
(key, index) => (
|
(key, index) => (
|
||||||
<div className="file-component-accordion-div" key={index}>
|
<div className="file-component-accordion-div" key={index}>
|
||||||
<AccordionComponent
|
<AccordionComponent
|
||||||
|
|
@ -491,7 +490,7 @@ export default function FormModal({
|
||||||
handleOnCheckedChange(value, key)
|
handleOnCheckedChange(value, key)
|
||||||
}
|
}
|
||||||
size="small"
|
size="small"
|
||||||
disabled={currentFlowState.formKeysData.handle_keys!.some(
|
disabled={flowState.handle_keys!.some(
|
||||||
(t) => t === key
|
(t) => t === key
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
|
@ -502,7 +501,7 @@ export default function FormModal({
|
||||||
keyValue={key}
|
keyValue={key}
|
||||||
>
|
>
|
||||||
<div className="file-component-tab-column">
|
<div className="file-component-tab-column">
|
||||||
{currentFlowState?.formKeysData.handle_keys!.some(
|
{flowState?.handle_keys!.some(
|
||||||
(t) => t === key
|
(t) => t === key
|
||||||
) && (
|
) && (
|
||||||
<div className="font-normal text-muted-foreground ">
|
<div className="font-normal text-muted-foreground ">
|
||||||
|
|
@ -512,14 +511,14 @@ export default function FormModal({
|
||||||
<Textarea
|
<Textarea
|
||||||
className="custom-scroll"
|
className="custom-scroll"
|
||||||
value={
|
value={
|
||||||
currentFlowState?.formKeysData.input_keys![key]
|
flowState?.input_keys![key]
|
||||||
}
|
}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
if (currentFlowState) {
|
if (flowState) {
|
||||||
setCurrentFlowState(
|
setFlowState(
|
||||||
(old: FlowState | undefined) => {
|
(old: FlowState | undefined) => {
|
||||||
let newFlowState = cloneDeep(old!);
|
let newFlowState = cloneDeep(old!);
|
||||||
newFlowState.formKeysData.input_keys![
|
newFlowState.input_keys![
|
||||||
key
|
key
|
||||||
] = e.target.value;
|
] = e.target.value;
|
||||||
return newFlowState;
|
return newFlowState;
|
||||||
|
|
@ -536,7 +535,7 @@ export default function FormModal({
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
: null}
|
: null}
|
||||||
{currentFlowState?.formKeysData.memory_keys!.map((key, index) => (
|
{flowState?.memory_keys!.map((key, index) => (
|
||||||
<div className="file-component-accordion-div" key={index}>
|
<div className="file-component-accordion-div" key={index}>
|
||||||
<AccordionComponent
|
<AccordionComponent
|
||||||
trigger={
|
trigger={
|
||||||
|
|
@ -628,11 +627,11 @@ export default function FormModal({
|
||||||
sendMessage={sendMessage}
|
sendMessage={sendMessage}
|
||||||
setChatValue={(value) => {
|
setChatValue={(value) => {
|
||||||
setChatValue(value);
|
setChatValue(value);
|
||||||
if (currentFlowState && chatKey) {
|
if (flowState && chatKey) {
|
||||||
setCurrentFlowState(
|
setFlowState(
|
||||||
(old: FlowState | undefined) => {
|
(old: FlowState | undefined) => {
|
||||||
let newFlowState = cloneDeep(old!);
|
let newFlowState = cloneDeep(old!);
|
||||||
newFlowState.formKeysData.input_keys![
|
newFlowState.input_keys![
|
||||||
chatKey
|
chatKey
|
||||||
] = value;
|
] = value;
|
||||||
return newFlowState;
|
return newFlowState;
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,5 @@
|
||||||
import _ from "lodash";
|
import _ from "lodash";
|
||||||
import {
|
import { MouseEvent, useCallback, useEffect, useRef, useState } from "react";
|
||||||
MouseEvent,
|
|
||||||
useCallback,
|
|
||||||
useContext,
|
|
||||||
useEffect,
|
|
||||||
useRef,
|
|
||||||
useState,
|
|
||||||
} from "react";
|
|
||||||
import ReactFlow, {
|
import ReactFlow, {
|
||||||
Background,
|
Background,
|
||||||
Connection,
|
Connection,
|
||||||
|
|
@ -18,13 +11,10 @@ import ReactFlow, {
|
||||||
SelectionDragHandler,
|
SelectionDragHandler,
|
||||||
addEdge,
|
addEdge,
|
||||||
updateEdge,
|
updateEdge,
|
||||||
useEdgesState,
|
|
||||||
useNodesState,
|
|
||||||
} from "reactflow";
|
} from "reactflow";
|
||||||
import GenericNode from "../../../../CustomNodes/GenericNode";
|
import GenericNode from "../../../../CustomNodes/GenericNode";
|
||||||
import Chat from "../../../../components/chatComponent";
|
import Chat from "../../../../components/chatComponent";
|
||||||
import Loading from "../../../../components/ui/loading";
|
import Loading from "../../../../components/ui/loading";
|
||||||
import { locationContext } from "../../../../contexts/locationContext";
|
|
||||||
import useAlertStore from "../../../../stores/alertStore";
|
import useAlertStore from "../../../../stores/alertStore";
|
||||||
import useFlowStore from "../../../../stores/flowStore";
|
import useFlowStore from "../../../../stores/flowStore";
|
||||||
import useFlowsManagerStore from "../../../../stores/flowsManagerStore";
|
import useFlowsManagerStore from "../../../../stores/flowsManagerStore";
|
||||||
|
|
@ -43,6 +33,7 @@ import { cn, getRandomName, isWrappedWithClass } from "../../../../utils/utils";
|
||||||
import ConnectionLineComponent from "../ConnectionLineComponent";
|
import ConnectionLineComponent from "../ConnectionLineComponent";
|
||||||
import SelectionMenu from "../SelectionMenuComponent";
|
import SelectionMenu from "../SelectionMenuComponent";
|
||||||
import ExtraSidebar from "../extraSidebarComponent";
|
import ExtraSidebar from "../extraSidebarComponent";
|
||||||
|
import { useLocationStore } from "../../../../stores/locationStore";
|
||||||
|
|
||||||
const nodeTypes = {
|
const nodeTypes = {
|
||||||
genericNode: GenericNode,
|
genericNode: GenericNode,
|
||||||
|
|
@ -64,11 +55,6 @@ export default function Page({
|
||||||
const setFilterEdge = useTypesStore((state) => state.setFilterEdge);
|
const setFilterEdge = useTypesStore((state) => state.setFilterEdge);
|
||||||
const reactFlowWrapper = useRef<HTMLDivElement>(null);
|
const reactFlowWrapper = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
const [lastCopiedSelection, setLastCopiedSelection] = useState<{
|
|
||||||
nodes: any;
|
|
||||||
edges: any;
|
|
||||||
} | null>(null);
|
|
||||||
|
|
||||||
const reactFlowInstance = useFlowStore((state) => state.reactFlowInstance);
|
const reactFlowInstance = useFlowStore((state) => state.reactFlowInstance);
|
||||||
const setReactFlowInstance = useFlowStore(
|
const setReactFlowInstance = useFlowStore(
|
||||||
(state) => state.setReactFlowInstance
|
(state) => state.setReactFlowInstance
|
||||||
|
|
@ -86,6 +72,13 @@ export default function Page({
|
||||||
const redo = useFlowsManagerStore((state) => state.redo);
|
const redo = useFlowsManagerStore((state) => state.redo);
|
||||||
const takeSnapshot = useFlowsManagerStore((state) => state.takeSnapshot);
|
const takeSnapshot = useFlowsManagerStore((state) => state.takeSnapshot);
|
||||||
const paste = useFlowStore((state) => state.paste);
|
const paste = useFlowStore((state) => state.paste);
|
||||||
|
const resetFlow = useFlowStore((state) => state.resetFlow);
|
||||||
|
const lastCopiedSelection = useFlowStore(
|
||||||
|
(state) => state.lastCopiedSelection
|
||||||
|
);
|
||||||
|
const setLastCopiedSelection = useFlowStore(
|
||||||
|
(state) => state.setLastCopiedSelection
|
||||||
|
);
|
||||||
|
|
||||||
const position = useRef({ x: 0, y: 0 });
|
const position = useRef({ x: 0, y: 0 });
|
||||||
const [lastSelection, setLastSelection] =
|
const [lastSelection, setLastSelection] =
|
||||||
|
|
@ -163,7 +156,12 @@ export default function Page({
|
||||||
|
|
||||||
const [selectionMenuVisible, setSelectionMenuVisible] = useState(false);
|
const [selectionMenuVisible, setSelectionMenuVisible] = useState(false);
|
||||||
|
|
||||||
const { setExtraComponent, setExtraNavigation } = useContext(locationContext);
|
const setExtraComponent = useLocationStore(
|
||||||
|
(state) => state.setExtraComponent
|
||||||
|
);
|
||||||
|
const setExtraNavigation = useLocationStore(
|
||||||
|
(state) => state.setExtraNavigation
|
||||||
|
);
|
||||||
const setErrorData = useAlertStore((state) => state.setErrorData);
|
const setErrorData = useAlertStore((state) => state.setErrorData);
|
||||||
|
|
||||||
const edgeUpdateSuccessful = useRef(true);
|
const edgeUpdateSuccessful = useRef(true);
|
||||||
|
|
@ -177,13 +175,11 @@ export default function Page({
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
if (reactFlowInstance) {
|
if (reactFlowInstance) {
|
||||||
useFlowStore.setState({
|
resetFlow({
|
||||||
nodes: flow?.data?.nodes ?? [],
|
nodes: flow?.data?.nodes ?? [],
|
||||||
edges: flow?.data?.edges ?? [],
|
edges: flow?.data?.edges ?? [],
|
||||||
});
|
viewport: flow?.data?.viewport ?? { zoom: 1, x: 0, y: 0 },
|
||||||
reactFlowInstance.setViewport(
|
})
|
||||||
flow?.data?.viewport ?? { zoom: 1, x: 0, y: 0 }
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear the previous timeout
|
// Clear the previous timeout
|
||||||
|
|
@ -224,8 +220,7 @@ export default function Page({
|
||||||
const onMoveEnd: OnMove = useCallback(() => {
|
const onMoveEnd: OnMove = useCallback(() => {
|
||||||
// 👇 make moving the canvas undoable
|
// 👇 make moving the canvas undoable
|
||||||
autoSaveCurrentFlow(nodes, edges, reactFlowInstance?.getViewport()!);
|
autoSaveCurrentFlow(nodes, edges, reactFlowInstance?.getViewport()!);
|
||||||
}
|
}, [takeSnapshot, autoSaveCurrentFlow, nodes, edges, reactFlowInstance]);
|
||||||
, [takeSnapshot, autoSaveCurrentFlow, nodes, edges, reactFlowInstance]);
|
|
||||||
|
|
||||||
const onSelectionDragStart: SelectionDragHandler = useCallback(() => {
|
const onSelectionDragStart: SelectionDragHandler = useCallback(() => {
|
||||||
// 👇 make dragging a selection undoable
|
// 👇 make dragging a selection undoable
|
||||||
|
|
@ -290,14 +285,16 @@ export default function Page({
|
||||||
const newNode: NodeType = {
|
const newNode: NodeType = {
|
||||||
id: newId,
|
id: newId,
|
||||||
type: "genericNode",
|
type: "genericNode",
|
||||||
position: {x: 0, y:0},
|
position: { x: 0, y: 0 },
|
||||||
data: {
|
data: {
|
||||||
...data,
|
...data,
|
||||||
id: newId,
|
id: newId,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
paste({ nodes: [newNode], edges: [] }, {x: event.clientX, y: event.clientY});
|
paste(
|
||||||
|
{ nodes: [newNode], edges: [] },
|
||||||
|
{ x: event.clientX, y: event.clientY }
|
||||||
|
);
|
||||||
} else if (event.dataTransfer.types.some((types) => types === "Files")) {
|
} else if (event.dataTransfer.types.some((types) => types === "Files")) {
|
||||||
takeSnapshot();
|
takeSnapshot();
|
||||||
if (event.dataTransfer.files.item(0)!.type === "application/json") {
|
if (event.dataTransfer.files.item(0)!.type === "application/json") {
|
||||||
|
|
@ -384,7 +381,6 @@ export default function Page({
|
||||||
setFilterEdge([]);
|
setFilterEdge([]);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex h-full overflow-hidden">
|
<div className="flex h-full overflow-hidden">
|
||||||
{!view && <ExtraSidebar />}
|
{!view && <ExtraSidebar />}
|
||||||
|
|
|
||||||
|
|
@ -28,16 +28,51 @@ import useFlowsManagerStore from "./flowsManagerStore";
|
||||||
|
|
||||||
// this is our useStore hook that we can use in our components to get parts of the store and call actions
|
// this is our useStore hook that we can use in our components to get parts of the store and call actions
|
||||||
const useFlowStore = create<FlowStoreType>((set, get) => ({
|
const useFlowStore = create<FlowStoreType>((set, get) => ({
|
||||||
reactFlowInstance: null,
|
sseData: {},
|
||||||
setReactFlowInstance: (newState) => {
|
flowState: undefined,
|
||||||
set({ reactFlowInstance: newState });
|
|
||||||
},
|
|
||||||
nodes: [],
|
nodes: [],
|
||||||
edges: [],
|
edges: [],
|
||||||
isBuilt: false,
|
isBuilding: false,
|
||||||
|
isBuilt: false,
|
||||||
|
reactFlowInstance: null,
|
||||||
|
lastCopiedSelection: null,
|
||||||
|
|
||||||
|
|
||||||
|
resetFlow: ({ nodes, edges, viewport }) => {
|
||||||
|
set({
|
||||||
|
nodes,
|
||||||
|
edges,
|
||||||
|
flowState: undefined,
|
||||||
|
sseData: {},
|
||||||
|
isBuilt: false,
|
||||||
|
|
||||||
|
});
|
||||||
|
get().reactFlowInstance!.setViewport(viewport);
|
||||||
|
},
|
||||||
|
updateSSEData: (sseData) => {
|
||||||
|
set((state) => ({ sseData: { ...state.sseData, ...sseData } }));
|
||||||
|
},
|
||||||
|
setIsBuilding: (isBuilding) => {
|
||||||
|
set({ isBuilding });
|
||||||
|
},
|
||||||
setIsBuilt: (isBuilt) => {
|
setIsBuilt: (isBuilt) => {
|
||||||
set({ isBuilt });
|
set({ isBuilt });
|
||||||
},
|
},
|
||||||
|
setFlowState: (flowState) => {
|
||||||
|
const newFlowState =
|
||||||
|
typeof flowState === "function"
|
||||||
|
? flowState(get().flowState)
|
||||||
|
: flowState;
|
||||||
|
|
||||||
|
if(newFlowState !== get().flowState){
|
||||||
|
set(() => ({
|
||||||
|
flowState: newFlowState,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
setReactFlowInstance: (newState) => {
|
||||||
|
set({ reactFlowInstance: newState });
|
||||||
|
},
|
||||||
onNodesChange: (changes: NodeChange[]) => {
|
onNodesChange: (changes: NodeChange[]) => {
|
||||||
set({
|
set({
|
||||||
nodes: applyNodeChanges(changes, get().nodes),
|
nodes: applyNodeChanges(changes, get().nodes),
|
||||||
|
|
@ -52,29 +87,30 @@ const useFlowStore = create<FlowStoreType>((set, get) => ({
|
||||||
let newChange = typeof change === "function" ? change(get().nodes) : change;
|
let newChange = typeof change === "function" ? change(get().nodes) : change;
|
||||||
let newEdges = cleanEdges(newChange, get().edges);
|
let newEdges = cleanEdges(newChange, get().edges);
|
||||||
|
|
||||||
set({ edges: newEdges });
|
set({ edges: newEdges, nodes: newChange, flowState: undefined, isBuilt: false, sseData: {} });
|
||||||
set({ nodes: newChange });
|
|
||||||
|
|
||||||
useFlowsManagerStore
|
const flowsManager = useFlowsManagerStore.getState()
|
||||||
.getState()
|
|
||||||
.autoSaveCurrentFlow(
|
flowsManager.autoSaveCurrentFlow(
|
||||||
newChange,
|
newChange,
|
||||||
newEdges,
|
newEdges,
|
||||||
get().reactFlowInstance?.getViewport() ?? { x: 0, y: 0, zoom: 1 }
|
get().reactFlowInstance?.getViewport() ?? { x: 0, y: 0, zoom: 1 }
|
||||||
);
|
);
|
||||||
|
|
||||||
},
|
},
|
||||||
setEdges: (change) => {
|
setEdges: (change) => {
|
||||||
let newChange = typeof change === "function" ? change(get().edges) : change;
|
let newChange = typeof change === "function" ? change(get().edges) : change;
|
||||||
|
|
||||||
set({ edges: newChange });
|
set({ edges: newChange, flowState: undefined, isBuilt: false, sseData: {} });
|
||||||
|
|
||||||
useFlowsManagerStore
|
const flowsManager = useFlowsManagerStore.getState()
|
||||||
.getState()
|
|
||||||
.autoSaveCurrentFlow(
|
flowsManager.autoSaveCurrentFlow(
|
||||||
get().nodes,
|
get().nodes,
|
||||||
newChange,
|
newChange,
|
||||||
get().reactFlowInstance?.getViewport() ?? { x: 0, y: 0, zoom: 1 }
|
get().reactFlowInstance?.getViewport() ?? { x: 0, y: 0, zoom: 1 }
|
||||||
);
|
);
|
||||||
|
|
||||||
},
|
},
|
||||||
setNode: (id: string, change: Node | ((oldState: Node) => Node)) => {
|
setNode: (id: string, change: Node | ((oldState: Node) => Node)) => {
|
||||||
let newChange =
|
let newChange =
|
||||||
|
|
@ -204,6 +240,9 @@ const useFlowStore = create<FlowStoreType>((set, get) => ({
|
||||||
});
|
});
|
||||||
set({ edges: newEdges });
|
set({ edges: newEdges });
|
||||||
},
|
},
|
||||||
|
setLastCopiedSelection: (newSelection) => {
|
||||||
|
set({ lastCopiedSelection: newSelection });
|
||||||
|
},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export default useFlowStore;
|
export default useFlowStore;
|
||||||
|
|
|
||||||
|
|
@ -10,8 +10,7 @@ import {
|
||||||
} from "../controllers/API";
|
} from "../controllers/API";
|
||||||
import { FlowType, NodeDataType } from "../types/flow";
|
import { FlowType, NodeDataType } from "../types/flow";
|
||||||
import { FlowState } from "../types/tabs";
|
import { FlowState } from "../types/tabs";
|
||||||
import { UseUndoRedoOptions } from "../types/typesContext";
|
import { FlowsManagerStoreType, UseUndoRedoOptions } from "../types/zustand/flowsManager";
|
||||||
import { FlowsManagerStoreType } from "../types/zustand/flowsManager";
|
|
||||||
import {
|
import {
|
||||||
addVersionToDuplicates,
|
addVersionToDuplicates,
|
||||||
createFlowComponent,
|
createFlowComponent,
|
||||||
|
|
@ -39,7 +38,6 @@ const useFlowsManagerStore = create<FlowsManagerStoreType>((set, get) => ({
|
||||||
setCurrentFlowId: (currentFlowId: string) => {
|
setCurrentFlowId: (currentFlowId: string) => {
|
||||||
set((state) => ({
|
set((state) => ({
|
||||||
currentFlowId,
|
currentFlowId,
|
||||||
currentFlowState: state.flowsState[state.currentFlowId],
|
|
||||||
currentFlow: state.flows.find((flow) => flow.id === currentFlowId),
|
currentFlow: state.flows.find((flow) => flow.id === currentFlowId),
|
||||||
}));
|
}));
|
||||||
},
|
},
|
||||||
|
|
@ -53,23 +51,6 @@ const useFlowsManagerStore = create<FlowsManagerStoreType>((set, get) => ({
|
||||||
currentFlow: undefined,
|
currentFlow: undefined,
|
||||||
isLoading: true,
|
isLoading: true,
|
||||||
setIsLoading: (isLoading: boolean) => set({ isLoading }),
|
setIsLoading: (isLoading: boolean) => set({ isLoading }),
|
||||||
flowsState: {},
|
|
||||||
currentFlowState: undefined,
|
|
||||||
setCurrentFlowState: (
|
|
||||||
flowState: FlowState | ((oldState: FlowState | undefined) => FlowState)
|
|
||||||
) => {
|
|
||||||
const newFlowState =
|
|
||||||
typeof flowState === "function"
|
|
||||||
? flowState(get().currentFlowState)
|
|
||||||
: flowState;
|
|
||||||
set((state) => ({
|
|
||||||
flowsState: {
|
|
||||||
...state.flowsState,
|
|
||||||
[state.currentFlowId]: newFlowState,
|
|
||||||
},
|
|
||||||
currentFlowState: newFlowState,
|
|
||||||
}));
|
|
||||||
},
|
|
||||||
refreshFlows: () => {
|
refreshFlows: () => {
|
||||||
return new Promise<void>((resolve, reject) => {
|
return new Promise<void>((resolve, reject) => {
|
||||||
set({ isLoading: true });
|
set({ isLoading: true });
|
||||||
|
|
|
||||||
28
src/frontend/src/stores/locationStore.tsx
Normal file
28
src/frontend/src/stores/locationStore.tsx
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
import { create } from "zustand";
|
||||||
|
import { LocationStoreType } from "../types/zustand/location";
|
||||||
|
|
||||||
|
export const useLocationStore = create<LocationStoreType>((set, get) => ({
|
||||||
|
current: window.location.pathname.replace(/\/$/g, "").split("/"),
|
||||||
|
isStackedOpen:
|
||||||
|
window.innerWidth > 1024 && window.location.pathname.split("/")[1]
|
||||||
|
? true
|
||||||
|
: false,
|
||||||
|
setCurrent: (newState) => {
|
||||||
|
set({ current: newState });
|
||||||
|
},
|
||||||
|
setIsStackedOpen: (newState) => {
|
||||||
|
set({ isStackedOpen: newState });
|
||||||
|
},
|
||||||
|
showSideBar: window.location.pathname.split("/")[1] ? true : false,
|
||||||
|
setShowSideBar: (newState) => {
|
||||||
|
set({ showSideBar: newState });
|
||||||
|
},
|
||||||
|
extraNavigation: { title: "" },
|
||||||
|
setExtraNavigation: (newState) => {
|
||||||
|
set({ extraNavigation: newState });
|
||||||
|
},
|
||||||
|
extraComponent: <></>,
|
||||||
|
setExtraComponent: (newState) => {
|
||||||
|
set({ extraComponent: newState });
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
@ -55,16 +55,14 @@ export type FlowsContextType = {
|
||||||
};
|
};
|
||||||
|
|
||||||
export type FlowsState = {
|
export type FlowsState = {
|
||||||
[key: string]: FlowState;
|
[key: string]: FlowState | undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type FlowState = {
|
export type FlowState = {
|
||||||
formKeysData: {
|
template?: string;
|
||||||
template?: string;
|
input_keys?: Object;
|
||||||
input_keys?: Object;
|
memory_keys?: Array<string>;
|
||||||
memory_keys?: Array<string>;
|
handle_keys?: Array<string>;
|
||||||
handle_keys?: Array<string>;
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export type errorsVarType = {
|
export type errorsVarType = {
|
||||||
|
|
|
||||||
|
|
@ -1,89 +0,0 @@
|
||||||
import { Edge, Node } from "reactflow";
|
|
||||||
import { AlertItemType } from "../alerts";
|
|
||||||
|
|
||||||
export type alertContextType = {
|
|
||||||
errorData: { title: string; list?: Array<string> };
|
|
||||||
setErrorData: (newState: { title: string; list?: Array<string> }) => void;
|
|
||||||
errorOpen: boolean;
|
|
||||||
setErrorOpen: (newState: boolean) => void;
|
|
||||||
noticeData: { title: string; link?: string };
|
|
||||||
setNoticeData: (newState: { title: string; link?: string }) => void;
|
|
||||||
noticeOpen: boolean;
|
|
||||||
setNoticeOpen: (newState: boolean) => void;
|
|
||||||
successData: { title: string };
|
|
||||||
setSuccessData: (newState: { title: string }) => void;
|
|
||||||
successOpen: boolean;
|
|
||||||
setSuccessOpen: (newState: boolean) => void;
|
|
||||||
notificationCenter: boolean;
|
|
||||||
setNotificationCenter: (newState: boolean) => void;
|
|
||||||
notificationList: Array<AlertItemType>;
|
|
||||||
pushNotificationList: (Object: AlertItemType) => void;
|
|
||||||
clearNotificationList: () => void;
|
|
||||||
removeFromNotificationList: (index: string) => void;
|
|
||||||
loading: boolean;
|
|
||||||
setLoading: (newState: boolean) => void;
|
|
||||||
modalContextOpen: boolean | null;
|
|
||||||
setModalContextOpen: (newState: boolean) => void;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type darkContextType = {
|
|
||||||
dark: {};
|
|
||||||
setDark: (newState: {}) => void;
|
|
||||||
stars: number;
|
|
||||||
setStars: (stars: number) => void;
|
|
||||||
gradientIndex: number;
|
|
||||||
setGradientIndex: (index: number) => void;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type locationContextType = {
|
|
||||||
current: Array<string>;
|
|
||||||
setCurrent: (newState: Array<string>) => void;
|
|
||||||
isStackedOpen: boolean;
|
|
||||||
setIsStackedOpen: (newState: boolean) => void;
|
|
||||||
showSideBar: boolean;
|
|
||||||
setShowSideBar: (newState: boolean) => void;
|
|
||||||
extraNavigation: {
|
|
||||||
title: string;
|
|
||||||
options?: Array<{
|
|
||||||
name: string;
|
|
||||||
href: string;
|
|
||||||
icon: React.ElementType;
|
|
||||||
children?: Array<JSX.Element>;
|
|
||||||
}>;
|
|
||||||
};
|
|
||||||
setExtraNavigation: (newState: {
|
|
||||||
title: string;
|
|
||||||
options?: Array<{
|
|
||||||
name: string;
|
|
||||||
href: string;
|
|
||||||
icon: React.ElementType;
|
|
||||||
children?: Array<JSX.Element>;
|
|
||||||
}>;
|
|
||||||
}) => void;
|
|
||||||
extraComponent: any;
|
|
||||||
setExtraComponent: (newState: JSX.Element) => void;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type undoRedoContextType = {
|
|
||||||
undo: () => void;
|
|
||||||
redo: () => void;
|
|
||||||
takeSnapshot: () => void;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type UseUndoRedoOptions = {
|
|
||||||
maxHistorySize: number;
|
|
||||||
enableShortcuts: boolean;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type UseUndoRedo = (options?: UseUndoRedoOptions) => {
|
|
||||||
undo: () => void;
|
|
||||||
redo: () => void;
|
|
||||||
takeSnapshot: () => void;
|
|
||||||
canUndo: boolean;
|
|
||||||
canRedo: boolean;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type HistoryItem = {
|
|
||||||
nodes: Node[];
|
|
||||||
edges: Edge[];
|
|
||||||
};
|
|
||||||
|
|
@ -5,11 +5,20 @@ import {
|
||||||
OnEdgesChange,
|
OnEdgesChange,
|
||||||
OnNodesChange,
|
OnNodesChange,
|
||||||
ReactFlowInstance,
|
ReactFlowInstance,
|
||||||
|
Viewport,
|
||||||
} from "reactflow";
|
} from "reactflow";
|
||||||
|
import { FlowState } from "../../tabs";
|
||||||
|
|
||||||
export type FlowStoreType = {
|
export type FlowStoreType = {
|
||||||
|
updateSSEData: (sseData: object) => void;
|
||||||
|
sseData: object;
|
||||||
|
isBuilding: boolean;
|
||||||
|
setIsBuilding: (isBuilding: boolean) => void;
|
||||||
|
resetFlow: (flow: {nodes: Node[], edges: Edge[], viewport: Viewport}) => void;
|
||||||
reactFlowInstance: ReactFlowInstance | null;
|
reactFlowInstance: ReactFlowInstance | null;
|
||||||
setReactFlowInstance: (newState: ReactFlowInstance) => void;
|
setReactFlowInstance: (newState: ReactFlowInstance) => void;
|
||||||
|
flowState: FlowState | undefined;
|
||||||
|
setFlowState: (state: FlowState | undefined | ((oldState: FlowState | undefined) => FlowState)) => void;
|
||||||
nodes: Node[];
|
nodes: Node[];
|
||||||
edges: Edge[];
|
edges: Edge[];
|
||||||
onNodesChange: OnNodesChange;
|
onNodesChange: OnNodesChange;
|
||||||
|
|
@ -24,6 +33,11 @@ export type FlowStoreType = {
|
||||||
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 }
|
||||||
) => void;
|
) => void;
|
||||||
|
lastCopiedSelection: { nodes: any; edges: any } | null;
|
||||||
|
setLastCopiedSelection: (
|
||||||
|
newSelection: { nodes: any; edges: any } | null
|
||||||
|
) => void;
|
||||||
isBuilt: boolean;
|
isBuilt: boolean;
|
||||||
setIsBuilt: (isBuilt: boolean) => void;
|
setIsBuilt: (isBuilt: boolean) => void;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -10,9 +10,6 @@ export type FlowsManagerStoreType = {
|
||||||
setCurrentFlowId: (currentFlowId: string) => void;
|
setCurrentFlowId: (currentFlowId: string) => void;
|
||||||
isLoading: boolean;
|
isLoading: boolean;
|
||||||
setIsLoading: (isLoading: boolean) => void;
|
setIsLoading: (isLoading: boolean) => void;
|
||||||
flowsState: FlowsState;
|
|
||||||
currentFlowState: FlowState | undefined;
|
|
||||||
setCurrentFlowState: (state: FlowState | ((oldState: FlowState | undefined) => FlowState)) => void;
|
|
||||||
refreshFlows: () => Promise<void>;
|
refreshFlows: () => Promise<void>;
|
||||||
saveFlow: (flow: FlowType, silent?: boolean) => Promise<void>;
|
saveFlow: (flow: FlowType, silent?: boolean) => Promise<void>;
|
||||||
autoSaveCurrentFlow: (nodes: Node[], edges: Edge[], viewport: Viewport) => void;
|
autoSaveCurrentFlow: (nodes: Node[], edges: Edge[], viewport: Viewport) => void;
|
||||||
|
|
@ -26,3 +23,8 @@ export type FlowsManagerStoreType = {
|
||||||
redo: () => void;
|
redo: () => void;
|
||||||
takeSnapshot: () => void;
|
takeSnapshot: () => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type UseUndoRedoOptions = {
|
||||||
|
maxHistorySize: number;
|
||||||
|
enableShortcuts: boolean;
|
||||||
|
};
|
||||||
28
src/frontend/src/types/zustand/location/index.ts
Normal file
28
src/frontend/src/types/zustand/location/index.ts
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
export type LocationStoreType = {
|
||||||
|
current: Array<string>;
|
||||||
|
setCurrent: (newState: Array<string>) => void;
|
||||||
|
isStackedOpen: boolean;
|
||||||
|
setIsStackedOpen: (newState: boolean) => void;
|
||||||
|
showSideBar: boolean;
|
||||||
|
setShowSideBar: (newState: boolean) => void;
|
||||||
|
extraNavigation: {
|
||||||
|
title: string;
|
||||||
|
options?: Array<{
|
||||||
|
name: string;
|
||||||
|
href: string;
|
||||||
|
icon: React.ElementType;
|
||||||
|
children?: Array<JSX.Element>;
|
||||||
|
}>;
|
||||||
|
};
|
||||||
|
setExtraNavigation: (newState: {
|
||||||
|
title: string;
|
||||||
|
options?: Array<{
|
||||||
|
name: string;
|
||||||
|
href: string;
|
||||||
|
icon: React.ElementType;
|
||||||
|
children?: Array<JSX.Element>;
|
||||||
|
}>;
|
||||||
|
}) => void;
|
||||||
|
extraComponent: any;
|
||||||
|
setExtraComponent: (newState: JSX.Element) => void;
|
||||||
|
};
|
||||||
|
|
@ -217,12 +217,11 @@ export function groupByFamily(
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
export function buildInputs(currentFlowState?: FlowState): string {
|
export function buildInputs(flowState?: FlowState): string {
|
||||||
return currentFlowState &&
|
return flowState &&
|
||||||
currentFlowState.formKeysData &&
|
flowState.input_keys &&
|
||||||
currentFlowState.formKeysData.input_keys &&
|
Object.keys(flowState.input_keys!).length > 0
|
||||||
Object.keys(currentFlowState.formKeysData.input_keys!).length > 0
|
? JSON.stringify(flowState.input_keys)
|
||||||
? JSON.stringify(currentFlowState.formKeysData.input_keys)
|
|
||||||
: '{"input": "message"}';
|
: '{"input": "message"}';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -297,16 +296,15 @@ export function buildTweakObject(tweak: tweakType) {
|
||||||
* @param {FlowsState} tabsState - The current tabs state.
|
* @param {FlowsState} tabsState - The current tabs state.
|
||||||
* @returns {string} - The chat input field
|
* @returns {string} - The chat input field
|
||||||
*/
|
*/
|
||||||
export function getChatInputField(flow: FlowType, currentFlowState?: FlowState) {
|
export function getChatInputField(flow: FlowType, flowState?: FlowState) {
|
||||||
let chat_input_field = "text";
|
let chat_input_field = "text";
|
||||||
|
|
||||||
if (
|
if (
|
||||||
currentFlowState &&
|
flowState &&
|
||||||
currentFlowState.formKeysData &&
|
flowState.input_keys
|
||||||
currentFlowState.formKeysData.input_keys
|
|
||||||
) {
|
) {
|
||||||
chat_input_field = Object.keys(
|
chat_input_field = Object.keys(
|
||||||
currentFlowState.formKeysData.input_keys!
|
flowState.input_keys!
|
||||||
)[0];
|
)[0];
|
||||||
}
|
}
|
||||||
return chat_input_field;
|
return chat_input_field;
|
||||||
|
|
@ -321,7 +319,7 @@ export function getPythonApiCode(
|
||||||
flow: FlowType,
|
flow: FlowType,
|
||||||
isAuth: boolean,
|
isAuth: boolean,
|
||||||
tweak?: any[],
|
tweak?: any[],
|
||||||
currentFlowState?: FlowState
|
flowState?: FlowState
|
||||||
): string {
|
): string {
|
||||||
const flowId = flow.id;
|
const flowId = flow.id;
|
||||||
|
|
||||||
|
|
@ -330,7 +328,7 @@ export function getPythonApiCode(
|
||||||
// node.data.id
|
// node.data.id
|
||||||
// }
|
// }
|
||||||
const tweaks = buildTweaks(flow);
|
const tweaks = buildTweaks(flow);
|
||||||
const inputs = buildInputs(currentFlowState);
|
const inputs = buildInputs(flowState);
|
||||||
return `import requests
|
return `import requests
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
|
|
@ -385,11 +383,11 @@ export function getCurlCode(
|
||||||
flow: FlowType,
|
flow: FlowType,
|
||||||
isAuth: boolean,
|
isAuth: boolean,
|
||||||
tweak?: any[],
|
tweak?: any[],
|
||||||
currentFlowState?: FlowState
|
flowState?: FlowState
|
||||||
): string {
|
): string {
|
||||||
const flowId = flow.id;
|
const flowId = flow.id;
|
||||||
const tweaks = buildTweaks(flow);
|
const tweaks = buildTweaks(flow);
|
||||||
const inputs = buildInputs(currentFlowState);
|
const inputs = buildInputs(flowState);
|
||||||
|
|
||||||
return `curl -X POST \\
|
return `curl -X POST \\
|
||||||
${window.location.protocol}//${
|
${window.location.protocol}//${
|
||||||
|
|
@ -413,11 +411,11 @@ export function getCurlCode(
|
||||||
export function getPythonCode(
|
export function getPythonCode(
|
||||||
flow: FlowType,
|
flow: FlowType,
|
||||||
tweak?: any[],
|
tweak?: any[],
|
||||||
currentFlowState?: FlowState
|
flowState?: FlowState
|
||||||
): string {
|
): string {
|
||||||
const flowName = flow.name;
|
const flowName = flow.name;
|
||||||
const tweaks = buildTweaks(flow);
|
const tweaks = buildTweaks(flow);
|
||||||
const inputs = buildInputs(currentFlowState);
|
const inputs = buildInputs(flowState);
|
||||||
return `from langflow import load_flow_from_json
|
return `from langflow import load_flow_from_json
|
||||||
TWEAKS = ${
|
TWEAKS = ${
|
||||||
tweak && tweak.length > 0
|
tweak && tweak.length > 0
|
||||||
|
|
@ -438,12 +436,12 @@ flow(inputs)`;
|
||||||
export function getWidgetCode(
|
export function getWidgetCode(
|
||||||
flow: FlowType,
|
flow: FlowType,
|
||||||
isAuth: boolean,
|
isAuth: boolean,
|
||||||
currentFlowState?: FlowState
|
flowState?: FlowState
|
||||||
): string {
|
): string {
|
||||||
const flowId = flow.id;
|
const flowId = flow.id;
|
||||||
const flowName = flow.name;
|
const flowName = flow.name;
|
||||||
const inputs = buildInputs(currentFlowState);
|
const inputs = buildInputs(flowState);
|
||||||
let chat_input_field = getChatInputField(flow, currentFlowState);
|
let chat_input_field = getChatInputField(flow, flowState);
|
||||||
|
|
||||||
return `<script src="https://cdn.jsdelivr.net/gh/logspace-ai/langflow-embedded-chat@main/dist/build/static/js/bundle.min.js"></script>
|
return `<script src="https://cdn.jsdelivr.net/gh/logspace-ai/langflow-embedded-chat@main/dist/build/static/js/bundle.min.js"></script>
|
||||||
|
|
||||||
|
|
@ -454,7 +452,7 @@ chat_input_field: Input key that you want the chat to send the user message with
|
||||||
window_title="${flowName}"
|
window_title="${flowName}"
|
||||||
flow_id="${flowId}"
|
flow_id="${flowId}"
|
||||||
${
|
${
|
||||||
currentFlowState && currentFlowState.formKeysData
|
flowState
|
||||||
? `chat_inputs='${inputs}'
|
? `chat_inputs='${inputs}'
|
||||||
chat_input_field="${chat_input_field}"
|
chat_input_field="${chat_input_field}"
|
||||||
`
|
`
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue