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({
|
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",
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -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) => {
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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 };
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -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[];
|
|
||||||
};
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue