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

View file

@ -1,25 +1,27 @@
import { useEffect, useRef, useState } from "react";
import { useNodes } from "reactflow";
import { ChatType } from "../../types/chat";
import BuildTrigger from "./buildTrigger";
import ChatTrigger from "./chatTrigger";
import * as _ from "lodash";
import FormModal from "../../modals/formModal";
import { CHAT_FORM_DIALOG_SUBTITLE } from "../../constants/constants";
import BaseModal from "../../modals/baseModal";
import useFlowStore from "../../stores/flowStore";
import { ChatType } from "../../types/chat";
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 {
const [open, setOpen] = useState(false);
const isBuilt = useFlowStore((state) => state.isBuilt);
const setIsBuilt = useFlowStore((state) => state.setIsBuilt);
const flowState = useFlowStore((state) => state.flowState);
const checkInputAndOutput = useFlowStore(
(state) => state.checkInputAndOutput
);
useEffect(() => {
const handleKeyDown = (event: KeyboardEvent) => {
if (
(event.key === "K" || event.key === "k") &&
(event.metaKey || event.ctrlKey) &&
isBuilt
checkInputAndOutput()
) {
event.preventDefault();
setOpen((oldState) => !oldState);
@ -29,39 +31,36 @@ export default function Chat({ flow }: ChatType): JSX.Element {
return () => {
document.removeEventListener("keydown", handleKeyDown);
};
}, [isBuilt]);
}, []);
const prevNodesRef = useRef<any[] | undefined>();
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 (
<>
<div>
<BuildTrigger
open={open}
flow={flow}
setIsBuilt={setIsBuilt}
isBuilt={isBuilt}
/>
{isBuilt && flowState && !!flowState?.input_keys && (
<FormModal key={flow.id} flow={flow} open={open} setOpen={setOpen} />
<div className="flex flex-col">
<BuildTrigger open={open} flow={flow} />
{checkInputAndOutput() && (
<BaseModal open={open} setOpen={setOpen}>
<BaseModal.Trigger asChild>
<ChatTrigger />
</BaseModal.Trigger>
{/* TODO ADAPT TO ALL TYPES OF INPUTS AND OUTPUTS */}
<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>
</>
);

View file

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

View file

@ -157,7 +157,7 @@ const useFlowStore = create<FlowStoreType>((set, get) => ({
})
);
},
checkInputandOutput: () => {
checkInputAndOutput: () => {
let has_input = false;
let has_output = false;
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;

View file

@ -87,5 +87,7 @@ export type FlowStoreType = {
getFilterEdge: any[];
onConnect: (connection: Connection) => 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 = {
result: string;
};
@ -21,16 +19,3 @@ export type FlowPoolObjectType = {
export type FlowPoolType = {
[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[];
};