Org Assistant chart with multiple Manager

Hi,
I need an org chart with the assistant feature that has multiple managers.
Here is my org chart sample image.

Would anyone please help me to solve this?

Would those managers have their own additional direct reports?

I hope No. Manager 1 and Manager 2 is the highest position.

The easiest thing to try is to group such multiple managers into a Group that uses a GridLayout to arrange those managers relative to each other.

Thanks for your reply. I have used a group template. But it does not show the group .
I am using the org chart asistant code.
this is my group template
myDiagram.groupTemplate =
$(go.Group, “Auto”,
{
background: “transparent”,
layout: $(go.GridLayout,
{
wrappingWidth: Infinity, alignment: go.GridLayout.Position,
cellSize: new go.Size(1, 1), spacing: new go.Size(1, 1)
}),
},
$(go.Shape, “Rectangle”,
{
fill: null,
stroke: “#F8F9E8”,
strokeWidth: 0,
cursor: ‘pointer’,
}),
$(go.Panel, “Vertical”, // title above Placeholder
$(go.Panel, “Vertical”, // button next to TextBlock
{
stretch: go.GraphObject.Horizontal,
background: “#F8F9E8
},
), // end Horizontal Panel
$(go.Placeholder,
{
padding: 0.5,
alignment: go.Spot.Center
})
) // end Vertical Panel
);

This is Data

“nodeDataArray”: [
{“key”:1, “name”:“group name”,“isGroup”:true},
{“key”:2, “name”:“test name”, “title”:“Manager 1”,“pic”:“1.jpg”,“group”:1},
{“key”:3 ,“name”:“test name 2”, “title”:“Manager 2”,“pic”:“1.jpg”,“group”:1},
{“key”:4, “name”:“Test name 3”, “title”:“Manager”, “pic”:“1.jpg”,“parent”:1},
{“key”:5, “name”:“Mayen Uddin”, “title”:“VP Marketing/Sales”, “pic”:“2.jpg”, “parent”:4}
]

Would you please check what am I doing wrong?

Ah, you are using TreeModel, and TreeModel naturally does not support Groups.

But how were you going to represent multiple parents for a node? You could use a GraphLinksModel. Or I suppose you could use a different property to refer to multiple managers and construct the links yourself as a separate step. But it’s easiest to use a GraphLinksModel.

I am using the Graph Links model. I modified the code of the assistant code for my own define left-side and right-side assistant. When applying the graph link model the left assistant links are not showing properly. if there are right and left assistant data or only right assistant data it’s showing fine.

I am sharing my Layout code and load method.

class SideTreeLayout extends go.TreeLayout {
makeNetwork(coll) {
const net = super.makeNetwork(coll);
// copy the collection of TreeVertexes, because we will modify the network
const vertexcoll = new go.Set(/go.TreeVertex/);
vertexcoll.addAll(net.vertexes);
for (const it = vertexcoll.iterator; it.next();) {
const parent = it.value;
// count the number of assistants
let acount = 0;
const ait = parent.destinationVertexes;
while (ait.next()) {
if (isAssistant(ait.value.node)) acount++;
}
// if a vertex has some number of children that should be assistants
if (acount > 0) {
// remember the assistant edges and the regular child edges
const asstedges = new go.Set(/go.TreeEdge/);
const childedges = new go.Set(/go.TreeEdge/);
const leftasstedges = new go.List(/go.TreeEdge/);
const rightasstedges = new go.List(/go.TreeEdge/);
let eit = parent.destinationEdges;
while (eit.next()) {
const e = eit.value;
if (isAssistant(e.toVertex.node)) {
if(e.toVertex.node.data.side==‘left’){
leftasstedges.add(e);
}else{
rightasstedges.add(e);
}
asstedges.add(e);
} else {
childedges.add(e);
}
}
// first remove all edges from PARENT
eit = asstedges.iterator;
while (eit.next()) { parent.deleteDestinationEdge(eit.value); }
eit = childedges.iterator;
while (eit.next()) { parent.deleteDestinationEdge(eit.value); }

   // if the number of assistants is odd, add a dummy assistant, to make the count even
   /* if (acount % 2 == 1) {
      const dummy = net.createVertex();
      net.addVertex(dummy);
      net.linkVertexes(parent, dummy, asstedges.first().link);
    }
    // now PARENT should get all of the assistant children
    eit = asstedges.iterator;
    while (eit.next()) {
      parent.addDestinationEdge(eit.value);
    }*/ 
											 
	 for(var i=0;asstedges.size > i;i++){								
		if(leftasstedges.size > i){
			parent.addDestinationEdge(leftasstedges.get(i));
		}else if(leftasstedges.size <= i && rightasstedges.size > i){
			 var dummy = net.createVertex();
			  dummy.bounds = asstedges.first().toVertex.bounds;
			  net.addVertex(dummy);
			  net.linkVertexes(parent, dummy, asstedges.first().link);
		}
		
		if(rightasstedges.size > i){
			parent.addDestinationEdge(rightasstedges.get(i));
		}else if(rightasstedges.size <= i && leftasstedges.size > i){
			  var dummy = net.createVertex();
			  dummy.bounds = asstedges.first().toVertex.bounds;
			  net.addVertex(dummy);
			  net.linkVertexes(parent, dummy, asstedges.first().link);
		}							
	 }	
	
    // create substitute vertex to be new parent of all regular children
    const subst = net.createVertex();
    net.addVertex(subst);
    // reparent regular children to the new substitute vertex
    eit = childedges.iterator;
    while (eit.next()) {
      const ce = eit.value;
      ce.fromVertex = subst;
      subst.addDestinationEdge(ce);
    }
    // finally can add substitute vertex as the final odd child,
    // to be positioned at the end of the PARENT's immediate subtree.
    const newedge = net.linkVertexes(parent, subst, null);
  }
}
return net;

};

assignTreeVertexValues(v) {
// if a vertex has any assistants, use Bus alignment
let any = false;
const children = v.children;
for (let i = 0; i < children.length; i++) {
const c = children[i];
if (isAssistant(c.node)) {
any = true;
break;
}
}
if (any) {
// this is the parent for the assistant(s)
v.alignment = go.TreeLayout.AlignmentBus; // this is required
v.nodeSpacing = 50; // control the distance of the assistants from the parent’s main links
} else if (v.node == null && v.childrenCount > 0) {
// found the substitute parent for non-assistant children
//v.alignment = go.TreeLayout.AlignmentCenterChildren;
//v.breadthLimit = 3000;
v.layerSpacing = 0;
}
};

commitLinks() {
super.commitLinks();
// make sure the middle segment of an orthogonal link does not cross over the assistant subtree
const eit = this.network.edges.iterator;
while (eit.next()) {
const e = eit.value;
if (e.link == null) continue;
const r = e.link;
console.log(‘==ppp==’);
console.log(e.fromVertex.node);
console.log(r);
// does this edge come from a substitute parent vertex?
const subst = e.fromVertex;
if (subst.node == null && r.routing == go.Link.Orthogonal) {
r.updateRoute();
r.startRoute();
// middle segment goes from point 2 to point 3
const p1 = subst.center; // assume artificial vertex has zero size
const p2 = r.getPoint(2).copy();
const p3 = r.getPoint(3).copy();
const p5 = r.getPoint(r.pointsCount - 1);
let dist = 10;
if (subst.angle == 270 || subst.angle == 180) dist = -20;
if (subst.angle == 90 || subst.angle == 270) {
p2.y = p5.y - dist; // (p1.y+p5.y)/2;
p3.y = p5.y - dist; // (p1.y+p5.y)/2;
} else {
p2.x = p5.x - dist; // (p1.x+p5.x)/2;
p3.x = p5.x - dist; // (p1.x+p5.x)/2;
}
r.setPoint(2, p2);
r.setPoint(3, p3);
r.commitRoute();
}
}
}
}

function load() {
var nodeDataArray = [
{“key”:2, “name”:“test name”, “title”:“Manager 1”,“pic”:“1.jpg”,“group”:1},
{“key”:3 ,“name”:“test name 3”, “title”:“Manager 3”,“pic”:“1.jpg”,“group”:1},
{“key”:4, “name”:“Test name 4”, “title”:“Manager”, “pic”:“1.jpg”,“parent”:1},
{“key”:5, “name”:“Mayen Uddin”, “title”:“VP Marketing/Sales”, “pic”:“2.jpg”, “parent”:4,“isAssistant”:false},
{“key”:6, “name”:“Test name 6”, “title”:“Manager”, “pic”:“1.jpg”,“isAssistant”:false},
{“key”:7, “name”:“Test name 7”, “title”:“Manager”, “pic”:“1.jpg”,“isAssistant”:true,“parent”:4,‘side’:‘left’}
];
var linkDataArray = [{from:2,to:4},{from:4,to:5},{from:4,to:6},{from:4,to:7},{from:4,to:8},{from:3,to:10},{from:3,to:4},{from:3,to:9}];
myDiagram.model = new go.GraphLinksModel(nodeDataArray, linkDataArray);

}

I got the solution for the current issue
var dummy = net.createVertex();
net.addVertex(dummy);
net.linkVertexes(parent, dummy, null);
parent.addDestinationEdge(eit.value);
it will solve side issue.