Format code

This commit is contained in:
igorrCarvalho 2024-05-02 20:54:25 -03:00
commit 8967a2694e
23 changed files with 411 additions and 334 deletions

View file

@ -1,7 +1,5 @@
from typing import Optional from typing import Optional
from langflow.field_typing import Text
from langflow.helpers.record import records_to_text
from langflow.interface.custom.custom_component import CustomComponent from langflow.interface.custom.custom_component import CustomComponent
from langflow.schema.schema import Record from langflow.schema.schema import Record

View file

@ -5,7 +5,6 @@ import orjson
from langchain_community.vectorstores import ( from langchain_community.vectorstores import (
FAISS, FAISS,
Chroma, Chroma,
ElasticsearchStore,
MongoDBAtlasVectorSearch, MongoDBAtlasVectorSearch,
Pinecone, Pinecone,
Qdrant, Qdrant,

View file

@ -4,7 +4,6 @@ from typing import Literal, Optional, cast
from langchain_core.documents import Document from langchain_core.documents import Document
from langchain_core.messages import AIMessage, BaseMessage, HumanMessage from langchain_core.messages import AIMessage, BaseMessage, HumanMessage
from pydantic import BaseModel, model_validator from pydantic import BaseModel, model_validator
from langchain_core.messages import HumanMessage, AIMessage
class Record(BaseModel): class Record(BaseModel):

View file

@ -1,54 +1,67 @@
import { saveAs } from "file-saver";
import OpenSeadragon from "openseadragon";
import { useEffect, useRef, useState } from "react"; import { useEffect, useRef, useState } from "react";
import ForwardedIconComponent from "../genericIconComponent";
import useFlowStore from "../../stores/flowStore";
import OpenSeadragon from 'openseadragon';
import { Separator } from "../ui/separator";
import { saveAs } from 'file-saver'
import useAlertStore from "../../stores/alertStore";
import { IMGViewErrorMSG, IMGViewErrorTitle } from "../../constants/constants"; import { IMGViewErrorMSG, IMGViewErrorTitle } from "../../constants/constants";
import useAlertStore from "../../stores/alertStore";
import ForwardedIconComponent from "../genericIconComponent";
import { Separator } from "../ui/separator";
export default function ImageViewer({ image }) { export default function ImageViewer({ image }) {
const viewerRef = useRef(null); const viewerRef = useRef(null);
const [errorDownloading, setErrordownloading] = useState(false) const [errorDownloading, setErrordownloading] = useState(false);
const setErrorList = useAlertStore(state => state.setErrorData); const setErrorList = useAlertStore((state) => state.setErrorData);
const [initialMsg, setInicialMsg] = useState("Please build your flow"); const [initialMsg, setInicialMsg] = useState("Please build your flow");
useEffect(() => { useEffect(() => {
try { try {
if (viewerRef.current) { if (viewerRef.current) {
// Initialize OpenSeadragon viewer // Initialize OpenSeadragon viewer
const viewer = OpenSeadragon({ const viewer = OpenSeadragon({
element: viewerRef.current, element: viewerRef.current,
prefixUrl: 'https://cdnjs.cloudflare.com/ajax/libs/openseadragon/2.4.2/images/', // Optional: Set the path to OpenSeadragon images prefixUrl:
tileSources: {type: 'image', url: image}, "https://cdnjs.cloudflare.com/ajax/libs/openseadragon/2.4.2/images/", // Optional: Set the path to OpenSeadragon images
tileSources: { type: "image", url: image },
defaultZoomLevel: 1, defaultZoomLevel: 1,
maxZoomPixelRatio: 4, maxZoomPixelRatio: 4,
showNavigationControl: false, showNavigationControl: false,
}); });
const zoomInButton = document.getElementById('zoom-in-button'); const zoomInButton = document.getElementById("zoom-in-button");
const zoomOutButton = document.getElementById('zoom-out-button'); const zoomOutButton = document.getElementById("zoom-out-button");
const homeButton = document.getElementById('home-button'); const homeButton = document.getElementById("home-button");
const fullPageButton = document.getElementById('full-page-button'); const fullPageButton = document.getElementById("full-page-button");
zoomInButton!.addEventListener('click', () => viewer.viewport.zoomBy(1.2)); zoomInButton!.addEventListener("click", () =>
zoomOutButton!.addEventListener('click', () => viewer.viewport.zoomBy(0.8)); viewer.viewport.zoomBy(1.2)
homeButton!.addEventListener('click', () => viewer.viewport.goHome()); );
fullPageButton!.addEventListener('click', () => viewer.setFullScreen(true)); zoomOutButton!.addEventListener("click", () =>
viewer.viewport.zoomBy(0.8)
);
homeButton!.addEventListener("click", () => viewer.viewport.goHome());
fullPageButton!.addEventListener("click", () =>
viewer.setFullScreen(true)
);
// Optionally, you can set additional viewer options here // Optionally, you can set additional viewer options here
// Cleanup function // Cleanup function
return () => { return () => {
viewer.destroy(); viewer.destroy();
zoomInButton!.removeEventListener('click', () => viewer.viewport.zoomBy(1.2)); zoomInButton!.removeEventListener("click", () =>
zoomOutButton!.removeEventListener('click', () => viewer.viewport.zoomBy(0.8)); viewer.viewport.zoomBy(1.2)
homeButton!.removeEventListener('click', () => viewer.viewport.goHome()); );
fullPageButton!.removeEventListener('click', () => viewer.setFullScreen(true)); zoomOutButton!.removeEventListener("click", () =>
viewer.viewport.zoomBy(0.8)
);
homeButton!.removeEventListener("click", () =>
viewer.viewport.goHome()
);
fullPageButton!.removeEventListener("click", () =>
viewer.setFullScreen(true)
);
}; };
} }
} catch (error) { } catch (error) {
console.error('Error initializing OpenSeadragon:', error); console.error("Error initializing OpenSeadragon:", error);
} }
}, [image]); }, [image]);
@ -56,86 +69,94 @@ export default function ImageViewer({image }) {
const imageUrl = image; const imageUrl = image;
// Fetch the image data // Fetch the image data
fetch(imageUrl) fetch(imageUrl)
.then(response => response.blob()) .then((response) => response.blob())
.then(blob => { .then((blob) => {
// Save the image using FileSaver.js // Save the image using FileSaver.js
saveAs(blob, 'image.jpg'); saveAs(blob, "image.jpg");
}) })
.catch(error => { .catch((error) => {
setErrorList({title: "There was an error downloading your image"}) setErrorList({ title: "There was an error downloading your image" });
console.error('Error downloading image:', error) console.error("Error downloading image:", error);
}); });
} }
return ( return image === "" ? (
image === "" ? ( <div className="align-center flex h-full w-full flex-col justify-center gap-5 rounded-md border border-border bg-muted">
<div className="w-full h-full bg-muted rounded-md flex align-center justify-center flex-col gap-5 border border-border"> <div className="align-center flex justify-center gap-2 ">
<div className="flex gap-2 align-center justify-center "> <ForwardedIconComponent name="Image" />
<ForwardedIconComponent
name="Image"
/>
{IMGViewErrorTitle} {IMGViewErrorTitle}
</div> </div>
<div className="flex align-center justify-center"> <div className="align-center flex justify-center">
<div className="langflow-chat-desc flex align-center justify-center"> <div className="langflow-chat-desc align-center flex justify-center">
<div className="langflow-chat-desc-span"> <div className="langflow-chat-desc-span">{IMGViewErrorMSG}</div>
{IMGViewErrorMSG}
</div>
</div> </div>
</div> </div>
</div> </div>
) : ( ) : (
<> <>
<div className="w-full flex align-center justify-center my-2 mb-4"> <div className="align-center my-2 mb-4 flex w-full justify-center">
<div className="shadow-round-btn-shadow hover:shadow-round-btn-shadow flex items-center justify-center rounded-sm border bg-muted shadow-md transition-all w-[50%]"> <div className="shadow-round-btn-shadow hover:shadow-round-btn-shadow flex w-[50%] items-center justify-center rounded-sm border bg-muted shadow-md transition-all">
<button id="zoom-in-button" className="relative inline-flex w-full items-center justify-center px-3 py-3 text-sm font-semibold transition-all w-full transition-all duration-500 ease-in-out ease-in-out hover:bg-hover"> <button
id="zoom-in-button"
className="relative inline-flex w-full w-full items-center justify-center px-3 py-3 text-sm font-semibold transition-all transition-all duration-500 ease-in-out ease-in-out hover:bg-hover"
>
<ForwardedIconComponent <ForwardedIconComponent
name="ZoomIn" name="ZoomIn"
className={"text-secondary-foreground w-5 h-5"} className={"h-5 w-5 text-secondary-foreground"}
/> />
</button> </button>
<div> <div>
<Separator orientation="vertical" /> <Separator orientation="vertical" />
</div> </div>
<button id="zoom-out-button" className="relative inline-flex w-full items-center justify-center px-3 py-3 text-sm font-semibold transition-all transition-all duration-500 ease-in-out ease-in-out hover:bg-hover"> <button
id="zoom-out-button"
className="relative inline-flex w-full items-center justify-center px-3 py-3 text-sm font-semibold transition-all transition-all duration-500 ease-in-out ease-in-out hover:bg-hover"
>
<ForwardedIconComponent <ForwardedIconComponent
name="ZoomOut" name="ZoomOut"
className={"text-secondary-foreground w-5 h-5"} className={"h-5 w-5 text-secondary-foreground"}
/> />
</button> </button>
<div> <div>
<Separator orientation="vertical" /> <Separator orientation="vertical" />
</div> </div>
<button id="home-button" className="relative inline-flex w-full items-center justify-center px-3 py-3 text-sm font-semibold transition-all transition-all duration-500 ease-in-out ease-in-out hover:bg-hover"> <button
id="home-button"
className="relative inline-flex w-full items-center justify-center px-3 py-3 text-sm font-semibold transition-all transition-all duration-500 ease-in-out ease-in-out hover:bg-hover"
>
<ForwardedIconComponent <ForwardedIconComponent
name="RotateCcw" name="RotateCcw"
className={"text-secondary-foreground w-5 h-5"} className={"h-5 w-5 text-secondary-foreground"}
/> />
</button> </button>
<div> <div>
<Separator orientation="vertical" /> <Separator orientation="vertical" />
</div> </div>
<button id="full-page-button" className="relative inline-flex w-full items-center justify-center px-3 py-3 text-sm font-semibold transition-all transition-all duration-500 ease-in-out ease-in-out hover:bg-hover"> <button
id="full-page-button"
className="relative inline-flex w-full items-center justify-center px-3 py-3 text-sm font-semibold transition-all transition-all duration-500 ease-in-out ease-in-out hover:bg-hover"
>
<ForwardedIconComponent <ForwardedIconComponent
name="Maximize2" name="Maximize2"
className={"text-secondary-foreground w-5 h-5"} className={"h-5 w-5 text-secondary-foreground"}
/> />
</button> </button>
<div> <div>
<Separator orientation="vertical" /> <Separator orientation="vertical" />
</div> </div>
<button onClick={download} className="relative inline-flex w-full items-center justify-center px-3 py-3 text-sm font-semibold transition-all transition-all duration-500 ease-in-out ease-in-out hover:bg-hover"> <button
onClick={download}
className="relative inline-flex w-full items-center justify-center px-3 py-3 text-sm font-semibold transition-all transition-all duration-500 ease-in-out ease-in-out hover:bg-hover"
>
<ForwardedIconComponent <ForwardedIconComponent
name="ArrowDownToLine" name="ArrowDownToLine"
className={"text-secondary-foreground w-5 h-5"} className={"h-5 w-5 text-secondary-foreground"}
/> />
</button> </button>
</div> </div>
</div> </div>
<div id="canvas" ref={viewerRef} className={`w-full h-[90%] `} /> <div id="canvas" ref={viewerRef} className={`h-[90%] w-full `} />
</> </>
)
); );
} }

View file

@ -22,9 +22,9 @@ export default function AddNewVariableButton({ children }): JSX.Element {
const [open, setOpen] = useState(false); const [open, setOpen] = useState(false);
const setErrorData = useAlertStore((state) => state.setErrorData); const setErrorData = useAlertStore((state) => state.setErrorData);
const componentFields = useTypesStore((state) => state.ComponentFields); const componentFields = useTypesStore((state) => state.ComponentFields);
const unavaliableFields =new Set(Object.keys(useGlobalVariablesStore( const unavaliableFields = new Set(
(state) => state.unavaliableFields Object.keys(useGlobalVariablesStore((state) => state.unavaliableFields))
))); );
const availableFields = Array.from(componentFields).filter( const availableFields = Array.from(componentFields).filter(
(field) => !unavaliableFields.has(field) (field) => !unavaliableFields.has(field)

View file

@ -1,21 +1,21 @@
import { Transition } from "@headlessui/react"; import { Transition } from "@headlessui/react";
import { useEffect, useMemo, useRef, useState } from "react"; import { useMemo, useRef, useState } from "react";
import { useHotkeys } from "react-hotkeys-hook";
import ApiModal from "../../modals/ApiModal"; import ApiModal from "../../modals/ApiModal";
import IOModal from "../../modals/IOModal"; import IOModal from "../../modals/IOModal";
import ShareModal from "../../modals/shareModal"; import ShareModal from "../../modals/shareModal";
import useFlowStore from "../../stores/flowStore"; import useFlowStore from "../../stores/flowStore";
import useFlowsManagerStore from "../../stores/flowsManagerStore"; import useFlowsManagerStore from "../../stores/flowsManagerStore";
import { useShortcutsStore } from "../../stores/shortcuts";
import { useStoreStore } from "../../stores/storeStore"; import { useStoreStore } from "../../stores/storeStore";
import { classNames } from "../../utils/utils"; import { classNames } from "../../utils/utils";
import ForwardedIconComponent from "../genericIconComponent"; import ForwardedIconComponent from "../genericIconComponent";
import { Separator } from "../ui/separator"; import { Separator } from "../ui/separator";
import { useHotkeys } from "react-hotkeys-hook";
import { useShortcutsStore } from "../../stores/shortcuts";
export default function FlowToolbar(): JSX.Element { export default function FlowToolbar(): JSX.Element {
function handleAPIWShortcut(e: KeyboardEvent) { function handleAPIWShortcut(e: KeyboardEvent) {
e.preventDefault(); e.preventDefault();
setOpenCodeModal((oldOpen) => !oldOpen) setOpenCodeModal((oldOpen) => !oldOpen);
} }
function handleChatWShortcut(e: KeyboardEvent) { function handleChatWShortcut(e: KeyboardEvent) {
@ -25,8 +25,8 @@ export default function FlowToolbar(): JSX.Element {
} }
} }
const openPlayground = useShortcutsStore(state => state.open); const openPlayground = useShortcutsStore((state) => state.open);
const api = useShortcutsStore(state => state.api); const api = useShortcutsStore((state) => state.api);
useHotkeys(openPlayground, handleChatWShortcut); useHotkeys(openPlayground, handleChatWShortcut);
useHotkeys(api, handleAPIWShortcut); useHotkeys(api, handleAPIWShortcut);
@ -121,7 +121,11 @@ export default function FlowToolbar(): JSX.Element {
</div> </div>
<div className="flex cursor-pointer items-center gap-2"> <div className="flex cursor-pointer items-center gap-2">
{currentFlow && currentFlow.data && ( {currentFlow && currentFlow.data && (
<ApiModal flow={currentFlow} open={openCodeModal} setOpen={setOpenCodeModal}> <ApiModal
flow={currentFlow}
open={openCodeModal}
setOpen={setOpenCodeModal}
>
<div <div
className={classNames( className={classNames(
"relative inline-flex w-full items-center justify-center gap-1 px-5 py-3 text-sm font-semibold text-foreground transition-all duration-150 ease-in-out hover:bg-hover" "relative inline-flex w-full items-center justify-center gap-1 px-5 py-3 text-sm font-semibold text-foreground transition-all duration-150 ease-in-out hover:bg-hover"

View file

@ -2,7 +2,6 @@ export const convertCSVToData = (csvFile, csvSeparator: string) => {
const lines = csvFile.data.trim().split("\n"); const lines = csvFile.data.trim().split("\n");
const headers = lines[0].trim().split(csvSeparator); const headers = lines[0].trim().split(csvSeparator);
const initialRowData: any = []; const initialRowData: any = [];
const initialColDefs = headers.map((header) => ({ const initialColDefs = headers.map((header) => ({
field: header.trim(), field: header.trim(),

View file

@ -49,7 +49,10 @@ export default function InputGlobalComponent({
!data.node?.template[name].value && !data.node?.template[name].value &&
data.node?.template[name].display_name data.node?.template[name].display_name
) { ) {
if (unavaliableFields[data.node?.template[name].display_name!] && !disabled) { if (
unavaliableFields[data.node?.template[name].display_name!] &&
!disabled
) {
setTimeout(() => { setTimeout(() => {
setDb(true); setDb(true);
onChange(unavaliableFields[data.node?.template[name].display_name!]); onChange(unavaliableFields[data.node?.template[name].display_name!]);

View file

@ -1,10 +1,9 @@
import { CHAT_FIRST_INITIAL_TEXT, CHAT_SECOND_INITIAL_TEXT, PDFCheckFlow, PDFLoadErrorTitle } from "../../../constants/constants"; import { PDFCheckFlow, PDFLoadErrorTitle } from "../../../constants/constants";
import IconComponent from "../../genericIconComponent"; import IconComponent from "../../genericIconComponent";
export default function Error(): JSX.Element { export default function Error(): JSX.Element {
return ( return (
<div className="flex flex-col items-center justify-center h-full w-full bg-muted"> <div className="flex h-full w-full flex-col items-center justify-center bg-muted">
<div className="chat-alert-box"> <div className="chat-alert-box">
<span className="flex gap-2"> <span className="flex gap-2">
<IconComponent name="FileX2" /> <IconComponent name="FileX2" />
@ -12,12 +11,9 @@ export default function Error(): JSX.Element {
</span> </span>
<br /> <br />
<div className="langflow-chat-desc"> <div className="langflow-chat-desc">
<span className="langflow-chat-desc-span"> <span className="langflow-chat-desc-span">{PDFCheckFlow} </span>
{PDFCheckFlow}{" "}
</span>
</div> </div>
</div> </div>
</div> </div>
); );
} }

View file

@ -787,68 +787,85 @@ export const SAVE_DEBOUNCE_TIME = 300;
export const defaultShortcuts = [ export const defaultShortcuts = [
{ {
name: "Advanced Settings", name: "Advanced Settings",
shortcut: "Ctrl + Shift + a" shortcut: "Ctrl + Shift + a",
}, },
{ {
name: "Minimize", name: "Minimize",
shortcut: "Ctrl + q" shortcut: "Ctrl + q",
}, },
{ {
name: "Code", name: "Code",
shortcut: "Ctrl + Shift + u" shortcut: "Ctrl + Shift + u",
}, },
{ {
name: "Copy", name: "Copy",
shortcut: "Ctrl + c" shortcut: "Ctrl + c",
}, },
{ {
name: "Duplicate", name: "Duplicate",
shortcut: "Ctrl + d" shortcut: "Ctrl + d",
}, },
{ {
name: "Share", name: "Share",
shortcut: "Ctrl + Shift + s" shortcut: "Ctrl + Shift + s",
}, },
{ {
name: "Docs", name: "Docs",
shortcut: "Ctrl + Shift + d" shortcut: "Ctrl + Shift + d",
}, },
{ {
name: "Save", name: "Save",
shortcut: "Ctrl + s" shortcut: "Ctrl + s",
}, },
{ {
name: "Delete", name: "Delete",
shortcut: "Backspace" shortcut: "Backspace",
}, },
{ {
name: "Open playground", name: "Open playground",
shortcut: "Ctrl + k" shortcut: "Ctrl + k",
}, },
{ {
name: "Undo", name: "Undo",
shortcut: "Ctrl + z" shortcut: "Ctrl + z",
}, },
{ {
name: "Redo", name: "Redo",
shortcut: "Ctrl + y" shortcut: "Ctrl + y",
}, },
{ {
name: "Group", name: "Group",
shortcut: "Ctrl + g" shortcut: "Ctrl + g",
}, },
{ {
name: "Cut", name: "Cut",
shortcut: "Ctrl + x" shortcut: "Ctrl + x",
}, },
{ {
name: "Paste", name: "Paste",
shortcut: "Ctrl + v" shortcut: "Ctrl + v",
}, },
{ {
name: "API", name: "API",
shortcut: "Ctrl + r" shortcut: "Ctrl + r",
}, },
]; ];
export const unavailableShortcutss = ["CTRL + R","CTRL + V", "CTRL + X", "CTRL + G", "CTRL + SHIFT + A", "CTRL + Q", "CTRL + SHIFT + U", "CTRL + C", "CTRL + D", "CTRL + SHIFT + S", "CTRL + SHIFT + D", "CTRL + S", "BACKSPACE", "CTRL + K", "CTRL + Z", "CTRL + Y"]; export const unavailableShortcutss = [
"CTRL + R",
"CTRL + V",
"CTRL + X",
"CTRL + G",
"CTRL + SHIFT + A",
"CTRL + Q",
"CTRL + SHIFT + U",
"CTRL + C",
"CTRL + D",
"CTRL + SHIFT + S",
"CTRL + SHIFT + D",
"CTRL + S",
"BACKSPACE",
"CTRL + K",
"CTRL + Z",
"CTRL + Y",
];

View file

@ -86,9 +86,9 @@ const EditNodeModal = forwardRef(
useEffect(() => { useEffect(() => {
return () => { return () => {
setOpenWDoubleClick(false) setOpenWDoubleClick(false);
} };
}, []) }, []);
const [errorDuplicateKey, setErrorDuplicateKey] = useState(false); const [errorDuplicateKey, setErrorDuplicateKey] = useState(false);

View file

@ -1,5 +1,6 @@
import { Loader2 } from "lucide-react"; import { Loader2 } from "lucide-react";
import { ReactNode, useEffect, useMemo, useState } from "react"; import { ReactNode, useEffect, useMemo, useState } from "react";
import { useHotkeys } from "react-hotkeys-hook";
import EditFlowSettings from "../../components/EditFlowSettingsComponent"; import EditFlowSettings from "../../components/EditFlowSettingsComponent";
import IconComponent from "../../components/genericIconComponent"; import IconComponent from "../../components/genericIconComponent";
import { TagsSelector } from "../../components/tagsSelectorComponent"; import { TagsSelector } from "../../components/tagsSelectorComponent";
@ -25,7 +26,6 @@ import {
import { getTagsIds } from "../../utils/storeUtils"; import { getTagsIds } from "../../utils/storeUtils";
import ConfirmationModal from "../ConfirmationModal"; import ConfirmationModal from "../ConfirmationModal";
import BaseModal from "../baseModal"; import BaseModal from "../baseModal";
import { useHotkeys } from "react-hotkeys-hook";
import ExportModal from "../exportModal"; import ExportModal from "../exportModal";
export default function ShareModal({ export default function ShareModal({
@ -45,8 +45,8 @@ export default function ShareModal({
}): JSX.Element { }): JSX.Element {
function handleOpenWShortcut(e: KeyboardEvent) { function handleOpenWShortcut(e: KeyboardEvent) {
if (hasApiKey || hasStore) { if (hasApiKey || hasStore) {
e.preventDefault() e.preventDefault();
internalSetOpen(state => !state); internalSetOpen((state) => !state);
} }
} }
const version = useDarkStore((state) => state.version); const version = useDarkStore((state) => state.version);
@ -59,7 +59,7 @@ export default function ShareModal({
const [openConfirmationModal, setOpenConfirmationModal] = useState(false); const [openConfirmationModal, setOpenConfirmationModal] = useState(false);
const nameComponent = is_component ? "component" : "workflow"; const nameComponent = is_component ? "component" : "workflow";
useHotkeys("mod+alt+s", handleOpenWShortcut) useHotkeys("mod+alt+s", handleOpenWShortcut);
const [tags, setTags] = useState<{ id: string; name: string }[]>([]); const [tags, setTags] = useState<{ id: string; name: string }[]>([]);
const [loadingTags, setLoadingTags] = useState<boolean>(false); const [loadingTags, setLoadingTags] = useState<boolean>(false);
@ -216,7 +216,8 @@ export default function ShareModal({
{children ? children : <></>} {children ? children : <></>}
</BaseModal.Trigger> </BaseModal.Trigger>
<BaseModal.Header <BaseModal.Header
description={`Publish ${is_component ? "your component" : "workflow" description={`Publish ${
is_component ? "your component" : "workflow"
} to the Langflow Store.`} } to the Langflow Store.`}
> >
<span className="pr-2">Share</span> <span className="pr-2">Share</span>
@ -260,7 +261,8 @@ export default function ShareModal({
<BaseModal.Footer> <BaseModal.Footer>
<div className="flex w-full justify-between gap-2"> <div className="flex w-full justify-between gap-2">
{!is_component && <ExportModal> {!is_component && (
<ExportModal>
<Button <Button
type="button" type="button"
variant="outline" variant="outline"
@ -273,8 +275,9 @@ export default function ShareModal({
Export Export
</Button> </Button>
</ExportModal> </ExportModal>
} )}
{is_component && <Button {is_component && (
<Button
type="button" type="button"
variant="outline" variant="outline"
className="gap-2" className="gap-2"
@ -286,8 +289,7 @@ export default function ShareModal({
<IconComponent name="Download" className="h-4 w-4" /> <IconComponent name="Download" className="h-4 w-4" />
Export Export
</Button> </Button>
)}
}
<Button <Button
disabled={loadingNames} disabled={loadingNames}
type="button" type="button"

View file

@ -1,5 +1,13 @@
import _, { cloneDeep } from "lodash"; import _, { cloneDeep } from "lodash";
import { KeyboardEvent, MouseEvent, useCallback, useEffect, useRef, useState } from "react"; import {
KeyboardEvent,
MouseEvent,
useCallback,
useEffect,
useRef,
useState,
} from "react";
import { useHotkeys } from "react-hotkeys-hook";
import ReactFlow, { import ReactFlow, {
Background, Background,
Connection, Connection,
@ -21,6 +29,7 @@ import {
import useAlertStore from "../../../../stores/alertStore"; import useAlertStore from "../../../../stores/alertStore";
import useFlowStore from "../../../../stores/flowStore"; import useFlowStore from "../../../../stores/flowStore";
import useFlowsManagerStore from "../../../../stores/flowsManagerStore"; import useFlowsManagerStore from "../../../../stores/flowsManagerStore";
import { useShortcutsStore } from "../../../../stores/shortcuts";
import { useTypesStore } from "../../../../stores/typesStore"; import { useTypesStore } from "../../../../stores/typesStore";
import { APIClassType } from "../../../../types/api"; import { APIClassType } from "../../../../types/api";
import { FlowType, NodeType } from "../../../../types/flow"; import { FlowType, NodeType } from "../../../../types/flow";
@ -37,8 +46,6 @@ import {
import { getRandomName, isWrappedWithClass } from "../../../../utils/utils"; import { getRandomName, isWrappedWithClass } from "../../../../utils/utils";
import ConnectionLineComponent from "../ConnectionLineComponent"; import ConnectionLineComponent from "../ConnectionLineComponent";
import SelectionMenu from "../SelectionMenuComponent"; import SelectionMenu from "../SelectionMenuComponent";
import { useHotkeys } from "react-hotkeys-hook";
import { useShortcutsStore } from "../../../../stores/shortcuts";
const nodeTypes = { const nodeTypes = {
genericNode: GenericNode, genericNode: GenericNode,
@ -169,31 +176,30 @@ export default function Page({
}; };
}, []); }, []);
function handleUndo(e: KeyboardEvent) { function handleUndo(e: KeyboardEvent) {
e.preventDefault() e.preventDefault();
if (!isWrappedWithClass(e, "noundo")) { if (!isWrappedWithClass(e, "noundo")) {
undo(); undo();
} }
} }
function handleRedo(e: KeyboardEvent) { function handleRedo(e: KeyboardEvent) {
e.preventDefault() e.preventDefault();
if (!isWrappedWithClass(e, "noundo")) { if (!isWrappedWithClass(e, "noundo")) {
redo(); redo();
} }
} }
function handleGroup(e: KeyboardEvent) { function handleGroup(e: KeyboardEvent) {
e.preventDefault() e.preventDefault();
if (selectionMenuVisible) { if (selectionMenuVisible) {
handleGroupNode() handleGroupNode();
} }
} }
function handleDuplicate(e: KeyboardEvent) { function handleDuplicate(e: KeyboardEvent) {
const selectedNode = nodes.filter((obj) => obj.selected); const selectedNode = nodes.filter((obj) => obj.selected);
e.preventDefault() e.preventDefault();
if (selectedNode.length > 0) { if (selectedNode.length > 0) {
paste( paste(
{ nodes: selectedNode, edges: [] }, { nodes: selectedNode, edges: [] },
@ -206,25 +212,34 @@ export default function Page({
} }
function handleCopy(e: KeyboardEvent) { function handleCopy(e: KeyboardEvent) {
e.preventDefault() e.preventDefault();
if (!isWrappedWithClass(e, "nocopy") && if (
window.getSelection()?.toString().length === 0 && lastSelection) { !isWrappedWithClass(e, "nocopy") &&
window.getSelection()?.toString().length === 0 &&
lastSelection
) {
setLastCopiedSelection(_.cloneDeep(lastSelection)); setLastCopiedSelection(_.cloneDeep(lastSelection));
} }
} }
function handleCut(e: KeyboardEvent) { function handleCut(e: KeyboardEvent) {
e.preventDefault() e.preventDefault();
if (!isWrappedWithClass(e, "nocopy") && if (
window.getSelection()?.toString().length === 0 && lastSelection) { !isWrappedWithClass(e, "nocopy") &&
window.getSelection()?.toString().length === 0 &&
lastSelection
) {
setLastCopiedSelection(_.cloneDeep(lastSelection), true); setLastCopiedSelection(_.cloneDeep(lastSelection), true);
} }
} }
function handlePaste(e: KeyboardEvent) { function handlePaste(e: KeyboardEvent) {
e.preventDefault() e.preventDefault();
if (!isWrappedWithClass(e, "nocopy") && if (
window.getSelection()?.toString().length === 0 && lastCopiedSelection) { !isWrappedWithClass(e, "nocopy") &&
window.getSelection()?.toString().length === 0 &&
lastCopiedSelection
) {
takeSnapshot(); takeSnapshot();
paste(lastCopiedSelection, { paste(lastCopiedSelection, {
x: position.current.x, x: position.current.x,
@ -234,7 +249,7 @@ export default function Page({
} }
function handleDelete(e: KeyboardEvent) { function handleDelete(e: KeyboardEvent) {
e.preventDefault() e.preventDefault();
if (!isWrappedWithClass(e, "nodelete") && lastSelection) { if (!isWrappedWithClass(e, "nodelete") && lastSelection) {
takeSnapshot(); takeSnapshot();
deleteNode(lastSelection.nodes.map((node) => node.id)); deleteNode(lastSelection.nodes.map((node) => node.id));
@ -242,14 +257,14 @@ export default function Page({
} }
} }
const undoAction = useShortcutsStore(state => state.undo); const undoAction = useShortcutsStore((state) => state.undo);
const redoAction = useShortcutsStore(state => state.redo); const redoAction = useShortcutsStore((state) => state.redo);
const copyAction = useShortcutsStore(state => state.copy); const copyAction = useShortcutsStore((state) => state.copy);
const duplicate = useShortcutsStore(state => state.duplicate); const duplicate = useShortcutsStore((state) => state.duplicate);
const deleteAction = useShortcutsStore(state => state.delete); const deleteAction = useShortcutsStore((state) => state.delete);
const groupAction = useShortcutsStore(state => state.group); const groupAction = useShortcutsStore((state) => state.group);
const cutAction = useShortcutsStore(state => state.cut); const cutAction = useShortcutsStore((state) => state.cut);
const pasteAction = useShortcutsStore(state => state.paste); const pasteAction = useShortcutsStore((state) => state.paste);
useHotkeys(undoAction, handleUndo); useHotkeys(undoAction, handleUndo);
useHotkeys(redoAction, handleRedo); useHotkeys(redoAction, handleRedo);

View file

@ -19,6 +19,7 @@ import useAlertStore from "../../../../stores/alertStore";
import { useDarkStore } from "../../../../stores/darkStore"; import { useDarkStore } from "../../../../stores/darkStore";
import useFlowStore from "../../../../stores/flowStore"; import useFlowStore from "../../../../stores/flowStore";
import useFlowsManagerStore from "../../../../stores/flowsManagerStore"; import useFlowsManagerStore from "../../../../stores/flowsManagerStore";
import { useShortcutsStore } from "../../../../stores/shortcuts";
import { useStoreStore } from "../../../../stores/storeStore"; import { useStoreStore } from "../../../../stores/storeStore";
import { useTypesStore } from "../../../../stores/typesStore"; import { useTypesStore } from "../../../../stores/typesStore";
import { APIClassType } from "../../../../types/api"; import { APIClassType } from "../../../../types/api";
@ -32,7 +33,6 @@ import {
} from "../../../../utils/reactflowUtils"; } from "../../../../utils/reactflowUtils";
import { classNames } from "../../../../utils/utils"; import { classNames } from "../../../../utils/utils";
import ToolbarSelectItem from "./toolbarSelectItem"; import ToolbarSelectItem from "./toolbarSelectItem";
import { useShortcutsStore } from "../../../../stores/shortcuts";
export default function NodeToolbarComponent({ export default function NodeToolbarComponent({
data, data,
@ -145,12 +145,12 @@ export default function NodeToolbarComponent({
downloadNode(flowComponent!); downloadNode(flowComponent!);
} }
const advanced = useShortcutsStore(state => state.advanced); const advanced = useShortcutsStore((state) => state.advanced);
const minimize = useShortcutsStore(state => state.minimize); const minimize = useShortcutsStore((state) => state.minimize);
const share = useShortcutsStore(state => state.share); const share = useShortcutsStore((state) => state.share);
const save = useShortcutsStore(state => state.save); const save = useShortcutsStore((state) => state.save);
const docs = useShortcutsStore(state => state.docs); const docs = useShortcutsStore((state) => state.docs);
const code = useShortcutsStore(state => state.code); const code = useShortcutsStore((state) => state.code);
useHotkeys(minimize, handleMinimizeWShortcut); useHotkeys(minimize, handleMinimizeWShortcut);
useHotkeys("mod+u", handleUpdateWShortcut); useHotkeys("mod+u", handleUpdateWShortcut);

View file

@ -1,9 +1,9 @@
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import useAlertStore from "../../../../../stores/alertStore"; import useAlertStore from "../../../../../stores/alertStore";
import BaseModal from "../../../../../modals/baseModal";
import { Button } from "../../../../../components/ui/button";
import ForwardedIconComponent from "../../../../../components/genericIconComponent"; import ForwardedIconComponent from "../../../../../components/genericIconComponent";
import { Button } from "../../../../../components/ui/button";
import BaseModal from "../../../../../modals/baseModal";
import { useShortcutsStore } from "../../../../../stores/shortcuts"; import { useShortcutsStore } from "../../../../../stores/shortcuts";
export default function EditShortcutButton({ export default function EditShortcutButton({
@ -17,85 +17,92 @@ export default function EditShortcutButton({
}: { }: {
children: JSX.Element; children: JSX.Element;
shortcut: string[]; shortcut: string[];
defaultShortcuts: Array<{name: string; shortcut: string;}>; defaultShortcuts: Array<{ name: string; shortcut: string }>;
defaultCombination: string; defaultCombination: string;
open: boolean; open: boolean;
setOpen: (bool: boolean) => void; setOpen: (bool: boolean) => void;
disable?: boolean; disable?: boolean;
}): JSX.Element { }): JSX.Element {
const isMac = navigator.userAgent.toUpperCase().includes("MAC"); const isMac = navigator.userAgent.toUpperCase().includes("MAC");
const [key, setKey] = useState<string>(isMac ? "Meta" : 'Ctrl'); const [key, setKey] = useState<string>(isMac ? "Meta" : "Ctrl");
const setSuccessData = useAlertStore(state => state.setSuccessData) const setSuccessData = useAlertStore((state) => state.setSuccessData);
const setShortcuts = useShortcutsStore(state => state.setShortcuts); const setShortcuts = useShortcutsStore((state) => state.setShortcuts);
const unavaliableShortcuts = useShortcutsStore(state => state.unavailableShortcuts); const unavaliableShortcuts = useShortcutsStore(
(state) => state.unavailableShortcuts
);
const setErrorData = useAlertStore((state) => state.setErrorData); const setErrorData = useAlertStore((state) => state.setErrorData);
function canEditCombination(newCombination: string): boolean { function canEditCombination(newCombination: string): boolean {
let canSave = true; let canSave = true;
unavaliableShortcuts.forEach((s) => { unavaliableShortcuts.forEach((s) => {
if (s.toLowerCase() === newCombination.toLowerCase()) { if (s.toLowerCase() === newCombination.toLowerCase()) {
canSave = false canSave = false;
} }
}) });
return canSave; return canSave;
} }
const setUniqueShortcut = useShortcutsStore(state => state.updateUniqueShortcut); const setUniqueShortcut = useShortcutsStore(
(state) => state.updateUniqueShortcut
);
function editCombination(): void { function editCombination(): void {
console.log(canEditCombination(key)) console.log(canEditCombination(key));
if (canEditCombination(key)) { if (canEditCombination(key)) {
const newCombination = defaultShortcuts.map((s) => { const newCombination = defaultShortcuts.map((s) => {
if (s.name === shortcut[0]) { if (s.name === shortcut[0]) {
return {name: s.name, shortcut: key} return { name: s.name, shortcut: key };
} }
return { name: s.name, shortcut: s.shortcut }; return { name: s.name, shortcut: s.shortcut };
}) });
const unavailable = unavaliableShortcuts.map((s) => { const unavailable = unavaliableShortcuts.map((s) => {
if (s.toLowerCase() === defaultCombination.toLowerCase()) return s = key.toUpperCase(); if (s.toLowerCase() === defaultCombination.toLowerCase())
return (s = key.toUpperCase());
return s; return s;
}) });
const fixCombination = key.split(" ") const fixCombination = key.split(" ");
fixCombination[0] = "mod" fixCombination[0] = "mod";
const shortcutName = shortcut[0].split(" ")[0].toLowerCase(); const shortcutName = shortcut[0].split(" ")[0].toLowerCase();
setUniqueShortcut(shortcutName, fixCombination.join("").toLowerCase()) setUniqueShortcut(shortcutName, fixCombination.join("").toLowerCase());
setShortcuts(newCombination, unavailable) setShortcuts(newCombination, unavailable);
setOpen(false) setOpen(false);
setSuccessData({title: `${shortcut[0]} shortcut successfully changed`}) setSuccessData({ title: `${shortcut[0]} shortcut successfully changed` });
setKey(isMac ? "META" : 'CTRL'); setKey(isMac ? "META" : "CTRL");
localStorage.setItem("langflow-shortcuts", JSON.stringify(newCombination)); localStorage.setItem(
"langflow-shortcuts",
JSON.stringify(newCombination)
);
localStorage.setItem("langflow-UShortcuts", JSON.stringify(unavailable)); localStorage.setItem("langflow-UShortcuts", JSON.stringify(unavailable));
return; return;
} }
setErrorData({title: "Error saving key combination", list: ["This combination already exists!"]}) setErrorData({
title: "Error saving key combination",
list: ["This combination already exists!"],
});
} }
useEffect(() => { useEffect(() => {
if (!open) setKey(isMac ? "META" : 'CTRL') if (!open) setKey(isMac ? "META" : "CTRL");
console.log(key) console.log(key);
}, [open, setOpen, key]) }, [open, setOpen, key]);
useEffect(() => { useEffect(() => {
function onKeyDown(e: KeyboardEvent) { function onKeyDown(e: KeyboardEvent) {
e.preventDefault() e.preventDefault();
if (key.toUpperCase().includes(e.key.toUpperCase())) return; if (key.toUpperCase().includes(e.key.toUpperCase())) return;
setKey(oldKey => `${oldKey.toUpperCase()} + ${e.key.toUpperCase()}`) setKey((oldKey) => `${oldKey.toUpperCase()} + ${e.key.toUpperCase()}`);
} }
document.addEventListener("keydown", onKeyDown); document.addEventListener("keydown", onKeyDown);
return () => { return () => {
document.removeEventListener("keydown", onKeyDown) document.removeEventListener("keydown", onKeyDown);
} };
}, [key, setKey]) }, [key, setKey]);
return ( return (
<BaseModal open={open} setOpen={setOpen} size="smaller" disable={disable}> <BaseModal open={open} setOpen={setOpen} size="smaller" disable={disable}>
<BaseModal.Header <BaseModal.Header description={"Recording your keyboard"}>
description={
"Recording your keyboard"
}
>
<span className="pr-2"> Key Combination </span> <span className="pr-2"> Key Combination </span>
<ForwardedIconComponent <ForwardedIconComponent
name="Keyboard" name="Keyboard"
@ -105,15 +112,21 @@ export default function EditShortcutButton({
</BaseModal.Header> </BaseModal.Header>
<BaseModal.Trigger>{children}</BaseModal.Trigger> <BaseModal.Trigger>{children}</BaseModal.Trigger>
<BaseModal.Content> <BaseModal.Content>
<div className="flex h-full w-full gap-4 align-center justify-center"> <div className="align-center flex h-full w-full justify-center gap-4">
<div className="font-bold text-lg flex items-center justify-center text-center"> <div className="flex items-center justify-center text-center text-lg font-bold">
{key.toUpperCase()} {key.toUpperCase()}
</div> </div>
</div> </div>
</BaseModal.Content> </BaseModal.Content>
<BaseModal.Footer> <BaseModal.Footer>
<Button onClick={editCombination}>Edit Combination</Button> <Button onClick={editCombination}>Edit Combination</Button>
<Button className="mr-5" variant={"destructive"} onClick={() => setKey(isMac ? "META" : 'CTRL')}>Reset Combination</Button> <Button
className="mr-5"
variant={"destructive"}
onClick={() => setKey(isMac ? "META" : "CTRL")}
>
Reset Combination
</Button>
</BaseModal.Footer> </BaseModal.Footer>
</BaseModal> </BaseModal>
); );

View file

@ -2,22 +2,18 @@ import { ColDef, ColGroupDef } from "ag-grid-community";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import ForwardedIconComponent from "../../../../components/genericIconComponent"; import ForwardedIconComponent from "../../../../components/genericIconComponent";
import TableComponent from "../../../../components/tableComponent"; import TableComponent from "../../../../components/tableComponent";
import {
Card,
CardContent,
CardDescription,
CardHeader,
CardTitle,
} from "../../../../components/ui/card";
import { Button } from "../../../../components/ui/button"; import { Button } from "../../../../components/ui/button";
import EditShortcutButton from "./EditShortcutButton"; import {
defaultShortcuts,
unavailableShortcutss,
} from "../../../../constants/constants";
import { useShortcutsStore } from "../../../../stores/shortcuts"; import { useShortcutsStore } from "../../../../stores/shortcuts";
import { defaultShortcuts, unavailableShortcutss } from "../../../../constants/constants"; import EditShortcutButton from "./EditShortcutButton";
export default function ShortcutsPage() { export default function ShortcutsPage() {
const [selectedRows, setSelectedRows] = useState<string[]>([]); const [selectedRows, setSelectedRows] = useState<string[]>([]);
const shortcuts = useShortcutsStore(state => state.shortcuts); const shortcuts = useShortcutsStore((state) => state.shortcuts);
const setShortcuts = useShortcutsStore(state => state.setShortcuts); const setShortcuts = useShortcutsStore((state) => state.setShortcuts);
// Column Definitions: Defines the columns to be displayed. // Column Definitions: Defines the columns to be displayed.
const [colDefs, setColDefs] = useState<(ColDef<any> | ColGroupDef<any>)[]>([ const [colDefs, setColDefs] = useState<(ColDef<any> | ColGroupDef<any>)[]>([
@ -37,23 +33,27 @@ export default function ShortcutsPage() {
}, },
]); ]);
const [nodesRowData, setNodesRowData] = useState<Array<{name: string; shortcut: string;}>>([]); const [nodesRowData, setNodesRowData] = useState<
Array<{ name: string; shortcut: string }>
>([]);
useEffect(() => { useEffect(() => {
setNodesRowData(shortcuts) setNodesRowData(shortcuts);
}, [shortcuts]) }, [shortcuts]);
const combinationToEdit = shortcuts.filter((s) => s.name === selectedRows[0]) const combinationToEdit = shortcuts.filter((s) => s.name === selectedRows[0]);
const [open, setOpen] = useState(false); const [open, setOpen] = useState(false);
const unavaliableShortcuts = useShortcutsStore(state => state.unavailableShortcuts); const unavaliableShortcuts = useShortcutsStore(
(state) => state.unavailableShortcuts
);
useEffect(() => { useEffect(() => {
if (localStorage.getItem("langflow-shortcuts")) { if (localStorage.getItem("langflow-shortcuts")) {
const savedShortcuts = localStorage.getItem("langflow-shortcuts"); const savedShortcuts = localStorage.getItem("langflow-shortcuts");
const savedUShortcuts = localStorage.getItem("langflow-UShortcuts"); const savedUShortcuts = localStorage.getItem("langflow-UShortcuts");
setShortcuts(JSON.parse(savedShortcuts!), JSON.parse(savedUShortcuts!)); setShortcuts(JSON.parse(savedShortcuts!), JSON.parse(savedUShortcuts!));
} }
}, []) }, []);
function handleRestore() { function handleRestore() {
setShortcuts(defaultShortcuts, unavailableShortcutss); setShortcuts(defaultShortcuts, unavailableShortcutss);
@ -73,13 +73,12 @@ export default function ShortcutsPage() {
/> />
</h2> </h2>
<p className="text-sm text-muted-foreground"> <p className="text-sm text-muted-foreground">
Manage Shortcuts for quick access to Manage Shortcuts for quick access to frequently used actions.
frequently used actions.
</p> </p>
</div> </div>
<div> <div>
<div className="w-full flex justify-end align-end mb-4"> <div className="align-end mb-4 flex w-full justify-end">
<div className="flex items-center justify center"> <div className="justify center flex items-center">
<EditShortcutButton <EditShortcutButton
disable={selectedRows.length === 0} disable={selectedRows.length === 0}
defaultCombination={combinationToEdit[0]?.shortcut} defaultCombination={combinationToEdit[0]?.shortcut}
@ -93,7 +92,11 @@ export default function ShortcutsPage() {
Customize Customize
</Button> </Button>
</EditShortcutButton> </EditShortcutButton>
<Button variant="primary" className="ml-3" onClick={handleRestore}> <Button
variant="primary"
className="ml-3"
onClick={handleRestore}
>
<ForwardedIconComponent name="RotateCcw" className="mr-2 w-4" /> <ForwardedIconComponent name="RotateCcw" className="mr-2 w-4" />
Restore Restore
</Button> </Button>
@ -105,7 +108,9 @@ export default function ShortcutsPage() {
<div> <div>
<TableComponent <TableComponent
onSelectionChanged={(event: SelectionChangedEvent) => { onSelectionChanged={(event: SelectionChangedEvent) => {
setSelectedRows(event.api.getSelectedRows().map((row) => row.name)); setSelectedRows(
event.api.getSelectedRows().map((row) => row.name)
);
}} }}
suppressRowClickSelection={true} suppressRowClickSelection={true}
domLayout="autoHeight" domLayout="autoHeight"

View file

@ -1,6 +1,9 @@
import { create } from "zustand"; import { create } from "zustand";
import {
defaultShortcuts,
unavailableShortcutss,
} from "../constants/constants";
import { shortcutsStoreType } from "../types/store"; import { shortcutsStoreType } from "../types/store";
import { defaultShortcuts, unavailableShortcutss } from "../constants/constants";
export const useShortcutsStore = create<shortcutsStoreType>((set, get) => ({ export const useShortcutsStore = create<shortcutsStoreType>((set, get) => ({
unavailableShortcuts: unavailableShortcutss, unavailableShortcuts: unavailableShortcutss,
@ -26,7 +29,7 @@ export const useShortcutsStore = create<shortcutsStoreType>((set, get) => ({
api: "mod+r", api: "mod+r",
updateUniqueShortcut: (name, combination) => { updateUniqueShortcut: (name, combination) => {
set({ set({
[name]: combination [name]: combination,
}) });
} },
})); }));

View file

@ -40,7 +40,10 @@ export type shortcutsStoreType = {
shortcuts: Array<{ shortcuts: Array<{
name: string; name: string;
shortcut: string; shortcut: string;
}> }>;
unavailableShortcuts: string[]; unavailableShortcuts: string[];
setShortcuts: (newShortcuts: Array<{name: string; shortcut: string;}>, unavailable: string[]) => void; setShortcuts: (
newShortcuts: Array<{ name: string; shortcut: string }>,
unavailable: string[]
) => void;
}; };

View file

@ -101,6 +101,7 @@ import {
Redo, Redo,
RefreshCcw, RefreshCcw,
Repeat, Repeat,
RotateCcw,
Save, Save,
SaveAll, SaveAll,
Scissors, Scissors,
@ -140,7 +141,6 @@ import {
X, X,
XCircle, XCircle,
Zap, Zap,
RotateCcw,
} from "lucide-react"; } from "lucide-react";
import { FaApple, FaGithub } from "react-icons/fa"; import { FaApple, FaGithub } from "react-icons/fa";
import { AWSIcon } from "../icons/AWS"; import { AWSIcon } from "../icons/AWS";
@ -515,5 +515,5 @@ export const nodeIconsLucide: iconsType = {
Command, Command,
ArrowBigUp, ArrowBigUp,
Dot, Dot,
RotateCcw RotateCcw,
}; };