Refactor flowStore and flowIOStore
This commit is contained in:
parent
2b62f903a3
commit
a755c8f44d
7 changed files with 86 additions and 71 deletions
31
src/frontend/src/components/ViewTriggers/chat/index.tsx
Normal file
31
src/frontend/src/components/ViewTriggers/chat/index.tsx
Normal 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>
|
||||
);
|
||||
}
|
||||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
</>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -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) => {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 };
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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[];
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue