-
Jorrit Schaap authoredJorrit Schaap authored
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
gridcontroller.js 24.80 KiB
// $Id: controller.js 32761 2015-11-02 11:50:21Z schaap $
var gridControllerMod = angular.module('GridControllerMod', ['ui.grid',
'ui.grid.edit',
'ui.grid.selection',
'ui.grid.cellNav',
'ui.grid.resizeColumns',
'ui.grid.autoResize']);
gridControllerMod.controller('GridController', ['$scope', 'dataService', 'uiGridConstants', function($scope, dataService, uiGridConstants) {
$scope.dataService = dataService;
$scope.columns = [
{ field: 'name',
enableCellEdit: false,
width: '12%'
},
{ field: 'project_name',
displayName:'Project',
enableCellEdit: false,
cellTemplate:'<a target="_blank" href="https://lofar.astron.nl/mom3/user/project/setUpMom2ObjectDetails.do?view=generalinfo&mom2ObjectId={{row.entity.project_mom2object_id}}">{{row.entity[col.field]}}</a>',
width: '12%',
filter: {
type: uiGridConstants.filter.SELECT,
selectOptions: []
}
},
{ field: 'starttime',
displayName: 'Start',
width: '11%',
type: 'date',
enableCellEdit: false,
enableCellEditOnFocus: false,
cellTemplate:'<div style=\'text-align:left\'>{{row.entity[col.field] | date:\'yyyy-MM-dd HH:mm:ss\'}}</div>',
sort: { direction: uiGridConstants.ASC }
},
{ field: 'endtime',
displayName: 'End',
width: '11%',
type: 'date',
enableCellEdit: false,
enableCellEditOnFocus: false,
cellTemplate:'<div style=\'text-align:left\'>{{row.entity[col.field] | date:\'yyyy-MM-dd HH:mm:ss\'}}</div>'
},
{ field: 'duration',
displayName: 'Duration',
width: '6%',
type: 'number',
enableFiltering: false,
enableCellEdit: false,
enableCellEditOnFocus: false,
cellTemplate:'<div style=\'text-align:left\'>{{row.entity[col.field] | secondsToHHmmss}}</div>'
},
{ field: 'status',
enableCellEdit: true,
width: '6%',
filter: {
condition: uiGridConstants.filter.EXACT,
type: uiGridConstants.filter.SELECT,
selectOptions: []
},
editableCellTemplate: 'ui-grid/dropdownEditor',
editDropdownOptionsArray: [],
cellClass: function(grid, row, col, rowRenderIndex, colRenderIndex) {
var value = grid.getCellValue(row,col);
return "grid-status-" + value;
}
},
{ field: 'type',
enableCellEdit: false,
width: '6%',
filter: {
condition: uiGridConstants.filter.EXACT,
type: uiGridConstants.filter.SELECT,
selectOptions: []
}
},
{ field: 'mom_object_group_id',
displayName: 'Group',
enableCellEdit: false,
cellTemplate:'<a target="_blank" href="https://lofar.astron.nl/mom3/user/project/setUpMom2ObjectDetails.do?view=generalinfo&mom2ObjectId={{row.entity.mom_object_group_mom2object_id}}">{{row.entity.mom_object_group_id}} {{row.entity.mom_object_group_name}}</a>',
width: '12%',
filter: {
condition: uiGridConstants.filter.EXACT,
type: uiGridConstants.filter.SELECT,
selectOptions: []
}
},
{ field: 'mom_id',
displayName: 'MoM ID',
enableCellEdit: false,
cellTemplate:'<a target="_blank" href="https://lofar.astron.nl/mom3/user/project/setUpMom2ObjectDetails.do?view=generalinfo&mom2ObjectId={{row.entity.mom2object_id}}">{{row.entity[col.field]}}</a>',
width: '6%'
},
{ field: 'otdb_id',
displayName: 'SAS ID',
enableCellEdit: false,
width: '6%'
},
{ field: 'id',
displayName: 'RADB ID',
enableCellEdit: false,
cellTemplate:'<a target="_blank" href="tasks/{{row.entity.id}}.html">{{row.entity[col.field]}}</a>',
width: '6%'
},
{ field: 'cluster',
displayName: 'cluster',
enableCellEdit: false,
width: '6%',
filter: {
condition: uiGridConstants.filter.EXACT,
type: uiGridConstants.filter.SELECT,
selectOptions: []
},
cellClass: function(grid, row, col, rowRenderIndex, colRenderIndex) {
var value = grid.getCellValue(row,col);
return "grid-cluster-" + value;
}
}];
$scope.gridOptions = {
enableGridMenu: false,
enableSorting: true,
enableFiltering: true,
enableCellEdit: false,
enableColumnResize: true,
enableHorizontalScrollbar: uiGridConstants.scrollbars.NEVER,
enableRowSelection: true,
enableRowHeaderSelection: true,
enableFullRowSelection: false,
modifierKeysToMultiSelect: true,
multiSelect:true,
enableSelectionBatchEvent:false,
gridMenuShowHideColumns: false,
columnDefs: $scope.columns,
data: [],
// rowTemplate: "<div ng-repeat=\"(colRenderIndex, col) in colContainer.renderedColumns track by col.uid\" ui-grid-one-bind-id-grid=\"rowRenderIndex + '-' + col.uid + '-cell'\" class=\"ui-grid-cell\" ng-class=\"{ 'ui-grid-row-header-cell': col.isRowHeader }\" role=\"{{col.isRowHeader ? 'rowheader' : 'gridcell'}}\" ui-grid-cell></div>"
rowTemplate: "<div ng-repeat=\"(colRenderIndex, col) in colContainer.renderedColumns track by col.uid\" ui-grid-one-bind-id-grid=\"rowRenderIndex + '-' + col.uid + '-cell'\" class=\"ui-grid-cell\" ng-class=\"{ 'ui-grid-row-header-cell': col.isRowHeader }\" role=\"{{col.isRowHeader ? 'rowheader' : 'gridcell'}}\" ui-grid-cell context-menu>",
onRegisterApi: function(gridApi){
$scope.gridApi = gridApi;
$scope.gridApi.core.on.rowsRendered($scope, function() {
//on.rowsRendered is called whenever the data/filtering of the grid changed
//update the filteredTasks in the dataService from the resulting new grid rows
$scope.$evalAsync(function() {
var taskDict = $scope.dataService.taskDict;
$scope.dataService.filteredTasks = [];
var rows = $scope.gridApi.core.getVisibleRows(grid);
var numRows = rows.length;
for(var i = 0; i < numRows; i++) {
var row = rows[i];
if(row.visible)
{
var task_id = row.entity.id;
var task = taskDict[task_id];
if(task) {
$scope.dataService.filteredTasks.push(task);
}
row.setSelected($scope.dataService.selected_task_ids.indexOf(task_id) != -1);
}
}
$scope.dataService.filteredTaskDict = $scope.dataService.toIdBasedDict($scope.dataService.filteredTasks);
$scope.dataService.filteredTaskChangeCntr++;
if($scope.dataService.filteredTasks.length == 0) {
var otdb_col = $scope.gridApi.grid.columns.find(function(c) {return c.field == 'otdb_id'; });
if(otdb_col && otdb_col.filters.length && otdb_col.filters[0].hasOwnProperty('term')) {
var otdb_id = otdb_col.filters[0].term;
$scope.$parent.$parent.loadTaskByOTDBIdSelectAndJumpIntoView(otdb_id).then(function() {
otdb_col.filters[0].term = null;
});
} else {
var mom_col = $scope.gridApi.grid.columns.find(function(c) {return c.field == 'mom_id'; });
if(mom_col && mom_col.filters.length && mom_col.filters[0].hasOwnProperty('term')) {
var mom_id = mom_col.filters[0].term;
$scope.$parent.$parent.loadTaskByMoMIdSelectAndJumpIntoView(mom_id).then(function(task) {
if(task) {
mom_col.filters[0].term = null;
} else {
//getting the task by mom_id did not find a task
//maybe the entered id was a mom group_id?
//let's try to loadTasksByMoMGroupIdSelectAndJumpIntoView
$scope.$parent.$parent.loadTasksByMoMGroupIdSelectAndJumpIntoView(mom_id).then(function(tasks) {
mom_col.filters[0].term = null;
});
}
});
}
}
}
});
});
gridApi.edit.on.afterCellEdit($scope,function(rowEntity, colDef, newValue, oldValue){
var task = $scope.dataService.taskDict[rowEntity.id];
var newTask = { id: task.id, status: task.status };
$scope.dataService.putTask(newTask);
});
gridApi.selection.on.rowSelectionChanged($scope,function(row){
if(row.entity.id) {
if(row.isSelected) {
$scope.dataService.addSelectedTaskId(row.entity.id);
} else if(!row.isSelected) {
$scope.dataService.removeSelectedTaskId(row.entity.id);
}
}
});
}
};
function fillColumFilterSelectOptions(options, columnDef) {
var columnSelectOptions = [];
if(options) {
for(var i = 0; i < options.length; i++)
{
var option = options[i];
if(option.hasOwnProperty('value') && option.hasOwnProperty('label')) {
columnSelectOptions.push({ value: option.value, label: option.label })
}
else {
columnSelectOptions.push({ value: option, label: option })
}
}
}
columnDef.filter.selectOptions = columnSelectOptions;
};
function populateList() {
if('tasks' in $scope.dataService && $scope.dataService.tasks.length > 0) {
var viewFrom = $scope.dataService.viewTimeSpan.from;
var viewTo = $scope.dataService.viewTimeSpan.to;
$scope.dataService.filteredTasks = [];
var gridTasks = [];
for(var task of $scope.dataService.tasks) {
if(task.endtime >= viewFrom && task.starttime <= viewTo) {
$scope.dataService.filteredTasks.push(task);
var gridTask = {
id: task.id,
name: task.name,
project_name: task.project_name,
mom_id: task.mom_id,
otdb_id: task.otdb_id,
starttime: task.starttime,
endtime: task.endtime,
duration: task.duration,
status: task.status,
type: task.type,
project_mom2object_id: task.project_mom2object_id,
mom2object_id: task.mom2object_id,
mom_object_group_id: task.mom_object_group_id,
mom_object_group_name: task.mom_object_group_name,
mom_object_group_mom2object_id: task.mom_object_group_mom2object_id,
cluster: task.cluster
};
gridTasks.push(gridTask);
}
}
$scope.gridOptions.data = gridTasks;
} else
$scope.gridOptions.data = []
fillProjectsColumFilterSelectOptions()
fillGroupsColumFilterSelectOptions();
};
function jumpToSelectedTaskRows() {
var rowIndices = dataService.selected_task_ids.map(function(t_id) { return $scope.gridOptions.data.findIndex(function(row) {return row.id == t_id; } ); });
rowIndices = rowIndices.filter(function(idx) {return idx > -1;}).sort();
for(var rowIndex of rowIndices) {
$scope.gridApi.core.scrollTo($scope.gridOptions.data[rowIndex], null);
}
};
function onSelectedTaskIdsChanged() {
var selected_task_ids = $scope.dataService.selected_task_ids;
var rows = $scope.gridApi.grid.rows;
for(var row of rows) {
row.setSelected(selected_task_ids.indexOf(row.entity.id) != -1);
}
//find out if we have selected all tasks in a single mom group
var selected_tasks = $scope.dataService.selected_task_ids.map(function(t_id) { return $scope.dataService.taskDict[t_id]; }).filter(function(t) { return t != undefined;});
if(selected_tasks && selected_tasks.length > 1) {
var selected_task_group_ids = selected_tasks.map(function(t) { return t.mom_object_group_id; });
selected_task_group_ids = selected_task_group_ids.unique();
if(selected_task_group_ids.length == 1) {
//we have selected tasks in a single mom group
//find out if we have selected all tasks within this mom group
var mom_object_group_id = selected_task_group_ids[0];
var all_group_tasks = $scope.dataService.tasks.filter(function(t) { return t.mom_object_group_id == mom_object_group_id; });
if(all_group_tasks.length == selected_tasks.length) {
//we have selected all tasks in a single mom group
//apply filter on group column to see only tasks within this group
var group_col = $scope.gridApi.grid.columns.find(function(c) {return c.field == 'mom_object_group_id'; });
if(group_col) {
var mom_object_group_name = all_group_tasks[0].mom_object_group_name;
var label = mom_object_group_id + ' ' + mom_object_group_name;
var groupSelectOptions = [ { value: mom_object_group_id, label: label} ];
fillColumFilterSelectOptions(groupSelectOptions, $scope.columns[7]);
group_col.filters[0].term = mom_object_group_id;
}
}
}
}
$scope.$evalAsync(jumpToSelectedTaskRows);
};
$scope.$watch('dataService.taskChangeCntr', function() { $scope.$evalAsync(populateList); });
$scope.$watch('dataService.claimChangeCntr', function() { $scope.$evalAsync(populateList); });
$scope.$watch('dataService.viewTimeSpan', function() {
$scope.$evalAsync(populateList);
$scope.$evalAsync(jumpToSelectedTaskRows);
}, true);
$scope.$watch('dataService.filteredTaskChangeCntr', function() {
$scope.$evalAsync(function() {
fillStatusColumFilterSelectOptions();
fillTypeColumFilterSelectOptions();
fillProjectsColumFilterSelectOptions();
fillGroupsColumFilterSelectOptions();
});
});
$scope.$watch('dataService.initialLoadComplete', function() {
$scope.$evalAsync(function() {
fillStatusColumFilterSelectOptions();
fillTypeColumFilterSelectOptions();
fillProjectsColumFilterSelectOptions();
fillGroupsColumFilterSelectOptions();
fillColumFilterSelectOptions(['CEP2', 'CEP4'], $scope.columns[11]);
});
});
function fillProjectsColumFilterSelectOptions() {
var projectNames = [];
var momProjectsDict = $scope.dataService.momProjectsDict;
var tasks = $scope.dataService.filteredTasks;
var project_col = $scope.gridApi.grid.columns.find(function(c) {return c.field == 'project_name'; });
if(project_col && project_col.filters.length && project_col.filters[0].term) {
tasks = $scope.dataService.tasks;
}
//get unique projectIds from tasks
var task_project_ids = tasks.map(function(t) { return t.project_mom_id; });
task_project_ids = task_project_ids.unique();
for(var project_id of task_project_ids) {
if(momProjectsDict.hasOwnProperty(project_id)) {
var projectName = momProjectsDict[project_id].name;
if(!(projectName in projectNames)) {
projectNames.push(projectName);
}
}
}
projectNames.sort();
fillColumFilterSelectOptions(projectNames, $scope.columns[1]);
};
function fillStatusColumFilterSelectOptions() {
var tasks = $scope.dataService.filteredTasks;
var status_col = $scope.gridApi.grid.columns.find(function(c) {return c.field == 'status'; });
if(status_col && status_col.filters.length && status_col.filters[0].term) {
tasks = $scope.dataService.tasks;
}
//get unique statuses from tasks
var task_statuses = tasks.map(function(t) { return t.status; });
task_statuses = task_statuses.unique();
task_statuses.sort();
fillColumFilterSelectOptions(task_statuses, $scope.columns[5]);
};
function fillTypeColumFilterSelectOptions() {
var tasks = $scope.dataService.filteredTasks;
var type_col = $scope.gridApi.grid.columns.find(function(c) {return c.field == 'type'; });
if(type_col && type_col.filters.length && type_col.filters[0].term) {
tasks = $scope.dataService.tasks;
}
//get unique types from tasks
var task_types = tasks.map(function(t) { return t.type; });
task_types = task_types.unique();
task_types.sort();
fillColumFilterSelectOptions(task_types, $scope.columns[6]);
};
function fillGroupsColumFilterSelectOptions() {
if($scope.columns[7].filter.term) {
return;
}
var tasks = $scope.dataService.filteredTasks;
//get unique groupNames from tasks
var groupId2Name = {};
var groupIds = [];
for(var task of tasks) {
if(task.mom_object_group_id) {
if(!groupId2Name.hasOwnProperty(task.mom_object_group_id)) {
groupId2Name[task.mom_object_group_id] = task.mom_object_group_name;
groupIds.push(task.mom_object_group_id);
}
}
}
var groupSelectOptions = groupIds.map(function(gid) { return { value: gid, label: gid + ' ' + groupId2Name[gid]}; });
groupSelectOptions.sort(function(a,b) { return a.value - b.value; });
fillColumFilterSelectOptions(groupSelectOptions, $scope.columns[7]);
};
$scope.$watch('dataService.selected_task_ids', onSelectedTaskIdsChanged, true);}
]);
gridControllerMod.directive('contextMenu', ['$document', '$window', function($document, $window) {
return {
restrict: 'A',
scope: {
},
link: function($scope, $element, $attrs) {
function handleContextMenuEvent(event) {
//pragmatic 'hard-coded' way of getting the dataService and the rowEntity via scope tree.
var dataService = $scope.$parent.$parent.$parent.$parent.$parent.$parent.$parent.$parent.dataService;
var cleanupCtrl = $scope.$parent.$parent.$parent.$parent.$parent.$parent.$parent.$parent.$parent.cleanupCtrl;
var rowEntity = $scope.$parent.$parent.$parent.row.entity;
if(!dataService || !rowEntity)
return true;
var taskId = rowEntity.id;
var task = dataService.taskDict[taskId];
if(!task)
return true;
if(!dataService.isTaskIdSelected(taskId)) {
dataService.setSelectedTaskId(taskId);
}
var docElement = angular.element($document);
//search for already existing contextmenu element
while($document.find('#grid-context-menu').length) {
//found, remove it, so we can create a fresh one
$document.find('#grid-context-menu')[0].remove();
//unbind document close event handlers
docElement.unbind('click', closeContextMenu);
docElement.unbind('contextmenu', closeContextMenu);
}
//create contextmenu element
//with list of menu items,
//each with it's own action
var contextmenuElement = angular.element('<div id="grid-context-menu"></div>');
var ulElement = angular.element('<ul class="dropdown-menu" role="menu" style="left:' + event.clientX + 'px; top:' + event.clientY + 'px; z-index: 100000; display:block;"></ul>');
contextmenuElement.append(ulElement);
var selected_tasks = dataService.selected_task_ids.map(function(t_id) { return dataService.taskDict[t_id]; });
var selected_cep4_tasks = selected_tasks.filter(function(t) {
var task_claims = dataService.resourceClaims.filter(function(rc) { return rc.task_id == t.id;});
return task_claims.length > 0;
});
// var liElement = angular.element('<li><a href="#">Copy Task</a></li>');
// ulElement.append(liElement);
// liElement.on('click', function() {
// closeContextMenu();
// //TODO: remove link to dataService in this generic plugin
// dataService.copyTask(task);
// });
var liElement = angular.element('<li><a href="#">Select group</a></li>');
ulElement.append(liElement);
liElement.on('click', function() {
closeContextMenu();
var dataCtrlScope = $scope.$parent.$parent.$parent.$parent.$parent.$parent.$parent.$parent.$parent.$parent;
dataCtrlScope.loadTasksByMoMGroupIdSelectAndJumpIntoView(task.mom_object_group_id);
});
if(task.type == 'observation' && dataService.config.inspection_plots_base_url) {
var liElement = angular.element('<li><a href="#">Inspection Plots</a></li>');
ulElement.append(liElement);
liElement.on('click', function() {
closeContextMenu();
for(var t of selected_tasks) {
if(t) {
var url = dataService.config.inspection_plots_base_url + '/' + t.otdb_id;
$window.open(url, '_blank');
}
}
});
}
var liContent = selected_cep4_tasks.length == selected_tasks.length ? '<li><a href="#">Show disk usage</a></li>' : '<li><a href="#" style="color:#aaaaaa">Show disk usage</a></li>'
var liElement = angular.element(liContent);
ulElement.append(liElement);
if(selected_cep4_tasks.length == selected_tasks.length) {
liElement.on('click', function() {
closeContextMenu();
cleanupCtrl.showTaskDiskUsage(task);
});
}
var completed_selected_cep4_tasks = selected_cep4_tasks.filter(function(t) { return t.status == 'finished' || t.status == 'aborted'; });
var liContent = completed_selected_cep4_tasks.length == selected_tasks.length ? '<li><a href="#">Delete data</a></li>' : '<li><a href="#" style="color:#aaaaaa">Delete data</a></li>'
var liElement = angular.element(liContent);
ulElement.append(liElement);
if(completed_selected_cep4_tasks.length == selected_tasks.length) {
liElement.on('click', function() {
closeContextMenu();
cleanupCtrl.deleteSelectedTasksDataWithConfirmation();
});
}
var closeContextMenu = function(cme) {
contextmenuElement.remove();
//unbind document close event handlers
docElement.unbind('click', closeContextMenu);
docElement.unbind('contextmenu', closeContextMenu);
};
//click anywhere to remove the contextmenu
docElement.bind('click', closeContextMenu);
docElement.bind('contextmenu', closeContextMenu);
//add contextmenu to body
var body = $document.find('body');
body.append(contextmenuElement);
//prevent bubbling event upwards
return false;
}
$element.bind('contextmenu', handleContextMenuEvent);
$scope.$on('$destroy', function() {
$element.unbind('contextmenu', handleContextMenuEvent);
});
}
};
}]);