Refactored just logic of IOView

This commit is contained in:
Lucas Oliveira 2024-02-23 22:00:53 +01:00
commit d192b50f76
3 changed files with 105 additions and 121 deletions

View file

@ -1,9 +1,7 @@
import { ReactNode, useState } from "react"; import { 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 useFlowStore from "../../stores/flowStore"; import useFlowStore from "../../stores/flowStore";
import { NodeType } from "../../types/flow";
import { isInputType, isOutputType } 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";
@ -14,60 +12,32 @@ import { Badge } from "../ui/badge";
import { Button } from "../ui/button"; import { Button } from "../ui/button";
export default function IOView({ children, open, setOpen }): JSX.Element { export default function IOView({ children, open, setOpen }): JSX.Element {
const inputs = useFlowStore((state) => state.inputs); const inputs = useFlowStore((state) => state.inputs).filter(
const outputs = useFlowStore((state) => state.outputs); (input) => input.type !== "ChatInput"
const inputIds = inputs.map((obj) => obj.id); );
const outputIds = outputs.map((obj) => obj.id); const outputs = useFlowStore((state) => state.outputs).filter(
const nodes = useFlowStore((state) => state.nodes); (output) => output.type !== "ChatOutput"
const setNode = useFlowStore((state) => state.setNode); );
const categories = getCategories(); const nodes = useFlowStore((state) => state.nodes).filter(
const [selectedCategory, setSelectedCategory] = useState<number>(0); (node) =>
const [showChat, setShowChat] = useState<boolean>(false); (inputs.some((input) => input.id === node.id) ||
const [selectedView, setSelectedView] = useState<{ outputs.some((output) => output.id === node.id)) &&
type: string; node.type !== "ChatInput" &&
id?: string; node.type !== "ChatOutput"
}>(handleInitialView()); );
const haveChat = useFlowStore((state) => state.outputs).some(
type CategoriesType = { name: string; icon: string }; (output) => output.type === "ChatOutput"
);
function handleInitialView() { const [selectedTab, setSelectedTab] = useState(
if ( inputs.length > 0 ? 1 : outputs.length > 0 ? 2 : 0
outputs.map((output) => output.type).includes("ChatOutput") || );
inputs.map((input) => input.type).includes("ChatInput") const [selectedViewField, setSelectedViewField] = useState<
) { { type: string; id: string } | undefined
return { type: "ChatOutput" }; >(undefined);
}
return { type: "" };
}
function getCategories() {
const categories: CategoriesType[] = [];
if (inputs.filter((input) => input.type !== "ChatInput").length > 0)
categories.push({ name: "Inputs", icon: "TextCursorInput" });
if (outputs.filter((output) => output.type !== "ChatOutput").length > 0)
categories.push({ name: "Outputs", icon: "TerminalSquare" });
return categories;
}
function handleSelectChange(): ReactNode {
const { type, id } = selectedView;
if (type === "ChatOutput") return <NewChatView />;
if (isInputType(type))
return <IOInputField inputId={id!} inputType={type} />;
if (isOutputType(type))
return <IOOutputView outputId={id!} outputType={type} />;
else return undefined;
}
function UpdateAccordion() {
return (categories[selectedCategory]?.name ?? "Inputs") === "Inputs"
? inputs
: outputs;
}
return ( return (
<BaseModal <BaseModal
size={handleSelectChange() ? "large" : "small"} size={haveChat ? "large" : "small"}
open={open} open={open}
setOpen={setOpen} setOpen={setOpen}
> >
@ -88,71 +58,72 @@ export default function IOView({ children, open, setOpen }): JSX.Element {
<div <div
className={cn( className={cn(
"mr-6 flex h-full w-2/6 flex-col justify-start overflow-auto scrollbar-hide", "mr-6 flex h-full w-2/6 flex-col justify-start overflow-auto scrollbar-hide",
handleSelectChange() ? "w-2/6" : "w-full" haveChat ? "w-2/6" : "w-full"
)} )}
> >
<div className="flex w-full items-center justify-between py-2"> <div className="flex w-full items-center justify-between py-2">
<div className="flex items-start gap-4"> <div className="flex items-start gap-4">
{categories.map((category, index) => {
return (
//hide chat button if chat is alredy on the view
<Button <Button
onClick={() => setSelectedCategory(index)} onClick={() => setSelectedTab(1)}
variant={ variant={selectedTab === 1 ? "primary" : "secondary"}
index === selectedCategory ? "primary" : "secondary"
}
key={index}
> >
<IconComponent <IconComponent
name={category.icon} name="FormInput"
className=" file-component-variable" className=" file-component-variable"
/> />
<span className="file-component-variables-span text-md"> <span className="file-component-variables-span text-md">
{category.name} Inputs
</span> </span>
</Button> </Button>
);
})}
</div>
{(outputs.map((output) => output.type).includes("ChatOutput") ||
inputs.map((output) => output.type).includes("chatInput")) &&
selectedView.type !== "ChatOutput" && (
<Button <Button
onClick={() => setSelectedView({ type: "ChatOutput" })} onClick={() => setSelectedTab(2)}
variant={selectedTab === 2 ? "primary" : "secondary"}
>
<IconComponent
name="ChevronRightSquare"
className=" file-component-variable"
/>
<span className="file-component-variables-span text-md">
Outputs
</span>
</Button>
</div>
{selectedViewField && haveChat && (
<Button
onClick={() => setSelectedViewField(undefined)}
variant="outline" variant="outline"
key={"chat"} key={"chat"}
className="self-end px-2.5" className="self-end px-2.5"
> >
<IconComponent <IconComponent name="MessageSquareMore" className="h-5 w-5" />
name="MessageSquareMore"
className="h-5 w-5"
/>
</Button> </Button>
)} )}
</div> </div>
<div className="mx-2 mb-2 mt-4 flex items-center gap-2 font-semibold"> <div className="mx-2 mb-2 mt-4 flex items-center gap-2 font-semibold">
{categories[selectedCategory]?.name === "Inputs" && ( {selectedTab === 1 && (
<> <>
<IconComponent name={"FormInput"} /> <IconComponent name={"FormInput"} />
Text Inputs Text Inputs
</> </>
)} )}
{categories[selectedCategory]?.name === "Outputs" && ( {selectedTab === 2 && (
<> <>
<IconComponent name={"ChevronRightSquare"} /> <IconComponent name={"ChevronRightSquare"} />
Prompt Outputs Prompt Outputs
</> </>
)} )}
</div> </div>
{UpdateAccordion() {nodes
.filter( .filter((node) =>
(input) => selectedTab === 1
input.type !== "ChatInput" && input.type !== "ChatOutput" ? inputs.some((input) => input.id === node.id)
: outputs.some((output) => output.id === node.id)
) )
.map((input, index) => { .map((node, index) => {
const node: NodeType = nodes.find( const input =
(node) => node.id === input.id selectedTab === 1
)!; ? inputs.find((input) => input.id === node.id)!
: outputs.find((output) => output.id === node.id)!;
return ( return (
<div className="file-component-accordion-div" key={index}> <div className="file-component-accordion-div" key={index}>
<AccordionComponent <AccordionComponent
@ -161,14 +132,12 @@ export default function IOView({ children, open, setOpen }): JSX.Element {
<Badge variant="gray" size="md"> <Badge variant="gray" size="md">
{input.id} {input.id}
</Badge> </Badge>
{haveChat && (
<div <div
className="-mb-1 pr-4" className="-mb-1 pr-4"
onClick={(event) => { onClick={(event) => {
event.stopPropagation(); event.stopPropagation();
setSelectedView({ setSelectedViewField(input);
type: input.type,
id: input.id,
});
}} }}
> >
<IconComponent <IconComponent
@ -176,6 +145,7 @@ export default function IOView({ children, open, setOpen }): JSX.Element {
name="ExternalLink" name="ExternalLink"
></IconComponent> ></IconComponent>
</div> </div>
)}
</div> </div>
} }
key={index} key={index}
@ -183,8 +153,8 @@ export default function IOView({ children, open, setOpen }): JSX.Element {
> >
<div className="file-component-tab-column"> <div className="file-component-tab-column">
<div className=""> <div className="">
{node && {input &&
(categories[selectedCategory]?.name === "Inputs" ? ( (selectedTab === 1 ? (
<IOInputField <IOInputField
inputType={input.type} inputType={input.type}
inputId={input.id} inputId={input.id}
@ -202,8 +172,22 @@ export default function IOView({ children, open, setOpen }): JSX.Element {
); );
})} })}
</div> </div>
{handleSelectChange() ? ( {haveChat ? (
handleSelectChange() selectedViewField ? (
inputs.some((input) => input.id === selectedViewField.id) ? (
<IOInputField
inputType={selectedViewField.type!}
inputId={selectedViewField.id!}
/>
) : (
<IOOutputView
outputType={selectedViewField.type!}
outputId={selectedViewField.id!}
/>
)
) : (
<NewChatView />
)
) : ( ) : (
<div className="absolute bottom-8 right-8"> <div className="absolute bottom-8 right-8">
<Button className="px-3"> <Button className="px-3">

View file

@ -17,7 +17,7 @@ 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(): JSX.Element {
const [chatValue, setChatValue] = useState(""); const [chatValue, setChatValue] = useState("");
const [chatHistory, setChatHistory] = useState<ChatMessageType[]>([]); const [chatHistory, setChatHistory] = useState<ChatMessageType[]>([]);
const { const {

View file

@ -681,4 +681,4 @@ export const LANGFLOW_SUPPORTED_TYPES = new Set([
export const priorityFields = new Set(["code", "template"]); export const priorityFields = new Set(["code", "template"]);
export const INPUT_TYPES = new Set(["ChatInput", "TextInput"]); export const INPUT_TYPES = new Set(["ChatInput", "TextInput"]);
export const OUTPUT_TYPES = new Set(["ChatOutput"]); export const OUTPUT_TYPES = new Set(["ChatOutput", "PromptTemplate"]);