How to make Sub-Operations Cover Panel

Good Morning,
I’m creating a Gantt Diagram, and my current objective is to create a panel that covers each sub-operation. In other words, my “Project” will consist in many Operations(each has it sub-operations).
Watching the imagem below my sub-operations is the “Task”, and the Main Operation is the panel that I’m trying to create.

imagem

Is there any way to achieve this effect? Or any example that already exists?

Current code:

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>Gantt chart</title>
  <meta name="description" content="A Gantt chart that supports zooming into the timeline." />
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <!-- Copyright 1998-2020 by Northwoods Software Corporation. -->

  <script src="go.js"></script>

 <script id="code">
  // Define Graduated Panels to show the days, to show the hours, and to separate the days and hours.

  // Assume x == 0 is OriginDate, local midnight of some date.
  var OriginDate = new Date(2020,4,8,0,0); // new Date Month starts at 0(January) and end in 11(December)

  // Assume 20 document units equals one hour.
  var HourLength = 20;
  var HoursPerDay = 24;
  var DayLength = HourLength * HoursPerDay;
  var MillisPerHour = 60 * 60 * 1000;
  var MillisPerPixel = MillisPerHour / HourLength;

  function init() {
var $ = go.GraphObject.make;

myDiagram =
  $(go.Diagram, "myDiagramDiv",  // create a Diagram for the DIV HTML element
    {
      isReadOnly: true,       // deny the user permission to alter the diagram or zoom in or out
      "animationManager.isEnabled": false,
      initialContentAlignment: go.Spot.TopLeft,
      grid:
        $(go.Panel, "Grid",
          { gridCellSize: new go.Size(HourLength, 30) },
          $(go.Shape, "LineH", { stroke: 'lightgray' }),
          $(go.Shape, "LineV", { stroke: 'lightgray' }),
        ),
      "draggingTool.isGridSnapEnabled": true,
      "resizingTool.isGridSnapEnabled": true,
      scrollMode: go.Diagram.InfiniteScroll,  // allow the diagram to be scrolled arbitrarily beyond content
      positionComputation: function(diag, pos) {  // but not too far vertically, or at all if fits in viewport
        var y = pos.y;
        if (diag.documentBounds.height < diag.viewportBounds.height) {
          y = 0;
        } else {
          y = Math.min(y, diag.documentBounds.bottom - diag.viewportBounds.height);
          if (y < 0) y = 0;  // don't show negative Y coordinates
        }
        return new go.Point(pos.x, y);
      },
      nodeTemplate:
        $(go.Node, "Auto",
          {
            height: 30,
            dragComputation: function(part, pt, gridpt) {
              return new go.Point(gridpt.x, Math.max(0, gridpt.y));
            },
            resizable: true,
            resizeAdornmentTemplate:
              $(go.Adornment, "Spot",
                $(go.Placeholder)//, //Comentado permite com que ele faça resize às "caixas"
                //$(go.Shape,  // only a right-side resize handle
                //  { alignment: go.Spot.Right, cursor: "col-resize", desiredSize: new go.Size(8, 8), fill: "dodgerblue" })
              ),
            toolTip:
              $("ToolTip",
                $(go.TextBlock,
                  new go.Binding("text", "", function(data) { return data.text + "\nstart: " + data.date + "\nhours: " + data.length; }))
              )
          },
          new go.Binding("position", "", function(data) { return new go.Point(convertDateToX(data.date), convertRowToY(data.row)); })
            .makeTwoWay(function(pos, data) { data.row = convertYToRow(pos.y); data.date = convertDateToX(pos.x); }),
          new go.Binding("width", "length", function(l) { return l * HourLength; })
            .makeTwoWay(function(w) { return w / HourLength; }),
          $(go.Shape, { fill: "white" },
            new go.Binding("fill", "color")),
          $(go.TextBlock, { editable: false }, //editable = true, permite com que ele alterar o texto
            new go.Binding("text").makeTwoWay())
        ),
      "ModelChanged": function(e) {  // just for debugging
        if (e.isTransactionFinished) {
          document.getElementById("mySavedModel").value = e.model.toJson();
        }
      },
      "undoManager.isEnabled": false // Se for igual a true, faz as funcionalidades do CTRL-Z
    });

myColumnHeaders =
  $(go.Diagram, "myColumnHeadersDiv",
    {
      isReadOnly: true,
      "animationManager.isEnabled": false,
      initialContentAlignment: go.Spot.TopLeft,
      allowHorizontalScroll: false,
      allowVerticalScroll: false,
      allowZoom: false,
      padding: 0
    });


// Basic coordinate conversions, between Dates and X values, and between rows and Y values:

function convertXToDate(x) { return new Date(OriginDate.valueOf() + x * MillisPerPixel); }

function convertDateToX(dt) { return (dt.valueOf() - OriginDate.valueOf()) / MillisPerPixel; }

function convertYToRow(y) { return Math.floor(y/30) + 1; }  // assume one-based row indexes

function convertRowToY(i) { i = Math.max(i, 1); return (i-1) * 30; }


function initColumnHeaders() {
  // Assume the Graduated Panels showing the days and hours are fixed in the document;
  // and by disallowing scrolling or zooming they will stay in the viewport.

  var gradScaleHoriz1 =
    $(go.Part, "Graduated",  // show days
      { layerName: "Grid", position: new go.Point(0, 0), graduatedTickUnit: HourLength },
      $(go.Shape, { geometryString: "M0 0 H3600" }),
      $(go.Shape, { geometryString: "M0 0 V20", interval: HoursPerDay }),  // once per day
      $(go.TextBlock,
        {
          font: "10pt sans-serif", interval: HoursPerDay,
          alignmentFocus: new go.Spot(0, 0, -2, -4),
          graduatedFunction: function(v) {
            var d = new Date(OriginDate);
            d.setDate(d.getDate() + v / DayLength);
            // format date output to string
            var options = { weekday: "short", month: "short", day: "2-digit", year: "numeric" };
            return d.toLocaleDateString("pt-PT", options);
          }
        })
    );

  var gradScaleHoriz2 =
    $(go.Part, "Graduated",  // show hour of day
      { layerName: "Grid", position: new go.Point(0, 20), graduatedTickUnit: HourLength },
      $(go.Shape, { geometryString: "M0 30 H3600" }),
      $(go.Shape, { geometryString: "M0 0 V20" }),  // every hour
      $(go.TextBlock,
        {
          font: "7pt sans-serif",
          segmentOffset: new go.Point(7, 7),
          graduatedFunction: function(v) {
            v = (v / HourLength) % HoursPerDay;  // convert document coordinates to hour of day
            if (v < 0) v += HoursPerDay;
            return Math.floor(v).toString();
          }
        }
      )
    );

  // Add each part to the diagram
  myColumnHeaders.add(gradScaleHoriz1);
  myColumnHeaders.add(gradScaleHoriz2);

  // Add listeners to keep the scales/indicators in sync with the viewport
  myDiagram.addDiagramListener("ViewportBoundsChanged", function(e) {
    var vb = myDiagram.viewportBounds;

    // Update properties of horizontal scale to reflect viewport
    gradScaleHoriz1.graduatedMin = vb.x;
    gradScaleHoriz1.graduatedMax = vb.x + vb.width;
    gradScaleHoriz1.elt(0).width = myColumnHeaders.viewportBounds.width;

    gradScaleHoriz2.graduatedMin = vb.x;
    gradScaleHoriz2.graduatedMax = vb.x + vb.width;
    gradScaleHoriz2.elt(0).width = myColumnHeaders.viewportBounds.width;
  });
}

function initRowHeaders() {
  myDiagram.addDiagramListener("ViewportBoundsChanged", function(e) {
    // Automatically synchronize this diagram's Y position with the Y position of the main diagram, and the scale too.
    myRowHeaders.scale = myDiagram.scale;
    myRowHeaders.position = new go.Point(0, myDiagram.position.y);
  });

  myDiagram.addDiagramListener("DocumentBoundsChanged", function(e) {
    // The row headers document bounds height needs to be the union of what's in this diagram itself and
    // the what's in the main diagram; but the width doesn't matter.
    myRowHeaders.fixedBounds = new go.Rect(0, myDiagram.documentBounds.y, 0, myDiagram.documentBounds.height)
      .unionRect(myRowHeaders.computePartsBounds(myRowHeaders.parts));
  });
}

function initRows() {
  myDiagram.groupTemplateMap.add("Project 1",
  $(go.Group, "Auto",
    $(go.Shape, { fill: "transparent", stroke: "black" }),
    $(go.Placeholder, { padding: 15 }),
    $(go.TextBlock,{
            alignment: go.Spot.Top,
            editable: false,
            margin: 1,
            font: "bold 15px sans-serif",
            opacity: 0.75,
          },
    new go.Binding("text", "GroupText")),
    {
      toolTip:
        $("ToolTip",
          $(go.TextBlock, { margin: 4 },
            new go.Binding("text", "GroupTextTooltip"))
        )
    }
  ));

  myDiagram.model = new go.GraphLinksModel(
    [
        { key: "Project 1",id:"asdadsasdasd", isGroup: true, category: "Project 1", GroupText:"Project 1", GroupTextTooltip:"Project 1" }, 
        { key: "a", group: "Project 1", row: 3, date: new Date(new Date(2020,04,08,17,40).valueOf()), length: 3, text: "1º Task", color: "lightgreen" },
        { key: "b", group: "Project 1", row: 4, date: new Date(new Date(2020,04,08,17,40).valueOf() + 3 * MillisPerHour), length: 1, text: "2º Task", color: "lightgreen" },
        { key: "c", group: "Project 1", row: 5, date: new Date(new Date(2020,04,08,17,40).valueOf() + 4 * MillisPerHour), length: 7.5, text: "3º Task", color: "yellow" },
        { key: "d", group: "Project 1", row: 6, date: new Date(new Date(2020,04,08,17,40).valueOf() + 16.5 * MillisPerHour), length: 10, text: "4º Task", color: "yellow" },
     
    ],
    [ // link data
      { from: "a", to: "b" },
      { from: "b", to: "c" },
      { from: "c", to: "d" },
    ]);
}

   function initOverview(){
 myDiagramOverview = 
  $(go.Diagram, "myOverviewDiv",
    {
      isReadOnly: true,
      "animationManager.isEnabled": false,
      initialContentAlignment: go.Spot.TopLeft,
      allowHorizontalScroll: false,
      allowVerticalScroll: false,
      allowZoom: false,
      padding:10,
    });


  myDiagramOverview.nodeTemplate =
  $(go.Node, "Auto",
    { locationSpot: go.Spot.Center },
    $(go.Panel, "Vertical",
      { margin: 5 },
      $("Button",
        { margin: 5,
          click: function(e, obj){
            var nodeOverview = obj.part;
            var dataOverview = nodeOverview.data;
            myDiagram.nodes.each(function(node) { 
            if (node instanceof go.Group){
                if(node.key == nodeOverview.key){
                   myDiagram.centerRect(node.actualBounds);
                }
              }
            });
          }
        },
        $(go.TextBlock, new go.Binding("text", "ProjectKey"),{
            editable: false,
            margin:5,
            font: "bold 10px sans-serif",
            opacity: 0.75,
        })),
    )
  );

  myDiagramOverview.layout = $(go.GridLayout, { wrappingColumn: 1 });


    
  var OverviewKeys = [];
  // Create buttons for each isGroup that exists, for better navegation for each Project
  myDiagram.nodes.each(function(node) { 
    if (node instanceof go.Group){
      console.log(node.hb.GroupText)
      OverviewKeys.push({key:node.key,ProjectKey:node.hb.GroupText})
    }
  });
  myDiagramOverview.model = new go.GraphLinksModel(OverviewKeys);
  console.log(OverviewKeys)
}


initColumnHeaders();
initRows();
initOverview();
  }
</script>
</head>
<body onload="init()">
  <div style="width: 100%; display: flex; justify-content: space-between">
<div id="myEmptyCorner" style="width: 155px; border: solid 1px white"></div>
<div id="myColumnHeadersDiv" style="flex-grow: 1; height: 40px; border: solid 1px black"></div>
  </div>
  <div style="width: 100%; display: flex; justify-content: space-between">
<div id="myOverviewDiv" style="width: 155px; background-color: whitesmoke; border: solid 1px black"></div>
<div id="myDiagramDiv" style="flex-grow: 1; height: 400px; border: solid 1px black"></div>
  </div>
  <textarea id="mySavedModel" style="width:100%;height:250px"></textarea>
</body>
</html>

Thanks in advance for your time and attention

Here’s something that might help:

go.Shape.defineFigureGenerator("RangeBar", function(shape, w, h) {
  var b = Math.min(5, w);  // minimum breadth
  var d = Math.min(6, h);   // minimum depth
  return new go.Geometry()
    .add(new go.PathFigure(0, 0, true)
      .add(new go.PathSegment(go.PathSegment.Line, w, 0))
      .add(new go.PathSegment(go.PathSegment.Line, w, h))
      .add(new go.PathSegment(go.PathSegment.Line, w-b, h-d))
      .add(new go.PathSegment(go.PathSegment.Line, b, h-d))
      .add(new go.PathSegment(go.PathSegment.Line, 0, h).close()));
});

Adjust the minimum breadth and depth of the “pointer” corners to suit your tastes.

Thanks for answering Walter.
That is the code I need to fullfill my purpose, but I’m still having problems with the nodes that are being shown in the Diagram.
I was reading your GoJS shapes topic (https://gojs.net/latest/intro/shapes.html) in order to know where that code that you provided fits in, and I noticed that, you create this function and then you use this in the Nodes, but if I use it in my nodes, isn’t my initial configuration going to disappear? Because when fitting this code and defining $ (go.Shape), {…} in nodeTemplate, the nodes of my sub-operations went “crazy”, including the Cover Panel Area.

 var $ = go.GraphObject.make;

    // Main Cover Panel Creator
    go.Shape.defineFigureGenerator("RangeBar", function(shape, w, h) {
      var b = Math.min(5, w);  // minimum breadth
      var d = Math.min(6, h);   // minimum depth
      return new go.Geometry()
        .add(new go.PathFigure(0, 0, true)
        .add(new go.PathSegment(go.PathSegment.Line, w, 0))
        .add(new go.PathSegment(go.PathSegment.Line, w, h))
        .add(new go.PathSegment(go.PathSegment.Line, w-b, h-d))
        .add(new go.PathSegment(go.PathSegment.Line, b, h-d))
        .add(new go.PathSegment(go.PathSegment.Line, 0, h).close()));
    });

    myDiagram =
      $(go.Diagram, "myDiagramDiv",  // create a Diagram for the DIV HTML element
        {
          isReadOnly: true,       // deny the user permission to alter the diagram or zoom in or out
          "animationManager.isEnabled": false,
          initialContentAlignment: go.Spot.TopLeft,
          grid:
            $(go.Panel, "Grid",
              { gridCellSize: new go.Size(HourLength, 30) },
              $(go.Shape, "LineH", { stroke: 'lightgray' }),
              $(go.Shape, "LineV", { stroke: 'lightgray' }),
            ),
          "draggingTool.isGridSnapEnabled": true,
          "resizingTool.isGridSnapEnabled": true,
          scrollMode: go.Diagram.InfiniteScroll,  // allow the diagram to be scrolled arbitrarily beyond content
          positionComputation: function(diag, pos) {  // but not too far vertically, or at all if fits in viewport
            var y = pos.y;
            if (diag.documentBounds.height < diag.viewportBounds.height) {
              y = 0;
            } else {
              y = Math.min(y, diag.documentBounds.bottom - diag.viewportBounds.height);
              if (y < 0) y = 0;  // don't show negative Y coordinates
            }
            return new go.Point(pos.x, y);
          },
          nodeTemplate:
            $(go.Node, "Auto",
              {
                height: 30,
                dragComputation: function(part, pt, gridpt) {
                  return new go.Point(gridpt.x, Math.max(0, gridpt.y));
                },
                resizable: true,
                resizeAdornmentTemplate:
                  $(go.Adornment, "Spot",
                    $(go.Placeholder)//, //Comentado permite com que ele faça resize às "caixas"
                    //$(go.Shape,  // only a right-side resize handle
                    //  { alignment: go.Spot.Right, cursor: "col-resize", desiredSize: new go.Size(8, 8), fill: "dodgerblue" })
                  ),
                toolTip:
                  $("ToolTip",
                    $(go.TextBlock,
                      new go.Binding("text", "", function(data) { return data.text + "\nstart: " + data.date + "\nhours: " + data.length; }))
                  )
              },$(go.Shape,
                {
                  name: "SHAPE",
                  fill: $(go.Brush, "Linear", { 0.0: "black", 1.0: "gray" })
                },
                new go.Binding("figure", "fig")),
              new go.Binding("position", "", function(data) { return new go.Point(convertDateToX(data.date), convertRowToY(data.row)); })
                .makeTwoWay(function(pos, data) { data.row = convertYToRow(pos.y); data.date = convertDateToX(pos.x); }),
              new go.Binding("width", "length", function(l) { return l * HourLength; })
                .makeTwoWay(function(w) { return w / HourLength; }),
              $(go.Shape, { fill: "white" },
                new go.Binding("fill", "color")),
              $(go.TextBlock, { editable: false }, //editable = true, permite com que ele alterar o texto
                new go.Binding("text").makeTwoWay())
            ),
          "ModelChanged": function(e) {  // just for debugging
            if (e.isTransactionFinished) {
              document.getElementById("mySavedModel").value = e.model.toJson();
            }
          },
          "undoManager.isEnabled": false // Se for igual a true, faz as funcionalidades do CTRL-Z
        });




      myDiagram.model = new go.GraphLinksModel(
        [
            { key: "Project 1",id:"Project 1", isGroup: true, category: "Project 1", GroupText:"Project 1", GroupTextTooltip:"Project 1" }, 
            { group: "Project 1", fig: "RangeBar", row: 2,date: new Date(new Date(2020,04,08,17,40).valueOf()),length: 26.5 }, // Cover Panel
            { key: "a", group: "Project 1", row: 3, date: new Date(new Date(2020,04,08,17,40).valueOf()), length: 3, text: "1º Task", color: "lightgreen" },
            { key: "b", group: "Project 1", row: 4, date: new Date(new Date(2020,04,08,17,40).valueOf() + 3 * MillisPerHour), length: 1, text: "2º Task", color: "lightgreen" },
            { key: "c", group: "Project 1", row: 5, date: new Date(new Date(2020,04,08,17,40).valueOf() + 4 * MillisPerHour), length: 7.5, text: "3º Task", color: "yellow" },
            { key: "d", group: "Project 1", row: 6, date: new Date(new Date(2020,04,08,17,40).valueOf() + 16.5 * MillisPerHour), length: 10, text: "4º Task", color: "yellow" },
         
        ],
        [ // link data
          { from: "a", to: "b" },
          { from: "b", to: "c" },
          { from: "c", to: "d" },
        ]);
    }

That’s odd – I cannot explain that. I was just suggesting using the “RangeBar” figure instead of a “Rectangle” figure for some bars. See for example: https://gojs.net/extras/ganttCollapsible.html

So it ought to be the case that the bar has changed shape in row 2, but nothing else should have changed.

Actually it changed in all of them, we cannot see the row 2 and row 3 because the lenght is small, but if we increase the lenght we will see the same effect.
But I will check your example and try to adapt to my case. I will let you know if I come across with some problem

Hi Walter
I have been trying to adapt this example for my case, but without success. Because the way it is done, in my “thinking” it would never work in the way I have done my development.
So I went back to look at what I have, and I noticed that the Node that works as “Cover Panel” has a white spacing, because I don’t have the text defined as well as the color (and by default it is white)

$(go.Shape,
              {  
                name: "SHAPE",
                fill: $(go.Brush, "Linear", { 0.0: "black", 1.0: "gray" })
              },
              new go.Binding("figure", "fig")),
              new go.Binding("position", "", function(data) { return new go.Point(convertDateToX(data.date), convertRowToY(data.row)); })
                .makeTwoWay(function(pos, data) { data.row = convertYToRow(pos.y); data.date = convertDateToX(pos.x); }),
              new go.Binding("width", "length", function(l) { return l * HourLength; })
                .makeTwoWay(function(w) { return w / HourLength; }),
              $(go.Shape, { fill: "white" }, //<-----------------------
                new go.Binding("fill", "color")), //<-------------------
              $(go.TextBlock, { editable: false }, //editable = true, permite com que ele alterar o texto
                new go.Binding("text").makeTwoWay()),

Not to mention that all my nodes were affected with this new addition, although we don’t see it in row 2 and row 3, because the length is too small and if we increase it we can also see that they were affected. All of my nodes were affected with this addition.

Is there some way on how to make this new addition of Cover Panel, just show on the respective Nodes, without affecting the other Nodes?

Thank you for your time and attention

If you don’t specify or constrain the size of a Shape, it gets the default size of 100x100, which is big enough to be obvious that something is wrong.

Don’t add objects unless you know exactly how the containing panel will use it.

Hi Walter,
I want to thank you for the help so far.
I’ve been re-checking the example you provided, and in this example it assumes that all keys that are TreeLeaf will be Rectangle, and if not then it will be a RangeBar.

In my case I cannot assume this way, because if I made a link from Task A to Task B, then Task A would be RangeBar.
To control this I did it in another way in which I created a new Binding isAgglo, in which I pass True or False, and in this way I know the Nodes that will work as RangeBar and the nodes that will work as Rectangle.

  myGantt =
    $(go.Diagram, "myGanttDiv",  // create a Diagram for the DIV HTML element
      {
        isReadOnly: false,       // deny the user permission to alter the diagram or zoom in or out
        allowCopy: false,
        allowDelete: false,
        "animationManager.isEnabled": false,
        initialContentAlignment: go.Spot.TopLeft, // Alignment of the Grid will start always at OriginDate
        grid:
          $(go.Panel, "Grid",
            { gridCellSize: new go.Size(HourLength, 30) }, // Tamanho das cells da grid(width,height)
            $(go.Shape, "LineH", { stroke: 'lightgray' }), // Figure already defined in GoJs library. Only changing the stroke color
            $(go.Shape, "LineV", { stroke: 'lightgray' }), // Figure already defined in GoJs library. Only changing the stroke color
          ),
        "draggingTool.isGridSnapEnabled": true,
        "resizingTool.isGridSnapEnabled": true,
        scrollMode: go.Diagram.InfiniteScroll,  // allow the diagram to be scrolled arbitrarily beyond content
        positionComputation: function(diag, pos) {  // but not too far vertically, or at all if fits in viewport
          var y = pos.y;
          if (diag.documentBounds.height < diag.viewportBounds.height) {
            y = 0;
          } else {
            y = Math.min(y, diag.documentBounds.bottom - diag.viewportBounds.height);
            if (y < 0) y = 0;  // don't show negative Y coordinates
          }
          return new go.Point(pos.x, y);
        },
        nodeTemplate:
          $(go.Node, "Auto",
            {
              height: 30, // Height of my node
              dragComputation: function(part, pt, gridpt) {
                return new go.Point(gridpt.x, Math.max(0, gridpt.y));
              },
              selectionAdorned:true, // If node is selected, we won't see the blue rectangle around it
              resizable:true, // If resizable = true, means I can resize node to a new lenght
              resizeAdornmentTemplate: $(go.Adornment,"Spot",
                  $(go.Placeholder),
                  $(go.Shape, "Diamond", // Shape Figure
                  {
                    alignment: go.Spot.Right, 
                    width: 8, height: 8,
                    strokeWidth: 0,
                    fill: "fuchsia",
                    cursor: 'e-resize' // Change cursor "type" to "resize figure"
                  })
                ),
              toolTip:
                $("ToolTip",
                  $(go.TextBlock,
                    new go.Binding("text", "", function(data) { return data.text + "\nstart: " + data.date + "\nhours: " + data.length; }))
                ),
            },
            new go.Binding("position", "", function(data) { return new go.Point(convertDateToX(data.date), convertRowToY(data.row)); })
            .makeTwoWay(function(pos, data) { data.row = convertYToRow(pos.y); data.date = convertDateToX(pos.x); }),
            new go.Binding("width", "length", function(l) { return l * HourLength; }).makeTwoWay(function(w) { return w / HourLength; }), // The width of my node equals the amount of time to complete the task
            new go.Binding("isAgglo", "isAgglo"),
            new go.Binding("selectable", "isAgglo", function(isAgglo) { return isAgglo ? false : true; }).ofObject(), // Only allow to select the nodes that arent Treeleaf
            new go.Binding("resizable", "isAgglo" , function(isAgglo) { return isAgglo ? false : true; }).ofObject(), // Only allow to resize the nodes that arent Treeleaf
            new go.Binding("isTreeExpanded").makeTwoWay(),
            $(go.Shape,
              { name: "SHAPE", height: 30, margin: 1, strokeWidth: 0, fill: "lightgray" },
              new go.Binding("fill", "color"),
              new go.Binding("figure", "isAgglo", function(isAgglo) { return isAgglo ? "RangeBar" : "Rectangle"; }).ofObject())
          ),
        "ModelChanged": function(e) {  // just for debugging
          if (e.isTransactionFinished) {
            document.getElementById("mySavedModel").value = e.model.toJson();
          }
        },
        "undoManager.isEnabled": false // Se for igual a true, faz as funcionalidades do CTRL-Z
      });
 function initRows() {
      var model = new go.GraphLinksModel(
        [
            { key: 0,  row: 2, date: new Date(new Date(2020,04,08,17,40).valueOf()), length: 3, text: "Project X", isAgglo: true},
            { key: 1,  row: 3, date: new Date(new Date(2020,04,08,17,40).valueOf()), length: 3, text: "1º Task", color: "orange", isAgglo: false},
            { key: 11, row: 4, date: new Date(new Date(2020,04,08,17,40).valueOf() + 3 * MillisPerHour), length: 1, text: "2º Task", color: "lightgreen", isAgglo: false },
            { key: 12, row: 5, date: new Date(new Date(2020,04,08,17,40).valueOf() + 4 * MillisPerHour), length: 7.5, text: "3º Task", color: "blue", isAgglo: false},
            { key: 2,  row: 6, date: new Date(new Date(2020,04,08,17,40).valueOf() + 16.5 * MillisPerHour), length: 10, text: "4º Task", color: "yellow", isAgglo: false},
         
        ],
        [ // link data
          { from: 0, to: 1 },
          { from: 1, to: 11 },
          { from: 1, to: 12 },
          { from: 0, to: 2 },
        ]);

       myGantt.model = model;
    }

Question I have:

1 - My question at the moment is how do I get my RangeBar Nodes to have the total lenght of their Child Nodes, and the date(mabye the date of first child node??Don’t know how I should proceed with date)

For the total lenght of the Child Nodes, will I have to readapt this code, that is provided by your example?

  function walkTree(node, start) {
    var model = node.diagram.model;
    if (node.isTreeLeaf) {
      var dur = node.data.duration;
      if (dur === undefined || isNaN(dur)) {
        dur = 100;  // default task length?
        model.set(node.data, "duration", dur);
      }
      var st = node.data.start;
      if (st === undefined || isNaN(st)) {
        st = start;  // use given START
        model.set(node.data, "start", st);
      }
      return st + dur;
    } else {
      // first recurse to fill in any missing data
      node.findTreeChildrenNodes().each(function(n) {
        start = walkTree(n, start);
      });
      // now can calculate this non-leaf node's data
      var min = Infinity;
      var max = -Infinity;
      var colors = new go.Set();
      node.findTreeChildrenNodes().each(function(n) {
        min = Math.min(min, n.data.start);
        max = Math.max(max, n.data.start + n.data.duration);
        if (n.data.color) colors.add(n.data.color);
      });
      model.set(node.data, "start", min);
      model.set(node.data, "duration", max - min);
      model.set(node.data, "color", (colors.count === 1 ? go.Brush.darken(colors.first()) : "gray"));
      return max;
    }

First, I should point out that:

new go.Binding("isAgglo", "isAgglo"),

cannot work because no GraphObject class has a settable property named “isAgglo”. You should be seeing a warning about that, especially if you are using go-debug.js.

Second, I suggested the “RangeBar” figure because you seemed to want that shape geometry for a bar, not for covering many rows at the same time as the background for a group. I don’t see your group template, so you might be using it the correct way, where the shape only occupies the top row of the group.

I switched for gojs-debug, and yes I see a warning about the variable that I created, but I created this variable to allow user input, because in order to accomplish what I pretended. I did it this way, reading your Binding library https://gojs.net/latest/api/symbols/Binding.html, where you mention the example:

{ key: 23, say: "hello!" }

Your simple node template might be like:

  var template = new go.Node(go.Panel.Auto);
  // . . . define the rest of the Node's visual tree . . .
  var txt = new go.TextBlock();
  txt.bind(new go.Binding("text", "say"));
  template.add(txt);
  myDiagram.nodeTemplate = template;

Using GraphObject.make it might look like:

  var $ = go.GraphObject.make;
  myDiagram.nodeTemplate =
    $(go.Node, "Auto",
      . . .
      $(go.TextBlock, new go.Binding("text", "say"))
    )

Conversions

Sometimes the data value needs to be modified or converted in order to be used as the new value of a GraphObject property. The most common conversion functions are provided for you – they convert a string to a geometric class: Point.parse, Size.parse, Rect.parse, Margin.parse, Spot.parse, and Geometry.parse. But you can easily define your own conversion function.

As an example of a conversion function, let’s use a function that adds some text prefixing the data property value:

  new go.Binding("text", "say", function(v) { return "I say: " + v; })

Your do mean that I should have done the following way:
new go.Binding("text", "isAgglo")

Because if I use this way my nodes will all be Rectangles…

Regarding the GroupTemplateMap, where it says “so you might be using it the correct way, where the shape only occupies the top row of the group.” I’m not actually showing the Group because I was doing this from the beginning in order to better understand what I had already done with what was in your example thar you provived.
But yes, I intend to show GroupTemplateMap, for each Project that exists, because I will be convering several projects in my GanttDiagram using the GroupTemplateMap for each, and inside each one I will have their nodes. But in the development I’m making, I’m only working with the keys for one Project.

I don’t want to be annoying, but any way to call this correctly? Since I’m creating a Binding in the incorrect way, which works(but it is wrong…)

Sorry, I did not see a question, even an implicit question, in your previous post.

So what exactly is the question?