(function (angular) {
'use strict';
/**
* @memberof spApp
* @ngdoc controller
* @name WorkflowCtrl
* @description
*/
angular.module('workflow-ctrl', [])
.controller('WorkflowCtrl', ['$scope', 'MapService', '$timeout', 'LayoutService', '$uibModalInstance',
'BiocacheService', '$http', 'LayersService', 'LoggerService', 'WorkflowService', '$q', 'EventService',
'data',
function ($scope, MapService, $timeout, LayoutService, $uibModalInstance, BiocacheService, $http,
LayersService, LoggerService, WorkflowService, $q, EventService, config) {
// During playback and editing the current dialog may close. Keep track of playback and edit position.
$scope.playStep = -1;
$scope.editing = -1;
// Workflow can generate layers. Layers mapped are used to offset the workflow self-referencial layerUid
$scope.layerUidOffset = MapService.getNextUid() - 1
$scope.speciesLayerId = -1; //$scope.getSpeciesLayer()
if (config && config.speciesLayerId) {
$scope.speciesLayerId = config.speciesLayerId
}
$scope.areaLayerId = -1; //$scope.getAreaLayer()
$scope.workflow = []
$scope.workflowProperties = {name: '', private: true, workflow: $scope.workflow}
$scope.speciesLayers = $.merge([{name: 'none', uid: -1}], MapService.speciesLayers())
$scope.areaLayers = $.merge([{name: 'none', uid: -1}], MapService.areaLayers())
$scope.workflows = []
$scope.sortType = 'created'
$scope.sortReverse = true
LayoutService.addToSave($scope);
$scope.loadWorkflow = function (id) {
if (id === undefined) {
// load current workflow
while ($scope.workflow.length > 0) $scope.workflow.pop();
$.map(LoggerService.localHistory(), function (v) {
if (v.category1 != 'Create' ||
v.category2 == 'scatterplotCreateInOut' ||
v.category2 == 'adhocCreateInOut' ||
v.category2 == 'facetNewLayer' ||
v.category2 == 'facetNewLayerOut') {
$scope.workflow.push(v)
}
})
WorkflowService.initDescriptions($scope.workflowProperties.workflow)
$scope.workflowProperties.name = $i18n(459, "My workflow") + " " + new Date().toLocaleString()
} else {
WorkflowService.get(id).then(function (response) {
while ($scope.workflow.length > 0) $scope.workflow.pop();
var items = JSON.parse(response.data.metadata)
$.map(items, function (i) {
$scope.workflow.push(i)
})
$scope.workflowProperties.name = response.data.name
$scope.workflowId = id
$scope.workflowProperties.id = id
$scope.workflowProperties.created = response.data.created
$scope.workflowProperties.private = response.data.isPrivate
WorkflowService.initDescriptions($scope.workflowProperties.workflow)
})
}
}
$scope.deleteWorkflow = function (id) {
WorkflowService.delete(id).then(function (response) {
for (var i = 0; i < $scope.workflows.length; i++) {
if ($scope.workflows[i].id == id) {
$scope.workflows.splice(i, 1)
}
}
})
}
$scope.getSpeciesLayer = function () {
// get selected layer
var layer = MapService.selectedLayer()
var layerId
if (layer.type !== 'species') {
$.each($scope.speciesLayers, function (l) {
// get topmost layer
if (layerId === undefined || layerId < l.uid) {
layerId = l.uid;
}
})
} else {
layerId = layer.uid
}
return layerId
}
$scope.getAreaLayer = function () {
// get selected layer
var layer = MapService.selectedLayer()
var layerId
if (layer.type !== 'area') {
$.each($scope.areaLayers, function (l) {
// get topmost layer
if (layerId === undefined || layerId < l.uid) {
layerId = l.uid;
}
})
} else {
layerId = layer.uid
}
return layerId
}
$scope.setLayerUid = function (item, newId) {
if (item instanceof Array) {
$.each(item, function (idx, i) {
$scope.setLayerUid(i, newId)
}
)
} else if (item instanceof Object) {
$.each(item, function (idx, i) {
if (idx === 'layerId') {
item[idx] = newId
} else {
$scope.setLayerUid(i, newId)
}
}
)
}
}
$scope.offsetLayerUid = function (item) {
if (item instanceof Array) {
$.each(item, function (idx, i) {
$scope.offsetLayerUid(i)
}
)
} else if (item instanceof Object) {
$.each(item, function (idx, i) {
if (idx === 'layerId') {
var newId = $scope.layerUidOffset + item[idx]
while (newId >= 0 && MapService.getFullLayer(newId) == null) {
$scope.layerUidOffset--
newId = $scope.layerUidOffset + item[idx]
}
item[idx] = $scope.layerUidOffset + item[idx]
} else {
$scope.offsetLayerUid(item[idx])
}
}
)
}
}
$scope.dataToOverrideValues = function (item) {
var input = []
$.map(item.data, function (v, k) {
input[k] = {constraints: {default: v}}
})
var ov = {};
ov[item.category2] = {input: input}
return ov;
}
$scope.edit = function (item) {
$scope.play(item, true);
}
$scope.play = function (item, editOnly) {
var stage = editOnly ? 'edit' : 'execute'
$scope.processData = {}
if (item.speciesLayerId >= 0) {
$scope.setLayerUid(item.data, item.speciesLayerId)
} else if ($scope.speciesLayerId >= 0) {
$scope.setLayerUid(item.data, $scope.speciesLayerId)
} else {
$scope.offsetLayerUid(item.data)
}
// All executions produce a promise, unless workflowCtrl is closed at the end of the step.
var promises = []
if ($scope.isTool(item)) {
// Execute tool. This will close workflowCtrl and reopen to continue after the tool is finished.
var processData = {
processName: item.category2,
stage: stage,
overrideValues: $scope.dataToOverrideValues(item)
};
$timeout(function () {
LayoutService.openModal('tool', processData, true)
}, 0)
} else if ($scope.isMap(item)) {
// Add to map.
if ("WMS" == item.category2) {
promises.push(MapService.add(item.data))
} else if ("Area" == item.category2) {
promises.push(MapService.mapFromPid(item.data))
}
} else if ($scope.isView(item)) {
if ("tabulation" == item.category2) {
LayoutService.openModal('tabulate', item.data, true)
} else if ("speciesInfo" == item.category2) {
var layer = MapService.getFullLayer(item.data.layerId)
LayoutService.openModal('speciesInfo', layer, true)
} else if ("timeSeriesPlayback" == item.category2) {
var layer = MapService.getFullLayer(item.data.layerId)
layer.playback = {
yearStepSize: item.data.yearStepSize,
monthStepSize: item.data.monthStepSize,
timeout: item.data.timeout,
type: item.data.type,
play: true,
pause: false,
stop: false
}
// time series playback is initiated by changing the selected layer
MapService.select(undefined)
$timeout(function () {
MapService.select(layer)
}, 0)
} else if (LayoutService.isPanel(item.category2)) {
LayoutService.openPanel(item.category2, item.data, true)
} else {
// Open view. This will close workflowCtrl and reopen to continue after the view is closed.
LayoutService.openModal(item.category2, item.data, true)
}
} else if ($scope.isCreate(item)) {
promises.push(EventService.execute(item.category2, item.data))
}
if (promises.length > 0) {
return $q.all(promises).then(function () {
return true
})
} else {
return $q.when(true).then(function () {
return false
})
}
}
$scope.playback = function () {
if ($scope.playStep < 0) {
$scope.playStep = 0;
}
if ($scope.workflow.length <= $scope.playStep) {
$timeout(function () {
$scope.$close()
}, 0)
} else {
$scope.play($scope.workflow[$scope.playStep]).then(function (loop) {
$scope.playStep++;
if (loop) {
$scope.playback();
} else {
$timeout(function () {
$scope.$close()
}, 0)
}
})
}
}
$scope.isTool = function (item) {
return item.category1 === 'Tool'
}
$scope.isMap = function (item) {
return item.category1 === 'Map'
}
$scope.isView = function (item) {
return item.category1 === 'View'
}
$scope.isCreate = function (item) {
return item.category1 === 'Create'
}
$scope.setWorkflow = function (workflow) {
$scope.workflow = workflow
}
$scope.makeModeless = function () {
$('.modal').addClass('modeless');
$('.modal-dialog').draggable({
handle: ".modal-header"
});
$('.modal-content').resizable({
minHeight: 180,
minWidth: 350
});
$('.modal-content').on("resize", function () {
$('.modal-body').height($('.modal-dialog').height() - $('.modal-header').outerHeight() - $('.modal-footer').outerHeight() - ($('.modal-body').outerHeight() - $('.modal-body').height()))
}).trigger('resize');
};
$scope.save = function () {
return WorkflowService.save($scope.workflowProperties.name, !$scope.workflowProperties.private, $scope.workflow).then(function (response) {
bootbox.alert('<h3>' + $i18n("Workflow Saved") + '</h3>')
$scope.$close()
});
}
$scope.back = function () {
$scope.workflow = []
$scope.playStep = 0
}
$scope.toDate = function (str) {
if (str == null) {
return ''
} else {
var date = new Date(str)
return date
}
}
$scope.makeModeless()
if (config && config.workflowId) {
$scope.loadWorkflow(config.workflowId)
} else {
if ($scope.workflows.length == 0) {
WorkflowService.search('', 0, 5000).then(function (response) {
$scope.workflows = $.merge([{name: 'Current session'}], response.data)
})
}
}
// restore playback step
if ($scope.playStep >= 0) {
$scope.playback();
}
// apply edit change
if ($scope.editing >= 0) {
$scope.workflow[$scope.editing].data = $scope.processData.inputs;
$scope.editing = -1;
}
}])
}(angular));