Formatting
This commit is contained in:
parent
a096e83474
commit
276a06976d
65 changed files with 4515 additions and 4390 deletions
|
|
@ -34,7 +34,10 @@ export default function SingleAlert({
|
||||||
key={dropItem.id}
|
key={dropItem.id}
|
||||||
>
|
>
|
||||||
<div className="flex-shrink-0">
|
<div className="flex-shrink-0">
|
||||||
<XCircleIcon className="h-5 w-5 text-red-400 dark:text-red-50" aria-hidden="true" />
|
<XCircleIcon
|
||||||
|
className="h-5 w-5 text-red-400 dark:text-red-50"
|
||||||
|
aria-hidden="true"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="ml-3">
|
<div className="ml-3">
|
||||||
<h3 className="text-sm break-words font-medium text-red-800 dark:text-white/80">
|
<h3 className="text-sm break-words font-medium text-red-800 dark:text-white/80">
|
||||||
|
|
@ -44,7 +47,9 @@ export default function SingleAlert({
|
||||||
<div className="mt-2 text-sm text-red-700 dark:text-red-50">
|
<div className="mt-2 text-sm text-red-700 dark:text-red-50">
|
||||||
<ul className="list-disc space-y-1 pl-5">
|
<ul className="list-disc space-y-1 pl-5">
|
||||||
{dropItem.list.map((item, idx) => (
|
{dropItem.list.map((item, idx) => (
|
||||||
<li className="break-words" key={idx}>{item}</li>
|
<li className="break-words" key={idx}>
|
||||||
|
{item}
|
||||||
|
</li>
|
||||||
))}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -82,7 +87,9 @@ export default function SingleAlert({
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="ml-3 flex-1 md:flex md:justify-between">
|
<div className="ml-3 flex-1 md:flex md:justify-between">
|
||||||
<p className="text-sm text-blue-700 dark:text-white/80">{dropItem.title}</p>
|
<p className="text-sm text-blue-700 dark:text-white/80">
|
||||||
|
{dropItem.title}
|
||||||
|
</p>
|
||||||
<p className="mt-3 text-sm md:mt-0 md:ml-6">
|
<p className="mt-3 text-sm md:mt-0 md:ml-6">
|
||||||
{dropItem.link ? (
|
{dropItem.link ? (
|
||||||
<Link
|
<Link
|
||||||
|
|
|
||||||
|
|
@ -43,10 +43,15 @@ export default function ErrorAlert({
|
||||||
>
|
>
|
||||||
<div className="flex">
|
<div className="flex">
|
||||||
<div className="flex-shrink-0">
|
<div className="flex-shrink-0">
|
||||||
<XCircleIcon className="h-5 w-5 text-red-400 dark:text-red-50" aria-hidden="true" />
|
<XCircleIcon
|
||||||
|
className="h-5 w-5 text-red-400 dark:text-red-50"
|
||||||
|
aria-hidden="true"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="ml-3">
|
<div className="ml-3">
|
||||||
<h3 className="text-sm font-medium text-red-800 dark:text-white/80">{title}</h3>
|
<h3 className="text-sm font-medium text-red-800 dark:text-white/80">
|
||||||
|
{title}
|
||||||
|
</h3>
|
||||||
{list.length !== 0 ? (
|
{list.length !== 0 ? (
|
||||||
<div className="mt-2 text-sm text-red-700 dark:text-red-50">
|
<div className="mt-2 text-sm text-red-700 dark:text-red-50">
|
||||||
<ul className="list-disc space-y-1 pl-5">
|
<ul className="list-disc space-y-1 pl-5">
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,9 @@ export default function SuccessAlert({
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="ml-3">
|
<div className="ml-3">
|
||||||
<p className="text-sm font-medium text-green-800 dark:text-white/80">{title}</p>
|
<p className="text-sm font-medium text-green-800 dark:text-white/80">
|
||||||
|
{title}
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,6 @@ export default function FloatComponent({
|
||||||
setMyValue(e.target.value);
|
setMyValue(e.target.value);
|
||||||
onChange(e.target.value);
|
onChange(e.target.value);
|
||||||
}}
|
}}
|
||||||
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,6 @@ export default function InputComponent({
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
value={myValue}
|
value={myValue}
|
||||||
|
|
||||||
className={classNames(
|
className={classNames(
|
||||||
"block w-full pr-12 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",
|
"block w-full pr-12 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" : "",
|
disabled ? " bg-gray-200 dark:bg-gray-700" : "",
|
||||||
|
|
|
||||||
|
|
@ -44,9 +44,7 @@ export default function IntComponent({
|
||||||
setMyValue(e.target.value);
|
setMyValue(e.target.value);
|
||||||
onChange(e.target.value);
|
onChange(e.target.value);
|
||||||
}}
|
}}
|
||||||
|
|
||||||
/>
|
/>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,11 @@ import { PopUpContext } from "../../contexts/popUpContext";
|
||||||
import TextAreaModal from "../../modals/textAreaModal";
|
import TextAreaModal from "../../modals/textAreaModal";
|
||||||
import { TextAreaComponentType } from "../../types/components";
|
import { TextAreaComponentType } from "../../types/components";
|
||||||
|
|
||||||
export default function TextAreaComponent({ value, onChange, disabled }:TextAreaComponentType) {
|
export default function TextAreaComponent({
|
||||||
|
value,
|
||||||
|
onChange,
|
||||||
|
disabled,
|
||||||
|
}: TextAreaComponentType) {
|
||||||
const [myValue, setMyValue] = useState(value);
|
const [myValue, setMyValue] = useState(value);
|
||||||
const { openPopUp } = useContext(PopUpContext);
|
const { openPopUp } = useContext(PopUpContext);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
@ -16,15 +20,38 @@ export default function TextAreaComponent({ value, onChange, disabled }:TextArea
|
||||||
return (
|
return (
|
||||||
<div className={disabled ? "pointer-events-none cursor-not-allowed" : ""}>
|
<div className={disabled ? "pointer-events-none cursor-not-allowed" : ""}>
|
||||||
<div className="w-full flex items-center gap-3">
|
<div className="w-full flex items-center gap-3">
|
||||||
<span onClick={()=>{openPopUp(<TextAreaModal value={myValue} setValue={(t:string) => {setMyValue(t); onChange(t);}}/>)}}
|
<span
|
||||||
|
onClick={() => {
|
||||||
|
openPopUp(
|
||||||
|
<TextAreaModal
|
||||||
|
value={myValue}
|
||||||
|
setValue={(t: string) => {
|
||||||
|
setMyValue(t);
|
||||||
|
onChange(t);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}}
|
||||||
className={
|
className={
|
||||||
"truncate block w-full text-gray-500 dark:text-gray-100 px-3 py-2 rounded-md border border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm" +
|
"truncate block w-full text-gray-500 dark:text-gray-100 px-3 py-2 rounded-md border border-gray-300 dark:border-gray-700 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm" +
|
||||||
(disabled ? " bg-gray-200" : "")
|
(disabled ? " bg-gray-200" : "")
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
{myValue !== "" ? myValue : 'Text empty'}
|
{myValue !== "" ? myValue : "Text empty"}
|
||||||
</span>
|
</span>
|
||||||
<button onClick={()=>{openPopUp(<TextAreaModal value={myValue} setValue={(t:string) => {setMyValue(t); onChange(t);}}/>)}}>
|
<button
|
||||||
|
onClick={() => {
|
||||||
|
openPopUp(
|
||||||
|
<TextAreaModal
|
||||||
|
value={myValue}
|
||||||
|
setValue={(t: string) => {
|
||||||
|
setMyValue(t);
|
||||||
|
onChange(t);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
>
|
||||||
<ArrowTopRightOnSquareIcon className="w-6 h-6 hover:text-blue-600 dark:text-gray-300" />
|
<ArrowTopRightOnSquareIcon className="w-6 h-6 hover:text-blue-600 dark:text-gray-300" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -21,8 +21,8 @@ export default function ToggleComponent({
|
||||||
setEnabled(x);
|
setEnabled(x);
|
||||||
}}
|
}}
|
||||||
className={classNames(
|
className={classNames(
|
||||||
enabled ? 'bg-indigo-600' : 'bg-gray-200',
|
enabled ? "bg-indigo-600" : "bg-gray-200",
|
||||||
'relative inline-flex h-6 w-11 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none focus:ring-2 focus:ring-indigo-600 focus:ring-offset-2'
|
"relative inline-flex h-6 w-11 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none focus:ring-2 focus:ring-indigo-600 focus:ring-offset-2"
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<span className="sr-only">Use setting</span>
|
<span className="sr-only">Use setting</span>
|
||||||
|
|
@ -43,8 +43,7 @@ export default function ToggleComponent({
|
||||||
"absolute inset-0 flex h-full w-full items-center justify-center transition-opacity"
|
"absolute inset-0 flex h-full w-full items-center justify-center transition-opacity"
|
||||||
)}
|
)}
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
>
|
></span>
|
||||||
</span>
|
|
||||||
<span
|
<span
|
||||||
className={classNames(
|
className={classNames(
|
||||||
enabled
|
enabled
|
||||||
|
|
@ -53,8 +52,7 @@ export default function ToggleComponent({
|
||||||
"absolute inset-0 flex h-full w-full items-center justify-center transition-opacity"
|
"absolute inset-0 flex h-full w-full items-center justify-center transition-opacity"
|
||||||
)}
|
)}
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
>
|
></span>
|
||||||
</span>
|
|
||||||
</span>
|
</span>
|
||||||
</Switch>
|
</Switch>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -27,10 +27,13 @@ const TabsContextInitialValue: TabsContextType = {
|
||||||
downloadFlow: (flow: FlowType) => {},
|
downloadFlow: (flow: FlowType) => {},
|
||||||
uploadFlow: () => {},
|
uploadFlow: () => {},
|
||||||
hardReset: () => {},
|
hardReset: () => {},
|
||||||
disableCopyPaste:false,
|
disableCopyPaste: false,
|
||||||
setDisableCopyPaste:(state:boolean)=>{},
|
setDisableCopyPaste: (state: boolean) => {},
|
||||||
getNodeId: () => "",
|
getNodeId: () => "",
|
||||||
paste: (selection: {nodes: any, edges: any}, position: {x: number, y: number}) => {},
|
paste: (
|
||||||
|
selection: { nodes: any; edges: any },
|
||||||
|
position: { x: number; y: number }
|
||||||
|
) => {},
|
||||||
};
|
};
|
||||||
|
|
||||||
export const TabsContext = createContext<TabsContextType>(
|
export const TabsContext = createContext<TabsContextType>(
|
||||||
|
|
@ -53,20 +56,21 @@ export function TabsProvider({ children }: { children: ReactNode }) {
|
||||||
let Saveflows = [...flows];
|
let Saveflows = [...flows];
|
||||||
if (Saveflows.length !== 0)
|
if (Saveflows.length !== 0)
|
||||||
Saveflows.forEach((flow) => {
|
Saveflows.forEach((flow) => {
|
||||||
if(flow.data && flow.data?.nodes) flow.data?.nodes.forEach((node) => {
|
if (flow.data && flow.data?.nodes)
|
||||||
console.log(node.data.type)
|
flow.data?.nodes.forEach((node) => {
|
||||||
|
console.log(node.data.type);
|
||||||
Object.keys(node.data.node.template).forEach((key) => {
|
Object.keys(node.data.node.template).forEach((key) => {
|
||||||
console.log(node.data.node.template[key].type)
|
console.log(node.data.node.template[key].type);
|
||||||
if(node.data.node.template[key].type==="file"){
|
if (node.data.node.template[key].type === "file") {
|
||||||
console.log(node.data.node.template[key])
|
console.log(node.data.node.template[key]);
|
||||||
node.data.node.template[key].content = "";
|
node.data.node.template[key].content = "";
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
})
|
});
|
||||||
})
|
});
|
||||||
window.localStorage.setItem(
|
window.localStorage.setItem(
|
||||||
"tabsData",
|
"tabsData",
|
||||||
JSON.stringify({ tabIndex, flows:Saveflows, id})
|
JSON.stringify({ tabIndex, flows: Saveflows, id })
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
@ -184,7 +188,7 @@ export function TabsProvider({ children }: { children: ReactNode }) {
|
||||||
* @param flow Optional flow to add.
|
* @param flow Optional flow to add.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function paste(selectionInstance, position){
|
function paste(selectionInstance, position) {
|
||||||
let minimumX = Infinity;
|
let minimumX = Infinity;
|
||||||
let minimumY = Infinity;
|
let minimumY = Infinity;
|
||||||
let idsMap = {};
|
let idsMap = {};
|
||||||
|
|
@ -223,7 +227,7 @@ export function TabsProvider({ children }: { children: ReactNode }) {
|
||||||
// Add the new node to the list of nodes in state
|
// Add the new node to the list of nodes in state
|
||||||
nodes = nodes
|
nodes = nodes
|
||||||
.map((e) => ({ ...e, selected: false }))
|
.map((e) => ({ ...e, selected: false }))
|
||||||
.concat({ ...newNode, selected: false })
|
.concat({ ...newNode, selected: false });
|
||||||
});
|
});
|
||||||
reactFlowInstance.setNodes(nodes);
|
reactFlowInstance.setNodes(nodes);
|
||||||
|
|
||||||
|
|
@ -261,7 +265,7 @@ export function TabsProvider({ children }: { children: ReactNode }) {
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
reactFlowInstance.setEdges(edges);
|
reactFlowInstance.setEdges(edges);
|
||||||
};
|
}
|
||||||
|
|
||||||
function addFlow(flow?: FlowType) {
|
function addFlow(flow?: FlowType) {
|
||||||
// Get data from the flow or set it to null if there's no flow provided.
|
// Get data from the flow or set it to null if there's no flow provided.
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ import reportWebVitals from "./reportWebVitals";
|
||||||
import { BrowserRouter } from "react-router-dom";
|
import { BrowserRouter } from "react-router-dom";
|
||||||
import ContextWrapper from "./contexts";
|
import ContextWrapper from "./contexts";
|
||||||
|
|
||||||
import './index.css';
|
import "./index.css";
|
||||||
|
|
||||||
const root = ReactDOM.createRoot(
|
const root = ReactDOM.createRoot(
|
||||||
document.getElementById("root") as HTMLElement
|
document.getElementById("root") as HTMLElement
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,10 @@
|
||||||
import { Dialog, Transition } from "@headlessui/react";
|
import { Dialog, Transition } from "@headlessui/react";
|
||||||
import { IconCheck, IconClipboard, IconDownload } from '@tabler/icons-react';
|
import { IconCheck, IconClipboard, IconDownload } from "@tabler/icons-react";
|
||||||
import { XMarkIcon, CommandLineIcon, CodeBracketSquareIcon } from "@heroicons/react/24/outline";
|
import {
|
||||||
|
XMarkIcon,
|
||||||
|
CommandLineIcon,
|
||||||
|
CodeBracketSquareIcon,
|
||||||
|
} from "@heroicons/react/24/outline";
|
||||||
import { Fragment, useContext, useRef, useState } from "react";
|
import { Fragment, useContext, useRef, useState } from "react";
|
||||||
import { PopUpContext } from "../../contexts/popUpContext";
|
import { PopUpContext } from "../../contexts/popUpContext";
|
||||||
import "ace-builds/src-noconflict/mode-python";
|
import "ace-builds/src-noconflict/mode-python";
|
||||||
|
|
@ -9,10 +13,8 @@ import "ace-builds/src-noconflict/theme-twilight";
|
||||||
import "ace-builds/src-noconflict/ext-language_tools";
|
import "ace-builds/src-noconflict/ext-language_tools";
|
||||||
// import "ace-builds/webpack-resolver";
|
// import "ace-builds/webpack-resolver";
|
||||||
import { darkContext } from "../../contexts/darkContext";
|
import { darkContext } from "../../contexts/darkContext";
|
||||||
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
|
import { Prism as SyntaxHighlighter } from "react-syntax-highlighter";
|
||||||
import { oneDark } from 'react-syntax-highlighter/dist/cjs/styles/prism';
|
import { oneDark } from "react-syntax-highlighter/dist/cjs/styles/prism";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export default function ApiModal({ flowName }) {
|
export default function ApiModal({ flowName }) {
|
||||||
const [open, setOpen] = useState(true);
|
const [open, setOpen] = useState(true);
|
||||||
|
|
@ -68,7 +70,8 @@ flow("Hey, have you heard of LangFlow?")`;
|
||||||
{
|
{
|
||||||
name: "Python API",
|
name: "Python API",
|
||||||
mode: "python",
|
mode: "python",
|
||||||
image: "https://images.squarespace-cdn.com/content/v1/5df3d8c5d2be5962e4f87890/1628015119369-OY4TV3XJJ53ECO0W2OLQ/Python+API+Training+Logo.png?format=1000w",
|
image:
|
||||||
|
"https://images.squarespace-cdn.com/content/v1/5df3d8c5d2be5962e4f87890/1628015119369-OY4TV3XJJ53ECO0W2OLQ/Python+API+Training+Logo.png?format=1000w",
|
||||||
code: pythonApiCode,
|
code: pythonApiCode,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
@ -77,8 +80,7 @@ flow("Hey, have you heard of LangFlow?")`;
|
||||||
image: "https://cdn-icons-png.flaticon.com/512/5968/5968350.png",
|
image: "https://cdn-icons-png.flaticon.com/512/5968/5968350.png",
|
||||||
code: pythonCode,
|
code: pythonCode,
|
||||||
},
|
},
|
||||||
|
];
|
||||||
]
|
|
||||||
return (
|
return (
|
||||||
<Transition.Root show={open} appear={true} as={Fragment}>
|
<Transition.Root show={open} appear={true} as={Fragment}>
|
||||||
<Dialog
|
<Dialog
|
||||||
|
|
@ -144,9 +146,17 @@ flow("Hey, have you heard of LangFlow?")`;
|
||||||
<div className="flex flex-col h-full w-full ">
|
<div className="flex flex-col h-full w-full ">
|
||||||
<div className="flex px-5 z-10">
|
<div className="flex px-5 z-10">
|
||||||
{tabs.map((tab, index) => (
|
{tabs.map((tab, index) => (
|
||||||
<button onClick={() => {
|
<button
|
||||||
|
onClick={() => {
|
||||||
setActiveTab(index);
|
setActiveTab(index);
|
||||||
}} className={"p-2 rounded-t-lg w-44 border border-b-0 border-gray-300 dark:border-gray-700 dark:text-gray-300 -mr-px flex justify-center items-center gap-4 " + (activeTab === index ? " bg-white dark:bg-gray-800" : "bg-gray-100 dark:bg-gray-900")}>
|
}}
|
||||||
|
className={
|
||||||
|
"p-2 rounded-t-lg w-44 border border-b-0 border-gray-300 dark:border-gray-700 dark:text-gray-300 -mr-px flex justify-center items-center gap-4 " +
|
||||||
|
(activeTab === index
|
||||||
|
? " bg-white dark:bg-gray-800"
|
||||||
|
: "bg-gray-100 dark:bg-gray-900")
|
||||||
|
}
|
||||||
|
>
|
||||||
{tab.name}
|
{tab.name}
|
||||||
<img src={tab.image} className="w-6" />
|
<img src={tab.image} className="w-6" />
|
||||||
</button>
|
</button>
|
||||||
|
|
@ -161,8 +171,12 @@ flow("Hey, have you heard of LangFlow?")`;
|
||||||
className="flex gap-1.5 items-center rounded bg-none p-1 text-xs text-gray-500 dark:text-gray-300"
|
className="flex gap-1.5 items-center rounded bg-none p-1 text-xs text-gray-500 dark:text-gray-300"
|
||||||
onClick={copyToClipboard}
|
onClick={copyToClipboard}
|
||||||
>
|
>
|
||||||
{isCopied ? <IconCheck size={18} /> : <IconClipboard size={18} />}
|
{isCopied ? (
|
||||||
{isCopied ? 'Copied!' : 'Copy code'}
|
<IconCheck size={18} />
|
||||||
|
) : (
|
||||||
|
<IconClipboard size={18} />
|
||||||
|
)}
|
||||||
|
{isCopied ? "Copied!" : "Copy code"}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<SyntaxHighlighter
|
<SyntaxHighlighter
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import { useEffect, useRef, useState } from "react";
|
||||||
import { ChatMessageType } from "../../../types/chat";
|
import { ChatMessageType } from "../../../types/chat";
|
||||||
import { classNames } from "../../../utils";
|
import { classNames } from "../../../utils";
|
||||||
import AiIcon from "../../../assets/Gooey Ring-5s-271px.svg";
|
import AiIcon from "../../../assets/Gooey Ring-5s-271px.svg";
|
||||||
import AiIconStill from "../../../assets/froze-flow.png"
|
import AiIconStill from "../../../assets/froze-flow.png";
|
||||||
import { UserIcon } from "@heroicons/react/24/solid";
|
import { UserIcon } from "@heroicons/react/24/solid";
|
||||||
import FileCard from "../fileComponent";
|
import FileCard from "../fileComponent";
|
||||||
import ReactMarkdown from "react-markdown";
|
import ReactMarkdown from "react-markdown";
|
||||||
|
|
@ -13,7 +13,13 @@ import remarkMath from "remark-math";
|
||||||
import { CodeBlock } from "./codeBlock";
|
import { CodeBlock } from "./codeBlock";
|
||||||
import Convert from "ansi-to-html";
|
import Convert from "ansi-to-html";
|
||||||
|
|
||||||
export default function ChatMessage({ chat, lockChat }: { chat: ChatMessageType, lockChat: boolean }) {
|
export default function ChatMessage({
|
||||||
|
chat,
|
||||||
|
lockChat,
|
||||||
|
}: {
|
||||||
|
chat: ChatMessageType;
|
||||||
|
lockChat: boolean;
|
||||||
|
}) {
|
||||||
const convert = new Convert({ newline: true });
|
const convert = new Convert({ newline: true });
|
||||||
const [message, setMessage] = useState("");
|
const [message, setMessage] = useState("");
|
||||||
const imgRef = useRef(null);
|
const imgRef = useRef(null);
|
||||||
|
|
@ -35,11 +41,27 @@ export default function ChatMessage({ chat, lockChat }: { chat: ChatMessageType,
|
||||||
"rounded-full overflow-hidden w-8 h-8 flex items-center my-3 justify-center"
|
"rounded-full overflow-hidden w-8 h-8 flex items-center my-3 justify-center"
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{!chat.isSend && <div className="relative w-8 h-8">
|
{!chat.isSend && (
|
||||||
<img className={"absolute transition-opacity duration-500 scale-150 " + (lockChat ? "opacity-100" : "opacity-0")} src={AiIcon} />
|
<div className="relative w-8 h-8">
|
||||||
<img className={"absolute transition-opacity duration-500 scale-150 " + (lockChat ? "opacity-0" : "opacity-100")} src={AiIconStill} />
|
<img
|
||||||
</div>}
|
className={
|
||||||
{chat.isSend && <UserIcon className="w-6 h-6 -mb-1 text-gray-800 dark:text-gray-200" />}
|
"absolute transition-opacity duration-500 scale-150 " +
|
||||||
|
(lockChat ? "opacity-100" : "opacity-0")
|
||||||
|
}
|
||||||
|
src={AiIcon}
|
||||||
|
/>
|
||||||
|
<img
|
||||||
|
className={
|
||||||
|
"absolute transition-opacity duration-500 scale-150 " +
|
||||||
|
(lockChat ? "opacity-0" : "opacity-100")
|
||||||
|
}
|
||||||
|
src={AiIconStill}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{chat.isSend && (
|
||||||
|
<UserIcon className="w-6 h-6 -mb-1 text-gray-800 dark:text-gray-200" />
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
{!chat.isSend ? (
|
{!chat.isSend ? (
|
||||||
<div className="w-full text-start flex items-center">
|
<div className="w-full text-start flex items-center">
|
||||||
|
|
|
||||||
|
|
@ -236,11 +236,14 @@ export default function ChatModal({
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if((ws.current.readyState=== ws.current.CLOSED || ws.current.readyState=== ws.current.CLOSING)){
|
if (
|
||||||
|
ws.current.readyState === ws.current.CLOSED ||
|
||||||
|
ws.current.readyState === ws.current.CLOSING
|
||||||
|
) {
|
||||||
connectWS();
|
connectWS();
|
||||||
setLockChat(false);
|
setLockChat(false);
|
||||||
}
|
}
|
||||||
},[lockChat]);
|
}, [lockChat]);
|
||||||
|
|
||||||
async function sendAll(data: sendAllProps) {
|
async function sendAll(data: sendAllProps) {
|
||||||
try {
|
try {
|
||||||
|
|
@ -346,7 +349,7 @@ export default function ChatModal({
|
||||||
function clearChat() {
|
function clearChat() {
|
||||||
setChatHistory([]);
|
setChatHistory([]);
|
||||||
ws.current.send(JSON.stringify({ clear_history: true }));
|
ws.current.send(JSON.stringify({ clear_history: true }));
|
||||||
if(lockChat) setLockChat(false);
|
if (lockChat) setLockChat(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
function setModalOpen(x: boolean) {
|
function setModalOpen(x: boolean) {
|
||||||
|
|
|
||||||
|
|
@ -151,7 +151,6 @@ export default function ExportModal() {
|
||||||
id="checkbox"
|
id="checkbox"
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
className="h-4 w-4 text-blue-600 border-gray-300 rounded dark:bg-gray-800 dark:border-gray-600 dark:focus:border-blue-500 dark:focus:ring-blue-500"
|
className="h-4 w-4 text-blue-600 border-gray-300 rounded dark:bg-gray-800 dark:border-gray-600 dark:focus:border-blue-500 dark:focus:ring-blue-500"
|
||||||
|
|
||||||
/>
|
/>
|
||||||
<span className="ml-2 font-medium text-gray-700 dark:text-white">
|
<span className="ml-2 font-medium text-gray-700 dark:text-white">
|
||||||
Save with my API keys
|
Save with my API keys
|
||||||
|
|
|
||||||
|
|
@ -75,7 +75,6 @@ export default function ButtonBox({
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<button disabled={deactivate} onClick={onClick}>
|
<button disabled={deactivate} onClick={onClick}>
|
||||||
<div
|
<div
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,9 @@ export default function TabsManagerComponent() {
|
||||||
/>
|
/>
|
||||||
<div className="ml-auto mr-2 flex gap-3">
|
<div className="ml-auto mr-2 flex gap-3">
|
||||||
<button
|
<button
|
||||||
onClick={() => openPopUp(<ApiModal flowName={flows[tabIndex].name} />)}
|
onClick={() =>
|
||||||
|
openPopUp(<ApiModal flowName={flows[tabIndex].name} />)
|
||||||
|
}
|
||||||
className="flex items-center gap-1 pr-2 border-gray-400 border-r text-sm text-gray-600 hover:text-gray-500 dark:text-gray-300 dark:hover:text-gray-200"
|
className="flex items-center gap-1 pr-2 border-gray-400 border-r text-sm text-gray-600 hover:text-gray-500 dark:text-gray-300 dark:hover:text-gray-200"
|
||||||
>
|
>
|
||||||
Code <CodeBracketSquareIcon className="w-5 h-5" />
|
Code <CodeBracketSquareIcon className="w-5 h-5" />
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { useCallback, useContext, useEffect, useState } from 'react';
|
import { useCallback, useContext, useEffect, useState } from "react";
|
||||||
import { Edge, Node, useReactFlow } from 'reactflow';
|
import { Edge, Node, useReactFlow } from "reactflow";
|
||||||
import { TabsContext } from '../../../contexts/tabsContext';
|
import { TabsContext } from "../../../contexts/tabsContext";
|
||||||
import { cloneDeep } from 'lodash';
|
import { cloneDeep } from "lodash";
|
||||||
|
|
||||||
type UseUndoRedoOptions = {
|
type UseUndoRedoOptions = {
|
||||||
maxHistorySize: number;
|
maxHistorySize: number;
|
||||||
|
|
@ -34,23 +34,25 @@ export const useUndoRedo: UseUndoRedo = ({
|
||||||
// the past and future arrays store the states that we can jump to
|
// the past and future arrays store the states that we can jump to
|
||||||
const { tabIndex, flows } = useContext(TabsContext);
|
const { tabIndex, flows } = useContext(TabsContext);
|
||||||
|
|
||||||
const [past, setPast] = useState<HistoryItem[][]>(flows.map(()=>[]));
|
const [past, setPast] = useState<HistoryItem[][]>(flows.map(() => []));
|
||||||
const [future, setFuture] = useState<HistoryItem[][]>(flows.map(()=>[]));
|
const [future, setFuture] = useState<HistoryItem[][]>(flows.map(() => []));
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// whenever the flows variable changes, we need to add one array to the past and future states
|
// whenever the flows variable changes, we need to add one array to the past and future states
|
||||||
setPast((old) => flows.map((f, i)=>old[i] ? old[i] : []));
|
setPast((old) => flows.map((f, i) => (old[i] ? old[i] : [])));
|
||||||
setFuture((old) => flows.map((f, i)=>old[i] ? old[i] : []));
|
setFuture((old) => flows.map((f, i) => (old[i] ? old[i] : [])));
|
||||||
}, [flows]);
|
}, [flows]);
|
||||||
|
|
||||||
|
|
||||||
const { setNodes, setEdges, getNodes, getEdges } = useReactFlow();
|
const { setNodes, setEdges, getNodes, getEdges } = useReactFlow();
|
||||||
|
|
||||||
const takeSnapshot = useCallback(() => {
|
const takeSnapshot = useCallback(() => {
|
||||||
// push the current graph to the past state
|
// push the current graph to the past state
|
||||||
setPast((old) => {
|
setPast((old) => {
|
||||||
let newPast = cloneDeep(old);
|
let newPast = cloneDeep(old);
|
||||||
newPast[tabIndex] = old[tabIndex].slice(old[tabIndex].length - maxHistorySize + 1, old[tabIndex].length);
|
newPast[tabIndex] = old[tabIndex].slice(
|
||||||
|
old[tabIndex].length - maxHistorySize + 1,
|
||||||
|
old[tabIndex].length
|
||||||
|
);
|
||||||
newPast[tabIndex].push({ nodes: getNodes(), edges: getEdges() });
|
newPast[tabIndex].push({ nodes: getNodes(), edges: getEdges() });
|
||||||
return newPast;
|
return newPast;
|
||||||
});
|
});
|
||||||
|
|
@ -59,9 +61,18 @@ export const useUndoRedo: UseUndoRedo = ({
|
||||||
setFuture((old) => {
|
setFuture((old) => {
|
||||||
let newFuture = cloneDeep(old);
|
let newFuture = cloneDeep(old);
|
||||||
newFuture[tabIndex] = [];
|
newFuture[tabIndex] = [];
|
||||||
return newFuture
|
return newFuture;
|
||||||
});
|
});
|
||||||
}, [getNodes, getEdges, past, future, tabIndex, setPast, setFuture, maxHistorySize]);
|
}, [
|
||||||
|
getNodes,
|
||||||
|
getEdges,
|
||||||
|
past,
|
||||||
|
future,
|
||||||
|
tabIndex,
|
||||||
|
setPast,
|
||||||
|
setFuture,
|
||||||
|
maxHistorySize,
|
||||||
|
]);
|
||||||
|
|
||||||
const undo = useCallback(() => {
|
const undo = useCallback(() => {
|
||||||
// get the last state that we want to go back to
|
// get the last state that we want to go back to
|
||||||
|
|
@ -72,20 +83,30 @@ export const useUndoRedo: UseUndoRedo = ({
|
||||||
setPast((old) => {
|
setPast((old) => {
|
||||||
let newPast = cloneDeep(old);
|
let newPast = cloneDeep(old);
|
||||||
newPast[tabIndex] = old[tabIndex].slice(0, old[tabIndex].length - 1);
|
newPast[tabIndex] = old[tabIndex].slice(0, old[tabIndex].length - 1);
|
||||||
return newPast
|
return newPast;
|
||||||
});
|
});
|
||||||
// we store the current graph for the redo operation
|
// we store the current graph for the redo operation
|
||||||
setFuture((old) => {
|
setFuture((old) => {
|
||||||
let newFuture = cloneDeep(old);
|
let newFuture = cloneDeep(old);
|
||||||
newFuture[tabIndex] = old[tabIndex]
|
newFuture[tabIndex] = old[tabIndex];
|
||||||
newFuture[tabIndex].push({ nodes: getNodes(), edges: getEdges() });
|
newFuture[tabIndex].push({ nodes: getNodes(), edges: getEdges() });
|
||||||
return newFuture
|
return newFuture;
|
||||||
});
|
});
|
||||||
// now we can set the graph to the past state
|
// now we can set the graph to the past state
|
||||||
setNodes(pastState.nodes);
|
setNodes(pastState.nodes);
|
||||||
setEdges(pastState.edges);
|
setEdges(pastState.edges);
|
||||||
}
|
}
|
||||||
}, [setNodes, setEdges, getNodes, getEdges, future, past, setFuture, setPast, tabIndex]);
|
}, [
|
||||||
|
setNodes,
|
||||||
|
setEdges,
|
||||||
|
getNodes,
|
||||||
|
getEdges,
|
||||||
|
future,
|
||||||
|
past,
|
||||||
|
setFuture,
|
||||||
|
setPast,
|
||||||
|
tabIndex,
|
||||||
|
]);
|
||||||
|
|
||||||
const redo = useCallback(() => {
|
const redo = useCallback(() => {
|
||||||
const futureState = future[tabIndex][future[tabIndex].length - 1];
|
const futureState = future[tabIndex][future[tabIndex].length - 1];
|
||||||
|
|
@ -94,18 +115,29 @@ export const useUndoRedo: UseUndoRedo = ({
|
||||||
setFuture((old) => {
|
setFuture((old) => {
|
||||||
let newFuture = cloneDeep(old);
|
let newFuture = cloneDeep(old);
|
||||||
newFuture[tabIndex] = old[tabIndex].slice(0, old[tabIndex].length - 1);
|
newFuture[tabIndex] = old[tabIndex].slice(0, old[tabIndex].length - 1);
|
||||||
return newFuture
|
return newFuture;
|
||||||
});
|
});
|
||||||
setPast((old) => {
|
setPast((old) => {
|
||||||
let newPast = cloneDeep(old);
|
let newPast = cloneDeep(old);
|
||||||
newPast[tabIndex] = old[tabIndex];
|
newPast[tabIndex] = old[tabIndex];
|
||||||
newPast[tabIndex].push({ nodes: getNodes(), edges: getEdges() });
|
newPast[tabIndex].push({ nodes: getNodes(), edges: getEdges() });
|
||||||
return newPast
|
return newPast;
|
||||||
});
|
});
|
||||||
setNodes(futureState.nodes);
|
setNodes(futureState.nodes);
|
||||||
setEdges(futureState.edges);
|
setEdges(futureState.edges);
|
||||||
}
|
}
|
||||||
}, [future, past, setFuture, setPast, setNodes, setEdges, getNodes, getEdges, future, tabIndex]);
|
}, [
|
||||||
|
future,
|
||||||
|
past,
|
||||||
|
setFuture,
|
||||||
|
setPast,
|
||||||
|
setNodes,
|
||||||
|
setEdges,
|
||||||
|
getNodes,
|
||||||
|
getEdges,
|
||||||
|
future,
|
||||||
|
tabIndex,
|
||||||
|
]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// this effect is used to attach the global event handlers
|
// this effect is used to attach the global event handlers
|
||||||
|
|
@ -114,21 +146,24 @@ export const useUndoRedo: UseUndoRedo = ({
|
||||||
}
|
}
|
||||||
|
|
||||||
const keyDownHandler = (event: KeyboardEvent) => {
|
const keyDownHandler = (event: KeyboardEvent) => {
|
||||||
if (event.key === 'z' && (event.ctrlKey || event.metaKey) && event.shiftKey) {
|
if (
|
||||||
|
event.key === "z" &&
|
||||||
|
(event.ctrlKey || event.metaKey) &&
|
||||||
|
event.shiftKey
|
||||||
|
) {
|
||||||
redo();
|
redo();
|
||||||
}
|
} else if (event.key === "y" && (event.ctrlKey || event.metaKey)) {
|
||||||
else if (event.key === 'y' && (event.ctrlKey || event.metaKey)) {
|
|
||||||
event.preventDefault(); // prevent the default action
|
event.preventDefault(); // prevent the default action
|
||||||
redo();
|
redo();
|
||||||
} else if (event.key === 'z' && (event.ctrlKey || event.metaKey)) {
|
} else if (event.key === "z" && (event.ctrlKey || event.metaKey)) {
|
||||||
undo();
|
undo();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
document.addEventListener('keydown', keyDownHandler);
|
document.addEventListener("keydown", keyDownHandler);
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
document.removeEventListener('keydown', keyDownHandler);
|
document.removeEventListener("keydown", keyDownHandler);
|
||||||
};
|
};
|
||||||
}, [undo, redo, enableShortcuts]);
|
}, [undo, redo, enableShortcuts]);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -302,10 +302,10 @@ export default function FlowPage({ flow }: { flow: FlowType }) {
|
||||||
setLastSelection(flow);
|
setLastSelection(flow);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const {setDisableCopyPaste} = useContext(TabsContext)
|
const { setDisableCopyPaste } = useContext(TabsContext);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="w-full h-full" ref={reactFlowWrapper} >
|
<div className="w-full h-full" ref={reactFlowWrapper}>
|
||||||
{Object.keys(templates).length > 0 && Object.keys(types).length > 0 ? (
|
{Object.keys(templates).length > 0 && Object.keys(types).length > 0 ? (
|
||||||
<>
|
<>
|
||||||
<ReactFlow
|
<ReactFlow
|
||||||
|
|
@ -314,9 +314,15 @@ export default function FlowPage({ flow }: { flow: FlowType }) {
|
||||||
updateFlow({ ...flow, data: reactFlowInstance.toObject() });
|
updateFlow({ ...flow, data: reactFlowInstance.toObject() });
|
||||||
}}
|
}}
|
||||||
edges={edges}
|
edges={edges}
|
||||||
onPaneClick={() => {setDisableCopyPaste(false);}}
|
onPaneClick={() => {
|
||||||
onNodeClick={() => {setDisableCopyPaste(true);}}
|
setDisableCopyPaste(false);
|
||||||
onPaneMouseLeave={() => {setDisableCopyPaste(true);}}
|
}}
|
||||||
|
onNodeClick={() => {
|
||||||
|
setDisableCopyPaste(true);
|
||||||
|
}}
|
||||||
|
onPaneMouseLeave={() => {
|
||||||
|
setDisableCopyPaste(true);
|
||||||
|
}}
|
||||||
onNodesChange={onNodesChange}
|
onNodesChange={onNodesChange}
|
||||||
onEdgesChange={onEdgesChangeMod}
|
onEdgesChange={onEdgesChangeMod}
|
||||||
onConnect={onConnect}
|
onConnect={onConnect}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,9 @@
|
||||||
import { ForwardRefExoticComponent, ReactElement, ReactFragment, ReactNode } from "react";
|
import {
|
||||||
|
ForwardRefExoticComponent,
|
||||||
|
ReactElement,
|
||||||
|
ReactFragment,
|
||||||
|
ReactNode,
|
||||||
|
} from "react";
|
||||||
import { NodeDataType } from "../flow/index";
|
import { NodeDataType } from "../flow/index";
|
||||||
export type InputComponentType = {
|
export type InputComponentType = {
|
||||||
value: string;
|
value: string;
|
||||||
|
|
|
||||||
|
|
@ -6,17 +6,20 @@ export type TabsContextType = {
|
||||||
setTabIndex: (index: number) => void;
|
setTabIndex: (index: number) => void;
|
||||||
flows: Array<FlowType>;
|
flows: Array<FlowType>;
|
||||||
removeFlow: (id: string) => void;
|
removeFlow: (id: string) => void;
|
||||||
addFlow: (flowData?: FlowType,newFlow?:boolean) => void;
|
addFlow: (flowData?: FlowType, newFlow?: boolean) => void;
|
||||||
updateFlow: (newFlow: FlowType) => void;
|
updateFlow: (newFlow: FlowType) => void;
|
||||||
incrementNodeId: () => string;
|
incrementNodeId: () => string;
|
||||||
downloadFlow: (flow: FlowType) => void;
|
downloadFlow: (flow: FlowType) => void;
|
||||||
uploadFlow: (newFlow?:boolean) => void;
|
uploadFlow: (newFlow?: boolean) => void;
|
||||||
hardReset: () => void;
|
hardReset: () => void;
|
||||||
//disable CopyPaste
|
//disable CopyPaste
|
||||||
disableCopyPaste: boolean;
|
disableCopyPaste: boolean;
|
||||||
setDisableCopyPaste: (value: boolean) => void;
|
setDisableCopyPaste: (value: boolean) => void;
|
||||||
getNodeId: () => string;
|
getNodeId: () => string;
|
||||||
paste: (selection: {nodes: any, edges: any}, position: {x: number, y: number}) => void;
|
paste: (
|
||||||
|
selection: { nodes: any; edges: any },
|
||||||
|
position: { x: number; y: number }
|
||||||
|
) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type LangFlowState = {
|
export type LangFlowState = {
|
||||||
|
|
|
||||||
|
|
@ -317,11 +317,9 @@ export function toFirstUpperCase(str: string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function snakeToSpaces(str: string) {
|
export function snakeToSpaces(str: string) {
|
||||||
let result = str
|
let result = str.split("_").join(" ");
|
||||||
.split("_")
|
|
||||||
.join(" ");
|
|
||||||
|
|
||||||
return result
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function toNormalCase(str: string) {
|
export function toNormalCase(str: string) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue