diff --git a/.gitattributes b/.gitattributes index 8da9e1b9ac3cd1c37f90a88a441cce8e225ec754..444a34e600bf8007460446644293d7196ec39179 100644 --- a/.gitattributes +++ b/.gitattributes @@ -4751,6 +4751,7 @@ SAS/ResourceAssignment/ResourceAssignmentEditor/lib/__init__.py -text SAS/ResourceAssignment/ResourceAssignmentEditor/lib/fakedata.py -text SAS/ResourceAssignment/ResourceAssignmentEditor/lib/static/app/app.js -text SAS/ResourceAssignment/ResourceAssignmentEditor/lib/static/app/controllers/datacontroller.js -text +SAS/ResourceAssignment/ResourceAssignmentEditor/lib/static/app/controllers/ganttcontroller.js -text SAS/ResourceAssignment/ResourceAssignmentEditor/lib/static/app/controllers/gridcontroller.js -text SAS/ResourceAssignment/ResourceAssignmentEditor/lib/static/css/bootstrap.min.css -text SAS/ResourceAssignment/ResourceAssignmentEditor/lib/static/css/main.css -text diff --git a/SAS/ResourceAssignment/ResourceAssignmentEditor/lib/fakedata.py b/SAS/ResourceAssignment/ResourceAssignmentEditor/lib/fakedata.py index 0ec3dfa2fdaad1239e42707d202a23ace2cb82f9..b7aa095810db0cca6408d4f424ec5cac53da4580 100644 --- a/SAS/ResourceAssignment/ResourceAssignmentEditor/lib/fakedata.py +++ b/SAS/ResourceAssignment/ResourceAssignmentEditor/lib/fakedata.py @@ -22,13 +22,13 @@ from datetime import datetime from datetime import timedelta -numProjects = 3 +numProjects = 5 numObsPerProject = 2 -numPipelinesPerObs = 2 +numPipelinesPerObs = 3 numCoreStations = 20 -numRemoteStations = 10 +numRemoteStations = 15 numCobaltNodes = 8 -numComputeNodes = 40 +numComputeNodes = 50 numIngestNodes = 4 _taskIdCntr = 0 @@ -65,9 +65,9 @@ resourceGroups = [] coreStationsGroup = {'id': 0, 'name': 'Core Stations', 'childGroupIds': [], 'resourceIds': []} remoteStationsGroup = {'id': 1, 'name': 'Remote Stations', 'childGroupIds': [], 'resourceIds': []} stationsGroup = {'id': 2, 'name': 'Stations', 'childGroupIds': [coreStationsGroup['id'], remoteStationsGroup['id']], 'resourceIds': []} -cobaltGroup = {'id': 3, 'name': 'CEP4 Nodes', 'childGroupIds': [], 'resourceIds': []} +cobaltGroup = {'id': 3, 'name': 'Cobalt', 'childGroupIds': [], 'resourceIds': []} cep4NodeGroup = {'id': 4, 'name': 'CEP4 Nodes', 'childGroupIds': [], 'resourceIds': []} -cep4StorageGroup = {'id': 5, 'name': 'CEP4 Storage', 'childGroupIds': [], 'resourceIds': []} +cep4StorageGroup = {'id': 5, 'name': 'Storage', 'childGroupIds': [], 'resourceIds': []} ingestGroup = {'id': 6, 'name': 'Ingest Nodes', 'childGroupIds': [], 'resourceIds': []} resourceGroups.append(coreStationsGroup) resourceGroups.append(remoteStationsGroup) @@ -116,7 +116,9 @@ computenodes = [r for r in resourceItems if r['typeId'] == 2] ingestnodes = [r for r in resourceItems if r['typeId'] == 3] resourceClaims = [] +resourceGroupClaims = [] for task in allTasks: + taskResourceGroupIds = set() taskResources = [] if task['type'] == 'Observation': taskResources = stations + correlators @@ -129,5 +131,12 @@ for task in allTasks: claim = {'id': len(resourceClaims), 'resourceId': resource['id'], 'taskId': task['id'], 'startTime': task['from'], 'endTime': task['to'], 'status': 'allocated'} resourceClaims.append(claim) - claim = {'id': len(resourceClaims), 'resourceId': cep4storage['id'], 'taskId': task['id'], 'startTime': task['from'], 'endTime': task['from'] + timedelta(days=3), 'status': 'allocated'} + groupIds = [rg['id'] for rg in resourceGroups if resource['id'] in rg['resourceIds']] + taskResourceGroupIds |= set(groupIds) + + claim = {'id': len(resourceClaims), 'resourceId': cep4storage['id'], 'taskId': task['id'], 'startTime': task['from'], 'endTime': task['from'] + timedelta(days=1), 'status': 'allocated'} resourceClaims.append(claim) + + for groupId in taskResourceGroupIds: + groupClaim = {'id': len(resourceGroupClaims), 'resourceGroupId': groupId, 'taskId': task['id'], 'startTime': task['from'], 'endTime': task['to'], 'status': 'allocated'} + resourceGroupClaims.append(groupClaim) diff --git a/SAS/ResourceAssignment/ResourceAssignmentEditor/lib/static/app/app.js b/SAS/ResourceAssignment/ResourceAssignmentEditor/lib/static/app/app.js index fb97d3c4cb367a41fd85708ad2e79fb68609db4e..20f4de822efc51a3ad6b3d457a72ef27bdaa1f26 100644 --- a/SAS/ResourceAssignment/ResourceAssignmentEditor/lib/static/app/app.js +++ b/SAS/ResourceAssignment/ResourceAssignmentEditor/lib/static/app/app.js @@ -1,11 +1,7 @@ // $Id$ var app = angular.module('raeApp', - ['ngTouch', - 'gantt', - 'gantt.table', - 'gantt.movable', - 'gantt.tooltips', - 'DataControllerMod', + ['DataControllerMod', + 'GanttControllerMod', 'GridControllerMod']); diff --git a/SAS/ResourceAssignment/ResourceAssignmentEditor/lib/static/app/controllers/datacontroller.js b/SAS/ResourceAssignment/ResourceAssignmentEditor/lib/static/app/controllers/datacontroller.js index af369285de7b5e1ab239a4fdc41dea2a9462f10b..63247e47743da243e6acbe75edd77a9f31260154 100644 --- a/SAS/ResourceAssignment/ResourceAssignmentEditor/lib/static/app/controllers/datacontroller.js +++ b/SAS/ResourceAssignment/ResourceAssignmentEditor/lib/static/app/controllers/datacontroller.js @@ -4,13 +4,18 @@ angular.module('raeApp').factory("dataService", function(){ var self = this; self.tasks = []; self.resources = []; - self.resourceclaims = []; + self.resourceGroups = []; + self.resourceClaims = []; + self.resourceGroupClaims = []; self.tasktypes = []; self.taskstatustypes = []; self.taskDict = {}; self.resourceDict = {}; - self.resourceclaimDict = {}; + self.resourceGroupsDict = {}; + self.resourceClaimDict = {}; + self.resourceGroupClaimDict = {}; + self.resourceIdToGroupIdsDict = {}; self.resourcesWithClaims = []; @@ -34,6 +39,29 @@ dataControllerMod.controller('DataController', return dict; }; + function mapResourcesToGroups() { + var dict = {} + var resources = self.dataService.resources; + var resourceGroups = self.dataService.resourceGroups; + + if(resources.length > 0) { + for(var i = resources.length-1; i >=0; i--) + dict[resources[i].id] = [] + + for(var i = resourceGroups.length-1; i >=0; i--) { + var group = resourceGroups[i]; + var childResourceIds = group.resourceIds; + + for(var j = childResourceIds.length-1; j >=0; j--) { + var childResourceId = childResourceIds[j]; + dict[childResourceId].push(group.id); + } + } + } + + self.dataService.resourceIdToGroupIdsDict = dict; + }; + function getTasks() { $http.get('/rest/tasks').success(function(result) { self.dataService.tasks = result.tasks; @@ -45,17 +73,29 @@ dataControllerMod.controller('DataController', $http.get('/rest/resourceitems').success(function(result) { self.dataService.resources = result.resourceitems; self.dataService.resourceDict = toIdBasedDict(self.dataService.resources); - - setTimeout(groupResourceClaims(), 10); + mapResourcesToGroups(); }); }; function getResourceClaims() { $http.get('/rest/resourceclaims').success(function(result) { - self.dataService.resourceclaims = result.resourceclaims; - self.dataService.resourceclaimDict = toIdBasedDict(self.dataService.resourceclaims); + self.dataService.resourceClaims = result.resourceclaims; + self.dataService.resourceClaimDict = toIdBasedDict(self.dataService.resourceClaims); + }); + }; - setTimeout(groupResourceClaims(), 10); + function getResourceGroups() { + $http.get('/rest/resourcegroups').success(function(result) { + self.dataService.resourceGroups = result.resourcegroups; + self.dataService.resourceGroupsDict = toIdBasedDict(self.dataService.resourceGroups); + mapResourcesToGroups(); + }); + }; + + function getResourceGroupClaims() { + $http.get('/rest/resourcegroupclaims').success(function(result) { + self.dataService.resourceGroupClaims = result.resourcegroupclaims; + self.dataService.resourceGroupClaimDict = toIdBasedDict(self.dataService.resourceGroupClaims); }); }; @@ -71,46 +111,11 @@ dataControllerMod.controller('DataController', }); }; - function groupResourceClaims() { - var grouped = {}; - var resources = self.dataService.resources; - - for(var i = resources.length-1; i >=0; i--) - { - var resource = resources[i]; - grouped[resource.id] = { - 'id': resource.id, - 'name': resource.name, - 'tasks': [] - }; - } - - setTimeout(function() { - var resourceclaims = self.dataService.resourceclaims; - for(var i = resourceclaims.length-1; i >=0; i--) - { - var claim = resourceclaims[i]; - var task = self.dataService.taskDict[claim.taskId]; - - var row = grouped[claim.resourceId]; - row.tasks.push({ - name: task ? task.name : '<unknown>', - 'from': claim.startTime, - 'to': claim.endTime - }); - } - var groupedArray = []; - - for (var groupId in grouped) - groupedArray.push(grouped[groupId]); - - self.dataService.resourcesWithClaims = groupedArray; - }, 10); - }; - getTasks(); getTaskTypes(); getTaskStatusTypes(); + getResourceGroups(); + getResourceGroupClaims(); getResources(); getResourceClaims(); } diff --git a/SAS/ResourceAssignment/ResourceAssignmentEditor/lib/static/app/controllers/ganttcontroller.js b/SAS/ResourceAssignment/ResourceAssignmentEditor/lib/static/app/controllers/ganttcontroller.js new file mode 100644 index 0000000000000000000000000000000000000000..3e8f84409b1bca8bc89b04d1f29a2a711448d128 --- /dev/null +++ b/SAS/ResourceAssignment/ResourceAssignmentEditor/lib/static/app/controllers/ganttcontroller.js @@ -0,0 +1,182 @@ +// $Id: ganttcontroller.js 32761 2015-11-02 11:50:21Z schaap $ + +var ganttControllerMod = angular.module('GanttControllerMod', [ + 'gantt', + 'gantt.sortable', + 'gantt.movable', + 'gantt.drawtask', + 'gantt.tooltips', + 'gantt.bounds', + 'gantt.progress', + 'gantt.table', + 'gantt.tree', + 'gantt.groups', + 'gantt.overlap', + 'gantt.resizeSensor']).config(['$compileProvider', function($compileProvider) { + $compileProvider.debugInfoEnabled(false); // Remove debug info (angularJS >= 1.3) +}]); + +ganttControllerMod.controller('GanttController', ['$scope', 'dataService', function($scope, dataService) { + + $scope.dataService = dataService; + $scope.ganttData = [] + + $scope.options = { + mode: 'custom', + scale: 'day', + sideMode: 'Tree', + columns: ['model.name', 'from', 'to'], + treeTableColumns: ['from', 'to'], + columnsHeaders: {'model.name' : 'Name', 'from': 'From', 'to': 'To'}, + columnsClasses: {'model.name' : 'gantt-column-name', 'from': 'gantt-column-from', 'to': 'gantt-column-to'}, + columnsFormatters: { + 'from': function(from) { + return from !== undefined ? from.format('lll') : undefined; + }, + 'to': function(to) { + return to !== undefined ? to.format('lll') : undefined; + } + }, + treeHeaderContent: '<i class="fa fa-align-justify"></i> {{getHeader()}}', + columnsHeaderContents: { + 'model.name': '<i class="fa fa-align-justify"></i> {{getHeader()}}', + 'from': '<i class="fa fa-calendar"></i> {{getHeader()}}', + 'to': '<i class="fa fa-calendar"></i> {{getHeader()}}' + }, + autoExpand: 'both', + api: function(api) { + // API Object is used to control methods and events from angular-gantt. + $scope.api = api; + } + }; + + function updateGanttData() { + var ganntRowsDict = {}; + + var resourceGroups = $scope.dataService.resourceGroups; + var numResourceGroups = resourceGroups.length; + + var resourceIdToGroupIdsDict = $scope.dataService.resourceIdToGroupIdsDict; + var resources = $scope.dataService.resources; + var numResources = resources.length; + + var resourceGroupsDict = $scope.dataService.resourceGroupsDict; + var taskDict = $scope.dataService.taskDict; + + var resourceGroupClaims = $scope.dataService.resourceGroupClaims; + var numResourceGroupClaims = resourceGroupClaims.length; + + var resourceClaims = $scope.dataService.resourceClaims; + var numResourceClaims = resourceClaims.length; + + var resourceDict = $scope.dataService.resourceDict; + + //create rows in gantt for resourceGroups + for(var i = 0; i < numResourceGroups; i++) + { + var resourceGroup = resourceGroups[i]; + var groupRowId = 'group_' + resourceGroup.id; + ganntRowsDict[groupRowId] = { + 'id': groupRowId, + 'name': resourceGroup.name, + 'tasks': [] + }; + } + + //create rows in gantt for resources + //add each resource row to all group rows of which group it is a member + for(var i = 0; i < numResources; i++) + { + var resource = resources[i]; + var groupIds = resourceIdToGroupIdsDict[resource.id]; + var numGroups = groupIds.length; + + if(numGroups > 0) { + for(var j = 0; j < numGroups; j++) { + var parentRowId = 'group_' + groupIds[j]; + var resourceRowId = 'group_' + groupIds[j] + '_resource_' + resource.id; + //make resource row child of group row + ganntRowsDict[resourceRowId] = { + 'id': resourceRowId, + 'parent': parentRowId, + 'name': resource.name, + 'tasks': [] + }; + } + } + else + { + //no parent groups, so one individual row + var resourceRowId = 'resource_' + resource.id; + ganntRowsDict[resourceRowId] = { + 'id': resourceRowId, + 'name': resource.name, + 'tasks': [] + }; + } + } + + //now that we have all rows for the gantt... + //assign each groupclaim to its resourcegroup + for(var i = 0; i < numResourceGroupClaims; i++) { + var groupClaim = resourceGroupClaims[i]; + var task = taskDict[groupClaim.taskId]; + + var groupClaimTask = { + name: task ? task.name : '<unknown>', + 'from': groupClaim.startTime, + 'to': groupClaim.endTime + }; + + var groupRowId = 'group_' + groupClaim.resourceGroupId; + var ganntGroupRow = ganntRowsDict[groupRowId]; + if(ganntGroupRow) + ganntGroupRow.tasks.push(groupClaimTask); + } + + //and assign each resourceclaim to its resource in each group + for(var i = 0; i < numResourceClaims; i++) { + var claim = resourceClaims[i]; + var task = taskDict[claim.taskId]; + + var groupIds = resourceIdToGroupIdsDict[claim.resourceId]; + var numGroups = groupIds.length; + + var claimTask = { + name: task ? task.name : '<unknown>', + 'from': claim.startTime, + 'to': claim.endTime + }; + + if(numGroups > 0) { + for(var j = 0; j < numGroups; j++) { + var resourceRowId = 'group_' + groupIds[j] + '_resource_' + claim.resourceId; + var ganntRow = ganntRowsDict[resourceRowId]; + if(ganntRow) + ganntRow.tasks.push(claimTask); + } + } + else { + var resourceRowId = 'resource_' + claim.resourceId; + var ganntRow = ganntRowsDict[resourceRowId]; + if(ganntRow) + ganntRow.tasks.push(claimTask); + } + } + + var ganntRows = []; + + for (var groupId in ganntRowsDict) + ganntRows.push(ganntRowsDict[groupId]); + + $scope.ganttData = ganntRows; + setTimeout($scope.api.tree.collapseAll(), 10) + }; + + $scope.$watch('dataService.tasks', updateGanttData); + $scope.$watch('dataService.resources', updateGanttData); + $scope.$watch('dataService.resourceclaims', updateGanttData); + $scope.$watch('dataService.resourceGroups', updateGanttData); + $scope.$watch('dataService.resourceGroupClaims', updateGanttData); +} +]); diff --git a/SAS/ResourceAssignment/ResourceAssignmentEditor/lib/templates/index.html b/SAS/ResourceAssignment/ResourceAssignmentEditor/lib/templates/index.html index 8cc3c4c4177610da3a259deeea20fc62ed77bf0a..8e4ddb2541ae0d421626c8de6995e0674ab810b9 100644 --- a/SAS/ResourceAssignment/ResourceAssignmentEditor/lib/templates/index.html +++ b/SAS/ResourceAssignment/ResourceAssignmentEditor/lib/templates/index.html @@ -5,14 +5,15 @@ <meta http-equiv='Content-Type' content='text/html; charset=utf-8'/> <title>{{title}}</title> <link rel='shortcut icon' href='{{ url_for('static', filename='favicon.ico') }}'> - <link href="/static/css/main.css" rel="stylesheet" type="text/css"> <link href="/static/css/bootstrap.min.css" rel="stylesheet" type="text/css"> + <link href="/static/css/main.css" rel="stylesheet" type="text/css"> <link href="/static/js/angular-ui-grid/ui-grid.min.css" rel="stylesheet" type="text/css"> <script src="/static/js/angular/angular.js"></script> <script src="/static/js/angular-route/angular-route.min.js"></script> <script src="/static/js/angular-touch/angular-touch.js"></script> <script src="/static/js/angular-resource/angular-resource.min.js"></script> <script src="/static/js/angular-ui-grid/ui-grid.js"></script> + <script src="/static/js/angular-ui-tree/angular-ui-tree.js"></script> <script src="/static/js/moment/moment.js"></script> <script src="/static/js/angular-moment/angular-moment.js"></script> <link href="/static/js/angular-gantt/angular-gantt.min.css" rel="stylesheet" type="text/css"> @@ -22,21 +23,27 @@ <script src="/static/app/app.js"></script> <script src="/static/app/controllers/datacontroller.js"></script> <script src="/static/app/controllers/gridcontroller.js"></script> + <script src="/static/app/controllers/ganttcontroller.js"></script> </head> <body> {% raw %} - <div ng-controller="GridController as gridCtrl"> - <strong>Tasks:</strong> - <div id="grid1" ui-grid="gridOptions" ui-grid-move-columns class="myGrid"></div> - </div> - <br/> - <br/> - <br/> <div ng-controller="DataController as dataCtrl"> - <div gantt "{ data= dataCtrl.dataService.resourcesWithClaims }" > - <gantt-table></gantt-table> - <gantt-movable></gantt-movable> - <gantt-tooltips></gantt-tooltips> + <div ng-controller="GridController as gridCtrl"> + <strong>Tasks:</strong> + <div id="grid1" ui-grid="gridOptions" ui-grid-move-columns class="myGrid"></div> + </div> + <br/> + <br/> + <br/> + <div ng-controller="GanttController as ganttCtrl"> + <div gantt data=ganttData + api=options.api + show-side='true'> + <gantt-tree enabled="true"></gantt-tree> +<!-- <gantt-table></gantt-table> --> + <gantt-movable></gantt-movable> + <gantt-tooltips></gantt-tooltips> + </div> </div> </div> {% endraw %} diff --git a/SAS/ResourceAssignment/ResourceAssignmentEditor/lib/webservice.py b/SAS/ResourceAssignment/ResourceAssignmentEditor/lib/webservice.py index 16b297a9a8a47f252b56a7657882466bfa9e55fc..7f4be997c823f5b5548a2c60275ed8138ac17749 100755 --- a/SAS/ResourceAssignment/ResourceAssignmentEditor/lib/webservice.py +++ b/SAS/ResourceAssignment/ResourceAssignmentEditor/lib/webservice.py @@ -73,6 +73,12 @@ def resourcegroups(): @gzipped def resourceclaims(): data = {'resourceclaims': resourceClaims} + return jsonify(data) + +@app.route('/rest/resourcegroupclaims') +@gzipped +def resourcegroupclaims(): + data = {'resourcegroupclaims': resourceGroupClaims} return jsonify(data)