diff --git a/SAS/ResourceAssignment/ResourceAssignmentEditor/lib/static/app/controllers/ganttprojectcontroller.js b/SAS/ResourceAssignment/ResourceAssignmentEditor/lib/static/app/controllers/ganttprojectcontroller.js index d0bd0eaadd16e3c31314fbb9b818a69e1deb540c..54a3890a5577fffc591afdf4c218d79886add294 100644 --- a/SAS/ResourceAssignment/ResourceAssignmentEditor/lib/static/app/controllers/ganttprojectcontroller.js +++ b/SAS/ResourceAssignment/ResourceAssignmentEditor/lib/static/app/controllers/ganttprojectcontroller.js @@ -126,9 +126,11 @@ ganttProjectControllerMod.controller('GanttProjectController', ['$scope', 'dataS var ganntRows = []; if(numProjecs > 0 && numTasks > 0) { - $scope.options.fromDate = $scope.dataService.viewTimeSpan.from; - $scope.options.toDate = $scope.dataService.viewTimeSpan.to; - var fullTimespanInMinutes = ($scope.options.toDate - $scope.options.fromDate) / (60 * 1000); + var lowerViewBound = $scope.dataService.viewTimeSpan.from; + var upperViewBound = $scope.dataService.viewTimeSpan.to; + $scope.options.fromDate = lowerViewBound; + $scope.options.toDate = upperViewBound; + var fullTimespanInMinutes = (upperViewBound - lowerViewBound) / (60 * 1000); if(fullTimespanInMinutes > 28*24*60) { $scope.options.viewScale = '7 days'; @@ -149,8 +151,77 @@ ganttProjectControllerMod.controller('GanttProjectController', ['$scope', 'dataS //only enable dependencies (arrows between tasks) in detailed view $scope.options.dependencies = (fullTimespanInMinutes <= 6*60) || numTasks < 20; - var editableTaskStatusIds = $scope.dataService.editableTaskStatusIds; + //start with aggregating all tasks per type, + //and plot these in the upper rows, + //so we can see the observartion and pipeline scheduling usage/efficiency + for(var type of ['observation', 'pipeline']) { + var typeTasks = tasks.filter(function(t) { return t.type == type;}).sort(function(a, b) { return a.starttime.getTime() - b.starttime.getTime(); });; + var numTypeTasks = typeTasks.length; + + if(numTypeTasks > 0) { + var typeAggregateRow = { + id: type + 's_aggregated', + name: ('All ' + type + 's').toUpperCase(), + tasks: [] + }; + ganntRows.push(typeAggregateRow); + + var task = typeTasks[0]; + + var rowTask = { + id: typeAggregateRow.id + '_task_' + typeAggregateRow.tasks.length, + from: task.starttime, + color: '#cceecc', + movable: false + }; + + if(rowTask.from < lowerViewBound) { + rowTask.from = lowerViewBound; + } + + for(var i = 1; i < numTypeTasks; i++) { + var prev_task = task; + task = typeTasks[i]; + + if(task.starttime > prev_task.endtime) { + rowTask.to = prev_task.endtime; + + if(rowTask.to > upperViewBound) { + rowTask.to = upperViewBound; + } + + typeAggregateRow.tasks.push(rowTask); + + rowTask = { + id: typeAggregateRow.id + '_task_' + typeAggregateRow.tasks.length, + from: task.starttime, + color: '#cceecc', + movable: false + }; + + if(rowTask.from < lowerViewBound) { + rowTask.from = lowerViewBound; + } + } + } + if(!rowTask.to) { + rowTask.to = task.endtime; + + if(rowTask.to > upperViewBound) { + rowTask.to = upperViewBound; + } + } + + typeAggregateRow.tasks.push(rowTask); + var aggTaskTotalDuration = 0.0 + typeAggregateRow.tasks.map(function(t) { return t.to - t.from;}).reduce(function(a, b) { return a+b; }); + var usage = aggTaskTotalDuration / (upperViewBound - lowerViewBound); + var usagePerc = parseFloat(Math.round(100.0 * usage * 10.0) / 10.0).toFixed(1); + typeAggregateRow.name += ' (' + usagePerc + '%)'; + } + } + + var editableTaskStatusIds = $scope.dataService.editableTaskStatusIds; var ganntRowsDict = {}; for(var i = 0; i < numTasks; i++) {