refactor: improve node toolbar code (#3311)
* remove repeated code * refactor: remove useless code * feat: sort input parameters in GenericNode renderInputParameter * refactor: remove unused code in GenericNode component * refactor: add NodeName component for displaying and editing node names * refactor: add NodeDescription component for displaying and editing node descriptions * fix import and add autofocus on nodeName * feat: add NodeStatus component for displaying and managing node status * [autofix.ci] apply automated fixes * refactor: remove unused code in GenericNode component * fix bugs on minimize * [autofix.ci] apply automated fixes * refactor: remove unused code and handle count in GenericNodeToolbar component * refactor: Add useShortcuts hook for handling keyboard shortcuts in nodeToolbarComponent * refactor: Add keyboard shortcuts handling to nodeToolbarComponent need to test * refactor: Update FreezeAllVertices function in NodeToolbarComponent * feat: Add getNodeLength function to calculate the length of a node's template fields * refactor: Update RenderIcons component to use navigator.platform for detecting macOS * refactor: Add ShortcutDisplay component to nodeToolbarComponent * refactor: Update nodeToolbarComponent to remove RenderIcons and add ShortcutDisplay * refactor: Improve keyboard shortcuts handling in nodeToolbarComponent * [autofix.ci] apply automated fixes --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
This commit is contained in:
parent
493b73f9d8
commit
7fe6c53b37
7 changed files with 266 additions and 203 deletions
|
|
@ -52,7 +52,6 @@ export default function GenericNode({
|
||||||
const takeSnapshot = useFlowsManagerStore((state) => state.takeSnapshot);
|
const takeSnapshot = useFlowsManagerStore((state) => state.takeSnapshot);
|
||||||
const [isOutdated, setIsOutdated] = useState(false);
|
const [isOutdated, setIsOutdated] = useState(false);
|
||||||
const [isUserEdited, setIsUserEdited] = useState(false);
|
const [isUserEdited, setIsUserEdited] = useState(false);
|
||||||
const [handles, setHandles] = useState<number>(0);
|
|
||||||
const [borderColor, setBorderColor] = useState<string>("");
|
const [borderColor, setBorderColor] = useState<string>("");
|
||||||
const [showNode, setShowNode] = useState(data.showNode ?? true);
|
const [showNode, setShowNode] = useState(data.showNode ?? true);
|
||||||
|
|
||||||
|
|
@ -108,15 +107,6 @@ export default function GenericNode({
|
||||||
checkNodeIconFragment,
|
checkNodeIconFragment,
|
||||||
);
|
);
|
||||||
|
|
||||||
function countHandles(): void {
|
|
||||||
const count = countHandlesFn(data);
|
|
||||||
setHandles(count);
|
|
||||||
}
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
countHandles();
|
|
||||||
}, [data, data.node]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setShowNode(data.showNode ?? true);
|
setShowNode(data.showNode ?? true);
|
||||||
}, [data.showNode]);
|
}, [data.showNode]);
|
||||||
|
|
@ -228,7 +218,6 @@ export default function GenericNode({
|
||||||
}));
|
}));
|
||||||
}}
|
}}
|
||||||
setShowState={setShowNode}
|
setShowState={setShowNode}
|
||||||
numberOfHandles={handles}
|
|
||||||
numberOfOutputHandles={shownOutputs.length ?? 0}
|
numberOfOutputHandles={shownOutputs.length ?? 0}
|
||||||
showNode={showNode}
|
showNode={showNode}
|
||||||
openAdvancedModal={false}
|
openAdvancedModal={false}
|
||||||
|
|
@ -244,7 +233,6 @@ export default function GenericNode({
|
||||||
takeSnapshot,
|
takeSnapshot,
|
||||||
setNode,
|
setNode,
|
||||||
setShowNode,
|
setShowNode,
|
||||||
handles,
|
|
||||||
showNode,
|
showNode,
|
||||||
updateNodeCode,
|
updateNodeCode,
|
||||||
isOutdated,
|
isOutdated,
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,12 @@
|
||||||
import ForwardedIconComponent from "../genericIconComponent";
|
import ForwardedIconComponent from "../genericIconComponent";
|
||||||
|
|
||||||
export default function RenderIcons({
|
export default function RenderIcons({
|
||||||
isMac,
|
isMac = navigator.platform.toUpperCase().includes("MAC"),
|
||||||
hasShift,
|
hasShift,
|
||||||
filteredShortcut,
|
filteredShortcut,
|
||||||
shortcutWPlus,
|
shortcutWPlus,
|
||||||
}: {
|
}: {
|
||||||
isMac: boolean;
|
isMac?: boolean;
|
||||||
hasShift: boolean;
|
hasShift: boolean;
|
||||||
filteredShortcut: string[];
|
filteredShortcut: string[];
|
||||||
shortcutWPlus: string[];
|
shortcutWPlus: string[];
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,115 @@
|
||||||
|
import { useShortcutsStore } from "@/stores/shortcuts";
|
||||||
|
import { useHotkeys } from "react-hotkeys-hook";
|
||||||
|
import isWrappedWithClass from "../../PageComponent/utils/is-wrapped-with-class";
|
||||||
|
|
||||||
|
export default function useShortcuts({
|
||||||
|
showOverrideModal,
|
||||||
|
showModalAdvanced,
|
||||||
|
openModal,
|
||||||
|
showconfirmShare,
|
||||||
|
FreezeAllVertices,
|
||||||
|
Freeze,
|
||||||
|
downloadFunction,
|
||||||
|
displayDocs,
|
||||||
|
saveComponent,
|
||||||
|
showAdvance,
|
||||||
|
handleCodeModal,
|
||||||
|
shareComponent,
|
||||||
|
ungroup,
|
||||||
|
minimizeFunction,
|
||||||
|
}: {
|
||||||
|
showOverrideModal: boolean;
|
||||||
|
showModalAdvanced: boolean;
|
||||||
|
openModal: boolean;
|
||||||
|
showconfirmShare: boolean;
|
||||||
|
FreezeAllVertices: () => void;
|
||||||
|
Freeze: () => void;
|
||||||
|
downloadFunction: () => void;
|
||||||
|
displayDocs: () => void;
|
||||||
|
saveComponent: () => void;
|
||||||
|
showAdvance: () => void;
|
||||||
|
handleCodeModal: () => void;
|
||||||
|
shareComponent: () => void;
|
||||||
|
ungroup: () => void;
|
||||||
|
minimizeFunction: () => void;
|
||||||
|
}) {
|
||||||
|
const advanced = useShortcutsStore((state) => state.advanced);
|
||||||
|
const minimize = useShortcutsStore((state) => state.minimize);
|
||||||
|
const component = useShortcutsStore((state) => state.component);
|
||||||
|
const save = useShortcutsStore((state) => state.save);
|
||||||
|
const docs = useShortcutsStore((state) => state.docs);
|
||||||
|
const code = useShortcutsStore((state) => state.code);
|
||||||
|
const group = useShortcutsStore((state) => state.group);
|
||||||
|
const download = useShortcutsStore((state) => state.download);
|
||||||
|
const freeze = useShortcutsStore((state) => state.freeze);
|
||||||
|
const freezeAll = useShortcutsStore((state) => state.FreezePath);
|
||||||
|
|
||||||
|
function handleFreezeAll(e: KeyboardEvent) {
|
||||||
|
if (isWrappedWithClass(e, "noflow")) return;
|
||||||
|
e.preventDefault();
|
||||||
|
FreezeAllVertices();
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleFreeze(e: KeyboardEvent) {
|
||||||
|
if (isWrappedWithClass(e, "noflow")) return;
|
||||||
|
e.preventDefault();
|
||||||
|
Freeze();
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleDownloadWShortcut(e: KeyboardEvent) {
|
||||||
|
e.preventDefault();
|
||||||
|
downloadFunction();
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleDocsWShortcut(e: KeyboardEvent) {
|
||||||
|
e.preventDefault();
|
||||||
|
displayDocs();
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleSaveWShortcut(e: KeyboardEvent) {
|
||||||
|
if (isWrappedWithClass(e, "noflow") && !showOverrideModal) return;
|
||||||
|
e.preventDefault();
|
||||||
|
saveComponent();
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleAdvancedWShortcut(e: KeyboardEvent) {
|
||||||
|
//check if there is another modal open
|
||||||
|
if (isWrappedWithClass(e, "noflow") && !showModalAdvanced) return;
|
||||||
|
e.preventDefault();
|
||||||
|
showAdvance();
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleCodeWShortcut(e: KeyboardEvent) {
|
||||||
|
if (isWrappedWithClass(e, "noflow") && !openModal) return;
|
||||||
|
e.preventDefault();
|
||||||
|
handleCodeModal();
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleShareWShortcut(e: KeyboardEvent) {
|
||||||
|
if (isWrappedWithClass(e, "noflow") && !showconfirmShare) return;
|
||||||
|
e.preventDefault();
|
||||||
|
shareComponent();
|
||||||
|
}
|
||||||
|
function handleGroupWShortcut(e: KeyboardEvent) {
|
||||||
|
if (isWrappedWithClass(e, "noflow")) return;
|
||||||
|
e.preventDefault();
|
||||||
|
ungroup();
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleMinimizeWShortcut(e: KeyboardEvent) {
|
||||||
|
if (isWrappedWithClass(e, "noflow")) return;
|
||||||
|
e.preventDefault();
|
||||||
|
minimizeFunction();
|
||||||
|
}
|
||||||
|
|
||||||
|
useHotkeys(minimize, handleMinimizeWShortcut, { preventDefault: true });
|
||||||
|
useHotkeys(group, handleGroupWShortcut, { preventDefault: true });
|
||||||
|
useHotkeys(component, handleShareWShortcut, { preventDefault: true });
|
||||||
|
useHotkeys(code, handleCodeWShortcut, { preventDefault: true });
|
||||||
|
useHotkeys(advanced, handleAdvancedWShortcut, { preventDefault: true });
|
||||||
|
useHotkeys(save, handleSaveWShortcut, { preventDefault: true });
|
||||||
|
useHotkeys(docs, handleDocsWShortcut, { preventDefault: true });
|
||||||
|
useHotkeys(download, handleDownloadWShortcut, { preventDefault: true });
|
||||||
|
useHotkeys(freeze, handleFreeze);
|
||||||
|
useHotkeys(freezeAll, handleFreezeAll);
|
||||||
|
}
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
import { countHandlesFn } from "@/CustomNodes/helpers/count-handles";
|
||||||
import useHandleOnNewValue from "@/CustomNodes/hooks/use-handle-new-value";
|
import useHandleOnNewValue from "@/CustomNodes/hooks/use-handle-new-value";
|
||||||
import useHandleNodeClass from "@/CustomNodes/hooks/use-handle-node-class";
|
import useHandleNodeClass from "@/CustomNodes/hooks/use-handle-node-class";
|
||||||
import { usePostRetrieveVertexOrder } from "@/controllers/API/queries/vertex";
|
import { usePostRetrieveVertexOrder } from "@/controllers/API/queries/vertex";
|
||||||
|
|
@ -5,11 +6,9 @@ import useAddFlow from "@/hooks/flows/use-add-flow";
|
||||||
import { APIClassType } from "@/types/api";
|
import { APIClassType } from "@/types/api";
|
||||||
import _, { cloneDeep } from "lodash";
|
import _, { cloneDeep } from "lodash";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { useHotkeys } from "react-hotkeys-hook";
|
|
||||||
import { useUpdateNodeInternals } from "reactflow";
|
import { useUpdateNodeInternals } from "reactflow";
|
||||||
import CodeAreaComponent from "../../../../components/codeAreaComponent";
|
import CodeAreaComponent from "../../../../components/codeAreaComponent";
|
||||||
import IconComponent from "../../../../components/genericIconComponent";
|
import IconComponent from "../../../../components/genericIconComponent";
|
||||||
import RenderIcons from "../../../../components/renderIconComponent";
|
|
||||||
import ShadTooltip from "../../../../components/shadTooltipComponent";
|
import ShadTooltip from "../../../../components/shadTooltipComponent";
|
||||||
import {
|
import {
|
||||||
Select,
|
Select,
|
||||||
|
|
@ -34,15 +33,20 @@ import {
|
||||||
expandGroupNode,
|
expandGroupNode,
|
||||||
updateFlowPosition,
|
updateFlowPosition,
|
||||||
} from "../../../../utils/reactflowUtils";
|
} from "../../../../utils/reactflowUtils";
|
||||||
import { classNames, cn } from "../../../../utils/utils";
|
import {
|
||||||
import isWrappedWithClass from "../PageComponent/utils/is-wrapped-with-class";
|
classNames,
|
||||||
|
cn,
|
||||||
|
getNodeLength,
|
||||||
|
openInNewTab,
|
||||||
|
} from "../../../../utils/utils";
|
||||||
|
import useShortcuts from "./hooks/use-shortcuts";
|
||||||
|
import ShortcutDisplay from "./shortcutDisplay";
|
||||||
import ToolbarSelectItem from "./toolbarSelectItem";
|
import ToolbarSelectItem from "./toolbarSelectItem";
|
||||||
|
|
||||||
export default function NodeToolbarComponent({
|
export default function NodeToolbarComponent({
|
||||||
data,
|
data,
|
||||||
deleteNode,
|
deleteNode,
|
||||||
setShowNode,
|
setShowNode,
|
||||||
numberOfHandles,
|
|
||||||
numberOfOutputHandles,
|
numberOfOutputHandles,
|
||||||
showNode,
|
showNode,
|
||||||
name = "code",
|
name = "code",
|
||||||
|
|
@ -58,36 +62,23 @@ export default function NodeToolbarComponent({
|
||||||
const [flowComponent, setFlowComponent] = useState<FlowType>(
|
const [flowComponent, setFlowComponent] = useState<FlowType>(
|
||||||
createFlowComponent(cloneDeep(data), version),
|
createFlowComponent(cloneDeep(data), version),
|
||||||
);
|
);
|
||||||
const preventDefault = true;
|
const nodeLength = getNodeLength(data);
|
||||||
const isMac = navigator.platform.toUpperCase().includes("MAC");
|
|
||||||
const nodeLength = Object.keys(data.node!.template).filter(
|
|
||||||
(templateField) =>
|
|
||||||
templateField.charAt(0) !== "_" &&
|
|
||||||
data.node?.template[templateField]?.show &&
|
|
||||||
(data.node.template[templateField]?.type === "str" ||
|
|
||||||
data.node.template[templateField]?.type === "bool" ||
|
|
||||||
data.node.template[templateField]?.type === "float" ||
|
|
||||||
data.node.template[templateField]?.type === "code" ||
|
|
||||||
data.node.template[templateField]?.type === "prompt" ||
|
|
||||||
data.node.template[templateField]?.type === "file" ||
|
|
||||||
data.node.template[templateField]?.type === "Any" ||
|
|
||||||
data.node.template[templateField]?.type === "int" ||
|
|
||||||
data.node.template[templateField]?.type === "dict" ||
|
|
||||||
data.node.template[templateField]?.type === "NestedDict"),
|
|
||||||
).length;
|
|
||||||
const updateFreezeStatus = useFlowStore((state) => state.updateFreezeStatus);
|
const updateFreezeStatus = useFlowStore((state) => state.updateFreezeStatus);
|
||||||
|
|
||||||
const hasStore = useStoreStore((state) => state.hasStore);
|
const hasStore = useStoreStore((state) => state.hasStore);
|
||||||
const hasApiKey = useStoreStore((state) => state.hasApiKey);
|
const hasApiKey = useStoreStore((state) => state.hasApiKey);
|
||||||
const validApiKey = useStoreStore((state) => state.validApiKey);
|
const validApiKey = useStoreStore((state) => state.validApiKey);
|
||||||
const shortcuts = useShortcutsStore((state) => state.shortcuts);
|
const shortcuts = useShortcutsStore((state) => state.shortcuts);
|
||||||
const unselectAll = useFlowStore((state) => state.unselectAll);
|
const unselectAll = useFlowStore((state) => state.unselectAll);
|
||||||
const currentFlowId = useFlowsManagerStore((state) => state.currentFlowId);
|
const currentFlowId = useFlowsManagerStore((state) => state.currentFlowId);
|
||||||
|
const [openModal, setOpenModal] = useState(false);
|
||||||
|
const isGroup = data.node?.flow ? true : false;
|
||||||
|
const frozen = data.node?.frozen ?? false;
|
||||||
|
|
||||||
const addFlow = useAddFlow();
|
const addFlow = useAddFlow();
|
||||||
|
|
||||||
function handleMinimizeWShortcut(e: KeyboardEvent) {
|
const isMinimal = countHandlesFn(data) <= 1 && numberOfOutputHandles <= 1;
|
||||||
if (isWrappedWithClass(e, "noflow")) return;
|
|
||||||
e.preventDefault();
|
function minimize() {
|
||||||
if (isMinimal) {
|
if (isMinimal) {
|
||||||
setShowState((show) => !show);
|
setShowState((show) => !show);
|
||||||
setShowNode(data.showNode ?? true ? false : true);
|
setShowNode(data.showNode ?? true ? false : true);
|
||||||
|
|
@ -100,54 +91,48 @@ export default function NodeToolbarComponent({
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleGroupWShortcut(e: KeyboardEvent) {
|
function handleungroup() {
|
||||||
if (isWrappedWithClass(e, "noflow")) return;
|
|
||||||
e.preventDefault();
|
|
||||||
if (isGroup) {
|
if (isGroup) {
|
||||||
handleSelectChange("ungroup");
|
takeSnapshot();
|
||||||
|
expandGroupNode(
|
||||||
|
data.id,
|
||||||
|
updateFlowPosition(getNodePosition(data.id), data.node?.flow!),
|
||||||
|
data.node!.template,
|
||||||
|
nodes,
|
||||||
|
edges,
|
||||||
|
setNodes,
|
||||||
|
setEdges,
|
||||||
|
data.node?.outputs,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleShareWShortcut(e: KeyboardEvent) {
|
function shareComponent() {
|
||||||
if (isWrappedWithClass(e, "noflow") && !showconfirmShare) return;
|
|
||||||
e.preventDefault();
|
|
||||||
if (hasApiKey || hasStore) {
|
if (hasApiKey || hasStore) {
|
||||||
setShowconfirmShare((state) => !state);
|
setShowconfirmShare((state) => !state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleCodeWShortcut(e: KeyboardEvent) {
|
function handleCodeModal() {
|
||||||
if (isWrappedWithClass(e, "noflow") && !openModal) return;
|
if (!hasCode)
|
||||||
e.preventDefault();
|
setNoticeData({ title: `You can not access ${data.id} code` });
|
||||||
if (hasCode) return setOpenModal((state) => !state);
|
setOpenModal((state) => !state);
|
||||||
setNoticeData({ title: `You can not access ${data.id} code` });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleAdvancedWShortcut(e: KeyboardEvent) {
|
function saveComponent() {
|
||||||
if (isWrappedWithClass(e, "noflow") && !showModalAdvanced) return;
|
|
||||||
e.preventDefault();
|
|
||||||
setShowModalAdvanced((state) => !state);
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleSaveWShortcut(e: KeyboardEvent) {
|
|
||||||
if (isWrappedWithClass(e, "noflow") && !showOverrideModal) return;
|
|
||||||
e.preventDefault();
|
|
||||||
if (isSaved) {
|
if (isSaved) {
|
||||||
setShowOverrideModal((state) => !state);
|
setShowOverrideModal((state) => !state);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (hasCode && !isSaved) {
|
addFlow({
|
||||||
addFlow({
|
flow: flowComponent,
|
||||||
flow: flowComponent,
|
override: false,
|
||||||
override: false,
|
});
|
||||||
});
|
setSuccessData({ title: `${data.id} saved successfully` });
|
||||||
setSuccessData({ title: `${data.id} saved successfully` });
|
return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleDocsWShortcut(e: KeyboardEvent) {
|
function openDocs() {
|
||||||
e.preventDefault();
|
|
||||||
if (data.node?.documentation) {
|
if (data.node?.documentation) {
|
||||||
return openInNewTab(data.node?.documentation);
|
return openInNewTab(data.node?.documentation);
|
||||||
}
|
}
|
||||||
|
|
@ -156,14 +141,7 @@ export default function NodeToolbarComponent({
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleDownloadWShortcut(e: KeyboardEvent) {
|
const freezeFunction = () => {
|
||||||
e.preventDefault();
|
|
||||||
downloadNode(flowComponent!);
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleFreeze(e: KeyboardEvent) {
|
|
||||||
if (isWrappedWithClass(e, "noflow")) return;
|
|
||||||
e.preventDefault();
|
|
||||||
setNode(data.id, (old) => ({
|
setNode(data.id, (old) => ({
|
||||||
...old,
|
...old,
|
||||||
data: {
|
data: {
|
||||||
|
|
@ -174,45 +152,31 @@ export default function NodeToolbarComponent({
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
}
|
};
|
||||||
|
|
||||||
function handleFreezeAll(e: KeyboardEvent) {
|
useShortcuts({
|
||||||
if (isWrappedWithClass(e, "noflow")) return;
|
showOverrideModal,
|
||||||
e.preventDefault();
|
showModalAdvanced,
|
||||||
FreezeAllVertices({ flowId: currentFlowId, stopNodeId: data.id });
|
openModal,
|
||||||
}
|
showconfirmShare,
|
||||||
|
FreezeAllVertices: () => {
|
||||||
|
FreezeAllVertices({ flowId: currentFlowId, stopNodeId: data.id });
|
||||||
|
},
|
||||||
|
Freeze: freezeFunction,
|
||||||
|
downloadFunction: () => downloadNode(flowComponent!),
|
||||||
|
displayDocs: openDocs,
|
||||||
|
saveComponent,
|
||||||
|
showAdvance: () => setShowModalAdvanced((state) => !state),
|
||||||
|
handleCodeModal,
|
||||||
|
shareComponent,
|
||||||
|
ungroup: handleungroup,
|
||||||
|
minimizeFunction: minimize,
|
||||||
|
});
|
||||||
|
|
||||||
const advanced = useShortcutsStore((state) => state.advanced);
|
|
||||||
const minimize = useShortcutsStore((state) => state.minimize);
|
|
||||||
const component = useShortcutsStore((state) => state.component);
|
|
||||||
const save = useShortcutsStore((state) => state.save);
|
|
||||||
const docs = useShortcutsStore((state) => state.docs);
|
|
||||||
const code = useShortcutsStore((state) => state.code);
|
|
||||||
const group = useShortcutsStore((state) => state.group);
|
|
||||||
const download = useShortcutsStore((state) => state.download);
|
|
||||||
const freeze = useShortcutsStore((state) => state.freeze);
|
|
||||||
const freezeAll = useShortcutsStore((state) => state.FreezePath);
|
|
||||||
|
|
||||||
useHotkeys(minimize, handleMinimizeWShortcut, { preventDefault });
|
|
||||||
useHotkeys(group, handleGroupWShortcut, { preventDefault });
|
|
||||||
useHotkeys(component, handleShareWShortcut, { preventDefault });
|
|
||||||
useHotkeys(code, handleCodeWShortcut, { preventDefault });
|
|
||||||
useHotkeys(advanced, handleAdvancedWShortcut, { preventDefault });
|
|
||||||
useHotkeys(save, handleSaveWShortcut, { preventDefault });
|
|
||||||
useHotkeys(docs, handleDocsWShortcut, { preventDefault });
|
|
||||||
useHotkeys(download, handleDownloadWShortcut, { preventDefault });
|
|
||||||
useHotkeys(freeze, handleFreeze);
|
|
||||||
useHotkeys(freezeAll, handleFreezeAll);
|
|
||||||
|
|
||||||
const isMinimal = numberOfHandles <= 1 && numberOfOutputHandles <= 1;
|
|
||||||
const isGroup = data.node?.flow ? true : false;
|
|
||||||
|
|
||||||
const frozen = data.node?.frozen ?? false;
|
|
||||||
const paste = useFlowStore((state) => state.paste);
|
const paste = useFlowStore((state) => state.paste);
|
||||||
const nodes = useFlowStore((state) => state.nodes);
|
const nodes = useFlowStore((state) => state.nodes);
|
||||||
const edges = useFlowStore((state) => state.edges);
|
const edges = useFlowStore((state) => state.edges);
|
||||||
const setNodes = useFlowStore((state) => state.setNodes);
|
const setNodes = useFlowStore((state) => state.setNodes);
|
||||||
|
|
||||||
const setEdges = useFlowStore((state) => state.setEdges);
|
const setEdges = useFlowStore((state) => state.setEdges);
|
||||||
const getNodePosition = useFlowStore((state) => state.getNodePosition);
|
const getNodePosition = useFlowStore((state) => state.getNodePosition);
|
||||||
const flows = useFlowsManagerStore((state) => state.flows);
|
const flows = useFlowsManagerStore((state) => state.flows);
|
||||||
|
|
@ -226,10 +190,6 @@ export default function NodeToolbarComponent({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const openInNewTab = (url) => {
|
|
||||||
window.open(url, "_blank", "noreferrer");
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!showModalAdvanced) {
|
if (!showModalAdvanced) {
|
||||||
onCloseAdvancedModal!(false);
|
onCloseAdvancedModal!(false);
|
||||||
|
|
@ -259,25 +219,10 @@ export default function NodeToolbarComponent({
|
||||||
const handleSelectChange = (event) => {
|
const handleSelectChange = (event) => {
|
||||||
switch (event) {
|
switch (event) {
|
||||||
case "save":
|
case "save":
|
||||||
if (isSaved) {
|
saveComponent();
|
||||||
return setShowOverrideModal(true);
|
|
||||||
}
|
|
||||||
addFlow({
|
|
||||||
flow: flowComponent,
|
|
||||||
override: false,
|
|
||||||
});
|
|
||||||
break;
|
break;
|
||||||
case "freeze":
|
case "freeze":
|
||||||
setNode(data.id, (old) => ({
|
freezeFunction();
|
||||||
...old,
|
|
||||||
data: {
|
|
||||||
...old.data,
|
|
||||||
node: {
|
|
||||||
...old.data.node,
|
|
||||||
frozen: old.data?.node?.frozen ? false : true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}));
|
|
||||||
break;
|
break;
|
||||||
case "freezeAll":
|
case "freezeAll":
|
||||||
FreezeAllVertices({ flowId: currentFlowId, stopNodeId: data.id });
|
FreezeAllVertices({ flowId: currentFlowId, stopNodeId: data.id });
|
||||||
|
|
@ -290,10 +235,10 @@ export default function NodeToolbarComponent({
|
||||||
break;
|
break;
|
||||||
case "show":
|
case "show":
|
||||||
takeSnapshot();
|
takeSnapshot();
|
||||||
setShowNode(data.showNode ?? true ? false : true);
|
minimize();
|
||||||
break;
|
break;
|
||||||
case "Share":
|
case "Share":
|
||||||
if (hasApiKey || hasStore) setShowconfirmShare(true);
|
shareComponent();
|
||||||
break;
|
break;
|
||||||
case "Download":
|
case "Download":
|
||||||
downloadNode(flowComponent!);
|
downloadNode(flowComponent!);
|
||||||
|
|
@ -305,7 +250,7 @@ export default function NodeToolbarComponent({
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
case "documentation":
|
case "documentation":
|
||||||
if (data.node?.documentation) openInNewTab(data.node?.documentation);
|
openDocs();
|
||||||
break;
|
break;
|
||||||
case "disabled":
|
case "disabled":
|
||||||
break;
|
break;
|
||||||
|
|
@ -313,17 +258,7 @@ export default function NodeToolbarComponent({
|
||||||
unselectAll();
|
unselectAll();
|
||||||
break;
|
break;
|
||||||
case "ungroup":
|
case "ungroup":
|
||||||
takeSnapshot();
|
handleungroup();
|
||||||
expandGroupNode(
|
|
||||||
data.id,
|
|
||||||
updateFlowPosition(getNodePosition(data.id), data.node?.flow!),
|
|
||||||
data.node!.template,
|
|
||||||
nodes,
|
|
||||||
edges,
|
|
||||||
setNodes,
|
|
||||||
setEdges,
|
|
||||||
data.node?.outputs,
|
|
||||||
);
|
|
||||||
break;
|
break;
|
||||||
case "override":
|
case "override":
|
||||||
setShowOverrideModal(true);
|
setShowOverrideModal(true);
|
||||||
|
|
@ -359,42 +294,6 @@ export default function NodeToolbarComponent({
|
||||||
Object.values(flow).includes(data.node?.display_name!),
|
Object.values(flow).includes(data.node?.display_name!),
|
||||||
);
|
);
|
||||||
|
|
||||||
function displayShortcut({
|
|
||||||
name,
|
|
||||||
shortcut,
|
|
||||||
}: {
|
|
||||||
name: string;
|
|
||||||
shortcut: string;
|
|
||||||
}): JSX.Element {
|
|
||||||
let hasShift: boolean = false;
|
|
||||||
const fixedShortcut = shortcut?.split("+");
|
|
||||||
fixedShortcut.forEach((key) => {
|
|
||||||
if (key.toLowerCase().includes("shift")) {
|
|
||||||
hasShift = true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
const filteredShortcut = fixedShortcut.filter(
|
|
||||||
(key) => !key.toLowerCase().includes("shift"),
|
|
||||||
);
|
|
||||||
let shortcutWPlus: string[] = [];
|
|
||||||
if (!hasShift) shortcutWPlus = filteredShortcut.join("+").split(" ");
|
|
||||||
return (
|
|
||||||
<div className="flex justify-center">
|
|
||||||
<span> {name} </span>
|
|
||||||
<span
|
|
||||||
className={`ml-3 flex items-center rounded-sm bg-muted px-1.5 py-[0.1em] text-lg text-muted-foreground`}
|
|
||||||
>
|
|
||||||
<RenderIcons
|
|
||||||
isMac={isMac}
|
|
||||||
hasShift={hasShift}
|
|
||||||
filteredShortcut={filteredShortcut}
|
|
||||||
shortcutWPlus={shortcutWPlus}
|
|
||||||
/>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const setNode = useFlowStore((state) => state.setNode);
|
const setNode = useFlowStore((state) => state.setNode);
|
||||||
|
|
||||||
const { handleOnNewValue: handleOnNewValueHook } = useHandleOnNewValue({
|
const { handleOnNewValue: handleOnNewValueHook } = useHandleOnNewValue({
|
||||||
|
|
@ -413,7 +312,6 @@ export default function NodeToolbarComponent({
|
||||||
handleNodeClassHook(newNodeClass, type);
|
handleNodeClassHook(newNodeClass, type);
|
||||||
};
|
};
|
||||||
|
|
||||||
const [openModal, setOpenModal] = useState(false);
|
|
||||||
const hasCode = Object.keys(data.node!.template).includes("code");
|
const hasCode = Object.keys(data.node!.template).includes("code");
|
||||||
const [deleteIsFocus, setDeleteIsFocus] = useState(false);
|
const [deleteIsFocus, setDeleteIsFocus] = useState(false);
|
||||||
|
|
||||||
|
|
@ -423,11 +321,13 @@ export default function NodeToolbarComponent({
|
||||||
<span className="isolate inline-flex rounded-md shadow-sm">
|
<span className="isolate inline-flex rounded-md shadow-sm">
|
||||||
{hasCode && (
|
{hasCode && (
|
||||||
<ShadTooltip
|
<ShadTooltip
|
||||||
content={displayShortcut(
|
content={
|
||||||
shortcuts.find(
|
<ShortcutDisplay
|
||||||
({ name }) => name.split(" ")[0].toLowerCase() === "code",
|
{...shortcuts.find(
|
||||||
)!,
|
({ name }) => name.split(" ")[0].toLowerCase() === "code",
|
||||||
)}
|
)!}
|
||||||
|
/>
|
||||||
|
}
|
||||||
side="top"
|
side="top"
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
|
|
@ -443,11 +343,14 @@ export default function NodeToolbarComponent({
|
||||||
)}
|
)}
|
||||||
{nodeLength > 0 && (
|
{nodeLength > 0 && (
|
||||||
<ShadTooltip
|
<ShadTooltip
|
||||||
content={displayShortcut(
|
content={
|
||||||
shortcuts.find(
|
<ShortcutDisplay
|
||||||
({ name }) => name.split(" ")[0].toLowerCase() === "advanced",
|
{...shortcuts.find(
|
||||||
)!,
|
({ name }) =>
|
||||||
)}
|
name.split(" ")[0].toLowerCase() === "advanced",
|
||||||
|
)!}
|
||||||
|
/>
|
||||||
|
}
|
||||||
side="top"
|
side="top"
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
|
|
@ -465,11 +368,13 @@ export default function NodeToolbarComponent({
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<ShadTooltip
|
<ShadTooltip
|
||||||
content={displayShortcut(
|
content={
|
||||||
shortcuts.find(
|
<ShortcutDisplay
|
||||||
({ name }) => name.toLowerCase() === "freeze path",
|
{...shortcuts.find(
|
||||||
)!,
|
({ name }) => name.toLowerCase() === "freeze path",
|
||||||
)}
|
)!}
|
||||||
|
/>
|
||||||
|
}
|
||||||
side="top"
|
side="top"
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,36 @@
|
||||||
|
import RenderIcons from "@/components/renderIconComponent";
|
||||||
|
|
||||||
|
export default function ShortcutDisplay({
|
||||||
|
name,
|
||||||
|
shortcut,
|
||||||
|
}: {
|
||||||
|
name: string;
|
||||||
|
shortcut: string;
|
||||||
|
}): JSX.Element {
|
||||||
|
let hasShift: boolean = false;
|
||||||
|
const fixedShortcut = shortcut?.split("+");
|
||||||
|
fixedShortcut.forEach((key) => {
|
||||||
|
if (key.toLowerCase().includes("shift")) {
|
||||||
|
hasShift = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const filteredShortcut = fixedShortcut.filter(
|
||||||
|
(key) => !key.toLowerCase().includes("shift"),
|
||||||
|
);
|
||||||
|
let shortcutWPlus: string[] = [];
|
||||||
|
if (!hasShift) shortcutWPlus = filteredShortcut.join("+").split(" ");
|
||||||
|
return (
|
||||||
|
<div className="flex justify-center">
|
||||||
|
<span> {name} </span>
|
||||||
|
<span
|
||||||
|
className={`ml-3 flex items-center rounded-sm bg-muted px-1.5 py-[0.1em] text-lg text-muted-foreground`}
|
||||||
|
>
|
||||||
|
<RenderIcons
|
||||||
|
hasShift={hasShift}
|
||||||
|
filteredShortcut={filteredShortcut}
|
||||||
|
shortcutWPlus={shortcutWPlus}
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -622,12 +622,9 @@ export type fileCardPropsType = {
|
||||||
};
|
};
|
||||||
|
|
||||||
export type nodeToolbarPropsType = {
|
export type nodeToolbarPropsType = {
|
||||||
// openWDoubleClick: boolean;
|
|
||||||
// setOpenWDoubleClick: (open: boolean) => void;
|
|
||||||
data: NodeDataType;
|
data: NodeDataType;
|
||||||
deleteNode: (idx: string) => void;
|
deleteNode: (idx: string) => void;
|
||||||
setShowNode: (boolean: any) => void;
|
setShowNode: (boolean: any) => void;
|
||||||
numberOfHandles: number;
|
|
||||||
numberOfOutputHandles: number;
|
numberOfOutputHandles: number;
|
||||||
showNode: boolean;
|
showNode: boolean;
|
||||||
name?: string;
|
name?: string;
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ import {
|
||||||
nodeGroupedObjType,
|
nodeGroupedObjType,
|
||||||
tweakType,
|
tweakType,
|
||||||
} from "../types/components";
|
} from "../types/components";
|
||||||
import { NodeType } from "../types/flow";
|
import { NodeDataType, NodeType } from "../types/flow";
|
||||||
import { FlowState } from "../types/tabs";
|
import { FlowState } from "../types/tabs";
|
||||||
import { isErrorLog } from "../types/utils/typeCheckingUtils";
|
import { isErrorLog } from "../types/utils/typeCheckingUtils";
|
||||||
|
|
||||||
|
|
@ -562,3 +562,25 @@ export function tryParseJson(json: string) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function openInNewTab(url) {
|
||||||
|
window.open(url, "_blank", "noreferrer");
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getNodeLength(data: NodeDataType) {
|
||||||
|
return Object.keys(data.node!.template).filter(
|
||||||
|
(templateField) =>
|
||||||
|
templateField.charAt(0) !== "_" &&
|
||||||
|
data.node?.template[templateField]?.show &&
|
||||||
|
(data.node.template[templateField]?.type === "str" ||
|
||||||
|
data.node.template[templateField]?.type === "bool" ||
|
||||||
|
data.node.template[templateField]?.type === "float" ||
|
||||||
|
data.node.template[templateField]?.type === "code" ||
|
||||||
|
data.node.template[templateField]?.type === "prompt" ||
|
||||||
|
data.node.template[templateField]?.type === "file" ||
|
||||||
|
data.node.template[templateField]?.type === "Any" ||
|
||||||
|
data.node.template[templateField]?.type === "int" ||
|
||||||
|
data.node.template[templateField]?.type === "dict" ||
|
||||||
|
data.node.template[templateField]?.type === "NestedDict"),
|
||||||
|
).length;
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue