/** * @author Martin Karkowski * @email m.karkowski@zema.de * @create date 2021-07-23 10:44:48 * @modify date 2021-07-23 10:44:48 * @desc [description] */ import * as go from "gojs"; import { ReactDiagram } from "gojs-react"; import * as React from "react"; import { generateGraph, ImplentedGraph } from "./graph-types/generateGraph"; interface DiagramProps { nodeDataArray: Array; linkDataArray: Array; initDiagram?: () => go.Diagram; diagramType?: ImplentedGraph; templates: Array<{ name: string; template: go.Part; }>; modelData?: go.ObjectData; skipsDiagramUpdate: boolean; onDiagramEvent?: (e: go.DiagramEvent) => void; eventsToSubscribe?: go.DiagramEventName[]; onModelChange?: (e: go.IncrementalData) => void; } export class DiagramWrapper extends React.Component { /** * Ref to keep a reference to the Diagram component, which provides access to the GoJS diagram via getDiagram(). */ private diagramRef: React.RefObject; /** @internal */ constructor(props: DiagramProps) { super(props); this.diagramRef = React.createRef(); } /** * Get the diagram reference and add any desired diagram listeners. * Typically the same function will be used for each listener, with the function using a switch statement to handle the events. */ public componentDidMount(): void { if (!this.diagramRef.current) return; const diagram = this.diagramRef.current.getDiagram(); // Adapt its size diagram.div.style.height = "100%"; diagram.div.style.width = "100%"; if (diagram instanceof go.Diagram) { // If the Diagram is ready, we try to add the Templates. const templates = Array.isArray(this.props.templates) ? this.props.templates : []; for (const template of templates) { diagram.nodeTemplateMap.add(template.name, template.template); } if (typeof this.props.onDiagramEvent === "function") { // Now we define the events we are listening on. // We will forward these events to the callback // "onDiagramEvent" const subscribedEvents: go.DiagramEventName[] = Array.isArray( this.props.eventsToSubscribe ) ? this.props.eventsToSubscribe : []; for (const eventName of subscribedEvents) { diagram.addDiagramListener(eventName, this.props.onDiagramEvent); } } } } /** * Get the diagram reference and remove listeners that were added during mounting. */ public componentWillUnmount(): void { if (!this.diagramRef.current) return; const diagram = this.diagramRef.current.getDiagram(); if (diagram instanceof go.Diagram) { diagram.removeDiagramListener( "ChangedSelection", this.props.onDiagramEvent ); } } /** * Diagram initialization method, which is passed to the ReactDiagram component. * This method is responsible for making the diagram and initializing the model, any templates, * and maybe doing other initialization tasks like customizing tools. * The model's data should not be set here, as the ReactDiagram component handles that. */ protected initDiagram(): go.Diagram { if (typeof this.props.initDiagram === "function") { return this.props.initDiagram(); } else if (typeof this.props.diagramType === "string") { return generateGraph(this.props.diagramType); } throw Error(""); } public render(): JSX.Element { const _this = this; return ( { const diagram = _this.initDiagram(); console.log("diagram", diagram); return diagram; }} nodeDataArray={_this.props.nodeDataArray} linkDataArray={_this.props.linkDataArray} modelData={_this.props.modelData} onModelChange={(e) => { if (typeof _this.props.onModelChange === "function") { _this.props.onModelChange(e); } }} skipsDiagramUpdate={_this.props.skipsDiagramUpdate} /> ); } }