Copy and Paste function done
This commit is contained in:
parent
c630f293b0
commit
3c49feecaf
1 changed files with 77 additions and 6 deletions
|
|
@ -1,4 +1,4 @@
|
||||||
import { useCallback, useContext, useEffect, useRef } from "react";
|
import { useCallback, useContext, useEffect, useRef, useState } from "react";
|
||||||
import ReactFlow, {
|
import ReactFlow, {
|
||||||
Background,
|
Background,
|
||||||
Controls,
|
Controls,
|
||||||
|
|
@ -10,6 +10,8 @@ import ReactFlow, {
|
||||||
EdgeChange,
|
EdgeChange,
|
||||||
Connection,
|
Connection,
|
||||||
Edge,
|
Edge,
|
||||||
|
useKeyPress,
|
||||||
|
useOnSelectionChange,
|
||||||
} from "reactflow";
|
} from "reactflow";
|
||||||
import { locationContext } from "../../contexts/locationContext";
|
import { locationContext } from "../../contexts/locationContext";
|
||||||
import ExtraSidebar from "./components/extraSidebarComponent";
|
import ExtraSidebar from "./components/extraSidebarComponent";
|
||||||
|
|
@ -36,6 +38,76 @@ export default function FlowPage({ flow }:{flow:FlowType}) {
|
||||||
useContext(typesContext);
|
useContext(typesContext);
|
||||||
const reactFlowWrapper = useRef(null);
|
const reactFlowWrapper = useRef(null);
|
||||||
|
|
||||||
|
const copied = useKeyPress(['Meta+c', 'Strg+c'])
|
||||||
|
const pasted = useKeyPress(['Meta+v', 'Strg+v'])
|
||||||
|
const [lastSelection, setLastSelection] = useState(null);
|
||||||
|
const [lastCopiedSelection, setLastCopiedSelection] = useState(null);
|
||||||
|
|
||||||
|
useOnSelectionChange({
|
||||||
|
onChange: (flow) => {setLastSelection(flow);},
|
||||||
|
})
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if(copied === true && lastSelection){
|
||||||
|
setLastCopiedSelection(lastSelection);
|
||||||
|
}
|
||||||
|
}, [copied])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if(pasted === true && lastCopiedSelection){
|
||||||
|
let maximumHeight = 0;
|
||||||
|
let minimumHeight = Infinity;
|
||||||
|
let idsMap = {};
|
||||||
|
lastCopiedSelection.nodes.forEach((n) => {
|
||||||
|
if(n.height + n.position.y > maximumHeight){
|
||||||
|
maximumHeight = n.height + n.position.y;
|
||||||
|
}
|
||||||
|
if(n.position.y < minimumHeight){
|
||||||
|
minimumHeight = n.position.y;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
let heightDifference = maximumHeight - minimumHeight + 30;
|
||||||
|
|
||||||
|
lastCopiedSelection.nodes.forEach((n) => {
|
||||||
|
|
||||||
|
// Generate a unique node ID
|
||||||
|
let newId = getId();
|
||||||
|
idsMap[n.id] = newId;
|
||||||
|
|
||||||
|
// Create a new node object
|
||||||
|
const newNode: NodeType = {
|
||||||
|
id: newId,
|
||||||
|
type: "genericNode",
|
||||||
|
position: {
|
||||||
|
x: n.position.x,
|
||||||
|
y: n.position.y + heightDifference,
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
...n.data,
|
||||||
|
id: newId,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
// Add the new node to the list of nodes in state
|
||||||
|
setNodes((nds) => nds.map((e) => ({...e, selected: false})).concat({...newNode, selected: false}));
|
||||||
|
})
|
||||||
|
|
||||||
|
lastCopiedSelection.edges.forEach((e) => {
|
||||||
|
let source = idsMap[e.source];
|
||||||
|
let target = idsMap[e.target];
|
||||||
|
let sourceHandleSplitted = e.sourceHandle.split('|');
|
||||||
|
let sourceHandle = sourceHandleSplitted[0] + '|' + source + '|' + sourceHandleSplitted.slice(2).join('|');
|
||||||
|
let targetHandleSplitted = e.targetHandle.split('|');
|
||||||
|
let targetHandle = targetHandleSplitted.slice(0, -1).join('|') + '|' + target;
|
||||||
|
let id = "reactflow__edge-" + source + sourceHandle + "-" + target + targetHandle;
|
||||||
|
setEdges((eds) =>
|
||||||
|
addEdge({ source, target, sourceHandle, targetHandle, id, className: "animate-pulse", selected: false }, eds.map((e) => ({...e, selected: false})))
|
||||||
|
);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}, [pasted])
|
||||||
|
|
||||||
|
|
||||||
const { setExtraComponent, setExtraNavigation } = useContext(locationContext);
|
const { setExtraComponent, setExtraNavigation } = useContext(locationContext);
|
||||||
const { setErrorData } = useContext(alertContext);
|
const { setErrorData } = useContext(alertContext);
|
||||||
const [nodes, setNodes, onNodesChange] = useNodesState(
|
const [nodes, setNodes, onNodesChange] = useNodesState(
|
||||||
|
|
@ -47,6 +119,10 @@ export default function FlowPage({ flow }:{flow:FlowType}) {
|
||||||
const { setViewport } = useReactFlow();
|
const { setViewport } = useReactFlow();
|
||||||
const edgeUpdateSuccessful = useRef(true);
|
const edgeUpdateSuccessful = useRef(true);
|
||||||
|
|
||||||
|
function getId() {
|
||||||
|
return `dndnode_` + incrementNodeId();
|
||||||
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (reactFlowInstance && flow) {
|
if (reactFlowInstance && flow) {
|
||||||
flow.data = reactFlowInstance.toObject();
|
flow.data = reactFlowInstance.toObject();
|
||||||
|
|
@ -101,11 +177,6 @@ export default function FlowPage({ flow }:{flow:FlowType}) {
|
||||||
(event: React.DragEvent) => {
|
(event: React.DragEvent) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
||||||
// Helper function to generate a unique node ID
|
|
||||||
function getId() {
|
|
||||||
return `dndnode_` + incrementNodeId();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the current bounds of the ReactFlow wrapper element
|
// Get the current bounds of the ReactFlow wrapper element
|
||||||
const reactflowBounds = reactFlowWrapper.current.getBoundingClientRect();
|
const reactflowBounds = reactFlowWrapper.current.getBoundingClientRect();
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue