+
+
{extraNavigation.title}
diff --git a/langflow/frontend/src/components/HeaderComponent/index.tsx b/langflow/frontend/src/components/HeaderComponent/index.tsx
deleted file mode 100644
index 40611e9c4..000000000
--- a/langflow/frontend/src/components/HeaderComponent/index.tsx
+++ /dev/null
@@ -1,51 +0,0 @@
-import { useContext, useState } from 'react'
-import {
- BellIcon,
- MoonIcon,
- SunIcon,
- } from '@heroicons/react/24/outline'
-import { alertContext } from '../../contexts/alertContext'
-import { useLayer } from 'react-laag'
-import AlertDropdown from '../../alerts/alertDropDown'
-import { darkContext } from '../../contexts/darkContext'
-
-export default function Header(){
- const {notificationCenter, setNotificationCenter} = useContext(alertContext)
- const [isOpen,setIsOpen] = useState(false)
- const {layerProps,renderLayer, triggerProps} = useLayer({
- isOpen,
- placement: "left-start",
- onOutsideClick:()=>setIsOpen(false),
- preferX: "left",
- triggerOffset: 10,
- containerOffset: 12,
- arrowOffset: 4,
- })
- const {dark, setDark} = useContext(darkContext);
- return (
-
- {/* Desktop nav area */}
-
-
-
-
-
- {renderLayer(setIsOpen(false)} open={isOpen}> )}
-
-
-
-
-
- )
-}
\ No newline at end of file
diff --git a/langflow/frontend/src/components/chatComponent/chatMessage/index.tsx b/langflow/frontend/src/components/chatComponent/chatMessage/index.tsx
new file mode 100644
index 000000000..e26a8c05d
--- /dev/null
+++ b/langflow/frontend/src/components/chatComponent/chatMessage/index.tsx
@@ -0,0 +1,49 @@
+import { ChatBubbleLeftEllipsisIcon, ChatBubbleOvalLeftEllipsisIcon, PlusSmallIcon } from "@heroicons/react/24/outline";
+import { useState } from "react";
+import { ChatMessageType } from "../../../types/chat";
+import { nodeColors } from "../../../utils";
+
+export default function ChatMessage({ chat }: { chat: ChatMessageType }) {
+ const [hidden, setHidden] = useState(true);
+ return (
+
+ {!chat.isSend ? (
+
+
+ {hidden && chat.thought && chat.thought !== "" && (
+
setHidden((prev) => !prev)}
+ className="absolute top-2 right-2 cursor-pointer"
+ >
+
+
+ )}
+ {chat.thought && chat.thought !== "" && !hidden && (
+
setHidden((prev) => !prev)}
+ style={{ backgroundColor: nodeColors["thought"] }}
+ className=" text-start inline-block w-full pb-3 pt-3 px-5 cursor-pointer"
+ dangerouslySetInnerHTML={{
+ __html: chat.thought.replace(/\n/g, "
"),
+ }}
+ >
+ )}
+ {chat.thought && chat.thought !== "" && !hidden &&
}
+
+ {chat.message}
+
+
+
+ ) : (
+
+ )}
+
+ );
+}
diff --git a/langflow/frontend/src/components/chatComponent/index.tsx b/langflow/frontend/src/components/chatComponent/index.tsx
index 99c7c1d20..8e4ed58d9 100644
--- a/langflow/frontend/src/components/chatComponent/index.tsx
+++ b/langflow/frontend/src/components/chatComponent/index.tsx
@@ -1,182 +1,217 @@
import { Transition } from "@headlessui/react";
import {
- Bars3CenterLeftIcon,
- PaperAirplaneIcon,
- XMarkIcon,
+ Bars3CenterLeftIcon,
+ LockClosedIcon,
+ PaperAirplaneIcon,
+ XMarkIcon,
} from "@heroicons/react/24/outline";
import { useContext, useEffect, useRef, useState } from "react";
import { sendAll } from "../../controllers/NodesServices";
import { alertContext } from "../../contexts/alertContext";
-import { nodeColors } from "../../utils";
+import { classNames, nodeColors } from "../../utils";
import { TabsContext } from "../../contexts/tabsContext";
import { ChatType } from "../../types/chat";
+import ChatMessage from "./chatMessage";
const _ = require("lodash");
-export default function Chat({flow, reactFlowInstance }:ChatType) {
- const {updateFlow} = useContext(TabsContext)
- const [saveChat,setSaveChat] = useState(false)
- const [open, setOpen] = useState(true);
- const [chatValue, setChatValue] = useState("");
- const [chatHistory, setChatHistory] = useState(flow.chat);
- const {setErrorData} = useContext(alertContext);
- const addChatHistory = (message:string, isSend:boolean) => {
- setChatHistory((old) => {
- let newChat = _.cloneDeep(old);
- newChat.push({ message, isSend });
- return newChat;
- });
- setSaveChat(chat=>!chat)
- };
- useEffect(()=>{
- updateFlow({..._.cloneDeep(flow),chat:chatHistory})
- // eslint-disable-next-line react-hooks/exhaustive-deps
- },[saveChat])
- useEffect(()=>{
- setChatHistory(flow.chat)
- },[flow])
- useEffect(()=>{
- if(ref.current)
- ref.current.scrollIntoView({behavior: 'smooth'});
- }, [chatHistory])
- function validateNodes(){
- if(reactFlowInstance.getNodes().some((n) => (n.data.node && Object.keys(n.data.node.template).some((t: any) => ((n.data.node.template[t].required && n.data.node.template[t].value === "") && (n.data.node.template[t].required && !reactFlowInstance.getEdges().some((e) => (e.sourceHandle.split('|')[1] === t && e.sourceHandle.split('|')[2] === n.id)))))))){
- return false;
- }
- return true;
- }
- function validateChatNodes(){
- if(!reactFlowInstance.getNodes().some((n)=> (n.type === 'chatOutputNode'))){
- return false;
- }
- return true;
- }
- const ref = useRef(null);
+export default function Chat({ flow, reactFlowInstance }: ChatType) {
+ const { updateFlow } = useContext(TabsContext);
+ const [saveChat, setSaveChat] = useState(false);
+ const [lockChat, setLockChat] = useState(false);
+ const [open, setOpen] = useState(true);
+ const [chatValue, setChatValue] = useState("");
+ const [chatHistory, setChatHistory] = useState(flow.chat);
+ const { setErrorData } = useContext(alertContext);
+ const addChatHistory = (
+ message: string,
+ isSend: boolean,
+ thought?: string
+ ) => {
+ setChatHistory((old) => {
+ let newChat = _.cloneDeep(old);
+ if (thought) {
+ newChat.push({ message, isSend, thought });
+ } else {
+ newChat.push({ message, isSend });
+ }
+ return newChat;
+ });
+ setSaveChat((chat) => !chat);
+ };
+ useEffect(() => {
+ updateFlow({ ..._.cloneDeep(flow), chat: chatHistory });
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [saveChat]);
+ useEffect(() => {
+ setChatHistory(flow.chat);
+ }, [flow]);
+ useEffect(() => {
+ if (ref.current) ref.current.scrollIntoView({ behavior: "smooth" });
+ }, [chatHistory]);
+ function validateNodes() {
+ if (
+ reactFlowInstance
+ .getNodes()
+ .some(
+ (n) =>
+ n.data.node &&
+ Object.keys(n.data.node.template).some(
+ (t: any) =>
+ n.data.node.template[t].required &&
+ n.data.node.template[t].value === "" &&
+ n.data.node.template[t].required &&
+ !reactFlowInstance
+ .getEdges()
+ .some(
+ (e) =>
+ e.sourceHandle.split("|")[1] === t &&
+ e.sourceHandle.split("|")[2] === n.id
+ )
+ )
+ )
+ ) {
+ return false;
+ }
+ return true;
+ }
+ const ref = useRef(null);
- function sendMessage(){
- if(chatValue !== ""){
- if(validateNodes()){
- if(validateChatNodes()){
- let message = chatValue;
- setChatValue("");
- addChatHistory(message, true);
- console.log({...reactFlowInstance.toObject(),message,chatHistory})
- sendAll({...reactFlowInstance.toObject(),message,chatHistory}).then((r) => {addChatHistory(r.data.result, false);});
- } else {
- setErrorData({title: 'Error sending message', list:['Chat nodes are missing.']})
- }
-
- } else {
- setErrorData({title: 'Error sending message', list:['There are required fields not filled yet.']})
- }
- } else {
- setErrorData({title: 'Error sending message', list:['The message cannot be empty.']})
- }
- }
+ function sendMessage() {
+ if (chatValue !== "") {
+ if (validateNodes()) {
+ setLockChat(true);
+ let message = chatValue;
+ setChatValue("");
+ addChatHistory(message, true);
+ console.log({ ...reactFlowInstance.toObject(), message, chatHistory });
- return (
- <>
-
-
-
-
-
-
- Chat
-
-
-
-
- {chatHistory.map((c, i) => (
-
- {!c.isSend ? (
-
- ) : (
-
- )}
-
- ))}
-
-
-
-
-
{
- if(event.key==='Enter'){
- sendMessage()
- }
- }}
- type="text"
- value={chatValue}
- onChange={(e) => {
- setChatValue(e.target.value);
- }}
- className="form-input block w-full rounded-md border-gray-300 dark:border-gray-600 dark:bg-gray-700 dark:text-white pr-10 sm:text-sm"
- placeholder="Send a message..."
- />
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- >
- );
+ sendAll({ ...reactFlowInstance.toObject(), message, chatHistory })
+ .then((r) => {
+ console.log(r.data);
+ addChatHistory(r.data.result, false,r.data.thought);
+ setLockChat(false);
+ })
+ .catch((error) => {
+ setErrorData({ title: error.message ?? "unknow error" });
+ setLockChat(false);
+ });
+ } else {
+ setErrorData({
+ title: "Error sending message",
+ list: ["There are required fields not filled yet."],
+ });
+ }
+ } else {
+ setErrorData({
+ title: "Error sending message",
+ list: ["The message cannot be empty."],
+ });
+ }
+ }
+
+ return (
+ <>
+
+
+
+
{
+ setOpen(false);
+ }}
+ className="flex justify-between cursor-pointer items-center px-5 py-2 border-b dark:border-b-gray-700"
+ >
+
+
+ Chat
+
+
+
+ {chatHistory.map((c, i) => (
+
+ ))}
+
+
+
+
+
{
+ if (event.key === "Enter" && !lockChat) {
+ sendMessage();
+ }
+ }}
+ type="text"
+ disabled={lockChat}
+ value={lockChat?"please wait for the response": chatValue}
+ onChange={(e) => {
+ setChatValue(e.target.value);
+ }}
+ className={classNames(
+ lockChat ? "bg-gray-500 text-white" : "dark:bg-gray-700",
+ "form-input block w-full rounded-md border-gray-300 dark:border-gray-600 dark:text-white pr-10 sm:text-sm"
+ )}
+ placeholder={"Send a message..."}
+ />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ >
+ );
}
diff --git a/langflow/frontend/src/components/floatComponent/index.tsx b/langflow/frontend/src/components/floatComponent/index.tsx
new file mode 100644
index 000000000..adce64ba5
--- /dev/null
+++ b/langflow/frontend/src/components/floatComponent/index.tsx
@@ -0,0 +1,26 @@
+import { useEffect, useState } from "react";
+import { FloatComponentType } from "../../types/components";
+
+export default function FloatComponent({value, onChange, disabled}: FloatComponentType){
+ const [myValue, setMyValue] = useState(value ?? "");
+ useEffect(()=> {
+ if(disabled){
+ setMyValue("");
+ onChange("");
+ }
+ }, [disabled, onChange])
+ return (
+
+ {
+ setMyValue(e.target.value);
+ onChange(e.target.value);
+ }}
+ />
+
+ );
+}
\ No newline at end of file
diff --git a/langflow/frontend/src/contexts/index.tsx b/langflow/frontend/src/contexts/index.tsx
index 3e28d3e37..6bb581f44 100644
--- a/langflow/frontend/src/contexts/index.tsx
+++ b/langflow/frontend/src/contexts/index.tsx
@@ -6,21 +6,21 @@ import PopUpProvider from "./popUpContext";
import { TabsProvider } from "./tabsContext";
import { TypesProvider } from "./typesContext";
-export default function ContextWrapper({ children }:{children:ReactNode}) {
- //element to wrap all context
- return (
- <>
-
-
-
-
-
- {children}
-
-
-
-
-
- >
- );
+export default function ContextWrapper({ children }: { children: ReactNode }) {
+ //element to wrap all context
+ return (
+ <>
+
+
+
+
+
+ {children}
+
+
+
+
+
+ >
+ );
}
diff --git a/langflow/frontend/src/modals/textAreaModal/index.tsx b/langflow/frontend/src/modals/textAreaModal/index.tsx
index c45bbd616..8cfcebcd1 100644
--- a/langflow/frontend/src/modals/textAreaModal/index.tsx
+++ b/langflow/frontend/src/modals/textAreaModal/index.tsx
@@ -59,17 +59,17 @@ export default function TextAreaModal({value, setValue}:{setValue:(value:string)