Refactor flowStore and flowIOStore

This commit is contained in:
anovazzi1 2024-01-23 17:56:37 -03:00
commit a755c8f44d
7 changed files with 86 additions and 71 deletions

View file

@ -0,0 +1,31 @@
import { Transition } from "@headlessui/react";
import IconComponent from "../../genericIconComponent";
export default function ChatTrigger({}): JSX.Element {
return (
<Transition
show={!open}
appear={true}
enter="transition ease-out duration-300"
enterFrom="translate-y-96"
enterTo="translate-y-0"
leave="transition ease-in duration-300"
leaveFrom="translate-y-0"
leaveTo="translate-y-96"
>
<button
className={
"shadow-round-btn-shadow hover:shadow-round-btn-shadow message-button cursor-pointer"
}
>
<div className="flex gap-3">
<IconComponent
name="MessagesSquare"
className={"message-button-icon h-6 w-6 transition-all"}
/>
</div>
</button>
</Transition>
);
}

View file

@ -14,12 +14,9 @@ import IconComponent from "../../genericIconComponent";
export default function BuildTrigger({ export default function BuildTrigger({
open, open,
flow, flow,
setIsBuilt,
}: { }: {
open: boolean; open: boolean;
flow: FlowType; flow: FlowType;
setIsBuilt: any;
isBuilt: boolean;
}): JSX.Element { }): JSX.Element {
const updateSSEData = useFlowStore((state) => state.updateSSEData); const updateSSEData = useFlowStore((state) => state.updateSSEData);
const isBuilding = useFlowStore((state) => state.isBuilding); const isBuilding = useFlowStore((state) => state.isBuilding);
@ -52,7 +49,6 @@ export default function BuildTrigger({
const allNodesValid = await streamNodeData(flow); const allNodesValid = await streamNodeData(flow);
await enforceMinimumLoadingTime(startTime, minimumLoadingTime); await enforceMinimumLoadingTime(startTime, minimumLoadingTime);
setIsBuilt(allNodesValid);
if (!allNodesValid) { if (!allNodesValid) {
setErrorData({ setErrorData({
title: "Oops! Looks like you missed something", title: "Oops! Looks like you missed something",

View file

@ -1,25 +1,27 @@
import { useEffect, useRef, useState } from "react"; import { useEffect, useRef, useState } from "react";
import { useNodes } from "reactflow"; import { useNodes } from "reactflow";
import { ChatType } from "../../types/chat"; import { CHAT_FORM_DIALOG_SUBTITLE } from "../../constants/constants";
import BuildTrigger from "./buildTrigger"; import BaseModal from "../../modals/baseModal";
import ChatTrigger from "./chatTrigger";
import * as _ from "lodash";
import FormModal from "../../modals/formModal";
import useFlowStore from "../../stores/flowStore"; import useFlowStore from "../../stores/flowStore";
import { ChatType } from "../../types/chat";
import { NodeType } from "../../types/flow"; import { NodeType } from "../../types/flow";
import IOView from "../IOview";
import ChatTrigger from "../ViewTriggers/chat";
import IconComponent from "../genericIconComponent";
import BuildTrigger from "./buildTrigger";
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 isBuilt = useFlowStore((state) => state.isBuilt);
const setIsBuilt = useFlowStore((state) => state.setIsBuilt);
const flowState = useFlowStore((state) => state.flowState); const flowState = useFlowStore((state) => state.flowState);
const checkInputAndOutput = useFlowStore(
(state) => state.checkInputAndOutput
);
useEffect(() => { useEffect(() => {
const handleKeyDown = (event: KeyboardEvent) => { const handleKeyDown = (event: KeyboardEvent) => {
if ( if (
(event.key === "K" || event.key === "k") && (event.key === "K" || event.key === "k") &&
(event.metaKey || event.ctrlKey) && (event.metaKey || event.ctrlKey) &&
isBuilt checkInputAndOutput()
) { ) {
event.preventDefault(); event.preventDefault();
setOpen((oldState) => !oldState); setOpen((oldState) => !oldState);
@ -29,39 +31,36 @@ export default function Chat({ flow }: ChatType): JSX.Element {
return () => { return () => {
document.removeEventListener("keydown", handleKeyDown); document.removeEventListener("keydown", handleKeyDown);
}; };
}, [isBuilt]); }, []);
const prevNodesRef = useRef<any[] | undefined>(); const prevNodesRef = useRef<any[] | undefined>();
const nodes: NodeType[] = useNodes(); const nodes: NodeType[] = useNodes();
useEffect(() => {
const prevNodes = prevNodesRef.current;
const currentNodes = nodes.map((node: NodeType) =>
_.cloneDeep(node.data.node?.template)
);
if (JSON.stringify(prevNodes) !== JSON.stringify(currentNodes)) {
setIsBuilt(false);
}
prevNodesRef.current = currentNodes;
}, [flowState, flow.id]);
return ( return (
<> <>
<div> <div className="flex flex-col">
<BuildTrigger <BuildTrigger open={open} flow={flow} />
open={open} {checkInputAndOutput() && (
flow={flow} <BaseModal open={open} setOpen={setOpen}>
setIsBuilt={setIsBuilt} <BaseModal.Trigger asChild>
isBuilt={isBuilt} <ChatTrigger />
/> </BaseModal.Trigger>
{isBuilt && flowState && !!flowState?.input_keys && ( {/* TODO ADAPT TO ALL TYPES OF INPUTS AND OUTPUTS */}
<FormModal key={flow.id} flow={flow} open={open} setOpen={setOpen} /> <BaseModal.Header description={CHAT_FORM_DIALOG_SUBTITLE}>
<div className="flex items-center">
<span className="pr-2">Chat</span>
<IconComponent
name="prompts"
className="h-6 w-6 pl-1 text-foreground"
aria-hidden="true"
/>
</div>
</BaseModal.Header>
<BaseModal.Content>
<IOView />
</BaseModal.Content>
</BaseModal>
)} )}
<ChatTrigger
canOpen={!!flowState?.input_keys}
open={open}
setOpen={setOpen}
isBuilt={isBuilt}
/>
</div> </div>
</> </>
); );

View file

@ -3,7 +3,6 @@ import { useEffect, useRef, useState } from "react";
import IconComponent from "../../components/genericIconComponent"; import IconComponent from "../../components/genericIconComponent";
import useAlertStore from "../../stores/alertStore"; import useAlertStore from "../../stores/alertStore";
import useFlowStore from "../../stores/flowStore"; import useFlowStore from "../../stores/flowStore";
import useFlowIOStore from "../../stores/flowsIOStore";
import { sendAllProps } from "../../types/api"; import { sendAllProps } from "../../types/api";
import { import {
ChatMessageType, ChatMessageType,
@ -19,16 +18,17 @@ import ChatMessage from "./chatMessage";
export default function newChatView(): JSX.Element { export default function newChatView(): JSX.Element {
const [chatValue, setChatValue] = useState(""); const [chatValue, setChatValue] = useState("");
const [chatHistory, setChatHistory] = useState<ChatMessageType[]>([]); const [chatHistory, setChatHistory] = useState<ChatMessageType[]>([]);
const { reactFlowInstance } = useFlowStore();
const { const {
flowPool, flowPool,
outputIds, outputIds,
inputIds, inputIds,
inputTypes, inputTypes,
updateNodeFlowData, getNode,
setNode,
buildFlow, buildFlow,
getFlow,
CleanFlowPool, CleanFlowPool,
} = useFlowIOStore(); } = useFlowStore();
const { setErrorData } = useAlertStore(); const { setErrorData } = useAlertStore();
const [lockChat, setLockChat] = useState(false); const [lockChat, setLockChat] = useState(false);
const messagesRef = useRef<HTMLDivElement | null>(null); const messagesRef = useRef<HTMLDivElement | null>(null);
@ -75,24 +75,19 @@ export default function newChatView(): JSX.Element {
}, []); }, []);
async function sendMessage(count = 1): Promise<void> { async function sendMessage(count = 1): Promise<void> {
let nodeValidationErrors = validateNodes( const { nodes, edges } = getFlow();
reactFlowInstance!.getNodes(), let nodeValidationErrors = validateNodes(nodes, edges);
reactFlowInstance!.getEdges()
);
if (nodeValidationErrors.length === 0) { if (nodeValidationErrors.length === 0) {
setLockChat(true); setLockChat(true);
setChatValue(""); setChatValue("");
const chatInputId = inputIds.find((inputId) => const chatInputId = inputIds.find((inputId) =>
inputId.includes("ChatInput") inputId.includes("ChatInput")
); );
const chatInput: NodeType = reactFlowInstance?.getNode( const chatInput: NodeType = getNode(chatInputId!) as NodeType;
chatInputId!
) as NodeType;
if (chatInput) { if (chatInput) {
let newData = cloneDeep(chatInput.data); let newNode = cloneDeep(chatInput);
newData.node!.template["message"].value = chatValue; newNode.data.node!.template["message"].value = chatValue;
chatInput.data = { ...newData }; setNode(chatInputId!, newNode);
updateNodeFlowData(chatInputId!, newData);
} }
for (let i = 0; i < count; i++) { for (let i = 0; i < count; i++) {
await buildFlow().catch((err) => { await buildFlow().catch((err) => {

View file

@ -157,7 +157,7 @@ const useFlowStore = create<FlowStoreType>((set, get) => ({
}) })
); );
}, },
checkInputandOutput: () => { checkInputAndOutput: () => {
let has_input = false; let has_input = false;
let has_output = false; let has_output = false;
const nodes = get().nodes; const nodes = get().nodes;
@ -427,6 +427,13 @@ const useFlowStore = create<FlowStoreType>((set, get) => ({
}, },
}); });
}, },
getFlow: () => {
return {
nodes: get().nodes,
edges: get().edges,
viewport: get().reactFlowInstance?.getViewport()!,
};
},
})); }));
export default useFlowStore; export default useFlowStore;

View file

@ -87,5 +87,7 @@ export type FlowStoreType = {
getFilterEdge: any[]; getFilterEdge: any[];
onConnect: (connection: Connection) => void; onConnect: (connection: Connection) => void;
unselectAll: () => void; unselectAll: () => void;
buildFlow: (nodeId?: string) => void; buildFlow: (nodeId?: string) => Promise<void>;
checkInputAndOutput: () => boolean;
getFlow: () => { nodes: Node[]; edges: Edge[]; viewport: Viewport };
}; };

View file

@ -1,5 +1,3 @@
import { FlowType, NodeType } from "../../flow";
export type chatInputType = { export type chatInputType = {
result: string; result: string;
}; };
@ -21,16 +19,3 @@ export type FlowPoolObjectType = {
export type FlowPoolType = { export type FlowPoolType = {
[key: string]: Array<FlowPoolObjectType>; [key: string]: Array<FlowPoolObjectType>;
}; };
export type flowIOStoreType = {
setOutputTypes: (outputTypes: string[]) => void;
setInputTypes: (inputTypes: string[]) => void;
setInputIds: (inputIds: string[]) => void;
setOutputIds: (outputIds: string[]) => void;
updateFlowPoolNodes: (nodes: NodeType[]) => void;
checkInputandOutput: (flow?: FlowType) => boolean;
getInputTypes: (flow?: FlowType) => string[];
getOutputTypes: (flow?: FlowType) => string[];
getInputIds: (flow?: FlowType) => string[];
getOutputIds: (flow?: FlowType) => string[];
};