added the implementation of flowsState in all the project

This commit is contained in:
Lucas Oliveira 2024-01-05 23:28:03 -03:00
commit 82f180315b
7 changed files with 193 additions and 189 deletions

View file

@ -8,8 +8,9 @@ import { FlowType } from "../../../types/flow";
import { FlowsContext } from "../../../contexts/flowsContext"; import { FlowsContext } from "../../../contexts/flowsContext";
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 { FlowsState } from "../../../types/tabs"; 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";
@ -25,11 +26,14 @@ export default function BuildTrigger({
isBuilt: boolean; isBuilt: boolean;
}): JSX.Element { }): JSX.Element {
const { updateSSEData, isBuilding, setIsBuilding, sseData } = useSSE(); const { updateSSEData, isBuilding, setIsBuilding, sseData } = useSSE();
const { setTabsState, saveFlow } = useContext(FlowsContext); const { saveFlow } = useContext(FlowsContext);
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(
(state) => state.setCurrentFlowState
);
const [isIconTouched, setIsIconTouched] = useState(false); const [isIconTouched, setIsIconTouched] = useState(false);
const eventClick = isBuilding ? "pointer-events-none" : ""; const eventClick = isBuilding ? "pointer-events-none" : "";
@ -99,15 +103,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) {
setTabsState((old: FlowsState) => { setCurrentFlowState(parsedData);
return {
...old,
[flowId]: {
...old[flowId],
formKeysData: parsedData,
},
};
});
} else { } else {
// Otherwise, process the data // Otherwise, process the data
const isValid = processStreamResult(parsedData); const isValid = processStreamResult(parsedData);

View file

@ -10,6 +10,7 @@ import { getBuildStatus } from "../../controllers/API";
import FormModal from "../../modals/formModal"; import FormModal from "../../modals/formModal";
import useFlowStore from "../../stores/flowStore"; import useFlowStore from "../../stores/flowStore";
import { NodeType } from "../../types/flow"; import { NodeType } from "../../types/flow";
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);
@ -17,7 +18,7 @@ export default function Chat({ flow }: ChatType): JSX.Element {
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 isPending = useFlowStore((state) => state.isPending); const isPending = useFlowStore((state) => state.isPending);
const { tabsState } = useContext(FlowsContext); const currentFlowState = useFlowsManagerStore((state) => state.currentFlowState);
useEffect(() => { useEffect(() => {
const handleKeyDown = (event: KeyboardEvent) => { const handleKeyDown = (event: KeyboardEvent) => {
@ -61,10 +62,9 @@ export default function Chat({ flow }: ChatType): JSX.Element {
setIsBuilt(false); setIsBuilt(false);
} }
if ( if (
tabsState && currentFlowState &&
tabsState[flow.id] && currentFlowState.formKeysData &&
tabsState[flow.id].formKeysData && currentFlowState.formKeysData.input_keys !== null
tabsState[flow.id].formKeysData.input_keys !== null
) { ) {
setCanOpen(true); setCanOpen(true);
} else { } else {
@ -72,7 +72,7 @@ export default function Chat({ flow }: ChatType): JSX.Element {
} }
prevNodesRef.current = currentNodes; prevNodesRef.current = currentNodes;
}, [tabsState, flow.id]); }, [currentFlowState, flow.id]);
return ( return (
<> <>
@ -84,8 +84,8 @@ export default function Chat({ flow }: ChatType): JSX.Element {
isBuilt={isBuilt} isBuilt={isBuilt}
/> />
{isBuilt && {isBuilt &&
tabsState[flow.id] && currentFlowState &&
tabsState[flow.id].formKeysData && currentFlowState.formKeysData &&
canOpen && ( canOpen && (
<FormModal <FormModal
key={flow.id} key={flow.id}

View file

@ -18,7 +18,7 @@ import {
LANGFLOW_SUPPORTED_TYPES, LANGFLOW_SUPPORTED_TYPES,
} from "../../constants/constants"; } from "../../constants/constants";
import { AuthContext } from "../../contexts/authContext"; import { AuthContext } from "../../contexts/authContext";
import { FlowsContext } from "../../contexts/flowsContext"; import useFlowsManagerStore from "../../stores/flowsManagerStore";
import { TemplateVariableType } from "../../types/api"; import { TemplateVariableType } from "../../types/api";
import { tweakType, uniqueTweakType } from "../../types/components"; import { tweakType, uniqueTweakType } from "../../types/components";
import { FlowType, NodeType } from "../../types/flow/index"; import { FlowType, NodeType } from "../../types/flow/index";
@ -48,17 +48,19 @@ const ApiModal = forwardRef(
const [activeTab, setActiveTab] = useState("0"); const [activeTab, setActiveTab] = useState("0");
const tweak = useRef<tweakType>([]); const tweak = useRef<tweakType>([]);
const tweaksList = useRef<string[]>([]); const tweaksList = useRef<string[]>([]);
const { tabsState } = useContext(FlowsContext);
const [getTweak, setTweak] = useState<tweakType>([]); const [getTweak, setTweak] = useState<tweakType>([]);
const currentFlowState = useFlowsManagerStore(
(state) => state.currentFlowState
);
const pythonApiCode = getPythonApiCode( const pythonApiCode = getPythonApiCode(
flow, flow,
autoLogin, autoLogin,
tweak.current, tweak.current,
tabsState currentFlowState
); );
const curl_code = getCurlCode(flow, autoLogin, tweak.current, tabsState); const curl_code = getCurlCode(flow, autoLogin, tweak.current, currentFlowState);
const pythonCode = getPythonCode(flow, tweak.current, tabsState); const pythonCode = getPythonCode(flow, tweak.current, currentFlowState);
const widgetCode = getWidgetCode(flow, autoLogin, tabsState); const widgetCode = getWidgetCode(flow, autoLogin, currentFlowState);
const tweaksCode = buildTweaks(flow); const tweaksCode = buildTweaks(flow);
const codesArray = [ const codesArray = [
curl_code, curl_code,
@ -169,11 +171,11 @@ const ApiModal = forwardRef(
flow, flow,
autoLogin, autoLogin,
tweak.current, tweak.current,
tabsState currentFlowState
); );
const curl_code = getCurlCode(flow, autoLogin, tweak.current, tabsState); const curl_code = getCurlCode(flow, autoLogin, tweak.current, currentFlowState);
const pythonCode = getPythonCode(flow, tweak.current, tabsState); const pythonCode = getPythonCode(flow, tweak.current, currentFlowState);
const widgetCode = getWidgetCode(flow, autoLogin, tabsState); const widgetCode = getWidgetCode(flow, autoLogin, currentFlowState);
tabs![0].code = curl_code; tabs![0].code = curl_code;
tabs![1].code = pythonApiCode; tabs![1].code = pythonApiCode;

View file

@ -6,7 +6,7 @@ import { classNames } from "../../utils/utils";
import ChatInput from "./chatInput"; import ChatInput from "./chatInput";
import ChatMessage from "./chatMessage"; import ChatMessage from "./chatMessage";
import _ from "lodash"; import _, { cloneDeep } from "lodash";
import AccordionComponent from "../../components/AccordionComponent"; import AccordionComponent from "../../components/AccordionComponent";
import IconComponent from "../../components/genericIconComponent"; import IconComponent from "../../components/genericIconComponent";
import ToggleShadComponent from "../../components/toggleShadComponent"; import ToggleShadComponent from "../../components/toggleShadComponent";
@ -22,11 +22,11 @@ import {
import { Textarea } from "../../components/ui/textarea"; import { Textarea } from "../../components/ui/textarea";
import { CHAT_FORM_DIALOG_SUBTITLE } from "../../constants/constants"; import { CHAT_FORM_DIALOG_SUBTITLE } from "../../constants/constants";
import { AuthContext } from "../../contexts/authContext"; import { AuthContext } from "../../contexts/authContext";
import { FlowsContext } from "../../contexts/flowsContext";
import { getBuildStatus } from "../../controllers/API"; import { getBuildStatus } from "../../controllers/API";
import useAlertStore from "../../stores/alertStore"; import useAlertStore from "../../stores/alertStore";
import useFlowStore from "../../stores/flowStore"; import useFlowStore from "../../stores/flowStore";
import { FlowsState } from "../../types/tabs"; import useFlowsManagerStore from "../../stores/flowsManagerStore";
import { FlowState, FlowsState } from "../../types/tabs";
import { validateNodes } from "../../utils/reactflowUtils"; import { validateNodes } from "../../utils/reactflowUtils";
export default function FormModal({ export default function FormModal({
@ -38,12 +38,17 @@ export default function FormModal({
setOpen: (open: boolean) => void; setOpen: (open: boolean) => void;
flow: FlowType; flow: FlowType;
}): JSX.Element { }): JSX.Element {
const { tabsState, setTabsState } = useContext(FlowsContext);
const 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(
(state) => state.currentFlowState
);
const setCurrentFlowState = useFlowsManagerStore(
(state) => state.setCurrentFlowState
);
const [chatValue, setChatValue] = useState(() => { const [chatValue, setChatValue] = useState(() => {
try { try {
const { formKeysData } = tabsState[flow.id]; const formKeysData = currentFlowState?.formKeysData;
if (!formKeysData) { if (!formKeysData) {
throw new Error("formKeysData is undefined"); throw new Error("formKeysData is undefined");
} }
@ -63,23 +68,20 @@ export default function FormModal({
}); });
const [chatHistory, setChatHistory] = useState<ChatMessageType[]>([]); const [chatHistory, setChatHistory] = useState<ChatMessageType[]>([]);
const template = useRef(tabsState[flow.id].formKeysData.template); const template = useRef(currentFlowState?.formKeysData.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);
const [lockChat, setLockChat] = useState(false); const [lockChat, setLockChat] = useState(false);
const isOpen = useRef(open); const isOpen = useRef(open);
const messagesRef = useRef<HTMLDivElement | null>(null); const messagesRef = useRef<HTMLDivElement | null>(null);
const id = useRef(flow.id);
const tabsStateFlowId = tabsState[flow.id];
const tabsStateFlowIdFormKeysData = tabsStateFlowId.formKeysData;
const [chatKey, setChatKey] = useState(() => { const [chatKey, setChatKey] = useState(() => {
if (tabsState[flow.id]?.formKeysData?.input_keys) { if (currentFlowState?.formKeysData?.input_keys) {
return Object.keys(tabsState[flow.id].formKeysData.input_keys!).find( return Object.keys(currentFlowState.formKeysData.input_keys!).find(
(key) => (key) =>
!tabsState[flow.id].formKeysData.handle_keys!.some( !currentFlowState.formKeysData.handle_keys!.some((j) => j === key) &&
(j) => j === key currentFlowState.formKeysData.input_keys![key] === ""
) && tabsState[flow.id].formKeysData.input_keys![key] === ""
); );
} }
// TODO: return a sensible default // TODO: return a sensible default
@ -94,9 +96,6 @@ export default function FormModal({
useEffect(() => { useEffect(() => {
isOpen.current = open; isOpen.current = open;
}, [open]); }, [open]);
useEffect(() => {
id.current = flow.id;
}, [flow.id, tabsStateFlowId, tabsStateFlowIdFormKeysData]);
var isStream = false; var isStream = false;
@ -297,7 +296,7 @@ export default function FormModal({
function connectWS(): void { function connectWS(): void {
try { try {
const urlWs = getWebSocketUrl( const urlWs = getWebSocketUrl(
id.current, flow.id,
process.env.NODE_ENV === "development" process.env.NODE_ENV === "development"
); );
const newWs = new WebSocket(urlWs); const newWs = new WebSocket(urlWs);
@ -388,7 +387,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 = tabsState[id.current].formKeysData.input_keys; let inputs = currentFlowState?.formKeysData.input_keys;
setChatValue(""); setChatValue("");
const message = inputs; const message = inputs;
addChatHistory(message!, true, chatKey!, template.current); addChatHistory(message!, true, chatKey!, template.current);
@ -400,12 +399,13 @@ export default function FormModal({
description: flow.description, description: flow.description,
chatKey: chatKey!, chatKey: chatKey!,
}); });
setTabsState((old: FlowsState) => { if (currentFlowState && chatKey) {
if (!chatKey) return old; setCurrentFlowState((old: FlowState | undefined) => {
let newTabsState = _.cloneDeep(old); let newFlowState = cloneDeep(old!);
newTabsState[id.current].formKeysData.input_keys![chatKey] = ""; newFlowState.formKeysData.input_keys![chatKey] = "";
return newTabsState; return newFlowState;
}); });
}
} else { } else {
setErrorData({ setErrorData({
title: "Oops! Looks like you missed some required information:", title: "Oops! Looks like you missed some required information:",
@ -415,7 +415,7 @@ export default function FormModal({
} }
function clearChat(): void { function clearChat(): void {
setChatHistory([]); setChatHistory([]);
template.current = tabsState[id.current].formKeysData.template; template.current = currentFlowState?.formKeysData.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 +423,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(tabsState[flow.id].formKeysData.input_keys![i]); setChatValue(currentFlowState?.formKeysData.input_keys![i] ?? "");
} else { } else {
setChatKey(null!); setChatKey(null!);
setChatValue(""); setChatValue("");
@ -432,7 +432,7 @@ export default function FormModal({
return ( return (
<Dialog open={open} onOpenChange={setOpen}> <Dialog open={open} onOpenChange={setOpen}>
<DialogTrigger hidden></DialogTrigger> <DialogTrigger hidden></DialogTrigger>
{tabsState[flow.id].formKeysData && ( {currentFlowState && currentFlowState.formKeysData && (
<DialogContent className="min-w-[80vw]"> <DialogContent className="min-w-[80vw]">
<DialogHeader> <DialogHeader>
<DialogTitle className="flex items-center"> <DialogTitle className="flex items-center">
@ -468,106 +468,103 @@ export default function FormModal({
</div> </div>
</div> </div>
{tabsState[id.current]?.formKeysData?.input_keys {currentFlowState?.formKeysData?.input_keys
? Object.keys( ? Object.keys(currentFlowState?.formKeysData.input_keys!).map(
tabsState[id.current].formKeysData.input_keys! (key, index) => (
).map((key, index) => ( <div className="file-component-accordion-div" key={index}>
<div className="file-component-accordion-div" key={index}> <AccordionComponent
<AccordionComponent trigger={
trigger={ <div className="file-component-badge-div">
<div className="file-component-badge-div"> <Badge variant="gray" size="md">
<Badge variant="gray" size="md"> {key}
{key} </Badge>
</Badge>
<div <div
className="-mb-1" className="-mb-1"
onClick={(event) => { onClick={(event) => {
event.stopPropagation(); event.stopPropagation();
}} }}
> >
<ToggleShadComponent <ToggleShadComponent
enabled={chatKey === key} enabled={chatKey === key}
setEnabled={(value) => setEnabled={(value) =>
handleOnCheckedChange(value, key) handleOnCheckedChange(value, key)
}
size="small"
disabled={currentFlowState.formKeysData.handle_keys!.some(
(t) => t === key
)}
/>
</div>
</div>
}
key={index}
keyValue={key}
>
<div className="file-component-tab-column">
{currentFlowState?.formKeysData.handle_keys!.some(
(t) => t === key
) && (
<div className="font-normal text-muted-foreground ">
Source: Component
</div>
)}
<Textarea
className="custom-scroll"
value={
currentFlowState?.formKeysData.input_keys![key]
}
onChange={(e) => {
if (currentFlowState) {
setCurrentFlowState(
(old: FlowState | undefined) => {
let newFlowState = cloneDeep(old!);
newFlowState.formKeysData.input_keys![
key
] = e.target.value;
return newFlowState;
}
);
} }
size="small" }}
disabled={tabsState[ disabled={chatKey === key}
id.current placeholder="Enter text..."
].formKeysData.handle_keys!.some( ></Textarea>
(t) => t === key
)}
/>
</div>
</div> </div>
} </AccordionComponent>
key={index} </div>
keyValue={key} )
> )
<div className="file-component-tab-column">
{tabsState[id.current].formKeysData.handle_keys!.some(
(t) => t === key
) && (
<div className="font-normal text-muted-foreground ">
Source: Component
</div>
)}
<Textarea
className="custom-scroll"
value={
tabsState[id.current].formKeysData.input_keys![
key
]
}
onChange={(e) => {
setTabsState((old: FlowsState) => {
let newTabsState = _.cloneDeep(old);
newTabsState[
id.current
].formKeysData.input_keys![key] =
e.target.value;
return newTabsState;
});
}}
disabled={chatKey === key}
placeholder="Enter text..."
></Textarea>
</div>
</AccordionComponent>
</div>
))
: null} : null}
{tabsState[id.current].formKeysData.memory_keys!.map( {currentFlowState?.formKeysData.memory_keys!.map((key, index) => (
(key, index) => ( <div className="file-component-accordion-div" key={index}>
<div className="file-component-accordion-div" key={index}> <AccordionComponent
<AccordionComponent trigger={
trigger={ <div className="file-component-badge-div">
<div className="file-component-badge-div"> <Badge variant="gray" size="md">
<Badge variant="gray" size="md"> {key}
{key} </Badge>
</Badge> <div className="-mb-1">
<div className="-mb-1"> <ToggleShadComponent
<ToggleShadComponent enabled={chatKey === key}
enabled={chatKey === key} setEnabled={() => {}}
setEnabled={() => {}} size="small"
size="small" disabled={true}
disabled={true} />
/>
</div>
</div>
}
key={index}
keyValue={key}
>
<div className="file-component-tab-column">
<div className="font-normal text-muted-foreground ">
Source: Memory
</div> </div>
</div> </div>
</AccordionComponent> }
</div> key={index}
) keyValue={key}
)} >
<div className="file-component-tab-column">
<div className="font-normal text-muted-foreground ">
Source: Memory
</div>
</div>
</AccordionComponent>
</div>
))}
</div> </div>
<div className="eraser-column-arrangement"> <div className="eraser-column-arrangement">
<div className="eraser-size"> <div className="eraser-size">
@ -631,13 +628,17 @@ export default function FormModal({
sendMessage={sendMessage} sendMessage={sendMessage}
setChatValue={(value) => { setChatValue={(value) => {
setChatValue(value); setChatValue(value);
setTabsState((old: FlowsState) => { if (currentFlowState && chatKey) {
let newTabsState = _.cloneDeep(old); setCurrentFlowState(
newTabsState[id.current].formKeysData.input_keys![ (old: FlowState | undefined) => {
chatKey! let newFlowState = cloneDeep(old!);
] = value; newFlowState.formKeysData.input_keys![
return newTabsState; chatKey
}); ] = value;
return newFlowState;
}
);
}
}} }}
inputRef={ref} inputRef={ref}
/> />

View file

@ -1,20 +1,29 @@
import { create } from "zustand"; import { create } from "zustand";
import { FlowsManagerStoreType } from "../types/zustand/flowsManager";
import { FlowState } from "../types/tabs"; import { FlowState } from "../types/tabs";
import { FlowsManagerStoreType } from "../types/zustand/flowsManager";
const useFlowsManagerStore = create<FlowsManagerStoreType>((set, get) => ({ const useFlowsManagerStore = create<FlowsManagerStoreType>((set, get) => ({
currentFlowId: "", currentFlowId: "",
setCurrentFlowId: (currentFlowId: string) => { setCurrentFlowId: (currentFlowId: string) => {
set({ currentFlowId, currentFlow: get().flows.find((flow) => flow.id === currentFlowId) }); set((state) => ({
}, currentFlowId,
currentFlowState: state.flowsState[state.currentFlowId],
currentFlow: state.flows.find((flow) => flow.id === currentFlowId),
}));
},
flows: [], flows: [],
currentFlow: undefined, currentFlow: undefined,
isLoading: true, isLoading: true,
setIsLoading: (isLoading: boolean) => set({ isLoading }), setIsLoading: (isLoading: boolean) => set({ isLoading }),
flowsState: {}, flowsState: {},
currentFlowState: undefined, currentFlowState: undefined,
setCurrentFlowState: (flowState: FlowState | ((oldState: FlowState | undefined) => FlowState)) => { setCurrentFlowState: (
const newFlowState = typeof flowState === "function" ? flowState(get().currentFlowState) : flowState; flowState: FlowState | ((oldState: FlowState | undefined) => FlowState)
) => {
const newFlowState =
typeof flowState === "function"
? flowState(get().currentFlowState)
: flowState;
set((state) => ({ set((state) => ({
flowsState: { flowsState: {
...state.flowsState, ...state.flowsState,
@ -23,7 +32,6 @@ const useFlowsManagerStore = create<FlowsManagerStoreType>((set, get) => ({
currentFlowState: newFlowState, currentFlowState: newFlowState,
})); }));
}, },
})); }));
export default useFlowsManagerStore; export default useFlowsManagerStore;

View file

@ -59,7 +59,6 @@ export type FlowsState = {
}; };
export type FlowState = { export type FlowState = {
isPending: boolean;
formKeysData: { formKeysData: {
template?: string; template?: string;
input_keys?: Object; input_keys?: Object;

View file

@ -13,7 +13,7 @@ import {
tweakType, tweakType,
} from "../types/components"; } from "../types/components";
import { FlowType, NodeType } from "../types/flow"; import { FlowType, NodeType } from "../types/flow";
import { FlowsState } from "../types/tabs"; import { FlowState, FlowsState } from "../types/tabs";
import { buildTweaks } from "./reactflowUtils"; import { buildTweaks } from "./reactflowUtils";
export function classNames(...classes: Array<string>): string { export function classNames(...classes: Array<string>): string {
@ -217,13 +217,12 @@ export function groupByFamily(
})); }));
} }
export function buildInputs(tabsState: FlowsState, id: string): string { export function buildInputs(currentFlowState?: FlowState): string {
return tabsState && return currentFlowState &&
tabsState[id] && currentFlowState.formKeysData &&
tabsState[id].formKeysData && currentFlowState.formKeysData.input_keys &&
tabsState[id].formKeysData.input_keys && Object.keys(currentFlowState.formKeysData.input_keys!).length > 0
Object.keys(tabsState[id].formKeysData.input_keys!).length > 0 ? JSON.stringify(currentFlowState.formKeysData.input_keys)
? JSON.stringify(tabsState[id].formKeysData.input_keys)
: '{"input": "message"}'; : '{"input": "message"}';
} }
@ -298,17 +297,16 @@ 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, tabsState?: FlowsState) { export function getChatInputField(flow: FlowType, currentFlowState?: FlowState) {
let chat_input_field = "text"; let chat_input_field = "text";
if ( if (
tabsState && currentFlowState &&
tabsState[flow.id] && currentFlowState.formKeysData &&
tabsState[flow.id].formKeysData && currentFlowState.formKeysData.input_keys
tabsState[flow.id].formKeysData.input_keys
) { ) {
chat_input_field = Object.keys( chat_input_field = Object.keys(
tabsState[flow.id].formKeysData.input_keys! currentFlowState.formKeysData.input_keys!
)[0]; )[0];
} }
return chat_input_field; return chat_input_field;
@ -323,7 +321,7 @@ export function getPythonApiCode(
flow: FlowType, flow: FlowType,
isAuth: boolean, isAuth: boolean,
tweak?: any[], tweak?: any[],
tabsState?: FlowsState currentFlowState?: FlowState
): string { ): string {
const flowId = flow.id; const flowId = flow.id;
@ -332,7 +330,7 @@ export function getPythonApiCode(
// node.data.id // node.data.id
// } // }
const tweaks = buildTweaks(flow); const tweaks = buildTweaks(flow);
const inputs = buildInputs(tabsState!, flow.id); const inputs = buildInputs(currentFlowState);
return `import requests return `import requests
from typing import Optional from typing import Optional
@ -387,11 +385,11 @@ export function getCurlCode(
flow: FlowType, flow: FlowType,
isAuth: boolean, isAuth: boolean,
tweak?: any[], tweak?: any[],
tabsState?: FlowsState currentFlowState?: FlowState
): string { ): string {
const flowId = flow.id; const flowId = flow.id;
const tweaks = buildTweaks(flow); const tweaks = buildTweaks(flow);
const inputs = buildInputs(tabsState!, flow.id); const inputs = buildInputs(currentFlowState);
return `curl -X POST \\ return `curl -X POST \\
${window.location.protocol}//${ ${window.location.protocol}//${
@ -415,11 +413,11 @@ export function getCurlCode(
export function getPythonCode( export function getPythonCode(
flow: FlowType, flow: FlowType,
tweak?: any[], tweak?: any[],
tabsState?: FlowsState currentFlowState?: FlowState
): string { ): string {
const flowName = flow.name; const flowName = flow.name;
const tweaks = buildTweaks(flow); const tweaks = buildTweaks(flow);
const inputs = buildInputs(tabsState!, flow.id); const inputs = buildInputs(currentFlowState);
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
@ -440,12 +438,12 @@ flow(inputs)`;
export function getWidgetCode( export function getWidgetCode(
flow: FlowType, flow: FlowType,
isAuth: boolean, isAuth: boolean,
tabsState?: FlowsState currentFlowState?: FlowState
): string { ): string {
const flowId = flow.id; const flowId = flow.id;
const flowName = flow.name; const flowName = flow.name;
const inputs = buildInputs(tabsState!, flow.id); const inputs = buildInputs(currentFlowState);
let chat_input_field = getChatInputField(flow, tabsState); let chat_input_field = getChatInputField(flow, currentFlowState);
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>
@ -456,7 +454,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}"
${ ${
tabsState![flow.id] && tabsState![flow.id].formKeysData currentFlowState && currentFlowState.formKeysData
? `chat_inputs='${inputs}' ? `chat_inputs='${inputs}'
chat_input_field="${chat_input_field}" chat_input_field="${chat_input_field}"
` `