Here you go, using your model data, plus a couple ImportNodes that I dropped into the Diagram and connected with Links:
This assumes that those blue ImportNodes are manually positioned.
<!DOCTYPE html>
<html>
<head>
<title>Minimal GoJS Editor</title>
<!-- Copyright 1998-2024 by Northwoods Software Corporation. -->
</head>
<body>
<div style="width: 100%; display: flex; justify-content: space-between">
<div style="display: flex; flex-direction: column; margin: 0 2px 0 0">
<div id="myPaletteDiv" style="flex-grow: 1; width: 200px; background-color: floralwhite; border: solid 1px black"></div>
</div>
<div id="myDiagramDiv" style="flex-grow: 1; height: 400px; border: solid 1px black"></div>
</div>
<div>
<button id="myLoadButton">Load</button>
<button id="mySaveButton">Save</button>
</div>
<textarea id="mySavedModel" style="width:100%;height:200px">
{ "class": "go.GraphLinksModel",
"nodeDataArray": [
{
"category": "DropDocletType",
"key": "prepend",
"id": "prepend",
"text": "Prepend Doclet Type"
},
{
"category": "DocletTypeNode",
"state": "Diagram",
"key": "1f409525-7df2-4bb6-b406-3e6be8e9b347-0",
"id": "1f409525-7df2-4bb6-b406-3e6be8e9b347",
"tags": "",
"templateIndex": "-",
"title": "Description of Work"
},
{
"category": "DocletTypeNode",
"state": "Diagram",
"key": "1f409525-7df2-4bb6-b406-3e6be8e9b347-1",
"id": "1f409525-7df2-4bb6-b406-3e6be8e9b347",
"tags": "",
"templateIndex": "-",
"title": "Description of Work"
},
{
"category": "DocletTypeNode",
"state": "Diagram",
"key": "2bb59c76-b54d-4b49-abbd-a0c6595d77bd-2",
"id": "2bb59c76-b54d-4b49-abbd-a0c6595d77bd",
"tags": "",
"templateIndex": "-",
"title": "Engagement Contacts"
},
{
"category": "DocletTypeNode",
"state": "Diagram",
"key": "fc386d42-4874-4e3e-bb36-2e38430a17f8-3",
"id": "fc386d42-4874-4e3e-bb36-2e38430a17f8",
"tags": "",
"templateIndex": "-",
"title": "Communications Plan"
},
{
"category": "DropDocletType",
"key": "append",
"id": "append",
"text": "Append Doclet Type"
}
],
"linkDataArray": [
{
"from": "prepend",
"to": "1f409525-7df2-4bb6-b406-3e6be8e9b347-0"
},
{
"from": "1f409525-7df2-4bb6-b406-3e6be8e9b347-0",
"to": "1f409525-7df2-4bb6-b406-3e6be8e9b347-1"
},
{
"from": "1f409525-7df2-4bb6-b406-3e6be8e9b347-1",
"to": "2bb59c76-b54d-4b49-abbd-a0c6595d77bd-2"
},
{
"from": "2bb59c76-b54d-4b49-abbd-a0c6595d77bd-2",
"to": "fc386d42-4874-4e3e-bb36-2e38430a17f8-3"
},
{
"from": "fc386d42-4874-4e3e-bb36-2e38430a17f8-3",
"to": "append"
}
]}
</textarea>
<script src="go.js"></script>
<script id="code">
const $ = go.GraphObject.make;
// initialize main Diagram
const myDiagram =
new go.Diagram("myDiagramDiv",
{
layout: $(go.TreeLayout, { angle: 90, layerSpacing: 20 }),
"undoManager.isEnabled": true
});
function nodeStyle() {
return [
{ locationSpot: go.Spot.Center },
new go.Binding("location", "location", go.Point.parse).makeTwoWay(go.Point.stringify)
];
}
myDiagram.nodeTemplate =
$(go.Node, "Auto", nodeStyle(),
$(go.Shape, "RoundedRectangle",
{ fill: "white", stroke: "royalblue", portId: "", toLinkable: true }),
$(go.Panel, "Table",
{ margin: 5 },
$(go.TextBlock,
{ font: "bold 10pt sans-serif", margin: new go.Margin(2, 2, 0, 2),
minSize: new go.Size(16, 16), maxSize: new go.Size(160, NaN) },
new go.Binding("text", "title")),
$("Button",
{
column: 1,
"ButtonBorder.figure": "Circle"
},
$(go.Shape, "XLine", { width: 8, height: 8 }))
)
);
myDiagram.nodeTemplateMap.add("DropDocletType",
$(go.Node, "Auto", nodeStyle(),
$(go.Shape, "Ellipse",
{ fill: "gold", strokeWidth: 0, portId: "", toLinkable: true }),
$(go.TextBlock,
{ margin: new go.Margin(5, 5, 3, 5), font: "10pt sans-serif",
minSize: new go.Size(16, 16), maxSize: new go.Size(120, NaN) },
new go.Binding("text"))
));
myDiagram.nodeTemplateMap.add("ImportNode",
$(go.Node, "Auto", nodeStyle(),
{ isLayoutPositioned: false },
$(go.Shape, "RoundedRectangle",
{ fill: "royalblue", strokeWidth: 0, portId: "", fromLinkable: true, cursor: "pointer" }),
$(go.TextBlock,
{ margin: new go.Margin(5, 5, 3, 5), font: "bold 10pt sans-serif", stroke: "white" },
new go.Binding("text"))
));
myDiagram.linkTemplate =
$(go.Link,
{ routing: go.Link.Orthogonal, corner: 10 },
$(go.Shape, { strokeWidth: 2 }),
$(go.Shape, { toArrow: "OpenTriangle", strokeWidth: 2 })
);
// initialize Palette
const palMap = myDiagram.nodeTemplateMap.copy();
const importnode = palMap.get("ImportNode").copyTemplate();
importnode.isLayoutPositioned = true;
palMap.add("ImportNode", importnode);
myPalette =
new go.Palette("myPaletteDiv",
{
layout: $(go.GridLayout, { wrappingColumn: 1, alignment: go.GridLayout.Location }),
initialAutoScale: go.Diagram.UniformToFill,
nodeTemplateMap: palMap,
groupTemplate:
$(go.Group,
{
locationSpot: go.Spot.Center,
layout: $(go.GridLayout, { wrappingColumn: 1 })
},
$(go.Placeholder)
),
model: new go.GraphLinksModel([
{
"key": 1,
"text": "Import Nodes",
isGroup: true,
"category": "Imports",
},
{
"key": 2,
isGroup: true,
"category": "PaletteDocletGroup",
},
{
"category": "ImportNode",
group: 1,
isAssistant: true,
"key": -1,
"state": "Palette",
"text": "PCD",
},
{
"category": "ImportNode",
isAssistant: true,
group: 1,
"key": -2,
"state": "Palette",
"text": "neo4j Query",
},
{
"category": "ImportNode",
isAssistant: true,
group: 1,
"key": -3,
"state": "Palette",
"text": "Python Script",
},
{
"category": "ImportNode",
isAssistant: true,
group: 1,
"key": -4,
"state": "Palette",
"text": "R Script",
},
{
"category": "DocletTypeNode",
group: 2,
"id": "a34cc470-584f-491d-852c-e337b03ba9a9",
"key": "b3dbd719-33f5-45bd-bba1-ad5cd152369f",
"state": "Palette",
"tags": "",
"templateIndex": 0,
"title": "Approach",
},
{
"category": "DocletTypeNode",
group: 2,
"id": "94358ae0-c808-46f1-bee1-ceb18d65e387",
"key": "9a444497-0183-4998-b790-011f65a8d8ae",
"state": "Palette",
"tags": "",
"templateIndex": 1,
"title": "Assumptions",
},
{
"category": "DocletTypeNode",
group: 2,
"id": "eea7c2f2-a5c8-4e27-981e-b99add938e4f",
"key": "407e8e11-dd29-474d-9bd3-81f61fc83334",
"state": "Palette",
"tags": "",
"templateIndex": 2,
"title": "Change Order Process",
},
{
"category": "DocletTypeNode",
group: 2,
"id": "6feb527c-d956-46f5-8cc1-42261be3a0ff",
"key": "91223f02-c8be-4cd4-a344-4e4bdee74f0c",
"state": "Palette",
"tags": "",
"templateIndex": 3,
"title": "Charges, Expenses and Invoicing",
},
{
"category": "DocletTypeNode",
group: 2,
"id": "fc386d42-4874-4e3e-bb36-2e38430a17f8",
"key": "adbee4fd-e067-42c1-887a-f60d0460a8d4",
"state": "Palette",
"tags": "",
"templateIndex": 4,
"title": "Communications Plan",
},
{
"category": "DocletTypeNode",
group: 2,
"id": "c145e9fd-66c7-47d2-9cd9-b1aa5f0e9906",
"key": "a495b561-c7a6-42ea-b4fc-92999bf3ba39",
"state": "Palette",
"tags": "",
"templateIndex": 5,
"title": "Deliverables",
},
{
"category": "DocletTypeNode",
group: 2,
"id": "1f409525-7df2-4bb6-b406-3e6be8e9b347",
"key": "34a15cc6-7e1a-40c1-9c41-791a6f9a71da",
"state": "Palette",
"tags": "",
"templateIndex": 6,
"title": "Description of Work",
},
{
"category": "DocletTypeNode",
group: 2,
"id": "2bb59c76-b54d-4b49-abbd-a0c6595d77bd",
"key": "9aa40170-bf05-4b5a-95e3-3d88b43f827e",
"state": "Palette",
"tags": "",
"templateIndex": 7,
"title": "Engagement Contacts",
},
{
"category": "DocletTypeNode",
group: 2,
"id": "bc98aa1c-8a5a-444c-b41a-191cf5cfa261",
"key": "1a9fe4a6-2ec3-4e82-9137-dc1ff4cad7d1",
"state": "Palette",
"tags": "",
"templateIndex": 8,
"title": "Escalation Process",
},
{
"category": "DocletTypeNode",
group: 2,
"id": "46f32999-4fd4-46fd-a49b-d2ffb1e90533",
"key": "c8523b52-07c2-4750-bf2e-821de65c8553",
"state": "Palette",
"tags": "",
"templateIndex": 9,
"title": "Initiation of Work",
},
{
"category": "DocletTypeNode",
group: 2,
"id": "e34723c4-efd1-48e5-b134-c16475362833",
"key": "ede62a24-3d17-49bd-aaf7-ab126e89a3cb",
"state": "Palette",
"tags": "",
"templateIndex": 10,
"title": "Introduction",
},
{
"category": "DocletTypeNode",
group: 2,
"id": "6c12812b-5cf4-4e6f-bce2-16afccfb91c0",
"key": "58be694e-7cf7-495f-88ee-412586e04ddd",
"state": "Palette",
"tags": "",
"templateIndex": 11,
"title": "IT&S Responsibilities",
},
{
"category": "DocletTypeNode",
group: 2,
"id": "c4330a2c-d559-4800-8d41-b178e29ee1f3",
"key": "1612b684-9cf8-4bb5-b308-3261edb82bb0",
"state": "Palette",
"tags": "",
"templateIndex": 12,
"title": "Kickoff Meeting",
},
{
"category": "DocletTypeNode",
group: 2,
"id": "91177f3a-3c6d-40ea-bb76-7121fd6580f5",
"key": "2603513c-02e2-40a7-a150-ef36b320cb8f",
"state": "Palette",
"tags": "",
"templateIndex": 13,
"title": "Project Dependencies",
},
{
"category": "DocletTypeNode",
group: 2,
"id": "c42d5d77-4adc-40b4-a651-eb44d27958b4",
"key": "5f7704ea-da1d-4989-969d-1e6581a460f0",
"state": "Palette",
"tags": "",
"templateIndex": 14,
"title": "Timeline",
},
{
"category": "DocletTypeNode",
group: 2,
"id": "b8e39e14-24bc-4b87-af6a-845d56ebf405",
"key": "a31e75d3-6a15-458c-aa27-443bf85b3119",
"state": "Palette",
"tags": "",
"templateIndex": 15,
"title": "TOC",
},
])
});
// save a model to and load a model from Json text, displayed below the Diagram
function save() {
const str = myDiagram.model.toJson();
document.getElementById("mySavedModel").value = str;
}
document.getElementById("mySaveButton").addEventListener("click", save);
function load() {
const str = document.getElementById("mySavedModel").value;
myDiagram.model = go.Model.fromJson(str);
}
document.getElementById("myLoadButton").addEventListener("click", load);
load();
</script>
</body>
</html>