nope/pages/test/test-gojs.tsx
Martin Karkowski 8516245f01 Adding Editor
2021-07-27 12:55:15 +02:00

317 lines
9.8 KiB
TypeScript

/**
* @author Martin Karkowski
* @email m.karkowski@zema.de
* @create date 2021-06-24 09:22:49
* @modify date 2021-06-24 09:22:49
* @desc [description]
*/
import * as go from "gojs";
import { ReactDiagram, ReactPalette } from "gojs-react";
import * as React from "react";
import { PETRINET as FLOWCHART } from "../../resources/ui/gojs/graph-types/petri-net";
import { addNodeNextTo } from "../../resources/ui/gojs/helpers/add-node-next-to";
import { transitionTemplate } from "../../resources/ui/gojs/nodes/transition";
// props passed in from a parent component holding state, some of which will be passed to ReactDiagram
interface WrapperProps {
nodeDataArray: Array<go.ObjectData>;
linkDataArray: Array<go.ObjectData>;
modelData: go.ObjectData;
skipsDiagramUpdate: boolean;
onDiagramEvent: (e: go.DiagramEvent) => void;
onModelChange: (e: go.IncrementalData) => void;
}
export class DiagramWrapper extends React.Component<WrapperProps, {}> {
/**
* Ref to keep a reference to the component, which provides access to the GoJS diagram via getDiagram().
*/
private diagramRef: React.RefObject<ReactDiagram>;
private paletteRef: React.RefObject<ReactPalette>;
constructor(props: WrapperProps) {
super(props);
this.diagramRef = React.createRef();
this.paletteRef = 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.
* This is only necessary when you want to define additional app-specific diagram listeners.
*/
public componentDidMount(): void {
if (!this.diagramRef.current) return;
const diagram = this.diagramRef.current.getDiagram();
if (diagram instanceof go.Diagram) {
// diagram.link
const make = go.GraphObject.make;
diagram.div.style.height = "800px";
diagram.div.style.width = "1000px";
diagram.nodeTemplateMap.add(
"transition",
transitionTemplate([
make(
"Button",
{
alignment: go.Spot.TopCenter,
alignmentFocus: go.Spot.Right,
click: (e, b) => {
// take a button panel in an Adornment, get its Adornment, and then get its adorned Node
const node: go.Node = b.part.adornedPart;
addNodeNextTo(
node,
{ category: "place" },
{ category: "logicFlow", toPort: "LogicFlowIn" },
"to",
"n"
);
},
},
make(go.Shape, "PlusLine", { width: 6, height: 6 })
),
make(
"Button",
{
alignment: go.Spot.BottomCenter,
click: (e, b) => {
// take a button panel in an Adornment, get its Adornment, and then get its adorned Node
const node: go.Node = b.part.adornedPart;
addNodeNextTo(
node,
{ category: "place" },
{ category: "logicFlow", fromPort: "LogicFlowOut" },
"from",
"s"
);
},
toolTip: make("ToolTip", ""),
},
make(go.Shape, "PlusLine", { width: 6, height: 6 })
),
])
);
// diagram.linkT;
diagram.nodeTemplateMap.add(
"place",
make(
go.Node,
"Spot",
{
desiredSize: new go.Size(75, 75),
},
make(go.Shape, "Circle", {
fill: "#52ce60" /* green */,
stroke: null,
portId: "test",
fromLinkable: true,
fromLinkableSelfNode: false,
fromLinkableDuplicates: false,
toLinkable: true,
toLinkableSelfNode: false,
toLinkableDuplicates: false,
cursor: "pointer",
}),
make(go.TextBlock, "Start", {
font: "bold 16pt helvetica, bold arial, sans-serif",
stroke: "whitesmoke",
})
)
);
diagram.linkTemplateMap.add(
"logicFlow",
make(
go.Link, // the whole link panel
{
routing: go.Link.Normal,
corner: 15,
curve: go.Link.Bezier,
// adjusting: go.Link.Scale,
reshapable: true,
resegmentable: true,
curviness: 20,
// relinkableFrom: true,
// relinkableTo: true,
// toShortLength: 1,
category: "logicFlow",
},
// new go.Binding("points").makeTwoWay(),
// new go.Binding("curviness"),
make(
go.Shape, // the link shape
{ strokeWidth: 1.5 },
new go.Binding("stroke", "progress", function (progress) {
return progress ? "#52ce60" /* green */ : "black";
}),
new go.Binding("strokeWidth", "progress", function (progress) {
return progress ? 2.5 : 1.5;
})
),
make(
go.Shape, // the arrowhead
{ toArrow: "standard", stroke: null },
new go.Binding("fill", "progress", function (progress) {
return progress ? "#52ce60" /* green */ : "black";
})
),
make(
go.Panel,
"Auto",
make(
go.Shape, // the label background, which becomes transparent around the edges,
"Rectangle",
{
fill: "white",
stroke: null,
}
),
make(
go.TextBlock,
"transition", // the label text
{
textAlign: "center",
font: "9pt helvetica, arial, sans-serif",
margin: 4,
editable: true, // enable in-place editing
},
// editing the text automatically updates the model data
new go.Binding("text").makeTwoWay()
)
)
)
);
diagram.addDiagramListener("LinkDrawn", (e) => {
console.log(e.subject);
});
}
if (!this.paletteRef.current) return;
const palette = this.paletteRef.current.getPalette();
palette.div.style.height = "800px";
palette.div.style.width = "1000px";
}
/**
* Get the diagram reference and remove listeners that were added during mounting.
* This is only necessary when you have defined additional app-specific diagram listeners.
*/
public componentWillUnmount() {
if (!this.diagramRef.current) return;
const diagram = this.diagramRef.current.getDiagram();
if (diagram instanceof go.Diagram) {
diagram.removeDiagramListener(
"ChangedSelection",
this.props.onDiagramEvent
);
}
}
onModelChange(...args) {
console.log(...args);
}
/**
* 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 via the other props.
*/
private initDiagram(): go.Diagram {
const diagram = FLOWCHART();
// diagram.grid.visible = true;
diagram.toolManager.draggingTool.isGridSnapEnabled = true;
diagram.toolManager.resizingTool.isGridSnapEnabled = true;
return diagram;
}
public render(): JSX.Element {
return (
<div style={{ background: "white" }}>
<div draggable="true">Water</div>
<ReactDiagram
ref={this.diagramRef}
divClassName="none"
initDiagram={this.initDiagram}
nodeDataArray={this.props.nodeDataArray}
linkDataArray={this.props.linkDataArray}
modelData={this.props.modelData}
skipsDiagramUpdate={this.props.skipsDiagramUpdate}
/>
<ReactPalette
ref={this.paletteRef}
initPalette={(...args) => {
const myPalette = new go.Palette();
// the list of data to show in the Palette
myPalette.nodeTemplateMap.add("transition", transitionTemplate());
// myPalette.nodeTemplateMap.add("test", );
return myPalette;
}}
divClassName="none"
nodeDataArray={[
{
label: "Transtion",
guard: "x+1",
category: "transition",
icon: "https://cdn-images-1.medium.com/max/1600/0*F9ptwf7KyiVfrX0x.jpg",
description: "General Legal Division Director",
serviceName: "testservice",
serviceInputs: [
{
portId: 21,
label: "i1",
},
{
portId: 22,
label: "i2",
},
{
portId: 23,
label: "i3",
},
],
serviceOutputs: [
{
portId: 10,
label: "outp",
},
],
guardInputs: [
{
portId: 31,
label: "g1",
},
{
portId: 32,
label: "g2",
},
{
portId: 33,
label: "g3",
},
],
guardOutputs: [
{
portId: 11,
label: "g1",
},
],
},
{},
]}
></ReactPalette>
</div>
);
}
}
export default DiagramWrapper;