Merge branch 'zustand/io/migration' into cz/fixTestsIo
This commit is contained in:
commit
6b2409643d
117 changed files with 2999 additions and 2224 deletions
|
|
@ -19,6 +19,8 @@ import { Button } from "../../../../components/ui/button";
|
|||
import {
|
||||
LANGFLOW_SUPPORTED_TYPES,
|
||||
TOOLTIP_EMPTY,
|
||||
inputHandleHover,
|
||||
outputHandleHover,
|
||||
} from "../../../../constants/constants";
|
||||
import { postCustomComponentUpdate } from "../../../../controllers/API";
|
||||
import useAlertStore from "../../../../stores/alertStore";
|
||||
|
|
@ -182,8 +184,8 @@ export default function ParameterComponent({
|
|||
{index === 0 && (
|
||||
<span>
|
||||
{left
|
||||
? "Avaliable input components:"
|
||||
: "Avaliable output components:"}
|
||||
? inputHandleHover
|
||||
: outputHandleHover}
|
||||
</span>
|
||||
)}
|
||||
<span
|
||||
|
|
@ -265,7 +267,7 @@ export default function ParameterComponent({
|
|||
<div className="flex">
|
||||
<ShadTooltip
|
||||
styleClasses={"tooltip-fixed-width custom-scroll nowheel"}
|
||||
delayDuration={0}
|
||||
delayDuration={1000}
|
||||
content={refHtml.current}
|
||||
side={left ? "left" : "right"}
|
||||
>
|
||||
|
|
|
|||
|
|
@ -8,7 +8,11 @@ import Checkmark from "../../components/ui/checkmark";
|
|||
import Loading from "../../components/ui/loading";
|
||||
import { Textarea } from "../../components/ui/textarea";
|
||||
import Xmark from "../../components/ui/xmark";
|
||||
import { priorityFields } from "../../constants/constants";
|
||||
import {
|
||||
priorityFields,
|
||||
statusBuild,
|
||||
statusBuilding,
|
||||
} from "../../constants/constants";
|
||||
import { BuildStatus } from "../../constants/enums";
|
||||
import NodeToolbarComponent from "../../pages/FlowPage/components/nodeToolbarComponent";
|
||||
import { useDarkStore } from "../../stores/darkStore";
|
||||
|
|
@ -135,7 +139,7 @@ export default function GenericNode({
|
|||
const iconName =
|
||||
iconElement || (data.node?.flow ? "group_components" : name);
|
||||
const iconClassName = `generic-node-icon ${
|
||||
!showNode ? "absolute inset-x-6 h-12 w-12" : ""
|
||||
!showNode ? " absolute inset-x-6 h-12 w-12 " : ""
|
||||
}`;
|
||||
if (iconElement && isEmoji) {
|
||||
return nodeIconFragment(iconElement);
|
||||
|
|
@ -211,9 +215,7 @@ export default function GenericNode({
|
|||
return "inactive-status";
|
||||
}
|
||||
if (buildStatus === BuildStatus.BUILT && isInvalid) {
|
||||
return isDark
|
||||
? "border-none ring ring-[#751C1C]"
|
||||
: "built-invalid-status";
|
||||
return isDark ? "built-invalid-status-dark" : "built-invalid-status";
|
||||
} else if (buildStatus === BuildStatus.BUILDING) {
|
||||
return "building-status";
|
||||
} else {
|
||||
|
|
@ -295,7 +297,7 @@ export default function GenericNode({
|
|||
<div
|
||||
className={
|
||||
"generic-node-title-arrangement rounded-full" +
|
||||
(!showNode && "justify-center")
|
||||
(!showNode && " justify-center ")
|
||||
}
|
||||
>
|
||||
{iconNodeRender()}
|
||||
|
|
@ -331,22 +333,21 @@ export default function GenericNode({
|
|||
) : (
|
||||
<ShadTooltip content={data.node?.display_name}>
|
||||
<div className="group flex items-center gap-2.5">
|
||||
<ShadTooltip content={data.node?.display_name}>
|
||||
<div
|
||||
onDoubleClick={(event) => {
|
||||
if (nameEditable) {
|
||||
setInputName(true);
|
||||
}
|
||||
takeSnapshot();
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
}}
|
||||
data-testid={"title-" + data.node?.display_name}
|
||||
className="generic-node-tooltip-div text-primary"
|
||||
>
|
||||
{data.node?.display_name}
|
||||
</div>
|
||||
</ShadTooltip>
|
||||
<div
|
||||
onDoubleClick={(event) => {
|
||||
if (nameEditable) {
|
||||
setInputName(true);
|
||||
}
|
||||
takeSnapshot();
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
}}
|
||||
data-testid={"title-" + data.node?.display_name}
|
||||
className="generic-node-tooltip-div text-primary"
|
||||
>
|
||||
{data.node?.display_name}
|
||||
</div>
|
||||
|
||||
{nameEditable && (
|
||||
<div
|
||||
onClick={(event) => {
|
||||
|
|
@ -471,17 +472,17 @@ export default function GenericNode({
|
|||
<ShadTooltip
|
||||
content={
|
||||
buildStatus === BuildStatus.BUILDING ? (
|
||||
<span>Building...</span>
|
||||
<span> {statusBuilding} </span>
|
||||
) : !validationStatus ? (
|
||||
<span className="flex">Build to validate status.</span>
|
||||
<span className="flex">{statusBuild}</span>
|
||||
) : (
|
||||
<div className="max-h-96 overflow-auto">
|
||||
{typeof validationStatus.params === "string"
|
||||
? (`${durationString}\n${validationStatus.params}`
|
||||
? `${durationString}\n${validationStatus.params}`
|
||||
.split("\n")
|
||||
.map((line, index) => (
|
||||
<div key={index}>{line}</div>
|
||||
)))
|
||||
))
|
||||
: durationString}
|
||||
</div>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import { Cross2Icon } from "@radix-ui/react-icons";
|
||||
import { useState } from "react";
|
||||
import IconComponent from "../../components/genericIconComponent";
|
||||
import {
|
||||
|
|
@ -8,6 +9,7 @@ import {
|
|||
import useAlertStore from "../../stores/alertStore";
|
||||
import { AlertDropdownType } from "../../types/alerts";
|
||||
import SingleAlert from "./components/singleAlertComponent";
|
||||
import { zeroNotifications } from "../../constants/constants";
|
||||
|
||||
export default function AlertDropdown({
|
||||
children,
|
||||
|
|
@ -45,15 +47,15 @@ export default function AlertDropdown({
|
|||
setTimeout(clearNotificationList, 100);
|
||||
}}
|
||||
>
|
||||
<IconComponent name="Trash2" className="h-[1.1rem] w-[1.1rem]" />
|
||||
<IconComponent name="Trash2" className="h-4 w-4" />
|
||||
</button>
|
||||
<button
|
||||
className="text-foreground hover:text-status-red"
|
||||
className="text-foreground opacity-70 hover:opacity-100"
|
||||
onClick={() => {
|
||||
setOpen(false);
|
||||
}}
|
||||
>
|
||||
<IconComponent name="X" className="h-5 w-5" />
|
||||
<Cross2Icon className="h-4 w-4" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -68,7 +70,7 @@ export default function AlertDropdown({
|
|||
))
|
||||
) : (
|
||||
<div className="flex h-full w-full items-center justify-center pb-16 text-ring">
|
||||
No new notifications
|
||||
{zeroNotifications}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { cloneDeep } from "lodash";
|
||||
import { useEffect, useState } from "react";
|
||||
import { CHAT_FORM_DIALOG_SUBTITLE } from "../../constants/constants";
|
||||
import { CHAT_FORM_DIALOG_SUBTITLE, outputsModalTitle, textInputModalTitle } from "../../constants/constants";
|
||||
import BaseModal from "../../modals/baseModal";
|
||||
import useAlertStore from "../../stores/alertStore";
|
||||
import useFlowStore from "../../stores/flowStore";
|
||||
|
|
@ -56,7 +56,7 @@ export default function IOView({ children, open, setOpen }): JSX.Element {
|
|||
const chatInputNode = nodes.find((node) => node.id === chatInput?.id);
|
||||
if (chatInputNode) {
|
||||
let newNode = cloneDeep(chatInputNode);
|
||||
newNode.data.node!.template["message"].value = chatValue;
|
||||
newNode.data.node!.template["input_value"].value = chatValue;
|
||||
setNode(chatInput!.id, newNode);
|
||||
}
|
||||
for (let i = 0; i < count; i++) {
|
||||
|
|
@ -97,14 +97,14 @@ export default function IOView({ children, open, setOpen }): JSX.Element {
|
|||
{selectedTab !== 0 && (
|
||||
<div
|
||||
className={cn(
|
||||
"mr-6 flex h-full w-2/6 flex-shrink-0 flex-col justify-start overflow-auto scrollbar-hide",
|
||||
"mr-6 flex h-full w-2/6 flex-shrink-0 flex-col justify-start",
|
||||
haveChat ? "w-2/6" : "w-full"
|
||||
)}
|
||||
>
|
||||
<Tabs
|
||||
value={selectedTab.toString()}
|
||||
className={
|
||||
"flex h-full flex-col overflow-hidden rounded-md border bg-muted text-center"
|
||||
"flex h-full flex-col overflow-y-auto custom-scroll rounded-md border bg-muted text-center"
|
||||
}
|
||||
onValueChange={(value) => {
|
||||
setSelectedTab(Number(value));
|
||||
|
|
@ -127,7 +127,7 @@ export default function IOView({ children, open, setOpen }): JSX.Element {
|
|||
>
|
||||
<div className="mx-2 mb-2 flex items-center gap-2 text-sm font-bold">
|
||||
<IconComponent className="h-4 w-4" name={"Type"} />
|
||||
Text Inputs
|
||||
{textInputModalTitle}
|
||||
</div>
|
||||
{nodes
|
||||
.filter((node) =>
|
||||
|
|
@ -188,7 +188,7 @@ export default function IOView({ children, open, setOpen }): JSX.Element {
|
|||
>
|
||||
<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
|
||||
{outputsModalTitle}
|
||||
</div>
|
||||
{nodes
|
||||
.filter((node) =>
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import useFlowStore from "../../../stores/flowStore";
|
|||
import { validateNodes } from "../../../utils/reactflowUtils";
|
||||
import RadialProgressComponent from "../../RadialProgress";
|
||||
import IconComponent from "../../genericIconComponent";
|
||||
import { MISSED_ERROR_ALERT } from "../../../alerts_constants";
|
||||
import { MISSED_ERROR_ALERT } from "../../../constants/alerts_constants";
|
||||
|
||||
export default function BuildTrigger({
|
||||
open,
|
||||
|
|
|
|||
|
|
@ -181,7 +181,7 @@ export default function CodeTabsComponent({
|
|||
{tabs.map((tab, idx) => (
|
||||
<TabsContent
|
||||
value={idx.toString()}
|
||||
className="api-modal-tabs-content"
|
||||
className="api-modal-tabs-content overflow-hidden"
|
||||
key={idx} // Remember to add a unique key prop
|
||||
>
|
||||
{idx < 4 ? (
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ import { cn } from "../../../../utils/utils";
|
|||
import ShadTooltip from "../../../ShadTooltipComponent";
|
||||
import IconComponent from "../../../genericIconComponent";
|
||||
import { Button } from "../../../ui/button";
|
||||
import { savedHover } from "../../../../constants/constants";
|
||||
|
||||
export const MenuBar = ({
|
||||
removeFunction,
|
||||
|
|
@ -127,7 +128,7 @@ export const MenuBar = ({
|
|||
</div>
|
||||
<ShadTooltip
|
||||
content={
|
||||
"Last saved at " +
|
||||
savedHover +
|
||||
new Date(currentFlow.updated_at ?? "").toLocaleString("en-US", {
|
||||
hour: "numeric",
|
||||
minute: "numeric",
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import useAlertStore from "../../stores/alertStore";
|
|||
import useFlowsManagerStore from "../../stores/flowsManagerStore";
|
||||
import { FileComponentType } from "../../types/components";
|
||||
import IconComponent from "../genericIconComponent";
|
||||
import { CONSOLE_ERROR_MSG, CONSOLE_SUCCESS_MSG, INVALID_FILE_ALERT } from "../../alerts_constants";
|
||||
import { CONSOLE_ERROR_MSG, CONSOLE_SUCCESS_MSG, INVALID_FILE_ALERT } from "../../constants/alerts_constants";
|
||||
|
||||
export default function InputFileComponent({
|
||||
value,
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import IconComponent from "../../../components/genericIconComponent";
|
|||
import { Textarea } from "../../../components/ui/textarea";
|
||||
import { chatInputType } from "../../../types/components";
|
||||
import { classNames } from "../../../utils/utils";
|
||||
import { chatInputPlaceholder, chatInputPlaceholderSend } from "../../../constants/constants";
|
||||
|
||||
export default function ChatInput({
|
||||
lockChat,
|
||||
|
|
@ -72,8 +73,8 @@ export default function ChatInput({
|
|||
)}
|
||||
placeholder={
|
||||
noInput
|
||||
? "No chat input variables found. Click to run your flow."
|
||||
: "Send a message..."
|
||||
? chatInputPlaceholder
|
||||
: chatInputPlaceholderSend
|
||||
}
|
||||
/>
|
||||
<div className="form-modal-send-icon-position">
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import Convert from "ansi-to-html";
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
import { useEffect, useMemo, useRef, useState } from "react";
|
||||
import Markdown from "react-markdown";
|
||||
import rehypeMathjax from "rehype-mathjax";
|
||||
import remarkGfm from "remark-gfm";
|
||||
|
|
@ -9,6 +9,7 @@ import Robot from "../../../assets/robot.png";
|
|||
import SanitizedHTMLWrapper from "../../../components/SanitizedHTMLWrapper";
|
||||
import CodeTabsComponent from "../../../components/codeTabsComponent";
|
||||
import IconComponent from "../../../components/genericIconComponent";
|
||||
import useFlowStore from "../../../stores/flowStore";
|
||||
import { chatMessagePropsType } from "../../../types/components";
|
||||
import { classNames } from "../../../utils/utils";
|
||||
import FileCard from "../fileComponent";
|
||||
|
|
@ -18,14 +19,26 @@ export default function ChatMessage({
|
|||
lockChat,
|
||||
lastMessage,
|
||||
updateChat,
|
||||
setLockChat,
|
||||
}: chatMessagePropsType): JSX.Element {
|
||||
const convert = new Convert({ newline: true });
|
||||
const [hidden, setHidden] = useState(true);
|
||||
const template = chat.template;
|
||||
const [promptOpen, setPromptOpen] = useState(false);
|
||||
const [streamUrl, setStreamUrl] = useState(chat.stream_url);
|
||||
const [chatMessage, setChatMessage] = useState(chat.message.toString());
|
||||
// We need to check if message is not undefined because
|
||||
// we need to run .toString() on it
|
||||
const chatMessageString = chat.message ? chat.message.toString() : "";
|
||||
const [chatMessage, setChatMessage] = useState(chatMessageString);
|
||||
const [isStreaming, setIsStreaming] = useState(false);
|
||||
const eventSource = useRef<EventSource | undefined>(undefined);
|
||||
const updateFlowPool = useFlowStore((state) => state.updateFlowPool);
|
||||
const chatMessageRef = useRef(chatMessage);
|
||||
|
||||
// Sync ref with state
|
||||
useEffect(() => {
|
||||
chatMessageRef.current = chatMessage;
|
||||
}, [chatMessage]);
|
||||
|
||||
// The idea now is that chat.stream_url MAY be a URL if we should stream the output of the chat
|
||||
// probably the message is empty when we have a stream_url
|
||||
|
|
@ -33,49 +46,50 @@ export default function ChatMessage({
|
|||
const streamChunks = (url: string) => {
|
||||
setIsStreaming(true); // Streaming starts
|
||||
return new Promise<boolean>((resolve, reject) => {
|
||||
const eventSource = new EventSource(url);
|
||||
eventSource.onmessage = (event) => {
|
||||
eventSource.current = new EventSource(url);
|
||||
eventSource.current.onmessage = (event) => {
|
||||
let parsedData = JSON.parse(event.data);
|
||||
if (parsedData.chunk) {
|
||||
setChatMessage((prev) => prev + parsedData.chunk);
|
||||
}
|
||||
};
|
||||
eventSource.onerror = (event) => {
|
||||
eventSource.current.onerror = (event) => {
|
||||
setIsStreaming(false);
|
||||
eventSource.current?.close();
|
||||
setStreamUrl(undefined);
|
||||
reject(new Error("Streaming failed"));
|
||||
setIsStreaming(false);
|
||||
eventSource.close();
|
||||
};
|
||||
eventSource.addEventListener("close", (event) => {
|
||||
setStreamUrl(null); // Update state to reflect the stream is closed
|
||||
resolve(true);
|
||||
eventSource.current.addEventListener("close", (event) => {
|
||||
setStreamUrl(undefined); // Update state to reflect the stream is closed
|
||||
eventSource.current?.close();
|
||||
setIsStreaming(false);
|
||||
eventSource.close();
|
||||
resolve(true);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (streamUrl && chat.message === "") {
|
||||
if (streamUrl && !isStreaming) {
|
||||
setLockChat(true);
|
||||
streamChunks(streamUrl)
|
||||
.then(() => {
|
||||
setLockChat(false);
|
||||
if (updateChat) {
|
||||
updateChat(chat, chatMessage, streamUrl);
|
||||
updateChat(chat, chatMessageRef.current);
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error(error);
|
||||
setLockChat(false);
|
||||
});
|
||||
}
|
||||
}, [streamUrl]);
|
||||
}, [streamUrl, chatMessage]);
|
||||
|
||||
useEffect(() => {
|
||||
// This effect is specifically for calling updateChat after streaming ends
|
||||
if (!isStreaming && streamUrl) {
|
||||
if (updateChat) {
|
||||
updateChat(chat, chatMessage, streamUrl);
|
||||
}
|
||||
}
|
||||
}, [isStreaming]);
|
||||
return () => {
|
||||
eventSource.current?.close();
|
||||
};
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
const element = document.getElementById("last-chat-message");
|
||||
|
|
@ -146,7 +160,7 @@ export default function ChatMessage({
|
|||
<div className="w-full">
|
||||
{useMemo(
|
||||
() =>
|
||||
chat.message.toString() === "" && lockChat ? (
|
||||
chatMessage === "" && lockChat ? (
|
||||
<IconComponent
|
||||
name="MoreHorizontal"
|
||||
className="h-8 w-8 animate-pulse"
|
||||
|
|
@ -288,11 +302,11 @@ dark:prose-invert"
|
|||
}
|
||||
return <p>{parts}</p>;
|
||||
})
|
||||
: chat.message.toString()}
|
||||
: chatMessage}
|
||||
</span>
|
||||
</>
|
||||
) : (
|
||||
<span>{chat.message.toString()}</span>
|
||||
<span>{chatMessage}</span>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,10 @@
|
|||
import _ from "lodash";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import IconComponent from "../../components/genericIconComponent";
|
||||
import { NOCHATOUTPUT_NOTICE_ALERT } from "../../constants/alerts_constants";
|
||||
import {
|
||||
chatFirstInitialText,
|
||||
chatSecondInitialText,
|
||||
} from "../../constants/constants";
|
||||
import { deleteFlowPool } from "../../controllers/API";
|
||||
import useAlertStore from "../../stores/alertStore";
|
||||
import useFlowStore from "../../stores/flowStore";
|
||||
|
|
@ -14,7 +18,6 @@ import {
|
|||
import { classNames } from "../../utils/utils";
|
||||
import ChatInput from "./chatInput";
|
||||
import ChatMessage from "./chatMessage";
|
||||
import { INFO_MISSING_ALERT, NOCHATOUTPUT_NOTICE_ALERT } from "../../alerts_constants";
|
||||
|
||||
export default function NewChatView({
|
||||
sendMessage,
|
||||
|
|
@ -33,6 +36,7 @@ export default function NewChatView({
|
|||
const inputIds = inputs.map((obj) => obj.id);
|
||||
const outputIds = outputs.map((obj) => obj.id);
|
||||
const outputTypes = outputs.map((obj) => obj.type);
|
||||
const updateFlowPool = useFlowStore((state) => state.updateFlowPool);
|
||||
|
||||
useEffect(() => {
|
||||
if (!outputTypes.includes("ChatOutput")) {
|
||||
|
|
@ -66,14 +70,12 @@ export default function NewChatView({
|
|||
const { sender, message, sender_name, stream_url } = output.data
|
||||
.artifacts as ChatOutputType;
|
||||
|
||||
const componentId = output.id + index;
|
||||
|
||||
const is_ai = sender === "Machine" || sender === null;
|
||||
return {
|
||||
isSend: !is_ai,
|
||||
message: message,
|
||||
sender_name,
|
||||
id: componentId,
|
||||
componentId: output.id,
|
||||
stream_url: stream_url,
|
||||
};
|
||||
} catch (e) {
|
||||
|
|
@ -82,7 +84,7 @@ export default function NewChatView({
|
|||
isSend: false,
|
||||
message: "Error parsing message",
|
||||
sender_name: "Error",
|
||||
id: output.id + index,
|
||||
componentId: output.id,
|
||||
};
|
||||
}
|
||||
});
|
||||
|
|
@ -119,27 +121,28 @@ export default function NewChatView({
|
|||
function updateChat(
|
||||
chat: ChatMessageType,
|
||||
message: string,
|
||||
stream_url: string | null
|
||||
stream_url?: string
|
||||
) {
|
||||
if (message === "") return;
|
||||
console.log(`updateChat: ${message}`);
|
||||
console.log("chatHistory:", chatHistory);
|
||||
chat.message = message;
|
||||
chat.stream_url = stream_url;
|
||||
// chat is one of the chatHistory
|
||||
setChatHistory((oldChatHistory) => {
|
||||
const index = oldChatHistory.findIndex((ch) => ch.id === chat.id);
|
||||
|
||||
if (index === -1) return oldChatHistory;
|
||||
let newChatHistory = _.cloneDeep(oldChatHistory);
|
||||
newChatHistory = [
|
||||
...newChatHistory.slice(0, index),
|
||||
chat,
|
||||
...newChatHistory.slice(index + 1),
|
||||
];
|
||||
console.log("newChatHistory:", newChatHistory);
|
||||
return newChatHistory;
|
||||
updateFlowPool(chat.componentId, {
|
||||
message,
|
||||
sender_name: chat.sender_name ?? "Bot",
|
||||
sender: chat.isSend ? "User" : "Machine",
|
||||
});
|
||||
// setChatHistory((oldChatHistory) => {
|
||||
// const index = oldChatHistory.findIndex((ch) => ch.id === chat.id);
|
||||
// if (index === -1) return oldChatHistory;
|
||||
// let newChatHistory = _.cloneDeep(oldChatHistory);
|
||||
// newChatHistory = [
|
||||
// ...newChatHistory.slice(0, index),
|
||||
// chat,
|
||||
// ...newChatHistory.slice(index + 1),
|
||||
// ];
|
||||
// console.log("newChatHistory:", newChatHistory);
|
||||
// return newChatHistory;
|
||||
// });
|
||||
}
|
||||
|
||||
return (
|
||||
|
|
@ -163,10 +166,11 @@ export default function NewChatView({
|
|||
{chatHistory?.length > 0 ? (
|
||||
chatHistory.map((chat, index) => (
|
||||
<ChatMessage
|
||||
setLockChat={setLockChat}
|
||||
lockChat={lockChat}
|
||||
chat={chat}
|
||||
lastMessage={chatHistory.length - 1 === index ? true : false}
|
||||
key={`${chat.id}-${index}`}
|
||||
key={`${chat.componentId}-${index}`}
|
||||
updateChat={updateChat}
|
||||
/>
|
||||
))
|
||||
|
|
@ -178,14 +182,14 @@ export default function NewChatView({
|
|||
<br />
|
||||
<div className="langflow-chat-desc">
|
||||
<span className="langflow-chat-desc-span">
|
||||
Start a conversation and click the agent's thoughts{" "}
|
||||
{chatFirstInitialText}{" "}
|
||||
<span>
|
||||
<IconComponent
|
||||
name="MessageSquare"
|
||||
className="mx-1 inline h-5 w-5 animate-bounce "
|
||||
/>
|
||||
</span>{" "}
|
||||
to inspect the chaining process.
|
||||
{chatSecondInitialText}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import GenericModal from "../../modals/genericModal";
|
|||
import { TextAreaComponentType } from "../../types/components";
|
||||
import IconComponent from "../genericIconComponent";
|
||||
import { Input } from "../ui/input";
|
||||
import { editTextModalTitle } from "../../constants/constants";
|
||||
|
||||
export default function TextAreaComponent({
|
||||
value,
|
||||
|
|
@ -37,7 +38,7 @@ export default function TextAreaComponent({
|
|||
<GenericModal
|
||||
type={TypeModal.TEXT}
|
||||
buttonText="Finish Editing"
|
||||
modalTitle="Edit Text"
|
||||
modalTitle={editTextModalTitle}
|
||||
value={value}
|
||||
setValue={(value: string) => {
|
||||
onChange(value);
|
||||
|
|
|
|||
|
|
@ -682,3 +682,35 @@ export const priorityFields = new Set(["code", "template"]);
|
|||
|
||||
export const INPUT_TYPES = new Set(["ChatInput", "TextInput"]);
|
||||
export const OUTPUT_TYPES = new Set(["ChatOutput", "TextOutput"]);
|
||||
|
||||
export const chatFirstInitialText = "Start a conversation and click the agent's thoughts";
|
||||
|
||||
export const chatSecondInitialText = "to inspect the chaining process.";
|
||||
|
||||
export const zeroNotifications = "No new notifications";
|
||||
|
||||
export const successBuild = "Built sucessfully ✨";
|
||||
|
||||
export const alertSaveWApi = "Caution: Uncheck this box only removes API keys from fields specifically designated for API keys."
|
||||
|
||||
export const saveWApiCheckbox = "Save with my API keys";
|
||||
export const editTextModalTitle = "Edit Text"
|
||||
export const editTextPlaceholder = "Type message here."
|
||||
export const inputHandleHover = "Avaliable input components:";
|
||||
export const outputHandleHover = "Avaliable output components:";
|
||||
export const textInputModalTitle = "Text Inputs";
|
||||
export const outputsModalTitle = "Prompt Outputs"
|
||||
export const langflowChatTitle = "Langflow Chat"
|
||||
export const chatInputPlaceholder = "No chat input variables found. Click to run your flow."
|
||||
export const chatInputPlaceholderSend = "Send a message..."
|
||||
export const editCodeTitle = "Edit Code"
|
||||
export const myCollectionDesc = "Manage your personal projects. Download or upload your collection."
|
||||
export const storeDesc = "Search flows and components from the community.";
|
||||
export const storeTitle = "Langflow Store"
|
||||
export const noApi = "You don't have an API key. "
|
||||
export const insertApi = "Insert your Langflow API key."
|
||||
export const invalidApi = "Your API key is not valid. "
|
||||
export const createApi = `Don’t have an API key? Sign up at`
|
||||
export const statusBuild = "Build to validate status."
|
||||
export const statusBuilding = "Building..."
|
||||
export const savedHover = "Last saved at "
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
Before Width: | Height: | Size: 156 KiB After Width: | Height: | Size: 406 KiB |
|
|
@ -8,7 +8,7 @@ import useAlertStore from "../../stores/alertStore";
|
|||
import { ApiKeyType } from "../../types/components";
|
||||
import { nodeIconsLucide } from "../../utils/styleUtils";
|
||||
import BaseModal from "../baseModal";
|
||||
import { COPIED_NOTICE_ALERT } from "../../alerts_constants";
|
||||
import { COPIED_NOTICE_ALERT } from "../../constants/alerts_constants";
|
||||
|
||||
export default function SecretKeyModal({
|
||||
title,
|
||||
|
|
|
|||
|
|
@ -9,7 +9,8 @@ import useAlertStore from "../../stores/alertStore";
|
|||
import { useStoreStore } from "../../stores/storeStore";
|
||||
import { StoreApiKeyType } from "../../types/components";
|
||||
import BaseModal from "../baseModal";
|
||||
import { API_ERROR_ALERT, API_SUCCESS_ALERT } from "../../alerts_constants";
|
||||
import { API_ERROR_ALERT, API_SUCCESS_ALERT } from "../../constants/alerts_constants";
|
||||
import { createApi, insertApi, invalidApi, noApi } from "../../constants/constants";
|
||||
|
||||
export default function StoreApiKeyModal({
|
||||
children,
|
||||
|
|
@ -60,10 +61,10 @@ export default function StoreApiKeyModal({
|
|||
<BaseModal.Header
|
||||
description={
|
||||
(hasApiKey && !validApiKey
|
||||
? "Your API key is not valid. "
|
||||
? invalidApi
|
||||
: !hasApiKey
|
||||
? "You don't have an API key. "
|
||||
: "") + "Insert your Langflow API key."
|
||||
? noApi
|
||||
: "") + insertApi
|
||||
}
|
||||
>
|
||||
<span className="pr-2">API Key</span>
|
||||
|
|
@ -98,7 +99,7 @@ export default function StoreApiKeyModal({
|
|||
</div>
|
||||
<div className="flex items-end justify-between">
|
||||
<span className="pr-1 text-xs text-muted-foreground">
|
||||
Don’t have an API key? Sign up at{" "}
|
||||
{createApi} {" "}
|
||||
<a
|
||||
className="text-high-indigo underline"
|
||||
href="https://langflow.store/"
|
||||
|
|
|
|||
|
|
@ -9,14 +9,14 @@ import AceEditor from "react-ace";
|
|||
import IconComponent from "../../components/genericIconComponent";
|
||||
import { Button } from "../../components/ui/button";
|
||||
import { Input } from "../../components/ui/input";
|
||||
import { CODE_PROMPT_DIALOG_SUBTITLE } from "../../constants/constants";
|
||||
import { CODE_PROMPT_DIALOG_SUBTITLE, editCodeTitle } from "../../constants/constants";
|
||||
import { postCustomComponent, postValidateCode } from "../../controllers/API";
|
||||
import useAlertStore from "../../stores/alertStore";
|
||||
import { useDarkStore } from "../../stores/darkStore";
|
||||
import useFlowStore from "../../stores/flowStore";
|
||||
import { codeAreaModalPropsType } from "../../types/components";
|
||||
import BaseModal from "../baseModal";
|
||||
import { BUG_ALERT, CODE_ERROR_ALERT, CODE_SUCCESS_ALERT, FUNC_ERROR_ALERT, IMPORT_ERROR_ALERT } from "../../alerts_constants";
|
||||
import { BUG_ALERT, CODE_ERROR_ALERT, CODE_SUCCESS_ALERT, FUNC_ERROR_ALERT, IMPORT_ERROR_ALERT } from "../../constants/alerts_constants";
|
||||
|
||||
export default function CodeAreaModal({
|
||||
value,
|
||||
|
|
@ -144,7 +144,7 @@ export default function CodeAreaModal({
|
|||
<BaseModal open={open} setOpen={setOpen}>
|
||||
<BaseModal.Trigger>{children}</BaseModal.Trigger>
|
||||
<BaseModal.Header description={CODE_PROMPT_DIALOG_SUBTITLE}>
|
||||
<span className="pr-2">Edit Code</span>
|
||||
<span className="pr-2"> {editCodeTitle} </span>
|
||||
<IconComponent
|
||||
name="prompts"
|
||||
className="h-6 w-6 pl-1 text-primary "
|
||||
|
|
|
|||
|
|
@ -3,13 +3,13 @@ import EditFlowSettings from "../../components/EditFlowSettingsComponent";
|
|||
import IconComponent from "../../components/genericIconComponent";
|
||||
import { Button } from "../../components/ui/button";
|
||||
import { Checkbox } from "../../components/ui/checkbox";
|
||||
import { EXPORT_DIALOG_SUBTITLE } from "../../constants/constants";
|
||||
import { EXPORT_DIALOG_SUBTITLE, alertSaveWApi, saveWApiCheckbox } from "../../constants/constants";
|
||||
import useAlertStore from "../../stores/alertStore";
|
||||
import { useDarkStore } from "../../stores/darkStore";
|
||||
import useFlowsManagerStore from "../../stores/flowsManagerStore";
|
||||
import { downloadFlow, removeApiKeys } from "../../utils/reactflowUtils";
|
||||
import BaseModal from "../baseModal";
|
||||
import { API_WARNING_NOTICE_ALERT } from "../../alerts_constants";
|
||||
import { API_WARNING_NOTICE_ALERT } from "../../constants/alerts_constants";
|
||||
|
||||
const ExportModal = forwardRef(
|
||||
(props: { children: ReactNode }, ref): JSX.Element => {
|
||||
|
|
@ -52,12 +52,11 @@ const ExportModal = forwardRef(
|
|||
}}
|
||||
/>
|
||||
<label htmlFor="terms" className="export-modal-save-api text-sm ">
|
||||
Save with my API keys
|
||||
{saveWApiCheckbox}
|
||||
</label>
|
||||
</div>
|
||||
<span className=" text-xs text-destructive ">
|
||||
Caution: Uncheck this box only removes API keys from fields
|
||||
specifically designated for API keys.
|
||||
{alertSaveWApi}
|
||||
</span>
|
||||
</BaseModal.Content>
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import IconComponent from "../../../components/genericIconComponent";
|
|||
import { Textarea } from "../../../components/ui/textarea";
|
||||
import { chatInputType } from "../../../types/components";
|
||||
import { classNames } from "../../../utils/utils";
|
||||
import { chatInputPlaceholder, chatInputPlaceholderSend } from "../../../constants/constants";
|
||||
|
||||
export default function ChatInput({
|
||||
lockChat,
|
||||
|
|
@ -51,7 +52,7 @@ export default function ChatInput({
|
|||
? "Thinking..."
|
||||
: typeof chatValue === "object" &&
|
||||
Object.keys(chatValue)?.length === 0
|
||||
? "No chat input variables found. Click to run your flow."
|
||||
? chatInputPlaceholder
|
||||
: chatValue
|
||||
}
|
||||
onChange={(event): void => {
|
||||
|
|
@ -68,8 +69,8 @@ export default function ChatInput({
|
|||
)}
|
||||
placeholder={
|
||||
noInput
|
||||
? "No chat input variables found. Click to run your flow."
|
||||
: "Send a message..."
|
||||
? chatInputPlaceholder
|
||||
: chatInputPlaceholderSend
|
||||
}
|
||||
/>
|
||||
<div className="form-modal-send-icon-position">
|
||||
|
|
|
|||
|
|
@ -20,14 +20,14 @@ import {
|
|||
DialogTrigger,
|
||||
} from "../../components/ui/dialog";
|
||||
import { Textarea } from "../../components/ui/textarea";
|
||||
import { CHAT_FORM_DIALOG_SUBTITLE } from "../../constants/constants";
|
||||
import { CHAT_FORM_DIALOG_SUBTITLE, chatFirstInitialText, chatSecondInitialText, langflowChatTitle } from "../../constants/constants";
|
||||
import { AuthContext } from "../../contexts/authContext";
|
||||
import { getBuildStatus } from "../../controllers/API";
|
||||
import useAlertStore from "../../stores/alertStore";
|
||||
import useFlowStore from "../../stores/flowStore";
|
||||
import { FlowState } from "../../types/tabs";
|
||||
import { validateNodes } from "../../utils/reactflowUtils";
|
||||
import { CHAT_ERROR_ALERT, INFO_MISSING_ALERT, MSG_ERROR_ALERT } from "../../alerts_constants";
|
||||
import { CHAT_ERROR_ALERT, INFO_MISSING_ALERT, MSG_ERROR_ALERT } from "../../constants/alerts_constants";
|
||||
|
||||
export default function FormModal({
|
||||
flow,
|
||||
|
|
@ -585,20 +585,20 @@ export default function FormModal({
|
|||
<span>
|
||||
👋{" "}
|
||||
<span className="langflow-chat-span">
|
||||
Langflow Chat
|
||||
{langflowChatTitle}
|
||||
</span>
|
||||
</span>
|
||||
<br />
|
||||
<div className="langflow-chat-desc">
|
||||
<span className="langflow-chat-desc-span">
|
||||
Start a conversation and click the agent's thoughts{" "}
|
||||
{chatFirstInitialText} {" "}
|
||||
<span>
|
||||
<IconComponent
|
||||
name="MessageSquare"
|
||||
className="mx-1 inline h-5 w-5 animate-bounce "
|
||||
/>
|
||||
</span>{" "}
|
||||
to inspect the chaining process.
|
||||
{chatSecondInitialText}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -10,6 +10,8 @@ import {
|
|||
MAX_WORDS_HIGHLIGHT,
|
||||
PROMPT_DIALOG_SUBTITLE,
|
||||
TEXT_DIALOG_SUBTITLE,
|
||||
editTextModalTitle,
|
||||
editTextPlaceholder,
|
||||
regexHighlight,
|
||||
} from "../../constants/constants";
|
||||
import { TypeModal } from "../../constants/enums";
|
||||
|
|
@ -19,7 +21,7 @@ import { genericModalPropsType } from "../../types/components";
|
|||
import { handleKeyDown } from "../../utils/reactflowUtils";
|
||||
import { classNames, varHighlightHTML } from "../../utils/utils";
|
||||
import BaseModal from "../baseModal";
|
||||
import { BUG_ALERT, PROMPT_ERROR_ALERT, PROMPT_SUCCESS_ALERT, TEMP_NOTICE_ALERT } from "../../alerts_constants";
|
||||
import { BUG_ALERT, PROMPT_ERROR_ALERT, PROMPT_SUCCESS_ALERT, TEMP_NOTICE_ALERT } from "../../constants/alerts_constants";
|
||||
|
||||
export default function GenericModal({
|
||||
field_name = "",
|
||||
|
|
@ -211,7 +213,7 @@ export default function GenericModal({
|
|||
setInputValue(event.target.value);
|
||||
checkVariables(event.target.value);
|
||||
}}
|
||||
placeholder="Type message here."
|
||||
placeholder={editTextPlaceholder}
|
||||
onKeyDown={(e) => {
|
||||
handleKeyDown(e, inputValue, "");
|
||||
}}
|
||||
|
|
@ -233,7 +235,7 @@ export default function GenericModal({
|
|||
onChange={(event) => {
|
||||
setInputValue(event.target.value);
|
||||
}}
|
||||
placeholder="Type message here."
|
||||
placeholder={editTextPlaceholder}
|
||||
onKeyDown={(e) => {
|
||||
handleKeyDown(e, value, "");
|
||||
}}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import {
|
|||
inputHandlerEventType,
|
||||
loginInputStateType,
|
||||
} from "../../../types/components";
|
||||
import { SIGNIN_ERROR_ALERT } from "../../../alerts_constants";
|
||||
import { SIGNIN_ERROR_ALERT } from "../../../constants/alerts_constants";
|
||||
|
||||
export default function LoginAdminPage() {
|
||||
const navigate = useNavigate();
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ import useAlertStore from "../../stores/alertStore";
|
|||
import useFlowsManagerStore from "../../stores/flowsManagerStore";
|
||||
import { Users } from "../../types/api";
|
||||
import { UserInputType } from "../../types/components";
|
||||
import { USER_ADD_ERROR_ALERT, USER_ADD_SUCCESS_ALERT, USER_DEL_ERROR_ALERT, USER_DEL_SUCCESS_ALERT, USER_EDIT_ERROR_ALERT, USER_EDIT_SUCCESS_ALERT } from "../../alerts_constants";
|
||||
import { USER_ADD_ERROR_ALERT, USER_ADD_SUCCESS_ALERT, USER_DEL_ERROR_ALERT, USER_DEL_SUCCESS_ALERT, USER_EDIT_ERROR_ALERT, USER_EDIT_SUCCESS_ALERT } from "../../constants/alerts_constants";
|
||||
|
||||
export default function AdminPage() {
|
||||
const [inputValue, setInputValue] = useState("");
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ import {
|
|||
} from "../../constants/constants";
|
||||
import useAlertStore from "../../stores/alertStore";
|
||||
import { ApiKey } from "../../types/components";
|
||||
import { DEL_KEY_ERROR_ALERT, DEL_KEY_SUCCESS_ALERT } from "../../alerts_constants";
|
||||
import { DEL_KEY_ERROR_ALERT, DEL_KEY_SUCCESS_ALERT } from "../../constants/alerts_constants";
|
||||
|
||||
export default function ApiKeysPage() {
|
||||
const [loadingKeys, setLoadingKeys] = useState(true);
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ import { getRandomName, isWrappedWithClass } from "../../../../utils/utils";
|
|||
import ConnectionLineComponent from "../ConnectionLineComponent";
|
||||
import SelectionMenu from "../SelectionMenuComponent";
|
||||
import ExtraSidebar from "../extraSidebarComponent";
|
||||
import { INVALID_SELECTION_ERROR_ALERT, UPLOAD_ALERT_LIST, UPLOAD_ERROR_ALERT, WRONG_FILE_ERROR_ALERT } from "../../../../alerts_constants";
|
||||
import { INVALID_SELECTION_ERROR_ALERT, UPLOAD_ALERT_LIST, UPLOAD_ERROR_ALERT, WRONG_FILE_ERROR_ALERT } from "../../../../constants/alerts_constants";
|
||||
|
||||
const nodeTypes = {
|
||||
genericNode: GenericNode,
|
||||
|
|
@ -87,8 +87,30 @@ export default function Page({
|
|||
const [lastSelection, setLastSelection] =
|
||||
useState<OnSelectionChangeParams | null>(null);
|
||||
|
||||
const setNode = useFlowStore((state) => state.setNode);
|
||||
useEffect(() => {
|
||||
const onKeyDown = (event: KeyboardEvent) => {
|
||||
const selectedNode = nodes.filter((obj) => obj.selected);
|
||||
if ((event.ctrlKey || event.metaKey) && event.key === "p" && selectedNode.length > 0) {
|
||||
event.preventDefault();
|
||||
setNode(selectedNode[0].id, (old) => ({
|
||||
...old,
|
||||
data: {
|
||||
...old.data,
|
||||
node: {
|
||||
...old.data.node,
|
||||
pinned: old.data?.node?.pinned ? false : true,
|
||||
},
|
||||
},
|
||||
}));
|
||||
}
|
||||
if ((event.ctrlKey || event.metaKey) && event.key === "d" && selectedNode.length > 0) {
|
||||
event.preventDefault();
|
||||
paste({nodes: selectedNode, edges: []}, {
|
||||
x: position.current.x,
|
||||
y: position.current.y,
|
||||
});
|
||||
}
|
||||
if (!isWrappedWithClass(event, "noundo")) {
|
||||
if (
|
||||
(event.key === "y" || (event.key === "z" && event.shiftKey)) &&
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ import {
|
|||
} from "../../../../utils/utils";
|
||||
import DisclosureComponent from "../DisclosureComponent";
|
||||
import SidebarDraggableComponent from "./sideBarDraggableComponent";
|
||||
import { UPLOAD_ERROR_ALERT } from "../../../../alerts_constants";
|
||||
import { UPLOAD_ERROR_ALERT } from "../../../../constants/alerts_constants";
|
||||
|
||||
export default function ExtraSidebar(): JSX.Element {
|
||||
const data = useTypesStore((state) => state.data);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { cloneDeep } from "lodash";
|
||||
import _, { cloneDeep } from "lodash";
|
||||
import { useEffect, useState } from "react";
|
||||
import { useUpdateNodeInternals } from "reactflow";
|
||||
import ShadTooltip from "../../../../components/ShadTooltipComponent";
|
||||
|
|
@ -89,6 +89,9 @@ export default function NodeToolbarComponent({
|
|||
}, [showModalAdvanced]);
|
||||
const updateNodeInternals = useUpdateNodeInternals();
|
||||
|
||||
const setLastCopiedSelection = useFlowStore(
|
||||
(state) => state.setLastCopiedSelection
|
||||
);
|
||||
useEffect(() => {
|
||||
setFlowComponent(createFlowComponent(cloneDeep(data), version));
|
||||
}, [
|
||||
|
|
@ -142,6 +145,9 @@ export default function NodeToolbarComponent({
|
|||
case "delete":
|
||||
deleteNode(data.id);
|
||||
break;
|
||||
case "copy":
|
||||
const node = nodes.filter((node) => node.id === data.id);
|
||||
setLastCopiedSelection({ nodes: _.cloneDeep(node), edges: [] });
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -229,7 +235,7 @@ export default function NodeToolbarComponent({
|
|||
id={"code-input-node-toolbar-" + name}
|
||||
/>
|
||||
</div>
|
||||
<IconComponent name="Code" className="h-4 w-4" />
|
||||
<IconComponent name="TerminalSquare" className="h-4 w-4" />
|
||||
</button>
|
||||
</ShadTooltip>
|
||||
) : (
|
||||
|
|
@ -360,6 +366,20 @@ export default function NodeToolbarComponent({
|
|||
</SelectItem>
|
||||
)
|
||||
)}
|
||||
<SelectItem value={"copy"}>
|
||||
<div className="flex">
|
||||
<IconComponent
|
||||
name="Copy"
|
||||
className="relative top-0.5 mr-2 h-4 w-4 "
|
||||
/>{" "}
|
||||
<span className="">Copy</span>{" "}
|
||||
<IconComponent
|
||||
name="Command"
|
||||
className="absolute right-[1.15rem] top-[0.65em] h-3.5 w-3.5 stroke-2"
|
||||
></IconComponent>
|
||||
<span className="absolute right-2 top-[0.5em]">C</span>
|
||||
</div>
|
||||
</SelectItem>
|
||||
{hasStore && (
|
||||
<SelectItem
|
||||
value={"Share"}
|
||||
|
|
@ -430,7 +450,7 @@ export default function NodeToolbarComponent({
|
|||
<span>
|
||||
<IconComponent
|
||||
name="Delete"
|
||||
className="absolute right-2 top-2 h-4 w-4 text-red-300"
|
||||
className="absolute right-2 top-2 h-4 w-4 stroke-2 text-red-400"
|
||||
></IconComponent>
|
||||
</span>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import { Button } from "../../../../components/ui/button";
|
|||
import useAlertStore from "../../../../stores/alertStore";
|
||||
import useFlowsManagerStore from "../../../../stores/flowsManagerStore";
|
||||
import { FlowType } from "../../../../types/flow";
|
||||
import { CONSOLE_ERROR_MSG, UPLOAD_ALERT_LIST, WRONG_FILE_ERROR_ALERT } from "../../../../alerts_constants";
|
||||
import { CONSOLE_ERROR_MSG, UPLOAD_ALERT_LIST, WRONG_FILE_ERROR_ALERT } from "../../../../constants/alerts_constants";
|
||||
|
||||
export default function ComponentsComponent({
|
||||
is_component = true,
|
||||
|
|
|
|||
|
|
@ -6,11 +6,11 @@ import IconComponent from "../../components/genericIconComponent";
|
|||
import PageLayout from "../../components/pageLayout";
|
||||
import SidebarNav from "../../components/sidebarComponent";
|
||||
import { Button } from "../../components/ui/button";
|
||||
import { USER_PROJECTS_HEADER } from "../../constants/constants";
|
||||
import { USER_PROJECTS_HEADER, myCollectionDesc } from "../../constants/constants";
|
||||
import useAlertStore from "../../stores/alertStore";
|
||||
import useFlowsManagerStore from "../../stores/flowsManagerStore";
|
||||
import { downloadFlows } from "../../utils/reactflowUtils";
|
||||
import { CONSOLE_ERROR_MSG } from "../../alerts_constants";
|
||||
import { CONSOLE_ERROR_MSG } from "../../constants/alerts_constants";
|
||||
export default function HomePage(): JSX.Element {
|
||||
const addFlow = useFlowsManagerStore((state) => state.addFlow);
|
||||
const uploadFlow = useFlowsManagerStore((state) => state.uploadFlow);
|
||||
|
|
@ -72,7 +72,7 @@ export default function HomePage(): JSX.Element {
|
|||
return (
|
||||
<PageLayout
|
||||
title={USER_PROJECTS_HEADER}
|
||||
description="Manage your personal projects. Download or upload your collection."
|
||||
description={myCollectionDesc}
|
||||
button={
|
||||
<div className="flex gap-2">
|
||||
<Button
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ import {
|
|||
patchUserInputStateType,
|
||||
} from "../../types/components";
|
||||
import { gradients } from "../../utils/styleUtils";
|
||||
import { EDIT_PASSWORD_ALERT_LIST, EDIT_PASSWORD_ERROR_ALERT, SAVE_ERROR_ALERT, SAVE_SUCCESS_ALERT } from "../../alerts_constants";
|
||||
import { EDIT_PASSWORD_ALERT_LIST, EDIT_PASSWORD_ERROR_ALERT, SAVE_ERROR_ALERT, SAVE_SUCCESS_ALERT } from "../../constants/alerts_constants";
|
||||
export default function ProfileSettingsPage(): JSX.Element {
|
||||
const setCurrentFlowId = useFlowsManagerStore(
|
||||
(state) => state.setCurrentFlowId
|
||||
|
|
|
|||
|
|
@ -28,7 +28,8 @@ import useFlowsManagerStore from "../../stores/flowsManagerStore";
|
|||
import { useStoreStore } from "../../stores/storeStore";
|
||||
import { storeComponent } from "../../types/store";
|
||||
import { cn } from "../../utils/utils";
|
||||
import { APIKEY_ERROR_ALERT, COMPONENTS_ERROR_ALERT, INVALID_API_ERROR_ALERT, NOAPI_ERROR_ALERT } from "../../alerts_constants";
|
||||
import { APIKEY_ERROR_ALERT, COMPONENTS_ERROR_ALERT, INVALID_API_ERROR_ALERT, NOAPI_ERROR_ALERT } from "../../constants/alerts_constants";
|
||||
import { storeDesc, storeTitle } from "../../constants/constants";
|
||||
|
||||
export default function StorePage(): JSX.Element {
|
||||
const hasApiKey = useStoreStore((state) => state.hasApiKey);
|
||||
|
|
@ -172,8 +173,8 @@ export default function StorePage(): JSX.Element {
|
|||
return (
|
||||
<PageLayout
|
||||
betaIcon
|
||||
title="Langflow Store"
|
||||
description="Search flows and components from the community."
|
||||
title={storeTitle}
|
||||
description={storeDesc}
|
||||
button={
|
||||
<>
|
||||
{StoreApiKeyModal && (
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ import {
|
|||
inputHandlerEventType,
|
||||
loginInputStateType,
|
||||
} from "../../types/components";
|
||||
import { SIGNIN_ERROR_ALERT } from "../../alerts_constants";
|
||||
import { SIGNIN_ERROR_ALERT } from "../../constants/alerts_constants";
|
||||
|
||||
export default function LoginPage(): JSX.Element {
|
||||
const [inputState, setInputState] =
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ import {
|
|||
inputHandlerEventType,
|
||||
signUpInputStateType,
|
||||
} from "../../types/components";
|
||||
import { SIGNUP_ERROR_ALERT } from "../../alerts_constants";
|
||||
import { SIGNUP_ERROR_ALERT } from "../../constants/alerts_constants";
|
||||
|
||||
export default function SignUp(): JSX.Element {
|
||||
const [inputState, setInputState] =
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import {
|
|||
applyNodeChanges,
|
||||
} from "reactflow";
|
||||
import { create } from "zustand";
|
||||
import { FLOW_BUILD_SUCCESS_ALERT } from "../alerts_constants";
|
||||
import { FLOW_BUILD_SUCCESS_ALERT, MISSED_ERROR_ALERT } from "../constants/alerts_constants";
|
||||
import { BuildStatus } from "../constants/enums";
|
||||
import { getFlowPool, updateFlowInDatabase } from "../controllers/API";
|
||||
import { VertexBuildTypeAPI } from "../types/api";
|
||||
|
|
@ -19,7 +19,7 @@ import {
|
|||
sourceHandleType,
|
||||
targetHandleType,
|
||||
} from "../types/flow";
|
||||
import { FlowStoreType } from "../types/zustand/flow";
|
||||
import { ChatOutputType, FlowPoolObjectType, FlowStoreType, chatInputType } from "../types/zustand/flow";
|
||||
import { buildVertices } from "../utils/buildUtils";
|
||||
import {
|
||||
cleanEdges,
|
||||
|
|
@ -51,7 +51,7 @@ const useFlowStore = create<FlowStoreType>((set, get) => ({
|
|||
setFlowPool: (flowPool) => {
|
||||
set({ flowPool });
|
||||
},
|
||||
addDataToFlowPool: (data: any, nodeId: string) => {
|
||||
addDataToFlowPool: (data: FlowPoolObjectType, nodeId: string) => {
|
||||
let newFlowPool = cloneDeep({ ...get().flowPool });
|
||||
if (!newFlowPool[nodeId]) newFlowPool[nodeId] = [data];
|
||||
else {
|
||||
|
|
@ -59,6 +59,28 @@ const useFlowStore = create<FlowStoreType>((set, get) => ({
|
|||
}
|
||||
get().setFlowPool(newFlowPool);
|
||||
},
|
||||
updateFlowPool:(nodeId:string,data:FlowPoolObjectType| ChatOutputType | chatInputType,buildId?:string)=>{
|
||||
let newFlowPool = cloneDeep({ ...get().flowPool });
|
||||
if (!newFlowPool[nodeId]){
|
||||
return;
|
||||
}
|
||||
else {
|
||||
let index = newFlowPool[nodeId].length-1;
|
||||
if(buildId){
|
||||
index = newFlowPool[nodeId].findIndex((flow)=>flow.id===buildId);
|
||||
}
|
||||
//check if the data is a flowpool object
|
||||
if((data as FlowPoolObjectType).data?.artifacts!==undefined){
|
||||
newFlowPool[nodeId][index] = (data as FlowPoolObjectType);
|
||||
}
|
||||
//update data artifact
|
||||
else
|
||||
{
|
||||
newFlowPool[nodeId][index].data.artifacts = data;
|
||||
}
|
||||
}
|
||||
get().setFlowPool(newFlowPool);
|
||||
},
|
||||
CleanFlowPool: () => {
|
||||
get().setFlowPool({});
|
||||
},
|
||||
|
|
@ -385,7 +407,7 @@ const useFlowStore = create<FlowStoreType>((set, get) => ({
|
|||
);
|
||||
if (errors.length > 0) {
|
||||
setErrorData({
|
||||
title: "Oops! Looks like you missed something",
|
||||
title: MISSED_ERROR_ALERT,
|
||||
list: errors,
|
||||
});
|
||||
get().setIsBuilding(false);
|
||||
|
|
@ -394,12 +416,13 @@ const useFlowStore = create<FlowStoreType>((set, get) => ({
|
|||
}
|
||||
function handleBuildUpdate(
|
||||
vertexBuildData: VertexBuildTypeAPI,
|
||||
status: BuildStatus
|
||||
status: BuildStatus,
|
||||
buildId:string
|
||||
) {
|
||||
if (vertexBuildData && vertexBuildData.inactive_vertices) {
|
||||
get().removeFromVerticesBuild(vertexBuildData.inactive_vertices);
|
||||
}
|
||||
get().addDataToFlowPool(vertexBuildData, vertexBuildData.id);
|
||||
get().addDataToFlowPool({...vertexBuildData,buildId}, vertexBuildData.id);
|
||||
useFlowStore.getState().updateBuildStatus([vertexBuildData.id], status);
|
||||
}
|
||||
await updateFlowInDatabase({
|
||||
|
|
|
|||
|
|
@ -315,6 +315,9 @@
|
|||
.built-invalid-status {
|
||||
@apply border-none ring ring-[#FF9090];
|
||||
}
|
||||
.built-invalid-status-dark {
|
||||
@apply border-none ring ring-[#751C1C]
|
||||
}
|
||||
.building-status {
|
||||
@apply border-none ring;
|
||||
}
|
||||
|
|
@ -848,7 +851,7 @@
|
|||
@apply flex items-center justify-between px-2 py-2;
|
||||
}
|
||||
.api-modal-tabs-content {
|
||||
@apply -mt-1 h-full w-full overflow-hidden px-4 pb-4;
|
||||
@apply -mt-1 h-full w-full px-4 pb-4;
|
||||
}
|
||||
.api-modal-accordion-display {
|
||||
@apply mt-2 flex h-full w-full;
|
||||
|
|
|
|||
|
|
@ -18,6 +18,8 @@ export type APIClassType = {
|
|||
template: APITemplateType;
|
||||
display_name: string;
|
||||
icon?: string;
|
||||
is_input?: boolean;
|
||||
is_output?: boolean;
|
||||
input_types?: Array<string>;
|
||||
output_types?: Array<string>;
|
||||
custom_fields?: CustomFieldsType;
|
||||
|
|
@ -133,6 +135,7 @@ export type Component = {
|
|||
|
||||
export type VerticesOrderTypeAPI = {
|
||||
ids: Array<Array<string>>;
|
||||
run_id: string;
|
||||
};
|
||||
|
||||
export type VertexBuildTypeAPI = {
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ export type ChatMessageType = {
|
|||
files?: Array<{ data: string; type: string; data_type: string }>;
|
||||
prompt?: string;
|
||||
chatKey?: string;
|
||||
id?: string;
|
||||
componentId: string;
|
||||
stream_url?: string | null;
|
||||
sender_name?: string;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -525,10 +525,11 @@ export type chatMessagePropsType = {
|
|||
chat: ChatMessageType;
|
||||
lockChat: boolean;
|
||||
lastMessage: boolean;
|
||||
setLockChat: (lock: boolean) => void;
|
||||
updateChat: (
|
||||
chat: ChatMessageType,
|
||||
message: string,
|
||||
stream_url: string
|
||||
stream_url?: string
|
||||
) => void;
|
||||
};
|
||||
|
||||
|
|
@ -633,9 +634,9 @@ export type validationStatusType = {
|
|||
id: string;
|
||||
data: object | any;
|
||||
params: string;
|
||||
progress: number;
|
||||
progress?: number;
|
||||
valid: boolean;
|
||||
duration: string;
|
||||
duration?: string;
|
||||
};
|
||||
|
||||
export type ApiKey = {
|
||||
|
|
|
|||
|
|
@ -18,16 +18,18 @@ export type ChatOutputType = {
|
|||
message: string;
|
||||
sender: string;
|
||||
sender_name: string;
|
||||
stream_url?: string;
|
||||
};
|
||||
|
||||
export type FlowPoolObjectType = {
|
||||
timestamp: string;
|
||||
valid: boolean;
|
||||
params: any;
|
||||
data: { artifacts: any; results: any | ChatOutputType | chatInputType };
|
||||
duration: string;
|
||||
progress: number;
|
||||
data: { artifacts: any | ChatOutputType | chatInputType; results: any | ChatOutputType | chatInputType };
|
||||
duration?: string;
|
||||
progress?: number;
|
||||
id: string;
|
||||
buildId: string;
|
||||
};
|
||||
|
||||
export type FlowPoolType = {
|
||||
|
|
@ -40,7 +42,7 @@ export type FlowStoreType = {
|
|||
outputs: Array<{ type: string; id: string }>;
|
||||
hasIO: boolean;
|
||||
setFlowPool: (flowPool: FlowPoolType) => void;
|
||||
addDataToFlowPool: (data: any, nodeId: string) => void;
|
||||
addDataToFlowPool: (data: FlowPoolObjectType, nodeId: string) => void;
|
||||
CleanFlowPool: () => void;
|
||||
isBuilding: boolean;
|
||||
isPending: boolean;
|
||||
|
|
@ -92,4 +94,5 @@ export type FlowStoreType = {
|
|||
updateBuildStatus: (nodeId: string[], status: BuildStatus) => void;
|
||||
revertBuiltStatusFromBuilding: () => void;
|
||||
flowBuildStatus: { [key: string]: BuildStatus };
|
||||
updateFlowPool: (nodeId:string, data:FlowPoolObjectType | ChatOutputType | chatInputType,buildId?:string) => void;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ type BuildVerticesParams = {
|
|||
flowId: string; // Assuming FlowType is the type for your flow
|
||||
nodeId?: string | null; // Assuming nodeId is of type string, and it's optional
|
||||
onGetOrderSuccess?: () => void;
|
||||
onBuildUpdate?: (data: VertexBuildTypeAPI, status: BuildStatus) => void; // Replace any with the actual type if it's not any
|
||||
onBuildUpdate?: (data: VertexBuildTypeAPI, status: BuildStatus,buildId:string) => void; // Replace any with the actual type if it's not any
|
||||
onBuildComplete?: (allNodesValid: boolean) => void;
|
||||
onBuildError?: (title, list, idList: string[]) => void;
|
||||
onBuildStart?: (idList: string[]) => void;
|
||||
|
|
@ -48,7 +48,7 @@ export async function buildVertices({
|
|||
let orderResponse;
|
||||
try {
|
||||
orderResponse = await getVerticesOrder(flowId, nodeId);
|
||||
} catch (error) {
|
||||
} catch (error:any) {
|
||||
console.log(error);
|
||||
setErrorData({
|
||||
title: "Oops! Looks like you missed something",
|
||||
|
|
@ -59,6 +59,7 @@ export async function buildVertices({
|
|||
}
|
||||
if (onGetOrderSuccess) onGetOrderSuccess();
|
||||
let verticesOrder: Array<Array<string>> = orderResponse.data.ids;
|
||||
const runId = orderResponse.data.run_id;
|
||||
let vertices_layers: Array<Array<string>> = [];
|
||||
let stop = false;
|
||||
if (validateNodes) {
|
||||
|
|
@ -102,14 +103,14 @@ export async function buildVertices({
|
|||
onBuildUpdate
|
||||
) {
|
||||
// If it is, skip building and set the state to inactive
|
||||
onBuildUpdate(getInactiveVertexData(id), BuildStatus.INACTIVE);
|
||||
onBuildUpdate(getInactiveVertexData(id), BuildStatus.INACTIVE,runId);
|
||||
buildResults.push(false);
|
||||
continue;
|
||||
}
|
||||
await buildVertex({
|
||||
flowId,
|
||||
id,
|
||||
onBuildUpdate,
|
||||
onBuildUpdate:(data: VertexBuildTypeAPI, status: BuildStatus) => {if(onBuildUpdate) onBuildUpdate(data, status,runId)},
|
||||
onBuildError,
|
||||
verticesIds,
|
||||
buildResults,
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import {
|
|||
LANGFLOW_SUPPORTED_TYPES,
|
||||
OUTPUT_TYPES,
|
||||
specialCharsRegex,
|
||||
successBuild,
|
||||
} from "../constants/constants";
|
||||
import { downloadFlowsFromDatabase } from "../controllers/API";
|
||||
import {
|
||||
|
|
@ -1087,7 +1088,7 @@ export function getGroupStatus(
|
|||
flow: FlowType,
|
||||
ssData: { [key: string]: { valid: boolean; params: string } }
|
||||
) {
|
||||
let status = { valid: true, params: "Built sucessfully ✨" };
|
||||
let status = { valid: true, params: successBuild };
|
||||
const { nodes } = flow.data!;
|
||||
const ids = nodes.map((n: NodeType) => n.data.id);
|
||||
ids.forEach((id) => {
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ import {
|
|||
Code,
|
||||
Code2,
|
||||
Combine,
|
||||
Command,
|
||||
Compass,
|
||||
Copy,
|
||||
Cpu,
|
||||
|
|
@ -218,7 +219,7 @@ export const nodeColors: { [char: string]: string } = {
|
|||
wrappers: "#E6277A",
|
||||
utilities: "#31A3CC",
|
||||
output_parsers: "#E6A627",
|
||||
str: "#049524",
|
||||
str: "#31a3cc",
|
||||
retrievers: "#e6b25a",
|
||||
unknown: "#9CA3AF",
|
||||
custom_components: "#ab11ab",
|
||||
|
|
@ -426,4 +427,5 @@ export const nodeIconsLucide: iconsType = {
|
|||
AlertCircle,
|
||||
Bot,
|
||||
Delete,
|
||||
Command,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ import {
|
|||
tweakType,
|
||||
} from "../types/components";
|
||||
import { FlowType, NodeType } from "../types/flow";
|
||||
import { FlowState, FlowsState } from "../types/tabs";
|
||||
import { FlowState } from "../types/tabs";
|
||||
import { buildTweaks } from "./reactflowUtils";
|
||||
|
||||
export function classNames(...classes: Array<string>): string {
|
||||
|
|
@ -217,12 +217,8 @@ export function groupByFamily(
|
|||
}));
|
||||
}
|
||||
|
||||
export function buildInputs(flowState?: FlowState): string {
|
||||
return flowState &&
|
||||
flowState.input_keys &&
|
||||
Object.keys(flowState.input_keys!).length > 0
|
||||
? JSON.stringify(flowState.input_keys)
|
||||
: '{"input": "message"}';
|
||||
export function buildInputs(): string {
|
||||
return '{"input_value": "message"}';
|
||||
}
|
||||
|
||||
export function getRandomElement<T>(array: T[]): T {
|
||||
|
|
@ -323,7 +319,7 @@ export function getPythonApiCode(
|
|||
// node.data.id
|
||||
// }
|
||||
const tweaks = buildTweaks(flow);
|
||||
const inputs = buildInputs(flowState);
|
||||
const inputs = buildInputs();
|
||||
return `import requests
|
||||
from typing import Optional
|
||||
|
||||
|
|
@ -382,12 +378,10 @@ export function getCurlCode(
|
|||
): string {
|
||||
const flowId = flow.id;
|
||||
const tweaks = buildTweaks(flow);
|
||||
const inputs = buildInputs(flowState);
|
||||
const inputs = buildInputs();
|
||||
|
||||
return `curl -X POST \\
|
||||
${window.location.protocol}//${
|
||||
window.location.host
|
||||
}/api/v1/process/${flowId} \\
|
||||
${window.location.protocol}//${window.location.host}/api/v1/run/${flowId} \\
|
||||
-H 'Content-Type: application/json'\\${
|
||||
!isAuth ? `\n -H 'x-api-key: <your api key>'\\` : ""
|
||||
}
|
||||
|
|
@ -410,7 +404,7 @@ export function getPythonCode(
|
|||
): string {
|
||||
const flowName = flow.name;
|
||||
const tweaks = buildTweaks(flow);
|
||||
const inputs = buildInputs(flowState);
|
||||
const inputs = buildInputs();
|
||||
return `from langflow import load_flow_from_json
|
||||
TWEAKS = ${
|
||||
tweak && tweak.length > 0
|
||||
|
|
@ -435,7 +429,7 @@ export function getWidgetCode(
|
|||
): string {
|
||||
const flowId = flow.id;
|
||||
const flowName = flow.name;
|
||||
const inputs = buildInputs(flowState);
|
||||
const inputs = buildInputs();
|
||||
let chat_input_field = getChatInputField(flow, flowState);
|
||||
|
||||
return `<script src="https://cdn.jsdelivr.net/gh/logspace-ai/langflow-embedded-chat@main/dist/build/static/js/bundle.min.js"></script>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue