Formatting

This commit is contained in:
Gabriel Almeida 2023-05-27 13:01:20 -03:00
commit 276a06976d
65 changed files with 4515 additions and 4390 deletions

View file

@ -34,7 +34,10 @@ export default function SingleAlert({
key={dropItem.id}
>
<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 className="ml-3">
<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">
<ul className="list-disc space-y-1 pl-5">
{dropItem.list.map((item, idx) => (
<li className="break-words" key={idx}>{item}</li>
<li className="break-words" key={idx}>
{item}
</li>
))}
</ul>
</div>
@ -82,7 +87,9 @@ export default function SingleAlert({
/>
</div>
<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">
{dropItem.link ? (
<Link

View file

@ -43,10 +43,15 @@ export default function ErrorAlert({
>
<div className="flex">
<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 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 ? (
<div className="mt-2 text-sm text-red-700 dark:text-red-50">
<ul className="list-disc space-y-1 pl-5">

View file

@ -44,7 +44,9 @@ export default function SuccessAlert({
/>
</div>
<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>

View file

@ -28,7 +28,6 @@ export default function FloatComponent({
setMyValue(e.target.value);
onChange(e.target.value);
}}
/>
</div>
);

View file

@ -27,7 +27,6 @@ export default function InputComponent({
>
<input
value={myValue}
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",
disabled ? " bg-gray-200 dark:bg-gray-700" : "",

View file

@ -44,9 +44,7 @@ export default function IntComponent({
setMyValue(e.target.value);
onChange(e.target.value);
}}
/>
</div>
);
}

View file

@ -4,7 +4,11 @@ import { PopUpContext } from "../../contexts/popUpContext";
import TextAreaModal from "../../modals/textAreaModal";
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 { openPopUp } = useContext(PopUpContext);
useEffect(() => {
@ -16,15 +20,38 @@ export default function TextAreaComponent({ value, onChange, disabled }:TextArea
return (
<div className={disabled ? "pointer-events-none cursor-not-allowed" : ""}>
<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={
"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" : "")
}
>
{myValue !== "" ? myValue : 'Text empty'}
{myValue !== "" ? myValue : "Text empty"}
</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" />
</button>
</div>

View file

@ -21,8 +21,8 @@ export default function ToggleComponent({
setEnabled(x);
}}
className={classNames(
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'
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"
)}
>
<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"
)}
aria-hidden="true"
>
</span>
></span>
<span
className={classNames(
enabled
@ -53,8 +52,7 @@ export default function ToggleComponent({
"absolute inset-0 flex h-full w-full items-center justify-center transition-opacity"
)}
aria-hidden="true"
>
</span>
></span>
</span>
</Switch>
</div>

View file

@ -27,10 +27,13 @@ const TabsContextInitialValue: TabsContextType = {
downloadFlow: (flow: FlowType) => {},
uploadFlow: () => {},
hardReset: () => {},
disableCopyPaste:false,
setDisableCopyPaste:(state:boolean)=>{},
disableCopyPaste: false,
setDisableCopyPaste: (state: boolean) => {},
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>(
@ -53,20 +56,21 @@ export function TabsProvider({ children }: { children: ReactNode }) {
let Saveflows = [...flows];
if (Saveflows.length !== 0)
Saveflows.forEach((flow) => {
if(flow.data && flow.data?.nodes) flow.data?.nodes.forEach((node) => {
console.log(node.data.type)
if (flow.data && flow.data?.nodes)
flow.data?.nodes.forEach((node) => {
console.log(node.data.type);
Object.keys(node.data.node.template).forEach((key) => {
console.log(node.data.node.template[key].type)
if(node.data.node.template[key].type==="file"){
console.log(node.data.node.template[key])
console.log(node.data.node.template[key].type);
if (node.data.node.template[key].type === "file") {
console.log(node.data.node.template[key]);
node.data.node.template[key].content = "";
}
})
})
})
});
});
});
window.localStorage.setItem(
"tabsData",
JSON.stringify({ tabIndex, flows:Saveflows, id})
JSON.stringify({ tabIndex, flows: Saveflows, id })
);
}
useEffect(() => {
@ -184,7 +188,7 @@ export function TabsProvider({ children }: { children: ReactNode }) {
* @param flow Optional flow to add.
*/
function paste(selectionInstance, position){
function paste(selectionInstance, position) {
let minimumX = Infinity;
let minimumY = Infinity;
let idsMap = {};
@ -223,7 +227,7 @@ export function TabsProvider({ children }: { children: ReactNode }) {
// Add the new node to the list of nodes in state
nodes = nodes
.map((e) => ({ ...e, selected: false }))
.concat({ ...newNode, selected: false })
.concat({ ...newNode, selected: false });
});
reactFlowInstance.setNodes(nodes);
@ -261,7 +265,7 @@ export function TabsProvider({ children }: { children: ReactNode }) {
);
});
reactFlowInstance.setEdges(edges);
};
}
function addFlow(flow?: FlowType) {
// Get data from the flow or set it to null if there's no flow provided.

View file

@ -5,7 +5,7 @@ import reportWebVitals from "./reportWebVitals";
import { BrowserRouter } from "react-router-dom";
import ContextWrapper from "./contexts";
import './index.css';
import "./index.css";
const root = ReactDOM.createRoot(
document.getElementById("root") as HTMLElement

View file

@ -1,6 +1,10 @@
import { Dialog, Transition } from "@headlessui/react";
import { IconCheck, IconClipboard, IconDownload } from '@tabler/icons-react';
import { XMarkIcon, CommandLineIcon, CodeBracketSquareIcon } from "@heroicons/react/24/outline";
import { IconCheck, IconClipboard, IconDownload } from "@tabler/icons-react";
import {
XMarkIcon,
CommandLineIcon,
CodeBracketSquareIcon,
} from "@heroicons/react/24/outline";
import { Fragment, useContext, useRef, useState } from "react";
import { PopUpContext } from "../../contexts/popUpContext";
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/webpack-resolver";
import { darkContext } from "../../contexts/darkContext";
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
import { oneDark } from 'react-syntax-highlighter/dist/cjs/styles/prism';
import { Prism as SyntaxHighlighter } from "react-syntax-highlighter";
import { oneDark } from "react-syntax-highlighter/dist/cjs/styles/prism";
export default function ApiModal({ flowName }) {
const [open, setOpen] = useState(true);
@ -68,7 +70,8 @@ flow("Hey, have you heard of LangFlow?")`;
{
name: "Python API",
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,
},
{
@ -77,8 +80,7 @@ flow("Hey, have you heard of LangFlow?")`;
image: "https://cdn-icons-png.flaticon.com/512/5968/5968350.png",
code: pythonCode,
},
]
];
return (
<Transition.Root show={open} appear={true} as={Fragment}>
<Dialog
@ -144,9 +146,17 @@ flow("Hey, have you heard of LangFlow?")`;
<div className="flex flex-col h-full w-full ">
<div className="flex px-5 z-10">
{tabs.map((tab, index) => (
<button onClick={() => {
<button
onClick={() => {
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}
<img src={tab.image} className="w-6" />
</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"
onClick={copyToClipboard}
>
{isCopied ? <IconCheck size={18} /> : <IconClipboard size={18} />}
{isCopied ? 'Copied!' : 'Copy code'}
{isCopied ? (
<IconCheck size={18} />
) : (
<IconClipboard size={18} />
)}
{isCopied ? "Copied!" : "Copy code"}
</button>
</div>
<SyntaxHighlighter

View file

@ -3,7 +3,7 @@ import { useEffect, useRef, useState } from "react";
import { ChatMessageType } from "../../../types/chat";
import { classNames } from "../../../utils";
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 FileCard from "../fileComponent";
import ReactMarkdown from "react-markdown";
@ -13,7 +13,13 @@ import remarkMath from "remark-math";
import { CodeBlock } from "./codeBlock";
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 [message, setMessage] = useState("");
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"
)}
>
{!chat.isSend && <div className="relative w-8 h-8">
<img className={"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" />}
{!chat.isSend && (
<div className="relative w-8 h-8">
<img
className={
"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>
{!chat.isSend ? (
<div className="w-full text-start flex items-center">

View file

@ -236,11 +236,14 @@ export default function ChatModal({
}, []);
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();
setLockChat(false);
}
},[lockChat]);
}, [lockChat]);
async function sendAll(data: sendAllProps) {
try {
@ -346,7 +349,7 @@ export default function ChatModal({
function clearChat() {
setChatHistory([]);
ws.current.send(JSON.stringify({ clear_history: true }));
if(lockChat) setLockChat(false);
if (lockChat) setLockChat(false);
}
function setModalOpen(x: boolean) {

View file

@ -151,7 +151,6 @@ export default function ExportModal() {
id="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"
/>
<span className="ml-2 font-medium text-gray-700 dark:text-white">
Save with my API keys

View file

@ -75,7 +75,6 @@ export default function ButtonBox({
break;
}
return (
<button disabled={deactivate} onClick={onClick}>
<div

View file

@ -58,7 +58,9 @@ export default function TabsManagerComponent() {
/>
<div className="ml-auto mr-2 flex gap-3">
<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"
>
Code <CodeBracketSquareIcon className="w-5 h-5" />

View file

@ -1,7 +1,7 @@
import { useCallback, useContext, useEffect, useState } from 'react';
import { Edge, Node, useReactFlow } from 'reactflow';
import { TabsContext } from '../../../contexts/tabsContext';
import { cloneDeep } from 'lodash';
import { useCallback, useContext, useEffect, useState } from "react";
import { Edge, Node, useReactFlow } from "reactflow";
import { TabsContext } from "../../../contexts/tabsContext";
import { cloneDeep } from "lodash";
type UseUndoRedoOptions = {
maxHistorySize: number;
@ -34,23 +34,25 @@ export const useUndoRedo: UseUndoRedo = ({
// the past and future arrays store the states that we can jump to
const { tabIndex, flows } = useContext(TabsContext);
const [past, setPast] = useState<HistoryItem[][]>(flows.map(()=>[]));
const [future, setFuture] = useState<HistoryItem[][]>(flows.map(()=>[]));
const [past, setPast] = useState<HistoryItem[][]>(flows.map(() => []));
const [future, setFuture] = useState<HistoryItem[][]>(flows.map(() => []));
useEffect(() => {
// 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] : []));
setFuture((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] : [])));
}, [flows]);
const { setNodes, setEdges, getNodes, getEdges } = useReactFlow();
const takeSnapshot = useCallback(() => {
// push the current graph to the past state
setPast((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() });
return newPast;
});
@ -59,9 +61,18 @@ export const useUndoRedo: UseUndoRedo = ({
setFuture((old) => {
let newFuture = cloneDeep(old);
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(() => {
// get the last state that we want to go back to
@ -72,20 +83,30 @@ export const useUndoRedo: UseUndoRedo = ({
setPast((old) => {
let newPast = cloneDeep(old);
newPast[tabIndex] = old[tabIndex].slice(0, old[tabIndex].length - 1);
return newPast
return newPast;
});
// we store the current graph for the redo operation
setFuture((old) => {
let newFuture = cloneDeep(old);
newFuture[tabIndex] = old[tabIndex]
newFuture[tabIndex] = old[tabIndex];
newFuture[tabIndex].push({ nodes: getNodes(), edges: getEdges() });
return newFuture
return newFuture;
});
// now we can set the graph to the past state
setNodes(pastState.nodes);
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 futureState = future[tabIndex][future[tabIndex].length - 1];
@ -94,18 +115,29 @@ export const useUndoRedo: UseUndoRedo = ({
setFuture((old) => {
let newFuture = cloneDeep(old);
newFuture[tabIndex] = old[tabIndex].slice(0, old[tabIndex].length - 1);
return newFuture
return newFuture;
});
setPast((old) => {
let newPast = cloneDeep(old);
newPast[tabIndex] = old[tabIndex];
newPast[tabIndex].push({ nodes: getNodes(), edges: getEdges() });
return newPast
return newPast;
});
setNodes(futureState.nodes);
setEdges(futureState.edges);
}
}, [future, past, setFuture, setPast, setNodes, setEdges, getNodes, getEdges, future, tabIndex]);
}, [
future,
past,
setFuture,
setPast,
setNodes,
setEdges,
getNodes,
getEdges,
future,
tabIndex,
]);
useEffect(() => {
// this effect is used to attach the global event handlers
@ -114,21 +146,24 @@ export const useUndoRedo: UseUndoRedo = ({
}
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();
}
else if (event.key === 'y' && (event.ctrlKey || event.metaKey)) {
} else if (event.key === "y" && (event.ctrlKey || event.metaKey)) {
event.preventDefault(); // prevent the default action
redo();
} else if (event.key === 'z' && (event.ctrlKey || event.metaKey)) {
} else if (event.key === "z" && (event.ctrlKey || event.metaKey)) {
undo();
}
};
document.addEventListener('keydown', keyDownHandler);
document.addEventListener("keydown", keyDownHandler);
return () => {
document.removeEventListener('keydown', keyDownHandler);
document.removeEventListener("keydown", keyDownHandler);
};
}, [undo, redo, enableShortcuts]);

View file

@ -302,10 +302,10 @@ export default function FlowPage({ flow }: { flow: FlowType }) {
setLastSelection(flow);
}, []);
const {setDisableCopyPaste} = useContext(TabsContext)
const { setDisableCopyPaste } = useContext(TabsContext);
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 ? (
<>
<ReactFlow
@ -314,9 +314,15 @@ export default function FlowPage({ flow }: { flow: FlowType }) {
updateFlow({ ...flow, data: reactFlowInstance.toObject() });
}}
edges={edges}
onPaneClick={() => {setDisableCopyPaste(false);}}
onNodeClick={() => {setDisableCopyPaste(true);}}
onPaneMouseLeave={() => {setDisableCopyPaste(true);}}
onPaneClick={() => {
setDisableCopyPaste(false);
}}
onNodeClick={() => {
setDisableCopyPaste(true);
}}
onPaneMouseLeave={() => {
setDisableCopyPaste(true);
}}
onNodesChange={onNodesChange}
onEdgesChange={onEdgesChangeMod}
onConnect={onConnect}

View file

@ -1,4 +1,9 @@
import { ForwardRefExoticComponent, ReactElement, ReactFragment, ReactNode } from "react";
import {
ForwardRefExoticComponent,
ReactElement,
ReactFragment,
ReactNode,
} from "react";
import { NodeDataType } from "../flow/index";
export type InputComponentType = {
value: string;

View file

@ -6,17 +6,20 @@ export type TabsContextType = {
setTabIndex: (index: number) => void;
flows: Array<FlowType>;
removeFlow: (id: string) => void;
addFlow: (flowData?: FlowType,newFlow?:boolean) => void;
addFlow: (flowData?: FlowType, newFlow?: boolean) => void;
updateFlow: (newFlow: FlowType) => void;
incrementNodeId: () => string;
downloadFlow: (flow: FlowType) => void;
uploadFlow: (newFlow?:boolean) => void;
uploadFlow: (newFlow?: boolean) => void;
hardReset: () => void;
//disable CopyPaste
disableCopyPaste: boolean;
setDisableCopyPaste: (value: boolean) => void;
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 = {

View file

@ -317,11 +317,9 @@ export function toFirstUpperCase(str: string) {
}
export function snakeToSpaces(str: string) {
let result = str
.split("_")
.join(" ");
let result = str.split("_").join(" ");
return result
return result;
}
export function toNormalCase(str: string) {