Difference between revisions of "HTML Presentation Object: Gantt chart"

From Mea Wiki
Jump to navigation Jump to search
m
 
(6 intermediate revisions by the same user not shown)
Line 2: Line 2:
  
 
<pre>
 
<pre>
data0=CreateDataset(Array('TaskName', 'StartDate', 'EndDate', 'PlannedStartDate', 'PlannedEndDate', 'Progress'))
+
data=CreateDataset(Array('TaskName', 'StartDate', 'EndDate', 'PlannedStartDate', 'PlannedEndDate', 'Progress'))
data1=AddDatasetRow([data0], 'Project Task 1', NewDatetime(2017,1,1), NewDatetime(2017,2,15), NewDatetime(2017,1,10), NewDatetime(2017,2,20), 35)
+
data=AddDatasetRow([data], 'Project Task 1', NewDatetime(2017,1,1), NewDatetime(2017,2,15), NewDatetime(2017,1,10), NewDatetime(2017,2,20), 35)
data2=AddDatasetRow([data1], 'Project Task 2', NewDatetime(2017,2,1), NewDatetime(2017,4,1), NewDatetime(2017,2,1), NewDatetime(2017,3,15), 90)
+
data=AddDatasetRow([data], 'Project Task 2', NewDatetime(2017,2,1), NewDatetime(2017,4,1), NewDatetime(2017,2,1), NewDatetime(2017,3,15), 90)
data3=AddDatasetRow([data2], 'Project Task 3', NewDatetime(2017,4,1), NewDatetime(2017,6,1), NewDatetime(2017,4,5), NewDatetime(2017,6,15), 15)
+
data=AddDatasetRow([data], 'Project Task 3', NewDatetime(2017,4,1), NewDatetime(2017,6,1), NewDatetime(2017,4,5), NewDatetime(2017,6,15), 15)
data4=AddDatasetRow([data3], 'Project Task 4', NewDatetime(2017,4,10), NewDatetime(2017,7,31), NewDatetime(2017,4,10), NewDatetime(2017,7,31), 10)
+
data=AddDatasetRow([data], 'Project Task 4', NewDatetime(2017,4,10), NewDatetime(2017,7,31), NewDatetime(2017,4,10), NewDatetime(2017,7,31), 10)
data5=AddDatasetRow([data4], 'Project Task 5', NewDatetime(2017,5,1), NewDatetime(2017,8,1), NewDatetime(2017,5,10), NewDatetime(2017,7,16), 100)
+
data=AddDatasetRow([data], 'Project Task 5', NewDatetime(2017,5,1), NewDatetime(2017,8,1), NewDatetime(2017,5,10), NewDatetime(2017,7,16), 100)
data6=AddDatasetRow([data5], 'Project Task 6', NewDatetime(2017,7,1), NewDatetime(2017,7,31), NewDatetime(2017,6,20), NewDatetime(2017,7,20), 0)
+
data=AddDatasetRow([data], 'Project Task 6', NewDatetime(2017,7,1), NewDatetime(2017,7,31), NewDatetime(2017,6,20), NewDatetime(2017,7,20), 0)
data7=AddDatasetRow([data6], 'Project Task 7', NewDatetime(2017,8,1), NewDatetime(2017,10,15), NewDatetime(2017,7,15), NewDatetime(2017,9,30), 50)
+
data=AddDatasetRow([data], 'Project Task 7', NewDatetime(2017,8,1), NewDatetime(2017,10,15), NewDatetime(2017,7,15), NewDatetime(2017,9,30), 50)
data8=AddDatasetRow([data7], 'Project Task 8', NewDatetime(2017,8,1), NewDatetime(2017,10,1), NewDatetime(2017,8,10), NewDatetime(2017,10,1), 30)
+
data=AddDatasetRow([data], 'Project Task 8', NewDatetime(2017,8,1), NewDatetime(2017,10,1), NewDatetime(2017,8,10), NewDatetime(2017,10,1), 30)
data9=AddDatasetRow([data8], 'Project Task 9', NewDatetime(2017,9,1), NewDatetime(2017,11,1), NewDatetime(2017,8,20), NewDatetime(2017,10,20), 5)
+
data=AddDatasetRow([data], 'Project Task 9', NewDatetime(2017,9,1), NewDatetime(2017,11,1), NewDatetime(2017,8,20), NewDatetime(2017,10,20), 5)
 
</pre>
 
</pre>
  
 
Set the '''Horizontal scrollbar''' and '''Vertical scrollbar'''  to '''Hidden'''.
 
Set the '''Horizontal scrollbar''' and '''Vertical scrollbar'''  to '''Hidden'''.
  
Use the HTML code below. Column names can be changed using the javascript variable in the beginning of the code. In the example the current date is fixed to '''Date.UTC(2017, 7,15)''' - change it to '''Date.now()'''.
+
Use the HTML code below. Column names can be changed using the javascript variable in the beginning of the code. In the example, the "current date" is fixed to '''Date.UTC(2017, 7,15)''', change it to '''Date.now()'''.
  
 
<pre>
 
<pre>
Line 37: Line 37:
 
   }
 
   }
 
}
 
}
 
+
 
function myDatasetAvailable<#uniqueId>(datasetData) {
 
function myDatasetAvailable<#uniqueId>(datasetData) {
 
   if (datasetData == null || datasetData.sheets == null || datasetData.sheets.length == 0 || datasetData.sheets[0] == null || datasetData.sheets[0].values == null || datasetData.sheets[0].values.length == 0) return;
 
   if (datasetData == null || datasetData.sheets == null || datasetData.sheets.length == 0 || datasetData.sheets[0] == null || datasetData.sheets[0].values == null || datasetData.sheets[0].values.length == 0) return;
   poData<#uniqueId> = [];
+
   datasetData.getDatasetAsObjectArray = getDatasetAsObjectArray;
  for (var row = 1; row < datasetData.sheets[0].values[0].length; row++) {
+
  datasetData.formatDataset = formatDataset;
    var rowObject = {};
+
  poData<#uniqueId> = datasetData.getDatasetAsObjectArray();
    for (var column = 0; column < datasetData.sheets[0].values.length; column++) {
 
      rowObject[datasetData.sheets[0].values[column][0].attribute] = datasetData.sheets[0].values[column][row].value;
 
    }
 
    poData<#uniqueId>.push(rowObject);
 
  }
 
 
   for (var i = 0; i < poData<#uniqueId>.length; i++) {  
 
   for (var i = 0; i < poData<#uniqueId>.length; i++) {  
 
     poData<#uniqueId>[i][startDateColumn] = parseInt(poData<#uniqueId>[i][startDateColumn].replace("/Date(", "").replace(")/", ""));
 
     poData<#uniqueId>[i][startDateColumn] = parseInt(poData<#uniqueId>[i][startDateColumn].replace("/Date(", "").replace(")/", ""));
Line 76: Line 71:
 
     },
 
     },
 
     title: {
 
     title: {
     text: 'Gantt charts' },
+
     text: 'Gantt chart' },
 
     xAxis: {
 
     xAxis: {
 
       type: "category",  
 
       type: "category",  
Line 97: Line 92:
 
         color: '#D00D20',
 
         color: '#D00D20',
 
         width: 2,
 
         width: 2,
         value: Date.UTC(2017, 7,15) // Real current date: Date.now()
+
         value: Date.UTC(2017, 7,15) // Real currentdate: Date.now()
 
     }],
 
     }],
 
       labels: {
 
       labels: {
Line 108: Line 103:
 
       useHTML: true,
 
       useHTML: true,
 
       formatter: function () {
 
       formatter: function () {
         return  "<span style='font-weight: bold;font-size:125%;'>" + this.point.name + "</span></br>Actual: <b>" +
+
         return  "<span style='font-weight: bold;font-size:125%;'>" + this.point[taskNameColumn] + "</span></br>Actual: <b>" +
           (new Date(this.point[startDateColumn])).toLocaleDateString() + "</b> - <b>" + (new Date(this.point.EndDate)).toLocaleDateString() + "</b></br>" +
+
           (new Date(this.point[startDateColumn])).toLocaleDateString() + "</b> - <b>" + (new Date(this.point[endDateColumn])).toLocaleDateString() + "</b></br>" +
           "Planned: <b>" + (new Date(this.point.PlannedStartDate)).toLocaleDateString() + "</b> - <b>" +
+
           "Planned: <b>" + (new Date(this.point[plannedStartDateColumn])).toLocaleDateString() + "</b> - <b>" +
           (new Date(this.point.PlannedEndDate)).toLocaleDateString() + "</b></br>" +  
+
           (new Date(this.point[plannedEndDateColumn])).toLocaleDateString() + "</b></br>" +  
           "Progress: <b>" + this.point.progress + " %</b>";
+
           "Progress: <b>" + this.point[progressColumn] + " %</b>";
 
       }
 
       }
 
     },
 
     },
Line 123: Line 118:
 
       borderRadius: 0,
 
       borderRadius: 0,
 
       borderWidth: 0,
 
       borderWidth: 0,
       data: formatDataset(poData<#uniqueId>, {"low": startDateColumn, "StartDate": startDateColumn, "high": "ProgressPoint", "progress": progressColumn, "name": taskNameColumn}),
+
       data: formatDataset(poData<#uniqueId>, {"low": startDateColumn, "high": "ProgressPoint", "name": taskNameColumn}, null, null, null, true),
 
       dataLabels: {
 
       dataLabels: {
 
         enabled: true,
 
         enabled: true,
Line 129: Line 124:
 
         inside: true,
 
         inside: true,
 
         verticalAlign:"middle",
 
         verticalAlign:"middle",
         format: '{point.progress} %',
+
         formatter: function () {
 +
          return this.point[progressColumn] + "%";
 +
        },
 
         style: {
 
         style: {
 
           fontSize: '13px'
 
           fontSize: '13px'
Line 142: Line 139:
 
       borderRadius: 0,
 
       borderRadius: 0,
 
       borderWidth: 0,
 
       borderWidth: 0,
       data: formatDataset(poData<#uniqueId>, {"low": "ProgressPoint", "high": endDateColumn, "EndDate": endDateColumn, "progress": progressColumn, "name": taskNameColumn}),
+
       data: formatDataset(poData<#uniqueId>, {"low": "ProgressPoint", "high": endDateColumn, "name": taskNameColumn}, null, null, null, true),
 
       dataLabels: {
 
       dataLabels: {
 
         enabled: true,
 
         enabled: true,
Line 159: Line 156:
 
       borderRadius: 0,
 
       borderRadius: 0,
 
       borderWidth: 0,
 
       borderWidth: 0,
       data: formatDataset(poData<#uniqueId>, {"low": plannedStartDateColumn, "PlannedStartDate": plannedStartDateColumn, "high": plannedEndDateColumn, "PlannedEndDate": plannedEndDateColumn, "progress": progressColumn, "name": taskNameColumn}),
+
       data: formatDataset(poData<#uniqueId>, {"low": plannedStartDateColumn, "high": plannedEndDateColumn, "name": taskNameColumn}, null, null, null, true),
 
     dataLabels: {
 
     dataLabels: {
 
       enabled: true,
 
       enabled: true,
Line 174: Line 171:
 
}
 
}
  
function formatDataset(inputData, mappings, groupColumn, groupAttribute, innerArrayAttribute) {
+
function getDatasetAsObjectArray(sheetIndex = 0) {
 +
  if (this.sheets[sheetIndex].values.length == 0) throw "Dataset contains no columns.";
 +
  var datasetAsObjectArray = [];
 +
  for (var row = 1; row < this.sheets[sheetIndex].values[0].length; row++) {
 +
    var rowObject = {};
 +
    for (var column = 0; column < this.sheets[sheetIndex].values.length; column++) {
 +
      rowObject[this.sheets[sheetIndex].values[column][0].attribute] = this.sheets[sheetIndex].values[column][row].value;
 +
    }
 +
    datasetAsObjectArray.push(rowObject);
 +
  }
 +
  return datasetAsObjectArray;
 +
}
 +
 
 +
function formatDataset(inputData, mappings = {}, groupColumn = null, groupAttribute = null, innerArrayAttribute = null, keepAlreadyMappedColumns = false) {
 +
  var datasetAsObjectArray = inputData;
 +
  if (datasetAsObjectArray == null) datasetAsObjectArray = this.getDatasetAsObjectArray();
 
   var mappedData = [];
 
   var mappedData = [];
 
   var namesToMap = Object.getOwnPropertyNames(mappings);
 
   var namesToMap = Object.getOwnPropertyNames(mappings);
   for (var i = 0; i < inputData.length; i++) {
+
   for (var i = 0; i < datasetAsObjectArray.length; i++) {
 
     var row = {};
 
     var row = {};
 
     var mappedColumns = [];
 
     var mappedColumns = [];
 
     for (var j = 0; j < namesToMap.length; j++) {
 
     for (var j = 0; j < namesToMap.length; j++) {
       row[namesToMap[j]] = inputData[i][mappings[namesToMap[j]]];
+
       row[namesToMap[j]] = datasetAsObjectArray[i][mappings[namesToMap[j]]];
 
       mappedColumns.push(mappings[namesToMap[j]]);
 
       mappedColumns.push(mappings[namesToMap[j]]);
 
     }
 
     }
     var dataColumns = Object.getOwnPropertyNames(inputData[i]);
+
     var dataColumns = Object.getOwnPropertyNames(datasetAsObjectArray[i]);
 
     for (j = 0; j < dataColumns.length; j++) {
 
     for (j = 0; j < dataColumns.length; j++) {
       if (mappedColumns.indexOf(dataColumns[j]) == -1) {
+
       if (keepAlreadyMappedColumns || mappedColumns.indexOf(dataColumns[j]) == -1) {
         row[dataColumns[j]] = inputData[i][dataColumns[j]];
+
         row[dataColumns[j]] = datasetAsObjectArray[i][dataColumns[j]];
 
       }
 
       }
 
     }
 
     }

Latest revision as of 06:57, 11 April 2018

The following query contains example data for the gantt chart. Add it to a HTML presentation object's dataset with name "exampleData". Note that this example needs QPR Reporting Expression datasource installed. To use the gantt charts for a real purpose, replace the example query with a query that access the data.

data=CreateDataset(Array('TaskName', 'StartDate', 'EndDate', 'PlannedStartDate', 'PlannedEndDate', 'Progress'))
data=AddDatasetRow([data], 'Project Task 1', NewDatetime(2017,1,1), NewDatetime(2017,2,15), NewDatetime(2017,1,10), NewDatetime(2017,2,20), 35)
data=AddDatasetRow([data], 'Project Task 2', NewDatetime(2017,2,1), NewDatetime(2017,4,1), NewDatetime(2017,2,1), NewDatetime(2017,3,15), 90)
data=AddDatasetRow([data], 'Project Task 3', NewDatetime(2017,4,1), NewDatetime(2017,6,1), NewDatetime(2017,4,5), NewDatetime(2017,6,15), 15)
data=AddDatasetRow([data], 'Project Task 4', NewDatetime(2017,4,10), NewDatetime(2017,7,31), NewDatetime(2017,4,10), NewDatetime(2017,7,31), 10)
data=AddDatasetRow([data], 'Project Task 5', NewDatetime(2017,5,1), NewDatetime(2017,8,1), NewDatetime(2017,5,10), NewDatetime(2017,7,16), 100)
data=AddDatasetRow([data], 'Project Task 6', NewDatetime(2017,7,1), NewDatetime(2017,7,31), NewDatetime(2017,6,20), NewDatetime(2017,7,20), 0)
data=AddDatasetRow([data], 'Project Task 7', NewDatetime(2017,8,1), NewDatetime(2017,10,15), NewDatetime(2017,7,15), NewDatetime(2017,9,30), 50)
data=AddDatasetRow([data], 'Project Task 8', NewDatetime(2017,8,1), NewDatetime(2017,10,1), NewDatetime(2017,8,10), NewDatetime(2017,10,1), 30)
data=AddDatasetRow([data], 'Project Task 9', NewDatetime(2017,9,1), NewDatetime(2017,11,1), NewDatetime(2017,8,20), NewDatetime(2017,10,20), 5)

Set the Horizontal scrollbar and Vertical scrollbar to Hidden.

Use the HTML code below. Column names can be changed using the javascript variable in the beginning of the code. In the example, the "current date" is fixed to Date.UTC(2017, 7,15), change it to Date.now().

<div id="container<#uniqueId>"></div>

<script>
var taskNameColumn = "TaskName";
var startDateColumn = "StartDate";
var endDateColumn = "EndDate";
var plannedStartDateColumn = "PlannedStartDate";
var plannedEndDateColumn = "PlannedEndDate";
var progressColumn = "Progress";
var poData<#uniqueId>;
var width<#uniqueId>;
var height<#uniqueId>;

function <#datasetChangeFunction>(datasetIdentifier, datasetChangeCallbackFunction) {
  if (datasetIdentifier == "exampleData") {
    datasetChangeCallbackFunction(myDatasetAvailable<#uniqueId>);
  }
}
 
function myDatasetAvailable<#uniqueId>(datasetData) {
  if (datasetData == null || datasetData.sheets == null || datasetData.sheets.length == 0 || datasetData.sheets[0] == null || datasetData.sheets[0].values == null || datasetData.sheets[0].values.length == 0) return;
  datasetData.getDatasetAsObjectArray = getDatasetAsObjectArray;
  datasetData.formatDataset = formatDataset;
  poData<#uniqueId> = datasetData.getDatasetAsObjectArray();
  for (var i = 0; i < poData<#uniqueId>.length; i++) { 
    poData<#uniqueId>[i][startDateColumn] = parseInt(poData<#uniqueId>[i][startDateColumn].replace("/Date(", "").replace(")/", ""));
    poData<#uniqueId>[i][endDateColumn] = parseInt(poData<#uniqueId>[i][endDateColumn].replace("/Date(", "").replace(")/", ""));
    poData<#uniqueId>[i][plannedStartDateColumn] = parseInt(poData<#uniqueId>[i][plannedStartDateColumn].replace("/Date(", "").replace(")/", ""));
    poData<#uniqueId>[i][plannedEndDateColumn] = parseInt(poData<#uniqueId>[i][plannedEndDateColumn].replace("/Date(", "").replace(")/", ""));
    poData<#uniqueId>[i]["ProgressPoint"] = (new Date(poData<#uniqueId>[i][startDateColumn] + (poData<#uniqueId>[i][endDateColumn] - poData<#uniqueId>[i][startDateColumn]) * poData<#uniqueId>[i][progressColumn] / 100)).getTime();
  }
  drawPO<#uniqueId>();
}
 
function <#resizeFunction>(newWidth, newHeight) {
  width<#uniqueId> = newWidth;
  height<#uniqueId> = newHeight;
  $("#container<#uniqueId>").width(newWidth);
  $("#container<#uniqueId>").height(newHeight);
  drawPO<#uniqueId>();
}

function drawPO<#uniqueId>() {
  if (poData<#uniqueId> == null || width<#uniqueId> == null) return;
  $("#container<#uniqueId>").empty();
  Highcharts.chart("container<#uniqueId>", {
    chart: {
      type: 'columnrange',
      inverted: true,
      zoomType: 'y'
    },
    title: {
    text: 'Gantt chart' },
    xAxis: {
      type: "category", 
      labels: {
        style: {
          fontSize: '13px'
        }
      }
    },
    credits: { enabled: false },
    yAxis: {
      type: 'datetime',
      opposite: true,
      tickPixelInterval: 90,
      dateTimeLabelFormats: {
        day: '%d/%m', week: '%d/%m', month: '%m/%Y', year: '%Y'
      },
      title: "",
      plotLines: [{
        color: '#D00D20',
        width: 2,
        value: Date.UTC(2017, 7,15) // Real currentdate: Date.now()
    }],
      labels: {
        style: {
          fontSize: '13px'
        }
      }
    },
    tooltip: {
      useHTML: true,
      formatter: function () {
        return  "<span style='font-weight: bold;font-size:125%;'>" + this.point[taskNameColumn] + "</span></br>Actual: <b>" +
          (new Date(this.point[startDateColumn])).toLocaleDateString() + "</b> - <b>" + (new Date(this.point[endDateColumn])).toLocaleDateString() + "</b></br>" +
          "Planned: <b>" + (new Date(this.point[plannedStartDateColumn])).toLocaleDateString() + "</b> - <b>" +
          (new Date(this.point[plannedEndDateColumn])).toLocaleDateString() + "</b></br>" + 
          "Progress: <b>" + this.point[progressColumn] + " %</b>";
      }
    },
    legend: { enabled: false },
    series: [{
      color: "#195283",
      stacking: "normal",
      pointPadding: 0,
      groupPadding: 0,
      borderRadius: 0,
      borderWidth: 0,
      data: formatDataset(poData<#uniqueId>, {"low": startDateColumn, "high": "ProgressPoint", "name": taskNameColumn}, null, null, null, true),
       dataLabels: {
         enabled: true,
         align: 'center',
         inside: true,
         verticalAlign:"middle",
         formatter: function () {
           return this.point[progressColumn] + "%";
         },
         style: {
           fontSize: '13px'
         }
      }
    },
    {
      color: "#3277b2",
      stacking:"normal",
      pointPadding: 0,
      groupPadding: 0,
      borderRadius: 0,
      borderWidth: 0,
      data: formatDataset(poData<#uniqueId>, {"low": "ProgressPoint", "high": endDateColumn, "name": taskNameColumn}, null, null, null, true),
      dataLabels: {
        enabled: true,
        align: 'center',
        inside: true,
        format: '',
        style: {
          fontSize: '13px'
        }
      }
    },
    {
      color: "#fba41c",
      pointPadding: 0,
      groupPadding: 0.4,
      borderRadius: 0,
      borderWidth: 0,
      data: formatDataset(poData<#uniqueId>, {"low": plannedStartDateColumn, "high": plannedEndDateColumn, "name": taskNameColumn}, null, null, null, true),
     dataLabels: {
       enabled: true,
       align: 'center',
       inside: true,
       format: '',
       style: {
         fontSize: '13px'
       }
     }
    }
  ]
  });
}

function getDatasetAsObjectArray(sheetIndex = 0) {
  if (this.sheets[sheetIndex].values.length == 0) throw "Dataset contains no columns.";
  var datasetAsObjectArray = [];
  for (var row = 1; row < this.sheets[sheetIndex].values[0].length; row++) {
    var rowObject = {};
    for (var column = 0; column < this.sheets[sheetIndex].values.length; column++) {
      rowObject[this.sheets[sheetIndex].values[column][0].attribute] = this.sheets[sheetIndex].values[column][row].value;
    }
    datasetAsObjectArray.push(rowObject);
  }
  return datasetAsObjectArray;
}

function formatDataset(inputData, mappings = {}, groupColumn = null, groupAttribute = null, innerArrayAttribute = null, keepAlreadyMappedColumns = false) {
  var datasetAsObjectArray = inputData;
  if (datasetAsObjectArray == null) datasetAsObjectArray = this.getDatasetAsObjectArray();
  var mappedData = [];
  var namesToMap = Object.getOwnPropertyNames(mappings);
  for (var i = 0; i < datasetAsObjectArray.length; i++) {
    var row = {};
    var mappedColumns = [];
    for (var j = 0; j < namesToMap.length; j++) {
      row[namesToMap[j]] = datasetAsObjectArray[i][mappings[namesToMap[j]]];
      mappedColumns.push(mappings[namesToMap[j]]);
    }
    var dataColumns = Object.getOwnPropertyNames(datasetAsObjectArray[i]);
    for (j = 0; j < dataColumns.length; j++) {
      if (keepAlreadyMappedColumns || mappedColumns.indexOf(dataColumns[j]) == -1) {
        row[dataColumns[j]] = datasetAsObjectArray[i][dataColumns[j]];
      }
    }
    mappedData.push(row);
  }

  if (groupColumn == null) {
    return mappedData;
  } else {
    var groups = {};
    for (var i = 0; i < mappedData.length; i++) {
      var groupName = mappedData[i][groupColumn];
      if (groups[groupName] == null) groups[groupName] = [];
      groups[groupName].push(mappedData[i]);
      delete mappedData[i][groupColumn];
    }
    var groupedData = [];
    var groupNames = Object.getOwnPropertyNames(groups);
    for (var i = 0; i < groupNames.length; i++) {
      var group = {};
      group[groupAttribute] = groupNames[i];
      group[innerArrayAttribute] = groups[groupNames[i]];
      groupedData.push(group);
    }
    return groupedData;
  }
}
</script>