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 langflow.field_typing import Text
from langflow.helpers.record import records_to_text
from langflow.interface.custom.custom_component import CustomComponent
from langflow.schema.schema import Record

View file

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

View file

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

View file

@ -1,141 +1,162 @@
import { saveAs } from "file-saver";
import OpenSeadragon from "openseadragon";
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 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 [errorDownloading, setErrordownloading] = useState(false)
const setErrorList = useAlertStore(state => state.setErrorData);
const [errorDownloading, setErrordownloading] = useState(false);
const setErrorList = useAlertStore((state) => state.setErrorData);
const [initialMsg, setInicialMsg] = useState("Please build your flow");
useEffect(() => {
try {
if (viewerRef.current) {
// Initialize OpenSeadragon viewer
const viewer = OpenSeadragon({
element: viewerRef.current,
prefixUrl:
"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,
maxZoomPixelRatio: 4,
showNavigationControl: false,
});
const zoomInButton = document.getElementById("zoom-in-button");
const zoomOutButton = document.getElementById("zoom-out-button");
const homeButton = document.getElementById("home-button");
const fullPageButton = document.getElementById("full-page-button");
useEffect(() => {
try {
if (viewerRef.current) {
// Initialize OpenSeadragon viewer
const viewer = OpenSeadragon({
element: viewerRef.current,
prefixUrl: '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,
maxZoomPixelRatio: 4,
showNavigationControl: false,
});
const zoomInButton = document.getElementById('zoom-in-button');
const zoomOutButton = document.getElementById('zoom-out-button');
const homeButton = document.getElementById('home-button');
const fullPageButton = document.getElementById('full-page-button');
zoomInButton!.addEventListener('click', () => viewer.viewport.zoomBy(1.2));
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
// Cleanup function
return () => {
viewer.destroy();
zoomInButton!.removeEventListener('click', () => viewer.viewport.zoomBy(1.2));
zoomOutButton!.removeEventListener('click', () => viewer.viewport.zoomBy(0.8));
homeButton!.removeEventListener('click', () => viewer.viewport.goHome());
fullPageButton!.removeEventListener('click', () => viewer.setFullScreen(true));
};
}
} catch (error) {
console.error('Error initializing OpenSeadragon:', error);
}
}, [image]);
zoomInButton!.addEventListener("click", () =>
viewer.viewport.zoomBy(1.2)
);
zoomOutButton!.addEventListener("click", () =>
viewer.viewport.zoomBy(0.8)
);
homeButton!.addEventListener("click", () => viewer.viewport.goHome());
fullPageButton!.addEventListener("click", () =>
viewer.setFullScreen(true)
);
function download() {
const imageUrl = image;
// Fetch the image data
fetch(imageUrl)
.then(response => response.blob())
.then(blob => {
// Save the image using FileSaver.js
saveAs(blob, 'image.jpg');
})
.catch(error => {
setErrorList({title: "There was an error downloading your image"})
console.error('Error downloading image:', error)
});
// Optionally, you can set additional viewer options here
// Cleanup function
return () => {
viewer.destroy();
zoomInButton!.removeEventListener("click", () =>
viewer.viewport.zoomBy(1.2)
);
zoomOutButton!.removeEventListener("click", () =>
viewer.viewport.zoomBy(0.8)
);
homeButton!.removeEventListener("click", () =>
viewer.viewport.goHome()
);
fullPageButton!.removeEventListener("click", () =>
viewer.setFullScreen(true)
);
};
}
} catch (error) {
console.error("Error initializing OpenSeadragon:", error);
}
}, [image]);
return (
image === "" ? (
<div className="w-full h-full bg-muted rounded-md flex align-center justify-center flex-col gap-5 border border-border">
<div className="flex gap-2 align-center justify-center ">
<ForwardedIconComponent
name="Image"
/>
{IMGViewErrorTitle}
</div>
<div className="flex align-center justify-center">
<div className="langflow-chat-desc flex align-center justify-center">
<div className="langflow-chat-desc-span">
{IMGViewErrorMSG}
</div>
</div>
</div>
function download() {
const imageUrl = image;
// Fetch the image data
fetch(imageUrl)
.then((response) => response.blob())
.then((blob) => {
// Save the image using FileSaver.js
saveAs(blob, "image.jpg");
})
.catch((error) => {
setErrorList({ title: "There was an error downloading your image" });
console.error("Error downloading image:", error);
});
}
return 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="align-center flex justify-center gap-2 ">
<ForwardedIconComponent name="Image" />
{IMGViewErrorTitle}
</div>
<div className="align-center flex justify-center">
<div className="langflow-chat-desc align-center flex justify-center">
<div className="langflow-chat-desc-span">{IMGViewErrorMSG}</div>
</div>
</div>
</div>
) : (
<>
<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 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 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
name="ZoomIn"
className={"h-5 w-5 text-secondary-foreground"}
/>
</button>
<div>
<Separator orientation="vertical" />
</div>
) : (
<>
<div className="w-full flex align-center justify-center my-2 mb-4">
<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%]">
<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">
<ForwardedIconComponent
name="ZoomIn"
className={"text-secondary-foreground w-5 h-5"}
/>
</button>
<div>
<Separator orientation="vertical" />
</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">
<ForwardedIconComponent
name="ZoomOut"
className={"text-secondary-foreground w-5 h-5"}
/>
</button>
<div>
<Separator orientation="vertical" />
</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">
<ForwardedIconComponent
name="RotateCcw"
className={"text-secondary-foreground w-5 h-5"}
/>
</button>
<div>
<Separator orientation="vertical" />
</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">
<ForwardedIconComponent
name="Maximize2"
className={"text-secondary-foreground w-5 h-5"}
/>
</button>
<div>
<Separator orientation="vertical" />
</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">
<ForwardedIconComponent
name="ArrowDownToLine"
className={"text-secondary-foreground w-5 h-5"}
/>
</button>
</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"
>
<ForwardedIconComponent
name="ZoomOut"
className={"h-5 w-5 text-secondary-foreground"}
/>
</button>
<div>
<Separator orientation="vertical" />
</div>
<div id="canvas" ref={viewerRef} className={`w-full h-[90%] `} />
</>
)
);
}
<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
name="RotateCcw"
className={"h-5 w-5 text-secondary-foreground"}
/>
</button>
<div>
<Separator orientation="vertical" />
</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"
>
<ForwardedIconComponent
name="Maximize2"
className={"h-5 w-5 text-secondary-foreground"}
/>
</button>
<div>
<Separator orientation="vertical" />
</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"
>
<ForwardedIconComponent
name="ArrowDownToLine"
className={"h-5 w-5 text-secondary-foreground"}
/>
</button>
</div>
</div>
<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 setErrorData = useAlertStore((state) => state.setErrorData);
const componentFields = useTypesStore((state) => state.ComponentFields);
const unavaliableFields =new Set(Object.keys(useGlobalVariablesStore(
(state) => state.unavaliableFields
)));
const unavaliableFields = new Set(
Object.keys(useGlobalVariablesStore((state) => state.unavaliableFields))
);
const availableFields = Array.from(componentFields).filter(
(field) => !unavaliableFields.has(field)

View file

@ -1,21 +1,21 @@
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 IOModal from "../../modals/IOModal";
import ShareModal from "../../modals/shareModal";
import useFlowStore from "../../stores/flowStore";
import useFlowsManagerStore from "../../stores/flowsManagerStore";
import { useShortcutsStore } from "../../stores/shortcuts";
import { useStoreStore } from "../../stores/storeStore";
import { classNames } from "../../utils/utils";
import ForwardedIconComponent from "../genericIconComponent";
import { Separator } from "../ui/separator";
import { useHotkeys } from "react-hotkeys-hook";
import { useShortcutsStore } from "../../stores/shortcuts";
export default function FlowToolbar(): JSX.Element {
function handleAPIWShortcut(e: KeyboardEvent) {
e.preventDefault();
setOpenCodeModal((oldOpen) => !oldOpen)
setOpenCodeModal((oldOpen) => !oldOpen);
}
function handleChatWShortcut(e: KeyboardEvent) {
@ -25,8 +25,8 @@ export default function FlowToolbar(): JSX.Element {
}
}
const openPlayground = useShortcutsStore(state => state.open);
const api = useShortcutsStore(state => state.api);
const openPlayground = useShortcutsStore((state) => state.open);
const api = useShortcutsStore((state) => state.api);
useHotkeys(openPlayground, handleChatWShortcut);
useHotkeys(api, handleAPIWShortcut);
@ -121,7 +121,11 @@ export default function FlowToolbar(): JSX.Element {
</div>
<div className="flex cursor-pointer items-center gap-2">
{currentFlow && currentFlow.data && (
<ApiModal flow={currentFlow} open={openCodeModal} setOpen={setOpenCodeModal}>
<ApiModal
flow={currentFlow}
open={openCodeModal}
setOpen={setOpenCodeModal}
>
<div
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"

View file

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

View file

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

View file

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

View file

@ -787,68 +787,85 @@ export const SAVE_DEBOUNCE_TIME = 300;
export const defaultShortcuts = [
{
name: "Advanced Settings",
shortcut: "Ctrl + Shift + a"
shortcut: "Ctrl + Shift + a",
},
{
name: "Minimize",
shortcut: "Ctrl + q"
shortcut: "Ctrl + q",
},
{
name: "Code",
shortcut: "Ctrl + Shift + u"
shortcut: "Ctrl + Shift + u",
},
{
name: "Copy",
shortcut: "Ctrl + c"
shortcut: "Ctrl + c",
},
{
name: "Duplicate",
shortcut: "Ctrl + d"
shortcut: "Ctrl + d",
},
{
name: "Share",
shortcut: "Ctrl + Shift + s"
shortcut: "Ctrl + Shift + s",
},
{
name: "Docs",
shortcut: "Ctrl + Shift + d"
shortcut: "Ctrl + Shift + d",
},
{
name: "Save",
shortcut: "Ctrl + s"
shortcut: "Ctrl + s",
},
{
name: "Delete",
shortcut: "Backspace"
shortcut: "Backspace",
},
{
name: "Open playground",
shortcut: "Ctrl + k"
shortcut: "Ctrl + k",
},
{
name: "Undo",
shortcut: "Ctrl + z"
shortcut: "Ctrl + z",
},
{
name: "Redo",
shortcut: "Ctrl + y"
shortcut: "Ctrl + y",
},
{
name: "Group",
shortcut: "Ctrl + g"
shortcut: "Ctrl + g",
},
{
name: "Cut",
shortcut: "Ctrl + x"
shortcut: "Ctrl + x",
},
{
name: "Paste",
shortcut: "Ctrl + v"
shortcut: "Ctrl + v",
},
{
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

@ -49,9 +49,9 @@ const ApiModal = forwardRef(
) => {
const { autoLogin } = useContext(AuthContext);
const [open, setOpen] =
mySetOpen !== undefined && myOpen !== undefined
? [myOpen, mySetOpen]
: useState(false);
mySetOpen !== undefined && myOpen !== undefined
? [myOpen, mySetOpen]
: useState(false);
const [activeTab, setActiveTab] = useState("0");
const tweak = useRef<tweakType>([]);
const tweaksList = useRef<string[]>([]);

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,12 +1,15 @@
import { create } from "zustand";
import {
defaultShortcuts,
unavailableShortcutss,
} from "../constants/constants";
import { shortcutsStoreType } from "../types/store";
import { defaultShortcuts, unavailableShortcutss } from "../constants/constants";
export const useShortcutsStore = create<shortcutsStoreType>((set, get) => ({
unavailableShortcuts: unavailableShortcutss,
shortcuts: defaultShortcuts,
setShortcuts: (newShortcuts, unavailable) => {
set({shortcuts: newShortcuts, unavailableShortcuts: unavailable} );
set({ shortcuts: newShortcuts, unavailableShortcuts: unavailable });
},
undo: "mod+z",
redo: "mod+y",
@ -26,7 +29,7 @@ export const useShortcutsStore = create<shortcutsStoreType>((set, get) => ({
api: "mod+r",
updateUniqueShortcut: (name, combination) => {
set({
[name]: combination
})
}
[name]: combination,
});
},
}));

View file

@ -735,7 +735,7 @@ export type toolbarSelectItemProps = {
isMac: boolean;
shift: boolean;
keyboardKey: string;
mod?:boolean;
mod?: boolean;
value: string;
icon: string;
styleObj?: {

View file

@ -34,13 +34,16 @@ export type shortcutsStoreType = {
copy: string;
duplicate: string;
share: string;
docs:string;
save:string;
docs: string;
save: string;
delete: string;
shortcuts: Array<{
name: string;
shortcut: 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

@ -25,7 +25,7 @@ export type GlobalVariablesStore = {
) => void;
removeGlobalVariable: (name: string) => Promise<void>;
getVariableId: (name: string) => string | undefined;
unavaliableFields: {[name: string]: string};
setUnavaliableFields: (fields: {[name: string]: string}) => void;
unavaliableFields: { [name: string]: string };
setUnavaliableFields: (fields: { [name: string]: string }) => void;
removeUnavaliableField: (field: string) => void;
};

View file

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

View file

@ -93,8 +93,8 @@ export function toTitleCase(
export function getUnavailableFields(variables: {
[key: string]: { default_fields?: string[] };
}): {[name: string]: string} {
const unVariables:{[name: string]: string} = {};
}): { [name: string]: string } {
const unVariables: { [name: string]: string } = {};
Object.keys(variables).forEach((key) => {
if (variables[key].default_fields) {
variables[key].default_fields!.forEach((field) => {