Fixed button
This commit is contained in:
parent
2913abb7bf
commit
db7f5c7582
2 changed files with 243 additions and 220 deletions
|
|
@ -1,7 +1,11 @@
|
||||||
|
import { cloneDeep } from "lodash";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { CHAT_FORM_DIALOG_SUBTITLE } from "../../constants/constants";
|
import { CHAT_FORM_DIALOG_SUBTITLE } from "../../constants/constants";
|
||||||
import BaseModal from "../../modals/baseModal";
|
import BaseModal from "../../modals/baseModal";
|
||||||
|
import useAlertStore from "../../stores/alertStore";
|
||||||
import useFlowStore from "../../stores/flowStore";
|
import useFlowStore from "../../stores/flowStore";
|
||||||
|
import { NodeType } from "../../types/flow";
|
||||||
|
import { validateNodes } from "../../utils/reactflowUtils";
|
||||||
import { cn } from "../../utils/utils";
|
import { cn } from "../../utils/utils";
|
||||||
import AccordionComponent from "../AccordionComponent";
|
import AccordionComponent from "../AccordionComponent";
|
||||||
import IOInputField from "../IOInputField";
|
import IOInputField from "../IOInputField";
|
||||||
|
|
@ -26,9 +30,13 @@ export default function IOView({ children, open, setOpen }): JSX.Element {
|
||||||
node.type !== "ChatInput" &&
|
node.type !== "ChatInput" &&
|
||||||
node.type !== "ChatOutput"
|
node.type !== "ChatOutput"
|
||||||
);
|
);
|
||||||
const haveChat = useFlowStore((state) => state.outputs).some(
|
const haveChat =
|
||||||
(output) => output.type === "ChatOutput" || output.type === "ChatInput"
|
useFlowStore((state) => state.outputs).some(
|
||||||
);
|
(output) => output.type === "ChatOutput"
|
||||||
|
) ||
|
||||||
|
useFlowStore((state) => state.inputs).some(
|
||||||
|
(input) => input.type === "ChatInput"
|
||||||
|
);
|
||||||
const [selectedTab, setSelectedTab] = useState(
|
const [selectedTab, setSelectedTab] = useState(
|
||||||
inputs.length > 0 ? 1 : outputs.length > 0 ? 2 : 0
|
inputs.length > 0 ? 1 : outputs.length > 0 ? 2 : 0
|
||||||
);
|
);
|
||||||
|
|
@ -36,6 +44,48 @@ export default function IOView({ children, open, setOpen }): JSX.Element {
|
||||||
{ type: string; id: string } | undefined
|
{ type: string; id: string } | undefined
|
||||||
>(undefined);
|
>(undefined);
|
||||||
|
|
||||||
|
const { getNode, setNode, buildFlow, getFlow } = useFlowStore();
|
||||||
|
const { setErrorData } = useAlertStore();
|
||||||
|
const setIsBuilding = useFlowStore((state) => state.setIsBuilding);
|
||||||
|
const [lockChat, setLockChat] = useState(false);
|
||||||
|
const [chatValue, setChatValue] = useState("");
|
||||||
|
const isBuilding = useFlowStore((state) => state.isBuilding);
|
||||||
|
|
||||||
|
async function sendMessage(count = 1): Promise<void> {
|
||||||
|
if (isBuilding) return;
|
||||||
|
const { nodes, edges } = getFlow();
|
||||||
|
let nodeValidationErrors = validateNodes(nodes, edges);
|
||||||
|
if (nodeValidationErrors.length === 0) {
|
||||||
|
setIsBuilding(true);
|
||||||
|
setLockChat(true);
|
||||||
|
setChatValue("");
|
||||||
|
const chatInputId = inputs
|
||||||
|
.map((obj) => obj.id)
|
||||||
|
.find((inputId) => inputId.includes("ChatInput"));
|
||||||
|
const chatInput: NodeType = getNode(chatInputId!) as NodeType;
|
||||||
|
if (chatInput) {
|
||||||
|
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) => {
|
||||||
|
console.error(err);
|
||||||
|
setLockChat(false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
setLockChat(false);
|
||||||
|
|
||||||
|
//set chat message in the flow and run build
|
||||||
|
//@ts-ignore
|
||||||
|
} else {
|
||||||
|
setErrorData({
|
||||||
|
title: "Oops! Looks like you missed some required information:",
|
||||||
|
list: nodeValidationErrors,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setSelectedViewField(undefined);
|
setSelectedViewField(undefined);
|
||||||
setSelectedTab(inputs.length > 0 ? 1 : outputs.length > 0 ? 2 : 0);
|
setSelectedTab(inputs.length > 0 ? 1 : outputs.length > 0 ? 2 : 0);
|
||||||
|
|
@ -60,178 +110,194 @@ export default function IOView({ children, open, setOpen }): JSX.Element {
|
||||||
</div>
|
</div>
|
||||||
</BaseModal.Header>
|
</BaseModal.Header>
|
||||||
<BaseModal.Content>
|
<BaseModal.Content>
|
||||||
<div className="flex-max-width mt-2 h-[80vh]">
|
<div className="flex h-full flex-col">
|
||||||
{selectedTab !== 0 && (
|
<div className="flex-max-width mt-2 h-full">
|
||||||
<div
|
{selectedTab !== 0 && (
|
||||||
className={cn(
|
<div
|
||||||
"mr-6 flex h-full w-2/6 flex-shrink-0 flex-col justify-start overflow-auto scrollbar-hide",
|
className={cn(
|
||||||
haveChat ? "w-2/6" : "w-full"
|
"mr-6 flex h-full w-2/6 flex-shrink-0 flex-col justify-start overflow-auto scrollbar-hide",
|
||||||
)}
|
haveChat ? "w-2/6" : "w-full"
|
||||||
>
|
)}
|
||||||
<Tabs
|
|
||||||
value={selectedTab.toString()}
|
|
||||||
className={"api-modal-tabs "}
|
|
||||||
onValueChange={(value) => {
|
|
||||||
setSelectedTab(Number(value));
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
<div className="api-modal-tablist-div">
|
<Tabs
|
||||||
<TabsList>
|
value={selectedTab.toString()}
|
||||||
{inputs.length > 0 && (
|
className={
|
||||||
<TabsTrigger value={"1"}>Inputs</TabsTrigger>
|
"flex h-full flex-col overflow-hidden rounded-md border bg-muted text-center"
|
||||||
)}
|
}
|
||||||
{outputs.length > 0 && (
|
onValueChange={(value) => {
|
||||||
<TabsTrigger value={"2"}>Outputs</TabsTrigger>
|
setSelectedTab(Number(value));
|
||||||
)}
|
}}
|
||||||
</TabsList>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<TabsContent
|
|
||||||
value={"1"}
|
|
||||||
className="api-modal-tabs-content mt-4"
|
|
||||||
>
|
>
|
||||||
<div className="mx-2 mb-2 flex items-center gap-2 text-sm font-bold">
|
<div className="api-modal-tablist-div">
|
||||||
<IconComponent className="h-4 w-4" name={"Type"} />
|
<TabsList>
|
||||||
Text Inputs
|
{inputs.length > 0 && (
|
||||||
|
<TabsTrigger value={"1"}>Inputs</TabsTrigger>
|
||||||
|
)}
|
||||||
|
{outputs.length > 0 && (
|
||||||
|
<TabsTrigger value={"2"}>Outputs</TabsTrigger>
|
||||||
|
)}
|
||||||
|
</TabsList>
|
||||||
</div>
|
</div>
|
||||||
{nodes
|
|
||||||
.filter((node) =>
|
|
||||||
inputs.some((input) => input.id === node.id)
|
|
||||||
)
|
|
||||||
.map((node, index) => {
|
|
||||||
const input = inputs.find(
|
|
||||||
(input) => input.id === node.id
|
|
||||||
)!;
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
className="file-component-accordion-div"
|
|
||||||
key={index}
|
|
||||||
>
|
|
||||||
<AccordionComponent
|
|
||||||
trigger={
|
|
||||||
<div className="file-component-badge-div">
|
|
||||||
<Badge variant="gray" size="md">
|
|
||||||
{input.id}
|
|
||||||
</Badge>
|
|
||||||
{haveChat && (
|
|
||||||
<div
|
|
||||||
className="-mb-1 pr-4"
|
|
||||||
onClick={(event) => {
|
|
||||||
event.stopPropagation();
|
|
||||||
setSelectedViewField(input);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<IconComponent
|
|
||||||
className="h-4 w-4"
|
|
||||||
name="ExternalLink"
|
|
||||||
></IconComponent>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
key={index}
|
|
||||||
keyValue={input.id}
|
|
||||||
>
|
|
||||||
<div className="file-component-tab-column">
|
|
||||||
<div className="">
|
|
||||||
{input && (
|
|
||||||
<IOInputField
|
|
||||||
inputType={input.type}
|
|
||||||
inputId={input.id}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</AccordionComponent>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</TabsContent>
|
|
||||||
<TabsContent
|
|
||||||
value={"2"}
|
|
||||||
className="api-modal-tabs-content mt-4"
|
|
||||||
>
|
|
||||||
<div className="mx-2 mb-2 flex items-center gap-2 text-sm font-bold">
|
|
||||||
<IconComponent className="h-4 w-4" name={"Braces"} />
|
|
||||||
Prompt Outputs
|
|
||||||
</div>
|
|
||||||
{nodes
|
|
||||||
.filter((node) =>
|
|
||||||
outputs.some((output) => output.id === node.id)
|
|
||||||
)
|
|
||||||
.map((node, index) => {
|
|
||||||
const output = outputs.find(
|
|
||||||
(output) => output.id === node.id
|
|
||||||
)!;
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
className="file-component-accordion-div"
|
|
||||||
key={index}
|
|
||||||
>
|
|
||||||
<AccordionComponent
|
|
||||||
trigger={
|
|
||||||
<div className="file-component-badge-div">
|
|
||||||
<Badge variant="gray" size="md">
|
|
||||||
{output.id}
|
|
||||||
</Badge>
|
|
||||||
{haveChat && (
|
|
||||||
<div
|
|
||||||
className="-mb-1 pr-4"
|
|
||||||
onClick={(event) => {
|
|
||||||
event.stopPropagation();
|
|
||||||
setSelectedViewField(output);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<IconComponent
|
|
||||||
className="h-4 w-4"
|
|
||||||
name="ExternalLink"
|
|
||||||
></IconComponent>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
key={index}
|
|
||||||
keyValue={output.id}
|
|
||||||
>
|
|
||||||
<div className="file-component-tab-column">
|
|
||||||
<div className="">
|
|
||||||
{output && (
|
|
||||||
<IOOutputView
|
|
||||||
outputType={output.type}
|
|
||||||
outputId={output.id}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</AccordionComponent>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</TabsContent>
|
|
||||||
</Tabs>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{haveChat ? (
|
<TabsContent
|
||||||
selectedViewField ? (
|
value={"1"}
|
||||||
inputs.some((input) => input.id === selectedViewField.id) ? (
|
className="api-modal-tabs-content mt-4"
|
||||||
<IOInputField
|
>
|
||||||
inputType={selectedViewField.type!}
|
<div className="mx-2 mb-2 flex items-center gap-2 text-sm font-bold">
|
||||||
inputId={selectedViewField.id!}
|
<IconComponent className="h-4 w-4" name={"Type"} />
|
||||||
/>
|
Text Inputs
|
||||||
|
</div>
|
||||||
|
{nodes
|
||||||
|
.filter((node) =>
|
||||||
|
inputs.some((input) => input.id === node.id)
|
||||||
|
)
|
||||||
|
.map((node, index) => {
|
||||||
|
const input = inputs.find(
|
||||||
|
(input) => input.id === node.id
|
||||||
|
)!;
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className="file-component-accordion-div"
|
||||||
|
key={index}
|
||||||
|
>
|
||||||
|
<AccordionComponent
|
||||||
|
trigger={
|
||||||
|
<div className="file-component-badge-div">
|
||||||
|
<Badge variant="gray" size="md">
|
||||||
|
{input.id}
|
||||||
|
</Badge>
|
||||||
|
{haveChat && (
|
||||||
|
<div
|
||||||
|
className="-mb-1 pr-4"
|
||||||
|
onClick={(event) => {
|
||||||
|
event.stopPropagation();
|
||||||
|
setSelectedViewField(input);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<IconComponent
|
||||||
|
className="h-4 w-4"
|
||||||
|
name="ExternalLink"
|
||||||
|
></IconComponent>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
key={index}
|
||||||
|
keyValue={input.id}
|
||||||
|
>
|
||||||
|
<div className="file-component-tab-column">
|
||||||
|
<div className="">
|
||||||
|
{input && (
|
||||||
|
<IOInputField
|
||||||
|
inputType={input.type}
|
||||||
|
inputId={input.id}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</AccordionComponent>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</TabsContent>
|
||||||
|
<TabsContent
|
||||||
|
value={"2"}
|
||||||
|
className="api-modal-tabs-content mt-4"
|
||||||
|
>
|
||||||
|
<div className="mx-2 mb-2 flex items-center gap-2 text-sm font-bold">
|
||||||
|
<IconComponent className="h-4 w-4" name={"Braces"} />
|
||||||
|
Prompt Outputs
|
||||||
|
</div>
|
||||||
|
{nodes
|
||||||
|
.filter((node) =>
|
||||||
|
outputs.some((output) => output.id === node.id)
|
||||||
|
)
|
||||||
|
.map((node, index) => {
|
||||||
|
const output = outputs.find(
|
||||||
|
(output) => output.id === node.id
|
||||||
|
)!;
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className="file-component-accordion-div"
|
||||||
|
key={index}
|
||||||
|
>
|
||||||
|
<AccordionComponent
|
||||||
|
trigger={
|
||||||
|
<div className="file-component-badge-div">
|
||||||
|
<Badge variant="gray" size="md">
|
||||||
|
{output.id}
|
||||||
|
</Badge>
|
||||||
|
{haveChat && (
|
||||||
|
<div
|
||||||
|
className="-mb-1 pr-4"
|
||||||
|
onClick={(event) => {
|
||||||
|
event.stopPropagation();
|
||||||
|
setSelectedViewField(output);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<IconComponent
|
||||||
|
className="h-4 w-4"
|
||||||
|
name="ExternalLink"
|
||||||
|
></IconComponent>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
key={index}
|
||||||
|
keyValue={output.id}
|
||||||
|
>
|
||||||
|
<div className="file-component-tab-column">
|
||||||
|
<div className="">
|
||||||
|
{output && (
|
||||||
|
<IOOutputView
|
||||||
|
outputType={output.type}
|
||||||
|
outputId={output.id}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</AccordionComponent>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</TabsContent>
|
||||||
|
</Tabs>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{haveChat ? (
|
||||||
|
selectedViewField ? (
|
||||||
|
inputs.some((input) => input.id === selectedViewField.id) ? (
|
||||||
|
<IOInputField
|
||||||
|
inputType={selectedViewField.type!}
|
||||||
|
inputId={selectedViewField.id!}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<IOOutputView
|
||||||
|
outputType={selectedViewField.type!}
|
||||||
|
outputId={selectedViewField.id!}
|
||||||
|
/>
|
||||||
|
)
|
||||||
) : (
|
) : (
|
||||||
<IOOutputView
|
<NewChatView
|
||||||
outputType={selectedViewField.type!}
|
sendMessage={sendMessage}
|
||||||
outputId={selectedViewField.id!}
|
chatValue={chatValue}
|
||||||
|
setChatValue={setChatValue}
|
||||||
|
lockChat={lockChat}
|
||||||
|
setLockChat={setLockChat}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
) : (
|
) : (
|
||||||
<NewChatView />
|
<div className="absolute bottom-8 right-8"></div>
|
||||||
)
|
)}
|
||||||
) : (
|
</div>
|
||||||
<div className="absolute bottom-8 right-8">
|
{!haveChat && (
|
||||||
<Button className="px-3">
|
<div className="flex w-full justify-end pt-6">
|
||||||
<IconComponent name="Play" className="h-6 w-6" />
|
<Button className="px-3" onClick={() => sendMessage(1)}>
|
||||||
|
<IconComponent
|
||||||
|
name={isBuilding ? "Loader2" : "Play"}
|
||||||
|
className={cn("h-6 w-6", isBuilding ? "animate-spin" : "")}
|
||||||
|
/>
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import _, { cloneDeep } from "lodash";
|
import _ from "lodash";
|
||||||
import { useEffect, useRef, useState } from "react";
|
import { useEffect, useRef, useState } from "react";
|
||||||
import IconComponent from "../../components/genericIconComponent";
|
import IconComponent from "../../components/genericIconComponent";
|
||||||
import { deleteFlowPool } from "../../controllers/API";
|
import { deleteFlowPool } from "../../controllers/API";
|
||||||
|
|
@ -11,30 +11,21 @@ import {
|
||||||
ChatOutputType,
|
ChatOutputType,
|
||||||
FlowPoolObjectType,
|
FlowPoolObjectType,
|
||||||
} from "../../types/chat";
|
} from "../../types/chat";
|
||||||
import { NodeType } from "../../types/flow";
|
|
||||||
import { validateNodes } from "../../utils/reactflowUtils";
|
|
||||||
import { classNames } from "../../utils/utils";
|
import { classNames } from "../../utils/utils";
|
||||||
import ChatInput from "./chatInput";
|
import ChatInput from "./chatInput";
|
||||||
import ChatMessage from "./chatMessage";
|
import ChatMessage from "./chatMessage";
|
||||||
|
|
||||||
export default function NewChatView(): JSX.Element {
|
export default function NewChatView({
|
||||||
const [chatValue, setChatValue] = useState("");
|
sendMessage,
|
||||||
const {
|
chatValue,
|
||||||
flowPool,
|
setChatValue,
|
||||||
outputs,
|
lockChat,
|
||||||
inputs,
|
setLockChat,
|
||||||
getNode,
|
}): JSX.Element {
|
||||||
setNode,
|
const { flowPool, outputs, inputs, CleanFlowPool } = useFlowStore();
|
||||||
buildFlow,
|
const { setNoticeData } = useAlertStore();
|
||||||
getFlow,
|
|
||||||
CleanFlowPool,
|
|
||||||
} = useFlowStore();
|
|
||||||
const { setErrorData, setNoticeData } = useAlertStore();
|
|
||||||
const currentFlowId = useFlowsManagerStore((state) => state.currentFlowId);
|
const currentFlowId = useFlowsManagerStore((state) => state.currentFlowId);
|
||||||
const setIsBuilding = useFlowStore((state) => state.setIsBuilding);
|
|
||||||
const [lockChat, setLockChat] = useState(false);
|
|
||||||
const messagesRef = useRef<HTMLDivElement | null>(null);
|
const messagesRef = useRef<HTMLDivElement | null>(null);
|
||||||
const isBuilding = useFlowStore((state) => state.isBuilding);
|
|
||||||
const [chatHistory, setChatHistory] = useState<ChatMessageType[]>([]);
|
const [chatHistory, setChatHistory] = useState<ChatMessageType[]>([]);
|
||||||
|
|
||||||
const inputTypes = inputs.map((obj) => obj.type);
|
const inputTypes = inputs.map((obj) => obj.type);
|
||||||
|
|
@ -115,40 +106,6 @@ export default function NewChatView(): JSX.Element {
|
||||||
}
|
}
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
async function sendMessage(count = 1): Promise<void> {
|
|
||||||
if (isBuilding) return;
|
|
||||||
const { nodes, edges } = getFlow();
|
|
||||||
let nodeValidationErrors = validateNodes(nodes, edges);
|
|
||||||
if (nodeValidationErrors.length === 0) {
|
|
||||||
setIsBuilding(true);
|
|
||||||
setLockChat(true);
|
|
||||||
setChatValue("");
|
|
||||||
const chatInputId = inputIds.find((inputId) =>
|
|
||||||
inputId.includes("ChatInput")
|
|
||||||
);
|
|
||||||
const chatInput: NodeType = getNode(chatInputId!) as NodeType;
|
|
||||||
if (chatInput) {
|
|
||||||
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) => {
|
|
||||||
console.error(err);
|
|
||||||
setLockChat(false);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
setLockChat(false);
|
|
||||||
|
|
||||||
//set chat message in the flow and run build
|
|
||||||
//@ts-ignore
|
|
||||||
} else {
|
|
||||||
setErrorData({
|
|
||||||
title: "Oops! Looks like you missed some required information:",
|
|
||||||
list: nodeValidationErrors,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
function clearChat(): void {
|
function clearChat(): void {
|
||||||
setChatHistory([]);
|
setChatHistory([]);
|
||||||
deleteFlowPool(currentFlowId).then((_) => {
|
deleteFlowPool(currentFlowId).then((_) => {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue