feat: add workflow editor shortcuts (#3382) (#3390)

This commit is contained in:
Pascal M 2024-04-12 14:40:19 +02:00 committed by GitHub
parent d7fd56051a
commit 17efc3ab79
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 122 additions and 1 deletions

View File

@ -715,6 +715,108 @@ export const useNodesInteractions = () => {
handleSyncWorkflowDraft() handleSyncWorkflowDraft()
}, [store, handleSyncWorkflowDraft, getNodesReadOnly, t]) }, [store, handleSyncWorkflowDraft, getNodesReadOnly, t])
const handleNodeCopySelected = useCallback((): undefined | Node[] => {
if (getNodesReadOnly())
return
const {
setClipboardElements,
} = workflowStore.getState()
const {
getNodes,
} = store.getState()
const nodes = getNodes()
const nodesToCopy = nodes.filter(node => node.data.selected)
setClipboardElements(nodesToCopy)
return nodesToCopy
}, [getNodesReadOnly, store, workflowStore])
const handleNodePaste = useCallback((): undefined | Node[] => {
if (getNodesReadOnly())
return
const {
clipboardElements,
} = workflowStore.getState()
const {
getNodes,
setNodes,
} = store.getState()
const nodesToPaste: Node[] = []
const nodes = getNodes()
for (const nodeToPaste of clipboardElements) {
const nodeType = nodeToPaste.data.type
const nodesWithSameType = nodes.filter(node => node.data.type === nodeType)
const newNode = generateNewNode({
data: {
...NODES_INITIAL_DATA[nodeType],
...nodeToPaste.data,
_connectedSourceHandleIds: [],
_connectedTargetHandleIds: [],
title: nodesWithSameType.length > 0 ? `${t(`workflow.blocks.${nodeType}`)} ${nodesWithSameType.length + 1}` : t(`workflow.blocks.${nodeType}`),
selected: true,
},
position: {
x: nodeToPaste.position.x + 10,
y: nodeToPaste.position.y + 10,
},
})
nodesToPaste.push(newNode)
}
setNodes([...nodes.map((n: Node) => ({ ...n, selected: false, data: { ...n.data, selected: false } })), ...nodesToPaste])
handleSyncWorkflowDraft()
return nodesToPaste
}, [getNodesReadOnly, handleSyncWorkflowDraft, store, t, workflowStore])
const handleNodeDuplicateSelected = useCallback(() => {
if (getNodesReadOnly())
return
handleNodeCopySelected()
handleNodePaste()
}, [getNodesReadOnly, handleNodeCopySelected, handleNodePaste])
const handleNodeCut = useCallback(() => {
if (getNodesReadOnly())
return
const nodesToCut = handleNodeCopySelected()
if (!nodesToCut)
return
for (const node of nodesToCut)
handleNodeDelete(node.id)
}, [getNodesReadOnly, handleNodeCopySelected, handleNodeDelete])
const handleNodeDeleteSelected = useCallback(() => {
if (getNodesReadOnly())
return
const {
getNodes,
} = store.getState()
const nodes = getNodes()
const nodesToDelete = nodes.filter(node => node.data.selected)
if (!nodesToDelete)
return
for (const node of nodesToDelete)
handleNodeDelete(node.id)
}, [getNodesReadOnly, handleNodeDelete, store])
return { return {
handleNodeDragStart, handleNodeDragStart,
handleNodeDrag, handleNodeDrag,
@ -729,5 +831,10 @@ export const useNodesInteractions = () => {
handleNodeDelete, handleNodeDelete,
handleNodeChange, handleNodeChange,
handleNodeAdd, handleNodeAdd,
handleNodeDuplicateSelected,
handleNodeCopySelected,
handleNodeCut,
handleNodeDeleteSelected,
handleNodePaste,
} }
} }

View File

@ -113,6 +113,11 @@ const Workflow: FC<WorkflowProps> = memo(({
handleNodeConnect, handleNodeConnect,
handleNodeConnectStart, handleNodeConnectStart,
handleNodeConnectEnd, handleNodeConnectEnd,
handleNodeDuplicateSelected,
handleNodeCopySelected,
handleNodeCut,
handleNodeDeleteSelected,
handleNodePaste,
} = useNodesInteractions() } = useNodesInteractions()
const { const {
handleEdgeEnter, handleEdgeEnter,
@ -128,7 +133,12 @@ const Workflow: FC<WorkflowProps> = memo(({
}, },
}) })
useKeyPress('Backspace', handleEdgeDelete) useKeyPress(['delete'], handleEdgeDelete)
useKeyPress(['delete'], handleNodeDeleteSelected)
useKeyPress(['ctrl.c', 'meta.c'], handleNodeCopySelected)
useKeyPress(['ctrl.x', 'meta.x'], handleNodeCut)
useKeyPress(['ctrl.v', 'meta.v'], handleNodePaste)
useKeyPress(['ctrl.alt.d', 'meta.shift.d'], handleNodeDuplicateSelected)
return ( return (
<div <div

View File

@ -63,6 +63,8 @@ type Shape = {
setBuildInTools: (tools: ToolWithProvider[]) => void setBuildInTools: (tools: ToolWithProvider[]) => void
customTools: ToolWithProvider[] customTools: ToolWithProvider[]
setCustomTools: (tools: ToolWithProvider[]) => void setCustomTools: (tools: ToolWithProvider[]) => void
clipboardElements: Node[]
setClipboardElements: (clipboardElements: Node[]) => void
} }
export const createWorkflowStore = () => { export const createWorkflowStore = () => {
@ -107,6 +109,8 @@ export const createWorkflowStore = () => {
setBuildInTools: buildInTools => set(() => ({ buildInTools })), setBuildInTools: buildInTools => set(() => ({ buildInTools })),
customTools: [], customTools: [],
setCustomTools: customTools => set(() => ({ customTools })), setCustomTools: customTools => set(() => ({ customTools })),
clipboardElements: [],
setClipboardElements: clipboardElements => set(() => ({ clipboardElements })),
})) }))
} }