feat: Support shortcut keys to copy nodes #3283 (#3293)

### What problem does this PR solve?

feat: Support shortcut keys to copy nodes #3283

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
This commit is contained in:
balibabu
2024-11-08 15:50:01 +08:00
committed by GitHub
parent 8b6e272197
commit 63f7d3bae2
5 changed files with 79 additions and 43 deletions

View File

@ -4,7 +4,6 @@ import { IGraph } from '@/interfaces/database/flow';
import { useIsFetching } from '@tanstack/react-query';
import React, {
ChangeEvent,
KeyboardEventHandler,
useCallback,
useEffect,
useMemo,
@ -20,7 +19,6 @@ import {
import { useFetchModelId, useSendMessageWithSse } from '@/hooks/logic-hooks';
import { Variable } from '@/interfaces/database/chat';
import api from '@/utils/api';
import { useDebounceEffect } from 'ahooks';
import { FormInstance, message } from 'antd';
import { humanId } from 'human-id';
import { lowerFirst } from 'lodash';
@ -253,20 +251,6 @@ export const useShowDrawer = () => {
};
};
export const useHandleKeyUp = () => {
const deleteEdge = useGraphStore((state) => state.deleteEdge);
const handleKeyUp: KeyboardEventHandler = useCallback(
(e) => {
if (e.code === 'Delete') {
deleteEdge();
}
},
[deleteEdge],
);
return { handleKeyUp };
};
export const useSaveGraph = () => {
const { data } = useFetchFlow();
const { setFlow } = useSetFlow();
@ -284,20 +268,6 @@ export const useSaveGraph = () => {
return { saveGraph };
};
export const useWatchGraphChange = () => {
const nodes = useGraphStore((state) => state.nodes);
const edges = useGraphStore((state) => state.edges);
useDebounceEffect(
() => {
// console.info('useDebounceEffect');
},
[nodes, edges],
{
wait: 1000,
},
);
};
export const useHandleFormValuesChange = (id?: string) => {
const updateNodeForm = useGraphStore((state) => state.updateNodeForm);
const handleValuesChange = useCallback(
@ -348,8 +318,6 @@ export const useFetchDataOnMount = () => {
setGraphInfo(data?.dsl?.graph ?? ({} as IGraph));
}, [setGraphInfo, data]);
useWatchGraphChange();
useEffect(() => {
refetch();
}, [refetch]);
@ -640,3 +608,63 @@ export const useGetComponentLabelByValue = (nodeId: string) => {
);
return getLabel;
};
export const useDuplicateNode = () => {
const duplicateNodeById = useGraphStore((store) => store.duplicateNode);
const getNodeName = useGetNodeName();
const duplicateNode = useCallback(
(id: string, label: string) => {
duplicateNodeById(id, getNodeName(label));
},
[duplicateNodeById, getNodeName],
);
return duplicateNode;
};
export const useCopyPaste = () => {
const nodes = useGraphStore((state) => state.nodes);
const duplicateNode = useDuplicateNode();
const onCopyCapture = useCallback(
(event: ClipboardEvent) => {
event.preventDefault();
const nodesStr = JSON.stringify(
nodes.filter((n) => n.selected && n.data.label !== Operator.Begin),
);
event.clipboardData?.setData('agent:nodes', nodesStr);
},
[nodes],
);
const onPasteCapture = useCallback(
(event: ClipboardEvent) => {
event.preventDefault();
const nodes = JSON.parse(
event.clipboardData?.getData('agent:nodes') || '[]',
) as Node[] | undefined;
if (nodes) {
nodes.forEach((n) => {
duplicateNode(n.id, n.data.label);
});
}
},
[duplicateNode],
);
useEffect(() => {
window.addEventListener('copy', onCopyCapture);
return () => {
window.removeEventListener('copy', onCopyCapture);
};
}, [onCopyCapture]);
useEffect(() => {
window.addEventListener('paste', onPasteCapture);
return () => {
window.removeEventListener('paste', onPasteCapture);
};
}, [onPasteCapture]);
};