import { FC, useState, useEffect } from "react"; import { values } from "lodash"; import { v4 as uuidv4 } from "uuid"; import eventBus from "../../events/eventBus"; import { Popover } from "./Popover"; import { IGraphData, CallbackFunction } from "../../types"; import { useJsPlumb } from "../useJsPlumb"; const CANVAS_ID: string = "canvas-container-" + uuidv4(); interface ICanvasProps { nodes: any; connections: any; canvasPosition: any; onNodeUpdate: CallbackFunction; onGraphUpdate: CallbackFunction; onCanvasUpdate: CallbackFunction; onConnectionAttached: CallbackFunction; onConnectionDetached: CallbackFunction; setNodeForEdit: CallbackFunction; setNodeForDelete: CallbackFunction; } export const Canvas: FC = (props) => { const { nodes, connections, canvasPosition, onNodeUpdate, onGraphUpdate, onCanvasUpdate, onConnectionAttached, onConnectionDetached, setNodeForEdit, setNodeForDelete } = props; const [nodeDragging, setNodeDragging] = useState(); const [nodeHovering, setNodeHovering] = useState(); const [dragging, setDragging] = useState(false); const [scale, setScale] = useState(1); const [_scale, _setScale] = useState(1); const [_left, _setLeft] = useState(0); const [_top, _setTop] = useState(0); const [_initX, _setInitX] = useState(0); const [_initY, _setInitY] = useState(0); const translateWidth = (document.documentElement.clientWidth * (1 - _scale)) / 2; const translateHeight = ((document.documentElement.clientHeight - 64) * (1 - _scale)) / 2; const [containerCallbackRef, setZoom, setStyle, removeEndpoint] = useJsPlumb( nodes, connections, (graphData: IGraphData) => onGraphUpdate(graphData), (positionData: any) => onNodeUpdate(positionData), (connectionData: any) => onConnectionAttached(connectionData), (connectionData: any) => onConnectionDetached(connectionData) ); const onCanvasMousewheel = (e: any) => { if (e.deltaY < 0) { _setScale(_scale + _scale * 0.25); setScale(_scale + _scale * 0.25); } if (e.deltaY > 0) { _setScale(_scale - _scale * 0.25); setScale(_scale - _scale * 0.25); } }; const onCanvasMouseUpLeave = (e: any) => { if (dragging) { const left = _left + e.pageX - _initX; const top = _top + e.pageY - _initY; _setLeft(left); _setTop(top); setDragging(false); onCanvasUpdate({ left: left, top: top }); } }; const onCanvasMouseMove = (e: any) => { if (!dragging) { return; } const styles = { left: _left + e.pageX - _initX + "px", top: _top + e.pageY - _initY + "px" }; setStyle(styles); }; const onCanvasMouseDown = (e: any) => { _setInitX(e.pageX); _setInitY(e.pageY); setDragging(true); }; useEffect(() => { setZoom(_scale); }, [_scale]); useEffect(() => { onCanvasUpdate({ scale: scale }); }, [scale]); useEffect(() => { const styles = { left: _left + "px", top: _top + "px" }; setStyle(styles); }, [_left, _top, setStyle]); useEffect(() => { _setTop(canvasPosition.top); _setLeft(canvasPosition.left); _setScale(canvasPosition.scale); }, [canvasPosition]); useEffect(() => { eventBus.on("EVENT_DRAG_START", (data: any) => { setNodeDragging(data.detail.message.id); }); eventBus.on("EVENT_DRAG_STOP", () => { setNodeDragging(null); }); eventBus.on("NODE_DELETED", (data: any) => { removeEndpoint(data.detail.message.node); }); return () => { eventBus.remove("NODE_DELETED", () => undefined); eventBus.remove("EVENT_DRAG_START", () => undefined); eventBus.remove("EVENT_DRAG_STOP", () => undefined); }; }, []); return ( <> {nodes && (
{ event.stopPropagation(); event.preventDefault(); }} >
{values(nodes).map((x) => (
setNodeHovering(x.key)} onMouseLeave={() => { if (nodeHovering === x.key) { setNodeHovering(null); } }} > {nodeHovering === x.key && nodeDragging !== x.key && ( { setNodeForEdit(x); }} onDeleteClick={() => { setNodeForDelete(x); }} > )}
{x.configuration.prettyName}
{x.configuration.prettyName}
))}
)} ); };