import { FC, useState, useEffect } from "react"; import { Dictionary, values } from "lodash"; import { v4 as uuidv4 } from "uuid"; import eventBus from "../../events/eventBus"; import { IGraphData, CallbackFunction, IServiceNodeItem, IVolumeNodeItem } from "../../types"; import { useJsPlumb } from "../useJsPlumb"; import ServiceNode from "./ServiceNode"; import VolumeNode from "./VolumeNode"; const CANVAS_ID: string = "canvas-container-" + uuidv4(); interface ICanvasProps { nodes: Dictionary; connections: any; canvasPosition: any; onNodeUpdate: CallbackFunction; onGraphUpdate: CallbackFunction; onCanvasUpdate: CallbackFunction; onConnectionAttached: CallbackFunction; onConnectionDetached: CallbackFunction; setServiceToEdit: CallbackFunction; setServiceToDelete: CallbackFunction; setVolumeToEdit: CallbackFunction | null; setVolumeToDelete: CallbackFunction | null; } export const Canvas: FC = (props) => { const { nodes, connections, canvasPosition, onNodeUpdate, onGraphUpdate, onCanvasUpdate, onConnectionAttached, onConnectionDetached, setServiceToEdit, setServiceToDelete, setVolumeToEdit, setVolumeToDelete } = props; 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 onCanvasMouseMove = (e: any) => { if (!dragging) { return; } if (e.pageX && e.pageY) { const styles = { left: _left + e.pageX - _initX + "px", top: _top + e.pageY - _initY + "px" }; setStyle(styles); } }; const onCanvasMouseUpLeave = (e: any) => { if (dragging) { if (e.pageX && e.pageY) { const left = _left + e.pageX - _initX; const top = _top + e.pageY - _initY; _setLeft(left); _setTop(top); setDragging(false); onCanvasUpdate({ left: left, top: top }); } } }; const onCanvasMouseDown = (e: any) => { if (e.pageX && e.pageY) { _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("NODE_DELETED", (data: any) => { removeEndpoint(data.detail.message.node); }); return () => { eventBus.remove("NODE_DELETED", () => undefined); }; }, []); return ( <> {nodes && (
{ event.stopPropagation(); event.preventDefault(); }} >
{values(nodes).map((x) => { if (x.type === "SERVICE") { x = x as IServiceNodeItem; return ( ); } if (x.type === "VOLUME" && setVolumeToEdit && setVolumeToDelete) { x = x as IVolumeNodeItem; return ( ); } })}
)} ); };