Merge branch 'uiRevision' into dev

This commit is contained in:
anovazzi1 2023-03-08 21:49:09 -03:00
commit 1d2a421813
9 changed files with 48 additions and 14 deletions

View file

@ -4,7 +4,7 @@
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title> <title>LangFLow</title>
</head> </head>
<body id='body' style="width: 100%; height:100%"> <body id='body' style="width: 100%; height:100%">
<noscript>You need to enable JavaScript to run this app.</noscript> <noscript>You need to enable JavaScript to run this app.</noscript>

View file

@ -52,6 +52,9 @@ export default function ParameterComponent({
{title} {title}
<span className="text-red-600">{required ? " *" : ""}</span> <span className="text-red-600">{required ? " *" : ""}</span>
</div> </div>
{left && (type === "str" || type === "bool" || type === "float") ?
<></>
:
<Tooltip title={tooltipTitle + (required ? " (required)" : "")}> <Tooltip title={tooltipTitle + (required ? " (required)" : "")}>
<Handle <Handle
type={left ? "target" : "source"} type={left ? "target" : "source"}
@ -62,10 +65,7 @@ export default function ParameterComponent({
} }
className={classNames( className={classNames(
left ? "-ml-0.5 " : "-mr-0.5 ", left ? "-ml-0.5 " : "-mr-0.5 ",
"w-3 h-3 rounded-full border-2 bg-white dark:bg-gray-800", "w-3 h-3 rounded-full border-2 bg-white dark:bg-gray-800"
left && (type === "str" || type === "bool" || type === "float")
? "hidden"
: ""
)} )}
style={{ style={{
borderColor: color, borderColor: color,
@ -73,6 +73,8 @@ export default function ParameterComponent({
}} }}
></Handle> ></Handle>
</Tooltip> </Tooltip>
}
{left === true && type === "str" ? ( {left === true && type === "str" ? (
<div className="mt-2 w-full"> <div className="mt-2 w-full">
{data.node.template[name].list ? ( {data.node.template[name].list ? (
@ -99,6 +101,7 @@ export default function ParameterComponent({
) : ( ) : (
<InputComponent <InputComponent
disabled={disabled} disabled={disabled}
password={data.node.template[name].password ?? true}
value={data.node.template[name].value ?? ""} value={data.node.template[name].value ?? ""}
onChange={(t) => { onChange={(t) => {
data.node.template[name].value = t; data.node.template[name].value = t;

View file

@ -5,7 +5,7 @@ import {
PaperAirplaneIcon, PaperAirplaneIcon,
XMarkIcon, XMarkIcon,
} from "@heroicons/react/24/outline"; } from "@heroicons/react/24/outline";
import { useContext, useEffect, useRef, useState } from "react"; import { MouseEventHandler, useContext, useEffect, useRef, useState } from "react";
import { sendAll } from "../../controllers/NodesServices"; import { sendAll } from "../../controllers/NodesServices";
import { alertContext } from "../../contexts/alertContext"; import { alertContext } from "../../contexts/alertContext";
import { classNames, nodeColors } from "../../utils"; import { classNames, nodeColors } from "../../utils";
@ -89,7 +89,7 @@ export default function Chat({ flow, reactFlowInstance }: ChatType) {
sendAll({ ...reactFlowInstance.toObject(), message, chatHistory }) sendAll({ ...reactFlowInstance.toObject(), message, chatHistory })
.then((r) => { .then((r) => {
console.log(r.data); console.log(r.data);
addChatHistory(r.data.result, false,r.data.thought); addChatHistory(r.data.result, false, r.data.thought);
setLockChat(false); setLockChat(false);
}) })
.catch((error) => { .catch((error) => {
@ -109,6 +109,10 @@ export default function Chat({ flow, reactFlowInstance }: ChatType) {
}); });
} }
} }
function clearChat() {
setChatHistory([])
updateFlow({ ..._.cloneDeep(flow), chat: []});
}
return ( return (
<> <>
@ -137,10 +141,18 @@ export default function Chat({ flow, reactFlowInstance }: ChatType) {
/> />
Chat Chat
</div> </div>
<button className="hover:text-blue-500"
onClick={(e) => {
e.stopPropagation()
clearChat();
}}
>
clear
</button>
</div> </div>
<div className="w-full h-[400px] flex gap-3 mb-auto overflow-y-auto scrollbar-hide flex-col bg-gray-50 dark:bg-gray-900 p-3 py-5"> <div className="w-full h-[400px] flex gap-3 mb-auto overflow-y-auto scrollbar-hide flex-col bg-gray-50 dark:bg-gray-900 p-3 py-5">
{chatHistory.map((c, i) => ( {chatHistory.map((c, i) => (
<ChatMessage chat={c} key={i}/> <ChatMessage chat={c} key={i} />
))} ))}
<div ref={ref}></div> <div ref={ref}></div>
</div> </div>
@ -154,7 +166,7 @@ export default function Chat({ flow, reactFlowInstance }: ChatType) {
}} }}
type="text" type="text"
disabled={lockChat} disabled={lockChat}
value={lockChat?"Thinking...": chatValue} value={lockChat ? "Thinking..." : chatValue}
onChange={(e) => { onChange={(e) => {
setChatValue(e.target.value); setChatValue(e.target.value);
}} }}

View file

@ -1,7 +1,7 @@
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { InputComponentType } from "../../types/components"; import { InputComponentType } from "../../types/components";
export default function InputComponent({value, onChange, disabled}: InputComponentType){ export default function InputComponent({value, onChange, disabled, password}: InputComponentType){
const [myValue, setMyValue] = useState(value ?? ""); const [myValue, setMyValue] = useState(value ?? "");
useEffect(()=> { useEffect(()=> {
if(disabled){ if(disabled){
@ -12,7 +12,7 @@ export default function InputComponent({value, onChange, disabled}: InputCompone
return ( return (
<div className={disabled ? "pointer-events-none cursor-not-allowed" : ""}> <div className={disabled ? "pointer-events-none cursor-not-allowed" : ""}>
<input <input
type="text" type={password ? "password" : "text"}
value={myValue} value={myValue}
className={"block w-full form-input dark:bg-gray-900 dark:border-gray-600 rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm" + (disabled ? " bg-gray-200 dark:bg-gray-700" : "")} className={"block w-full form-input dark:bg-gray-900 dark:border-gray-600 rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm" + (disabled ? " bg-gray-200 dark:bg-gray-700" : "")}
placeholder="Type a text" placeholder="Type a text"

View file

@ -1,6 +1,7 @@
import { createContext, useEffect, useState, useRef, ReactNode } from "react"; import { createContext, useEffect, useState, useRef, ReactNode } from "react";
import { FlowType } from "../types/flow"; import { FlowType } from "../types/flow";
import { TabsContextType } from "../types/tabs"; import { TabsContextType } from "../types/tabs";
import { normalCaseToSnakeCase } from "../utils";
const TabsContextInitialValue: TabsContextType = { const TabsContextInitialValue: TabsContextType = {
tabIndex: 0, tabIndex: 0,
@ -61,7 +62,7 @@ export function TabsProvider({ children }: { children: ReactNode }) {
// create a link element and set its properties // create a link element and set its properties
const link = document.createElement("a"); const link = document.createElement("a");
link.href = jsonString; link.href = jsonString;
link.download = `${flows[tabIndex].name}.json`; link.download = `${normalCaseToSnakeCase(flows[tabIndex].name)}.json`;
// simulate a click on the link element to trigger the download // simulate a click on the link element to trigger the download
link.click(); link.click();
@ -124,7 +125,7 @@ export function TabsProvider({ children }: { children: ReactNode }) {
// Create a new flow with a default name if no flow is provided. // Create a new flow with a default name if no flow is provided.
let newFlow: FlowType = { let newFlow: FlowType = {
name: flow ? flow.name : "flow" + id, name: flow ? flow.name : "New Flow " + id,
id: id.toString(), id: id.toString(),
data, data,
chat: flow ? flow.chat : [], chat: flow ? flow.chat : [],

View file

@ -21,6 +21,7 @@ export function TypesProvider({ children }:{children:ReactNode}) {
reactFlowInstance.setNodes( reactFlowInstance.setNodes(
reactFlowInstance.getNodes().filter((n:Node) => n.id !== idx) reactFlowInstance.getNodes().filter((n:Node) => n.id !== idx)
); );
reactFlowInstance.setEdges(reactFlowInstance.getEdges().filter((ns) => ns.source !== idx && ns.target !== idx));
} }
return ( return (
<typesContext.Provider <typesContext.Provider

View file

@ -155,6 +155,10 @@ export default function FlowPage({ flow }:{flow:FlowType}) {
); );
const onDelete = (mynodes) => {
setEdges(edges.filter((ns) => !nodes.some((n) => ns.source === n.id || ns.target === n.id)));
}
return ( return (
<div className="w-full h-full" ref={reactFlowWrapper}> <div className="w-full h-full" ref={reactFlowWrapper}>
{Object.keys(types).length > 0 ? ( {Object.keys(types).length > 0 ? (
@ -174,6 +178,7 @@ export default function FlowPage({ flow }:{flow:FlowType}) {
connectionLineComponent={ConnectionLineComponent} connectionLineComponent={ConnectionLineComponent}
onDragOver={onDragOver} onDragOver={onDragOver}
onDrop={onDrop} onDrop={onDrop}
onNodesDelete={onDelete}
> >
<Background className="dark:bg-gray-900"/> <Background className="dark:bg-gray-900"/>
<Controls className="[&>button]:text-black [&>button]:dark:bg-gray-800 hover:[&>button]:dark:bg-gray-700 [&>button]:dark:text-gray-400 [&>button]:dark:fill-gray-400 [&>button]:dark:border-gray-600"> <Controls className="[&>button]:text-black [&>button]:dark:bg-gray-800 hover:[&>button]:dark:bg-gray-700 [&>button]:dark:text-gray-400 [&>button]:dark:fill-gray-400 [&>button]:dark:border-gray-600">

View file

@ -4,6 +4,7 @@ export type InputComponentType = {
value: string; value: string;
disabled?: boolean; disabled?: boolean;
onChange: (value: string) => void; onChange: (value: string) => void;
password: boolean;
}; };
export type ToggleComponentType = { export type ToggleComponentType = {
enabled: boolean; enabled: boolean;

View file

@ -286,6 +286,18 @@ export function snakeToNormalCase(str: string) {
.join(" "); .join(" ");
} }
export function normalCaseToSnakeCase(str:string){
return str
.split(" ")
.map((word, index) => {
if (index === 0) {
return word[0].toUpperCase() + word.slice(1).toLowerCase();
}
return word.toLowerCase();
})
.join("_");
}
export function roundNumber(x:number, decimals:number) { export function roundNumber(x:number, decimals:number) {
return Math.round(x * Math.pow(10, decimals)) / Math.pow(10, decimals); return Math.round(x * Math.pow(10, decimals)) / Math.pow(10, decimals);
} }
@ -303,7 +315,6 @@ export function isValidConnection(
{ source, target, sourceHandle, targetHandle }:Connection, { source, target, sourceHandle, targetHandle }:Connection,
reactFlowInstance:ReactFlowInstance reactFlowInstance:ReactFlowInstance
) { ) {
console.log(target)
if ( if (
sourceHandle.split('|')[0] === targetHandle.split("|")[0] || sourceHandle.split('|')[0] === targetHandle.split("|")[0] ||
sourceHandle.split('|').slice(2).some((t) => t === targetHandle.split("|")[0]) || sourceHandle.split('|').slice(2).some((t) => t === targetHandle.split("|")[0]) ||