From a71fc185309f8b1fdc1dc079b3f6185848189091 Mon Sep 17 00:00:00 2001 From: Yi Xiao <54782454+YIXIAO0@users.noreply.github.com> Date: Fri, 23 Aug 2024 13:11:55 +0800 Subject: [PATCH 1/3] feat: set workflow zoom range for shortcut (#7563) --- .../workflow/hooks/use-shortcuts.ts | 21 +++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/web/app/components/workflow/hooks/use-shortcuts.ts b/web/app/components/workflow/hooks/use-shortcuts.ts index 9484f9c16e..666c3a45ba 100644 --- a/web/app/components/workflow/hooks/use-shortcuts.ts +++ b/web/app/components/workflow/hooks/use-shortcuts.ts @@ -37,12 +37,25 @@ export const useShortcuts = (): void => { const { handleLayout } = useWorkflowOrganize() const { - zoomIn, - zoomOut, zoomTo, + getZoom, fitView, } = useReactFlow() + // Zoom out to a minimum of 0.5 for shortcut + const constrainedZoomOut = () => { + const currentZoom = getZoom() + const newZoom = Math.max(currentZoom - 0.1, 0.5) + zoomTo(newZoom) + } + + // Zoom in to a maximum of 1 for shortcut + const constrainedZoomIn = () => { + const currentZoom = getZoom() + const newZoom = Math.min(currentZoom + 0.1, 1) + zoomTo(newZoom) + } + const shouldHandleShortcut = useCallback((e: KeyboardEvent) => { const { showFeaturesPanel } = workflowStore.getState() return !showFeaturesPanel && !isEventTargetInputArea(e.target as HTMLElement) @@ -165,7 +178,7 @@ export const useShortcuts = (): void => { useKeyPress(`${getKeyboardKeyCodeBySystem('ctrl')}.dash`, (e) => { if (shouldHandleShortcut(e)) { e.preventDefault() - zoomOut() + constrainedZoomOut() handleSyncWorkflowDraft() } }, { @@ -176,7 +189,7 @@ export const useShortcuts = (): void => { useKeyPress(`${getKeyboardKeyCodeBySystem('ctrl')}.equalsign`, (e) => { if (shouldHandleShortcut(e)) { e.preventDefault() - zoomIn() + constrainedZoomIn() handleSyncWorkflowDraft() } }, { From 9618f86980a69ffaa5f48373267dc5aa22c3771a Mon Sep 17 00:00:00 2001 From: Yi Xiao <54782454+YIXIAO0@users.noreply.github.com> Date: Fri, 23 Aug 2024 13:14:17 +0800 Subject: [PATCH 2/3] fix: workflow context menu popup issue (#7530) --- web/app/components/workflow/node-contextmenu.tsx | 12 +++++++++--- web/app/components/workflow/panel-contextmenu.tsx | 8 +++++++- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/web/app/components/workflow/node-contextmenu.tsx b/web/app/components/workflow/node-contextmenu.tsx index adfed37b26..311bf1fddf 100644 --- a/web/app/components/workflow/node-contextmenu.tsx +++ b/web/app/components/workflow/node-contextmenu.tsx @@ -1,5 +1,6 @@ import { memo, + useEffect, useRef, } from 'react' import { useClickAway } from 'ahooks' @@ -9,13 +10,18 @@ import type { Node } from './types' import { useStore } from './store' import { usePanelInteractions } from './hooks' -const PanelContextmenu = () => { +const NodeContextmenu = () => { const ref = useRef(null) const nodes = useNodes() - const { handleNodeContextmenuCancel } = usePanelInteractions() + const { handleNodeContextmenuCancel, handlePaneContextmenuCancel } = usePanelInteractions() const nodeMenu = useStore(s => s.nodeMenu) const currentNode = nodes.find(node => node.id === nodeMenu?.nodeId) as Node + useEffect(() => { + if (nodeMenu) + handlePaneContextmenuCancel() + }, [nodeMenu, handlePaneContextmenuCancel]) + useClickAway(() => { handleNodeContextmenuCancel() }, ref) @@ -42,4 +48,4 @@ const PanelContextmenu = () => { ) } -export default memo(PanelContextmenu) +export default memo(NodeContextmenu) diff --git a/web/app/components/workflow/panel-contextmenu.tsx b/web/app/components/workflow/panel-contextmenu.tsx index 502967ce2c..f01e3037a2 100644 --- a/web/app/components/workflow/panel-contextmenu.tsx +++ b/web/app/components/workflow/panel-contextmenu.tsx @@ -1,5 +1,6 @@ import { memo, + useEffect, useRef, } from 'react' import { useTranslation } from 'react-i18next' @@ -23,11 +24,16 @@ const PanelContextmenu = () => { const clipboardElements = useStore(s => s.clipboardElements) const setShowImportDSLModal = useStore(s => s.setShowImportDSLModal) const { handleNodesPaste } = useNodesInteractions() - const { handlePaneContextmenuCancel } = usePanelInteractions() + const { handlePaneContextmenuCancel, handleNodeContextmenuCancel } = usePanelInteractions() const { handleStartWorkflowRun } = useWorkflowStartRun() const { handleAddNote } = useOperator() const { exportCheck } = useDSL() + useEffect(() => { + if (panelMenu) + handleNodeContextmenuCancel() + }, [panelMenu, handleNodeContextmenuCancel]) + useClickAway(() => { handlePaneContextmenuCancel() }, ref) From 0a7ab9a47dc4858ed6d0cf8279add6ad299b6031 Mon Sep 17 00:00:00 2001 From: edo1z <89882017+edo1z@users.noreply.github.com> Date: Fri, 23 Aug 2024 14:16:15 +0900 Subject: [PATCH 3/3] fix: incorrect duplication when no target node is selected (#7539) --- .../workflow/hooks/use-nodes-interactions.ts | 30 ++++++++++++------- .../panel-operator/panel-operator-popup.tsx | 2 +- 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/web/app/components/workflow/hooks/use-nodes-interactions.ts b/web/app/components/workflow/hooks/use-nodes-interactions.ts index 87d1b4de8c..3645e18449 100644 --- a/web/app/components/workflow/hooks/use-nodes-interactions.ts +++ b/web/app/components/workflow/hooks/use-nodes-interactions.ts @@ -1027,7 +1027,7 @@ export const useNodesInteractions = () => { handleNodeSelect(node.id) }, [workflowStore, handleNodeSelect]) - const handleNodesCopy = useCallback(() => { + const handleNodesCopy = useCallback((nodeId?: string) => { if (getNodesReadOnly()) return @@ -1038,17 +1038,27 @@ export const useNodesInteractions = () => { } = store.getState() const nodes = getNodes() - const bundledNodes = nodes.filter(node => node.data._isBundled && node.data.type !== BlockEnum.Start && !node.data.isInIteration) - if (bundledNodes.length) { - setClipboardElements(bundledNodes) - return + if (nodeId) { + // If nodeId is provided, copy that specific node + const nodeToCopy = nodes.find(node => node.id === nodeId && node.data.type !== BlockEnum.Start) + if (nodeToCopy) + setClipboardElements([nodeToCopy]) } + else { + // If no nodeId is provided, fall back to the current behavior + const bundledNodes = nodes.filter(node => node.data._isBundled && node.data.type !== BlockEnum.Start && !node.data.isInIteration) - const selectedNode = nodes.find(node => node.data.selected && node.data.type !== BlockEnum.Start) + if (bundledNodes.length) { + setClipboardElements(bundledNodes) + return + } - if (selectedNode) - setClipboardElements([selectedNode]) + const selectedNode = nodes.find(node => node.data.selected && node.data.type !== BlockEnum.Start) + + if (selectedNode) + setClipboardElements([selectedNode]) + } }, [getNodesReadOnly, store, workflowStore]) const handleNodesPaste = useCallback(() => { @@ -1128,11 +1138,11 @@ export const useNodesInteractions = () => { } }, [getNodesReadOnly, workflowStore, store, reactflow, saveStateToHistory, handleSyncWorkflowDraft, handleNodeIterationChildrenCopy]) - const handleNodesDuplicate = useCallback(() => { + const handleNodesDuplicate = useCallback((nodeId?: string) => { if (getNodesReadOnly()) return - handleNodesCopy() + handleNodesCopy(nodeId) handleNodesPaste() }, [getNodesReadOnly, handleNodesCopy, handleNodesPaste]) diff --git a/web/app/components/workflow/nodes/_base/components/panel-operator/panel-operator-popup.tsx b/web/app/components/workflow/nodes/_base/components/panel-operator/panel-operator-popup.tsx index aade4d8be8..bd642fcd66 100644 --- a/web/app/components/workflow/nodes/_base/components/panel-operator/panel-operator-popup.tsx +++ b/web/app/components/workflow/nodes/_base/components/panel-operator/panel-operator-popup.tsx @@ -138,7 +138,7 @@ const PanelOperatorPopup = ({ className='flex items-center justify-between px-3 h-8 text-sm text-gray-700 rounded-lg cursor-pointer hover:bg-gray-50' onClick={() => { onClosePopup() - handleNodesDuplicate() + handleNodesDuplicate(id) }} > {t('workflow.common.duplicate')}