Here is the node templates:
One on the top (root node)
/** Folder Node */
export const nodeTemplate = $(
go.Node,
'Horizontal',
{
selectionAdorned: false,
layerName: 'Foreground',
height: 36,
},
new go.Binding('selectable', '', n => !n.isDisabled),
$(
go.Panel,
'Horizontal',
{
height: 32,
padding: new go.Margin(0, 24, 0, 0),
alignment: go.Spot.BottomLeft
},
new go.Binding('background', '', (n: NodeForTree) => {
if (n.isDisabled) { return Diagram.Color.GreyLight; }
return n.isSelected
? Diagram.Color.Blue
: n.category === GoType.SubRootNode
? Diagram.Color.GreyLight
: Diagram.Color.White;
}),
$(Element.VerticalLine),
$(Element.ArrowButton),
$(
go.Panel,
'Table',
{
maxSize: new go.Size(220, NaN),
alignment: go.Spot.Left,
},
new go.Binding('minSize', '', (n: NodeForTree) => new go.Size(n.isFeatured || n.isPendingApproval ? NaN : 40, NaN)),
$(
go.TextBlock,
{
row: 0,
column: 0,
font: '600 14px Open Sans, sans-serif',
wrap: go.TextBlock.None,
alignment: go.Spot.Left,
overflow: go.TextBlock.OverflowEllipsis
},
new go.Binding('maxSize', '', n => (n.isFeatured ? new go.Size(192, NaN) : null)),
new go.Binding('stroke', '', (n: NodeForTree) => n.isSelected ? Diagram.Color.White : Diagram.Color.Black),
new go.Binding('text', '', (n: NodeForTree) => n.shortName),
new go.Binding('opacity', 'status', status => status === NodeStatus.MarkedForRemoval ? 0.4 : 1),
),
),
$(Element.ClockIcon),
$(Element.FeaturedIcon),
),
$(Element.StatusCircle),
{
toolTip: nodeTooltip
},
{
click(e, obj): void {
// Do nothing
}
},
);
And for child nodes:
/** Non-Folder Node */
export const innerNodeTemplate = $(
go.Node,
'Horizontal',
{
selectionAdorned: false,
layerName: 'Foreground',
height: 54,
},
new go.Binding('selectable', '', n => !n.isDisabled),
$(
go.Panel,
'Horizontal',
{
height: 50,
padding: new go.Margin(0, 24, 0, 0),
alignment: go.Spot.BottomLeft
},
new go.Binding('background', '', (n: NodeForTree) => {
if (n.isDisabled) { return Diagram.Color.GreyLight; }
if (n.isSelected) {
switch (n.category) {
case NodeType.FRA:
return NodeTypesColor.FRA;
case NodeType.CustomBot:
return NodeTypesColor.CustomBot;
case NodeType.Router:
return NodeTypesColor.Router;
case NodeType.Skill:
return NodeTypesColor.Skill;
}
}
return Diagram.Color.White;
}),
$(Element.VerticalLine),
$(Element.ArrowButton),
$(
go.Panel,
'Table',
{
maxSize: new go.Size(220, NaN),
alignment: go.Spot.Left,
},
new go.Binding('minSize', '', (n: NodeForTree) => new go.Size(n.isFeatured || n.isPendingApproval ? NaN : 40, NaN)),
$(
go.TextBlock,
{
row: 0,
column: 0,
font: '400 14px Open Sans, sans-serif',
wrap: go.TextBlock.None,
alignment: go.Spot.Left,
overflow: go.TextBlock.OverflowEllipsis
},
new go.Binding('maxSize', '', n => (n.isFeatured ? new go.Size(192, NaN) : null)),
new go.Binding('stroke', '', (n: NodeForTree) => n.isSelected ? Diagram.Color.White : Diagram.Color.Black),
new go.Binding('text', '', (n: NodeForTree) => n.shortName),
new go.Binding('opacity', 'status', status => status === NodeStatus.MarkedForRemoval ? 0.4 : 1),
),
$(
go.TextBlock,
{
row: 1,
column: 0
},
{
font: '400 13px Open Sans, sans-serif',
alignment: go.Spot.Left,
margin: new go.Margin(3, 0, 0, 0),
},
new go.Binding('stroke', '', (n: NodeForTree) => n.isSelected ? Diagram.Color.White : Diagram.Color.Black),
new go.Binding('text', '', (n: NodeForTree) => n.normalizedName.normalized),
new go.Binding('opacity', '', n => n.isDisabled ? 0.3 : 0.5),
new go.Binding('opacity', 'status', status => status === NodeStatus.MarkedForRemoval ? 0.3 : 0.5),
)
),
$(Element.ClockIcon),
$(Element.FeaturedIcon),
),
$(Element.StatusCircle),
{
toolTip: nodeTooltip
},
{
click(e, obj): void {
// Do nothing
}
},
);
And here is the Arrow button (to expand/collapse)
go.GraphObject.defineBuilder(Element.ArrowButton, (): go.Panel => {
const size: number = 17;
const arrowButton = $(
'Button',
{
visible: false,
name: Diagram.Target.ARROW,
margin: new go.Margin(0, 8, 0, 0),
},
new go.Binding('visible', 'isTreeLeaf', isLeaf => !isLeaf).ofObject(),
$(
go.Shape,
'Ellipse',
{
desiredSize: new go.Size(size, size),
stroke: null,
isPanelMain: true
},
new go.Binding('fill', '', n => n.isCollapsed ? Diagram.Color.BlueLight : n.category === GoType.SubRootNode ? Diagram.Color.White : Diagram.Color.Grey)
),
$(
go.Shape,
{
geometry: new Arrow().geometry,
strokeWidth: 1,
stroke: Diagram.Color.White
},
new go.Binding('geometry', 'isCollapsed', c => c ? new Arrow().geometry.rotate(-90) : new Arrow().geometry),
new go.Binding('stroke', '', n => n.isCollapsed ? Diagram.Color.White : n.category === GoType.SubRootNode ? Diagram.Color.GreyDark : Diagram.Color.White),
),
{
click(e, btn): void {
let node = btn.part;
if (node instanceof go.Adornment) {
node = node.adornedPart;
}
if (!(node instanceof go.Node)) { return; }
const diagram = node.diagram;
if (diagram === null) { return; }
const cmd = diagram.commandHandler;
if (node.isTreeExpanded) {
if (!cmd.canCollapseTree(node)) { return; }
} else {
if (!cmd.canExpandTree(node)) { return; }
}
e.handled = true;
const expandedNodes = JSON.parse(sessionStorage.getItem(Common.SessionStorageKey.ExpandedNodes)) || [];
if (node.isTreeExpanded) {
cmd.collapseTree(node);
const index = expandedNodes.indexOf(node.data.id);
expandedNodes.splice(index, 1);
node.diagram.model.setDataProperty(node.data, 'isCollapsed', true);
} else {
cmd.expandTree(node);
node.diagram.model.setDataProperty(node.data, 'isCollapsed', false);
expandedNodes.push(node.data.id);
}
sessionStorage.setItem(Common.SessionStorageKey.ExpandedNodes, JSON.stringify(expandedNodes));
}
}
);
return arrowButton;
});