Format code
This commit is contained in:
parent
61b894c2e8
commit
8967a2694e
23 changed files with 411 additions and 334 deletions
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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):
|
||||||
|
|
|
||||||
|
|
@ -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 `} />
|
||||||
</>
|
</>
|
||||||
)
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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"
|
||||||
|
|
|
||||||
|
|
@ -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(),
|
||||||
|
|
|
||||||
|
|
@ -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!]);
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -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",
|
||||||
|
];
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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"
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -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"
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
})
|
});
|
||||||
}
|
},
|
||||||
}));
|
}));
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue