From d82d48453f0b31e565ad4f8a9e074ff327e15d45 Mon Sep 17 00:00:00 2001 From: Timur Sufiev Date: Mon, 13 Jul 2015 13:29:27 +0300 Subject: [PATCH] Add Mistral js files to linter and fix linting errors As a consequence, change how the workbookCtrl controller is used (and unit-tests for it). Change-Id: I21514ac01baa81c5a760abd9e7d0f909d89617d6 --- .../mistral/static/mistral/js/mistral.init.js | 17 +- .../js/mistral.workbook.controllers.js | 141 +- .../mistral/js/mistral.workbook.models.js | 1155 +++++++++-------- .../mistral/templates/mistral/create.html | 34 +- .../test/js/workbook.controller.spec.js | 32 +- package.json | 2 +- 6 files changed, 697 insertions(+), 684 deletions(-) diff --git a/extensions/mistral/static/mistral/js/mistral.init.js b/extensions/mistral/static/mistral/js/mistral.init.js index 6f7b864..3e06ddf 100644 --- a/extensions/mistral/static/mistral/js/mistral.init.js +++ b/extensions/mistral/static/mistral/js/mistral.init.js @@ -4,10 +4,15 @@ (function() { 'use strict'; - angular.module('mistral', ['merlin']) - .run(['merlin.templates', function(templates) { - templates.prefetch('/static/mistral/templates/fields/', - ['varlist', 'yaqllist']); - }]) + angular + .module('mistral', ['merlin']) + .run(initModule); -})(); \ No newline at end of file + initModule.$inject = ['merlin.templates']; + + function initModule(templates) { + templates.prefetch('/static/mistral/templates/fields/', + ['varlist', 'yaqllist']); + } + +})(); diff --git a/extensions/mistral/static/mistral/js/mistral.workbook.controllers.js b/extensions/mistral/static/mistral/js/mistral.workbook.controllers.js index 77d15e9..f4830dd 100644 --- a/extensions/mistral/static/mistral/js/mistral.workbook.controllers.js +++ b/extensions/mistral/static/mistral/js/mistral.workbook.controllers.js @@ -4,82 +4,87 @@ (function() { 'use strict'; - angular.module('mistral') + angular + .module('mistral') .value('baseActionID', 'action') .value('baseWorkflowID', 'workflow') - .controller('workbookCtrl', - ['$scope', 'mistral.workbook.models', '$http', - 'baseActionID', 'baseWorkflowID', - function($scope, models, $http, baseActionId, baseWorkflowId) { - $scope.init = function(id, yaml, commitUrl, discardUrl) { - $scope.workbookID = id; - $scope.commitUrl = commitUrl; - $scope.discardUrl = discardUrl; - if ( id !== undefined ) { - $scope.workbook = models.Workbook.create(jsyaml.safeLoad(yaml)); - } else { - $scope.workbook = models.Workbook.create({name: 'My Workbook'}); - } - $scope.root = models.Root.create(); - $scope.root.set('workbook', $scope.workbook); + .controller('WorkbookController', WorkbookController); - $scope.root.set('standardActions', { - 'nova.create_server': ['image', 'flavor', 'network_id'], - 'neutron.create_network': ['name', 'create_subnet'], - 'glance.create_image': ['image_url'] - }); - }; + WorkbookController.$inject = ['mistral.workbook.models', '$http', + '$window', 'baseActionID', 'baseWorkflowID']; - function getNextIDSuffix(container, regexp) { - var max = Math.max.apply(Math, container.getIDs().map(function(id) { - var match = regexp.exec(id); - return match && +match[2]; - })); - return max > 0 ? max + 1 : 1; - } + function WorkbookController(models, $http, $window, + baseActionId, baseWorkflowId) { + var vm = this; + vm.init = function(id, yaml, commitUrl, discardUrl) { + vm.workbookID = id; + vm.commitUrl = commitUrl; + vm.discardUrl = discardUrl; + if (angular.isDefined(id)) { + vm.workbook = models.Workbook.create(jsyaml.safeLoad(yaml)); + } else { + vm.workbook = models.Workbook.create({name: 'My Workbook'}); + } + vm.root = models.Root.create(); + vm.root.set('workbook', vm.workbook); - function getWorkbookNextIDSuffix(base) { - var containerName = base + 's', - regexp = /(workflow|action)([0-9]+)/, - container = $scope.workbook.get(containerName); - if ( !container ) { - throw 'Base should be either "action" or "workflow"!'; - } - return getNextIDSuffix(container, regexp); - } + vm.root.set('standardActions', { + 'nova.create_server': ['image', 'flavor', 'network_id'], + 'neutron.create_network': ['name', 'create_subnet'], + 'glance.create_image': ['image_url'] + }); + }; - $scope.addAction = function() { - var nextSuffix = getWorkbookNextIDSuffix(baseActionId), - newID = baseActionId + nextSuffix; - $scope.workbook.get('actions').push( - {name: 'Action ' + nextSuffix}, {id: newID}); - }; + function getNextIDSuffix(container, regexp) { + var max = Math.max.apply(Math, container.getIDs().map(function(id) { + var match = regexp.exec(id); + return match && +match[2]; + })); + return max > 0 ? max + 1 : 1; + } - $scope.addWorkflow = function() { - var nextSuffix = getWorkbookNextIDSuffix(baseWorkflowId), - newID = baseWorkflowId + nextSuffix; - $scope.workbook.get('workflows').push( - {name: 'Workflow ' + nextSuffix}, {id: newID}); - }; + function getWorkbookNextIDSuffix(base) { + var containerName = base + 's'; + var regexp = /(workflow|action)([0-9]+)/; + var container = vm.workbook.get(containerName); + if ( !container ) { + throw new Error('Base should be either "action" or "workflow"!'); + } + return getNextIDSuffix(container, regexp); + } - $scope.commitWorkbook = function() { - var data = { - name: $scope.workbook.get('name').get(), - yaml: $scope.workbook.toYAML() - }; + vm.addAction = function() { + var nextSuffix = getWorkbookNextIDSuffix(baseActionId); + var newID = baseActionId + nextSuffix; + vm.workbook.get('actions').push( + {name: 'Action ' + nextSuffix}, {id: newID}); + }; - $http({ - url: $scope.commitUrl, - method: 'POST', - data: data - }).success(function(data, status, headers, config) { - document.location = $scope.discardUrl; - }); - }; + vm.addWorkflow = function() { + var nextSuffix = getWorkbookNextIDSuffix(baseWorkflowId); + var newID = baseWorkflowId + nextSuffix; + vm.workbook.get('workflows').push( + {name: 'Workflow ' + nextSuffix}, {id: newID}); + }; - $scope.discardWorkbook = function() { - document.location = $scope.discardUrl; - }; + vm.commitWorkbook = function() { + var data = { + name: vm.workbook.get('name').get(), + yaml: vm.workbook.toYAML() + }; - }]) -})(); \ No newline at end of file + $http({ + url: vm.commitUrl, + method: 'POST', + data: data + }).success(function() { + $window.location.href = vm.discardUrl; + }); + }; + + vm.discardWorkbook = function() { + $window.location.href = vm.discardUrl; + }; + + } +})(); diff --git a/extensions/mistral/static/mistral/js/mistral.workbook.models.js b/extensions/mistral/static/mistral/js/mistral.workbook.models.js index 9a95df7..cad9f40 100644 --- a/extensions/mistral/static/mistral/js/mistral.workbook.models.js +++ b/extensions/mistral/static/mistral/js/mistral.workbook.models.js @@ -4,659 +4,662 @@ (function() { 'use strict'; - angular.module('mistral') - .factory('mistral.workbook.models', - ['merlin.field.models', 'merlin.panel.models', 'merlin.utils', '$http', '$q', - function(fields, panel, utils, $http, $q) { - var models = {}; + angular + .module('mistral') + .factory('mistral.workbook.models', ModelsService); - function varlistValueFactory(json, parameters) { - var type = Barricade.getType(json); - if ( json === undefined || type === String ) { - return fields.string.create(json, parameters); - } else if ( type === Array ) { - return fields.list.extend({}, { - '*': {'@class': fields.string} - }).create(json, parameters); - } else if ( type === Object ) { - return fields.dictionary.extend({}, { - '?': {'@class': fields.string} - }).create(json, parameters); - } - } + ModelsService.$inject = ['merlin.field.models', 'merlin.utils']; - models.varlist = fields.list.extend({ - create: function(json, parameters) { - var self = fields.list.create.call(this, json, parameters); - self.setType('varlist'); - self.on('childChange', function(child, op) { - if ( op == 'empty' ) { - self.each(function(index, item) { - if ( child === item ) { - self.remove(index); - } - }) + function ModelsService(fields, utils) { + var models = {}; + + function varlistValueFactory(json, parameters) { + var type = Barricade.getType(json); + if ( angular.isUndefined(json) || type === String ) { + return fields.string.create(json, parameters); + } else if ( type === Array ) { + return fields.list.extend({}, { + '*': {'@class': fields.string} + }).create(json, parameters); + } else if ( type === Object ) { + return fields.dictionary.extend({}, { + '?': {'@class': fields.string} + }).create(json, parameters); + } + } + + models.varlist = fields.list.extend({ + create: function(json, parameters) { + var self = fields.list.create.call(this, json, parameters); + self.setType('varlist'); + self.on('childChange', function(child, op) { + if ( op == 'empty' ) { + self.each(function(index, item) { + if ( child === item ) { + self.remove(index); } }); - return self; - } - }, { - '*': { - '@class': fields.frozendict.extend({ - create: function(json, parameters) { - var self = fields.frozendict.create.call(this, json, parameters); - self.on('childChange', function(child) { - if ( child.instanceof(Barricade.Enumerated) ) { // type change - var value = self.get('value'); - switch ( child.get() ) { - case 'string': - self.set('value', varlistValueFactory('')); - break; - case 'list': - self.set('value', varlistValueFactory([''])); - break; - case 'dictionary': - self.set('value', varlistValueFactory({'key1': ''})); - break; - } - } else if ( child.instanceof(Barricade.Arraylike) && !child.length() ) { - self.emit('change', 'empty'); - } - }); - return self; - }, - _getPrettyJSON: function() { - var json = fields.frozendict._getPrettyJSON.apply(this, arguments); - return json.value; - } - }, { - 'type': { - '@class': fields.string.extend({}, { - '@enum': ['string', 'list', 'dictionary'], - '@default': 'string' - }) - }, - 'value': { - '@class': fields.wildcard, - '@factory': varlistValueFactory - } - }) } }); - - models.yaqllist = fields.list.extend({ + return self; + } + }, { + '*': { + '@class': fields.frozendict.extend({ create: function(json, parameters) { - var self = fields.list.create.call(this, json, parameters); - self.setType('yaqllist'); - return self; - } - }, { - '*': { - '@class': fields.frozendict.extend({}, { - 'yaql': { - '@class': fields.string - }, - 'action': { - '@class': fields.string - } - }) - } - }); - - models.Action = fields.frozendict.extend({ - create: function(json, parameters) { - var self = fields.frozendict.create.call(this, json, parameters), - base = self.get('base'); - base.on('change', function(operation) { - var argsEntry, pos, entry; - if ( operation != 'id' ) { - pos = base._collection.getPosByID(base.get()); - if ( pos > -1 ) { - entry = self.get('base-input'); - argsEntry = base._collection.get(pos); - entry.resetKeys(argsEntry.toJSON()); + var self = fields.frozendict.create.call(this, json, parameters); + self.on('childChange', function(child) { + if ( child.instanceof(Barricade.Enumerated) ) { // type change + var value = self.get('value'); + switch ( child.get() ) { + case 'string': + self.set('value', varlistValueFactory('')); + break; + case 'list': + self.set('value', varlistValueFactory([''])); + break; + case 'dictionary': + self.set('value', varlistValueFactory({'key1': ''})); + break; } + } else if ( child.instanceof(Barricade.Arraylike) && !child.length() ) { + self.emit('change', 'empty'); } }); return self; + }, + _getPrettyJSON: function() { + var json = fields.frozendict._getPrettyJSON.apply(this, arguments); + return json.value; } }, { - 'base': { - '@class': fields.linkedcollection.extend({ - create: function(json, parameters) { - parameters = Object.create(parameters); - parameters.toCls = models.StandardActions; - parameters.neededCls = models.Root; - parameters.substitutedEntryID = 'standardActions'; - return fields.linkedcollection.create.call(this, json, parameters); - } - }, { + 'type': { + '@class': fields.string.extend({}, { + '@enum': ['string', 'list', 'dictionary'], + '@default': 'string' + }) + }, + 'value': { + '@class': fields.wildcard, + '@factory': varlistValueFactory + } + }) + } + }); + + models.yaqllist = fields.list.extend({ + create: function(json, parameters) { + var self = fields.list.create.call(this, json, parameters); + self.setType('yaqllist'); + return self; + } + }, { + '*': { + '@class': fields.frozendict.extend({}, { + 'yaql': { + '@class': fields.string + }, + 'action': { + '@class': fields.string + } + }) + } + }); + + models.Action = fields.frozendict.extend({ + create: function(json, parameters) { + var self = fields.frozendict.create.call(this, json, parameters); + var base = self.get('base'); + base.on('change', function(operation) { + var argsEntry, pos, entry; + if ( operation != 'id' ) { + pos = base._collection.getPosByID(base.get()); + if ( pos > -1 ) { + entry = self.get('base-input'); + argsEntry = base._collection.get(pos); + entry.resetKeys(argsEntry.toJSON()); + } + } + }); + return self; + } + }, { + 'base': { + '@class': fields.linkedcollection.extend({ + create: function(json, parameters) { + parameters = Object.create(parameters); + parameters.toCls = models.StandardActions; + parameters.neededCls = models.Root; + parameters.substitutedEntryID = 'standardActions'; + return fields.linkedcollection.create.call(this, json, parameters); + } + }, { + '@meta': { + 'index': 1, + 'row': 0 + } + }) + }, + 'base-input': { + '@class': fields.dictionary.extend({ + create: function(json, parameters) { + var self = fields.dictionary.create.call(this, json, parameters); + self.setType('frozendict'); + return self; + } + }, { + '@required': false, + '?': { + '@class': fields.string.extend({}, { '@meta': { - 'index': 1, 'row': 0 } }) }, - 'base-input': { - '@class': fields.dictionary.extend({ - create: function(json, parameters) { - var self = fields.dictionary.create.call(this, json, parameters); - self.setType('frozendict'); - return self; - } - }, { - '@required': false, - '?': { - '@class': fields.string.extend({}, { - '@meta': { - 'row': 0 - } - }) - }, - '@meta': { - 'index': 2, - 'title': 'Base Input' - } - }) + '@meta': { + 'index': 2, + 'title': 'Base Input' + } + }) + }, + 'input': { + '@class': fields.list.extend({}, { + '@meta': { + 'index': 3 }, - 'input': { - '@class': fields.list.extend({}, { - '@meta': { - 'index': 3 - }, - '*': {'@class': fields.string} - }) - }, - 'output': { - '@class': models.varlist.extend({}, { - '@meta': { - 'index': 4 - } - }) + '*': {'@class': fields.string} + }) + }, + 'output': { + '@class': models.varlist.extend({}, { + '@meta': { + 'index': 4 + } + }) + } + }); + + models.Task = fields.frozendict.extend({ + create: function(json, parameters) { + var self = fields.frozendict.create.call(this, json, parameters); + self.on('childChange', function(child, op) { + if ( child === self.get('type') && op !== 'id' ) { + self.emit('change', 'taskType'); } }); - - models.Task = fields.frozendict.extend({ - create: function(json, parameters) { - var self = fields.frozendict.create.call(this, json, parameters); - self.on('childChange', function(child, op) { - if ( child === self.get('type') && op !== 'id' ) { - self.emit('change', 'taskType'); - } - }); - return self; + return self; + }, + remove: function() { + this.emit('change', 'taskRemove', this.getID()); + }, + _getPrettyJSON: function() { + var json = fields.frozendict._getPrettyJSON.apply(this, arguments); + delete json.type; + return json; + } + }, { + '@meta': { + 'baseKey': 'task', + 'baseName': 'Task ', + 'group': true, + 'additive': false, + 'removable': true + }, + 'type': { + '@class': fields.string.extend({}, { + '@enum': [{ + value: 'action', label: 'Action-based' + }, { + value: 'workflow', label: 'Workflow-based' + }], + '@default': 'action', + '@meta': { + 'index': 0, + 'row': 0 + } + }) + }, + 'description': { + '@class': fields.text.extend({}, { + '@meta': { + 'index': 2, + 'row': 1 + } + }) + }, + 'input': { + '@class': fields.dictionary.extend({}, { + '@meta': { + 'index': 4 }, - remove: function() { - this.emit('change', 'taskRemove', this.getID()); + '?': { + '@class': fields.string + } + }) + }, + 'publish': { + '@class': fields.dictionary.extend({}, { + '@meta': { + 'index': 5 }, + '?': { + '@class': fields.string + } + }) + }, + 'policies': { + '@class': fields.frozendict.extend({ _getPrettyJSON: function() { var json = fields.frozendict._getPrettyJSON.apply(this, arguments); - delete json.type; + json.retry = { + count: utils.pop(json, 'retry-count'), + delay: utils.pop(json, 'retry-delay'), + 'break-on': utils.pop(json, 'retry-break-on') + }; return json; } }, { '@meta': { - 'baseKey': 'task', - 'baseName': 'Task ', - 'group': true, - 'additive': false, - 'removable': true + 'index': 9 }, - 'type': { - '@class': fields.string.extend({}, { - '@enum': [{ - value: 'action', label: 'Action-based' - }, { - value: 'workflow', label: 'Workflow-based' - }], - '@default': 'action', + '@required': false, + 'wait-before': { + '@class': fields.number.extend({}, { + '@required': false, '@meta': { 'index': 0, - 'row': 0 + 'row': 0, + 'title': 'Wait before' } }) }, - 'description': { - '@class': fields.text.extend({}, { + 'wait-after': { + '@class': fields.number.extend({}, { + '@required': false, + '@meta': { + 'index': 1, + 'row': 0, + 'title': 'Wait after' + } + }) + }, + 'timeout': { + '@class': fields.number.extend({}, { + '@required': false, '@meta': { 'index': 2, 'row': 1 } }) }, - 'input': { - '@class': fields.dictionary.extend({}, { - '@meta': { - 'index': 4 - }, - '?': { - '@class': fields.string - } - }) - }, - 'publish': { - '@class': fields.dictionary.extend({}, { - '@meta': { - 'index': 5 - }, - '?': { - '@class': fields.string - } - }) - }, - 'policies': { - '@class': fields.frozendict.extend({ - _getPrettyJSON: function() { - var json = fields.frozendict._getPrettyJSON.apply(this, arguments); - json.retry = { - count: utils.pop(json, 'retry-count'), - delay: utils.pop(json, 'retry-delay'), - 'break-on': utils.pop(json, 'retry-break-on') - }; - return json; - } - }, { - '@meta': { - 'index': 9 - }, + 'retry-count': { + '@class': fields.number.extend({}, { '@required': false, - 'wait-before': { - '@class': fields.number.extend({}, { - '@required': false, - '@meta': { - 'index': 0, - 'row': 0, - 'title': 'Wait before' - } - }) - }, - 'wait-after': { - '@class': fields.number.extend({}, { - '@required': false, - '@meta': { - 'index': 1, - 'row': 0, - 'title': 'Wait after' - } - }) - }, - 'timeout': { - '@class': fields.number.extend({}, { - '@required': false, - '@meta': { - 'index': 2, - 'row': 1 - } - }) - }, - 'retry-count': { - '@class': fields.number.extend({}, { - '@required': false, - '@meta': { - 'index': 3, - 'row': 2, - 'title': 'Retry count' - } - }) - }, - 'retry-delay': { - '@class': fields.number.extend({}, { - '@required': false, - '@meta': { - 'index': 4, - 'row': 2, - 'title': 'Retry delay' - } - }) - }, - 'retry-break-on': { - '@class': fields.number.extend({}, { - '@required': false, - '@meta': { - 'index': 5, - 'row': 3, - 'title': 'Retry break on' - } - }) - } - }) - } - }); - - models.ReverseWFTask = models.Task.extend({}, { - 'requires': { - '@class': fields.string.extend({}, { '@meta': { + 'index': 3, 'row': 2, - 'index': 3 + 'title': 'Retry count' + } + }) + }, + 'retry-delay': { + '@class': fields.number.extend({}, { + '@required': false, + '@meta': { + 'index': 4, + 'row': 2, + 'title': 'Retry delay' + } + }) + }, + 'retry-break-on': { + '@class': fields.number.extend({}, { + '@required': false, + '@meta': { + 'index': 5, + 'row': 3, + 'title': 'Retry break on' } }) } - }); + }) + } + }); - models.DirectWFTask = models.Task.extend({}, { + models.ReverseWFTask = models.Task.extend({}, { + 'requires': { + '@class': fields.string.extend({}, { + '@meta': { + 'row': 2, + 'index': 3 + } + }) + } + }); + + models.DirectWFTask = models.Task.extend({}, { + 'on-error': { + '@class': fields.list.extend({}, { + '@meta': { + 'title': 'On error', + 'index': 6 + }, + '*': { + '@class': fields.string + } + }) + }, + 'on-success': { + '@class': fields.list.extend({}, { + '@meta': { + 'title': 'On success', + 'index': 7 + }, + '*': { + '@class': fields.string + } + }) + }, + 'on-complete': { + '@class': fields.list.extend({}, { + '@meta': { + 'title': 'On complete', + 'index': 8 + }, + '*': { + '@class': fields.string + } + }) + } + }); + + models.ActionTaskMixin = Barricade.Blueprint.create(function() { + return this.extend({}, { + 'action': { + '@class': fields.linkedcollection.extend({ + create: function(json, parameters) { + parameters = Object.create(parameters); + parameters.toCls = models.Actions; + parameters.neededCls = models.Workbook; + parameters.substitutedEntryID = 'actions'; + return fields.linkedcollection.create.call(this, json, parameters); + } + }, { + '@meta': { + 'row': 0, + 'index': 1 + } + }) + } + }); + }); + + models.WorkflowTaskMixin = Barricade.Blueprint.create(function() { + return this.extend({}, { + 'workflow': { + '@class': fields.linkedcollection.extend({ + create: function(json, parameters) { + parameters = Object.create(parameters); + parameters.toCls = models.Workflows; + parameters.neededCls = models.Workbook; + parameters.substitutedEntryID = 'workflows'; + return fields.linkedcollection.create.call(this, json, parameters); + } + }, { + '@meta': { + 'row': 0, + 'index': 1 + } + }) + } + }); + }); + + var taskTypes = { + 'direct': models.DirectWFTask, + 'reverse': models.ReverseWFTask, + 'action': models.ActionTaskMixin, + 'workflow': models.WorkflowTaskMixin + }; + + function TaskFactory(json, parameters) { + var type = json.type || 'action'; + var baseClass = taskTypes[parameters.wfType]; + var mixinClass = taskTypes[type]; + var taskClass = mixinClass.call(baseClass); + return taskClass.create(json, parameters); + } + + models.Workflow = fields.frozendict.extend({ + create: function(json, parameters) { + var self = fields.frozendict.create.call(this, json, parameters); + self.on('childChange', function(child, op) { + if ( child === self.get('type') && op !== 'id' ) { + self.emit('change', 'workflowType'); + } + }); + return self; + } + }, { + 'type': { + '@class': fields.string.extend({}, { + '@enum': ['reverse', 'direct'], + '@default': 'direct', + '@meta': { + 'index': 1, + 'row': 0 + } + }) + }, + 'input': { + '@class': fields.list.extend({}, { + '@required': false, + '@meta': { + 'index': 2 + }, + '*': { + '@class': fields.string + } + }) + }, + 'output': { + '@class': fields.list.extend({}, { + '@required': false, + '@meta': { + 'index': 3 + }, + '*': { + '@class': fields.string + } + }) + }, + 'tasks': { + '@class': fields.dictionary.extend({ + create: function(json, parameters) { + var self = fields.dictionary.create.call(this, json, parameters); + self.on('childChange', function(child, op, arg) { + if ( op === 'taskType' ) { + var taskId = child.getID(); + var params = child._parameters; + var taskPos = self.getPosByID(taskId); + var taskData = child.toJSON(); + params.id = taskId; + self.set(taskPos, TaskFactory(taskData, params)); + } else if ( op === 'taskRemove' ) { + self.removeItem(arg); + } + }); + return self; + } + }, { + '@meta': { + 'index': 5, + 'group': true + }, + '?': { + '@class': models.Task, + '@factory': TaskFactory + } + }) + } + + }); + + models.ReverseWorkflow = models.Workflow.extend({}); + models.DirectWorkflow = models.Workflow.extend({}, { + 'task-defaults': { + '@class': fields.frozendict.extend({}, { + '@required': false, + '@meta': { + 'index': 4, + 'group': true, + 'additive': false + }, 'on-error': { - '@class': fields.list.extend({}, { + '@class': models.yaqllist.extend({}, { '@meta': { 'title': 'On error', - 'index': 6 - }, - '*': { - '@class': fields.string + 'index': 0 } }) }, 'on-success': { - '@class': fields.list.extend({}, { + '@class': models.yaqllist.extend({}, { '@meta': { 'title': 'On success', - 'index': 7 - }, - '*': { - '@class': fields.string + 'index': 1 } }) }, 'on-complete': { - '@class': fields.list.extend({}, { + '@class': models.yaqllist.extend({}, { '@meta': { 'title': 'On complete', - 'index': 8 - }, - '*': { - '@class': fields.string - } - }) - } - }); - - models.ActionTaskMixin = Barricade.Blueprint.create(function() { - return this.extend({}, { - 'action': { - '@class': fields.linkedcollection.extend({ - create: function(json, parameters) { - parameters = Object.create(parameters); - parameters.toCls = models.Actions; - parameters.neededCls = models.Workbook; - parameters.substitutedEntryID = 'actions'; - return fields.linkedcollection.create.call(this, json, parameters); - } - }, { - '@meta': { - 'row': 0, - 'index': 1 - } - }) - } - }) - }); - - models.WorkflowTaskMixin = Barricade.Blueprint.create(function() { - return this.extend({}, { - 'workflow': { - '@class': fields.linkedcollection.extend({ - create: function(json, parameters) { - parameters = Object.create(parameters); - parameters.toCls = models.Workflows; - parameters.neededCls = models.Workbook; - parameters.substitutedEntryID = 'workflows'; - return fields.linkedcollection.create.call(this, json, parameters); - } - }, { - '@meta': { - 'row': 0, - 'index': 1 - } - }) - } - }); - }); - - var taskTypes = { - 'direct': models.DirectWFTask, - 'reverse': models.ReverseWFTask, - 'action': models.ActionTaskMixin, - 'workflow': models.WorkflowTaskMixin - }; - - function TaskFactory(json, parameters) { - var type = json.type || 'action', - baseClass = taskTypes[parameters.wfType], - mixinClass = taskTypes[type], - taskClass = mixinClass.call(baseClass); - return taskClass.create(json, parameters); - } - - models.Workflow = fields.frozendict.extend({ - create: function(json, parameters) { - var self = fields.frozendict.create.call(this, json, parameters); - self.on('childChange', function(child, op) { - if ( child === self.get('type') && op !== 'id' ) { - self.emit('change', 'workflowType'); - } - }); - return self; - } - }, { - 'type': { - '@class': fields.string.extend({}, { - '@enum': ['reverse', 'direct'], - '@default': 'direct', - '@meta': { - 'index': 1, - 'row': 0 - } - }) - }, - 'input': { - '@class': fields.list.extend({}, { - '@required': false, - '@meta': { 'index': 2 - }, - '*': { - '@class': fields.string - } - }) - }, - 'output': { - '@class': fields.list.extend({}, { - '@required': false, - '@meta': { - 'index': 3 - }, - '*': { - '@class': fields.string - } - }) - }, - 'tasks': { - '@class': fields.dictionary.extend({ - create: function(json, parameters) { - var self = fields.dictionary.create.call(this, json, parameters); - self.on('childChange', function(child, op, arg) { - if ( op === 'taskType' ) { - var taskId = child.getID(), - params = child._parameters, - taskPos = self.getPosByID(taskId), - taskData = child.toJSON(); - params.id = taskId; - self.set(taskPos, TaskFactory(taskData, params)); - } else if ( op === 'taskRemove' ) { - self.removeItem(arg); - } - }); - return self; - } - }, { - '@meta': { - 'index': 5, - 'group': true - }, - '?': { - '@class': models.Task, - '@factory': TaskFactory } }) } + }) + } + }); - }); + var workflowTypes = { + 'direct': models.DirectWorkflow, + 'reverse': models.ReverseWorkflow + }; - models.ReverseWorkflow = models.Workflow.extend({}); - models.DirectWorkflow = models.Workflow.extend({}, { - 'task-defaults': { - '@class': fields.frozendict.extend({}, { - '@required': false, - '@meta': { - 'index': 4, - 'group': true, - 'additive': false - }, - 'on-error': { - '@class': models.yaqllist.extend({}, { - '@meta': { - 'title': 'On error', - 'index': 0 - } - }) - }, - 'on-success': { - '@class': models.yaqllist.extend({}, { - '@meta': { - 'title': 'On success', - 'index': 1 - } - }) - }, - 'on-complete': { - '@class': models.yaqllist.extend({}, { - '@meta': { - 'title': 'On complete', - 'index': 2 - } - }) - } - }) + function workflowFactory(json, parameters) { + var type = json.type || 'direct'; + parameters.wfType = type; + return workflowTypes[type].create(json, parameters); + } + + models.Actions = fields.dictionary.extend({}, { + '@required': false, + '@meta': { + 'index': 3, + 'panelIndex': 1 + }, + '?': { + '@class': models.Action + } + }); + + models.Workflows = fields.dictionary.extend({ + create: function(json, parameters) { + var self = fields.dictionary.create.call(this, json, parameters); + self.on('childChange', function(child, op) { + if ( op === 'workflowType' ) { + var workflowId = child.getID(); + var workflowPos = self.getPosByID(workflowId); + var params = child._parameters; + var workflowData = child.toJSON(); + params.wfType = child.type; + params.id = workflowId; + self.set(workflowPos, workflowFactory(workflowData, params)); } }); + return self; + } + }, { + '@meta': { + 'index': 4, + 'panelIndex': 2 + }, + '?': { + '@class': models.Workflow, + '@factory': workflowFactory + } + }); - var workflowTypes = { - 'direct': models.DirectWorkflow, - 'reverse': models.ReverseWorkflow - }; - - function workflowFactory(json, parameters) { - var type = json.type || 'direct'; - parameters.wfType = type; - return workflowTypes[type].create(json, parameters); - } - - models.Actions = fields.dictionary.extend({}, { - '@required': false, + models.Workbook = fields.frozendict.extend({ + toYAML: function() { + return jsyaml.dump(this.toJSON({pretty: true})); + } + }, { + 'version': { + '@class': fields.string.extend({}, { + '@enum': ['2.0'], '@meta': { - 'index': 3, - 'panelIndex': 1 + 'index': 2, + 'panelIndex': 0, + 'row': 1 }, - '?': { - '@class': models.Action - } - }); - - models.Workflows = fields.dictionary.extend({ - create: function(json, parameters) { - var self = fields.dictionary.create.call(this, json, parameters); - self.on('childChange', function(child, op) { - if ( op === 'workflowType' ) { - var workflowId = child.getID(), - workflowPos = self.getPosByID(workflowId), - params = child._parameters, - workflowData = child.toJSON(); - params.wfType = child.type; - params.id = workflowId; - self.set(workflowPos, workflowFactory(workflowData, params)); - } - }); - return self; - } - }, { + '@default': '2.0' + }) + }, + 'name': { + '@class': fields.string.extend({}, { '@meta': { - 'index': 4, - 'panelIndex': 2 + 'index': 0, + 'panelIndex': 0, + 'row': 0 }, - '?': { - '@class': models.Workflow, - '@factory': workflowFactory - } - }); - - models.Workbook = fields.frozendict.extend({ - toYAML: function() { - return jsyaml.dump(this.toJSON({pretty: true})); - } - }, { - 'version': { - '@class': fields.string.extend({}, { - '@enum': ['2.0'], - '@meta': { - 'index': 2, - 'panelIndex': 0, - 'row': 1 - }, - '@default': '2.0' - }) - }, - 'name': { - '@class': fields.string.extend({}, { - '@meta': { - 'index': 0, - 'panelIndex': 0, - 'row': 0 - }, - '@constraints': [ - function(value) { - return value !== 'workbook1' ? true : 'The sample validation failure.'; - } - ] - }) - }, - 'description': { - '@class': fields.text.extend({}, { - '@meta': { - 'index': 1, - 'panelIndex': 0, - 'row': 0 - }, - '@required': false - }) - }, - 'actions': { - '@class': models.Actions - }, - 'workflows': { - '@class': models.Workflows - } - }); - - models.StandardActions = Barricade.create({ - '@type': Object, - '?': { - '@type': Array, - '*': { - '@type': String + '@constraints': [ + function(value) { + return value !== 'workbook1' ? true : 'The sample validation failure.'; } - } - }); - - models.Root = Barricade.ImmutableObject.extend({}, { - '@type': Object, - 'standardActions': { - '@class': models.StandardActions + ] + }) + }, + 'description': { + '@class': fields.text.extend({}, { + '@meta': { + 'index': 1, + 'panelIndex': 0, + 'row': 0 }, - 'workbook': { - '@class': models.Workbook - } - }); + '@required': false + }) + }, + 'actions': { + '@class': models.Actions + }, + 'workflows': { + '@class': models.Workflows + } + }); - return models; - }]) + models.StandardActions = Barricade.create({ + '@type': Object, + '?': { + '@type': Array, + '*': { + '@type': String + } + } + }); + + models.Root = Barricade.ImmutableObject.extend({}, { + '@type': Object, + 'standardActions': { + '@class': models.StandardActions + }, + 'workbook': { + '@class': models.Workbook + } + }); + + return models; + } })(); diff --git a/extensions/mistral/templates/mistral/create.html b/extensions/mistral/templates/mistral/create.html index 430d208..27be743 100644 --- a/extensions/mistral/templates/mistral/create.html +++ b/extensions/mistral/templates/mistral/create.html @@ -38,34 +38,36 @@ {% block main %}

Create Workbook

-
+
-

{$ workbook.get('name') $}

+

{$ wb.workbook.get('name') $}

- - + +
- - + +
-
@@ -81,10 +83,10 @@
-
-
{$ workbook.toYAML() $}
+
+
{$ wb.workbook.toYAML() $}
-
+
Here will be a fancy Graph View as soon as we implement it!
@@ -94,9 +96,9 @@
- - +
diff --git a/extensions/mistral/test/js/workbook.controller.spec.js b/extensions/mistral/test/js/workbook.controller.spec.js index 92317fb..c2ce5ee 100644 --- a/extensions/mistral/test/js/workbook.controller.spec.js +++ b/extensions/mistral/test/js/workbook.controller.spec.js @@ -27,24 +27,22 @@ describe('together workbook model and controller', function() { describe('define top-level actions available to user:', function () { - var $scope; + var wbCtrl; beforeEach(inject(function (_$controller_) { - var $controller = _$controller_; - $scope = {}; - $controller('workbookCtrl', {$scope: $scope}); - $scope.workbook = workbook; + wbCtrl = _$controller_('WorkbookController', {}); + wbCtrl.workbook = workbook; })); describe("'Add Action' action", function () { it('adds a new Action', function () { - $scope.addAction(); + wbCtrl.addAction(); expect(workbook.get('actions').get(0)).toBeDefined(); }); it('creates action with predefined name', function () { - $scope.addAction(); + wbCtrl.addAction(); expect(workbook.get('actions').get(0).getID()).toBeGreaterThan(''); }); @@ -56,7 +54,7 @@ describe('together workbook model and controller', function() { })); it("corresponding JSON has the right key for the Action", function () { - $scope.addAction(); + wbCtrl.addAction(); expect(workbook.toJSON({pretty: true}).actions[actionID]).toBeDefined(); }); @@ -64,7 +62,7 @@ describe('together workbook model and controller', function() { it("once the Action ID is changed, it's reflected in JSON", function () { var newID = 'action10'; - $scope.addAction(); + wbCtrl.addAction(); workbook.get('actions').getByID(actionID).setID(newID); expect(workbook.toJSON({pretty: true}).actions[actionID]).toBeUndefined(); @@ -74,8 +72,8 @@ describe('together workbook model and controller', function() { }); it('creates actions with different names on 2 successive calls', function () { - $scope.addAction(); - $scope.addAction(); + wbCtrl.addAction(); + wbCtrl.addAction(); expect(workbook.get('actions').get(0).getID()).not.toEqual( workbook.get('actions').get(1).getID()) @@ -84,7 +82,7 @@ describe('together workbook model and controller', function() { describe("'Add Workflow' action", function () { it('adds a new Workflow', function () { - $scope.addWorkflow(); + wbCtrl.addWorkflow(); expect(workbook.get('workflows').get(0)).toBeDefined(); }); @@ -96,7 +94,7 @@ describe('together workbook model and controller', function() { })); it("corresponding JSON has the right key for the Workflow", function () { - $scope.addWorkflow(); + wbCtrl.addWorkflow(); expect(workbook.toJSON({pretty: true}).workflows[workflowID]).toBeDefined(); }); @@ -104,7 +102,7 @@ describe('together workbook model and controller', function() { it("once the workflow ID is changed, it's reflected in JSON", function () { var newID = 'workflow10'; - $scope.addWorkflow(); + wbCtrl.addWorkflow(); workbook.get('workflows').getByID(workflowID).setID(newID); expect(workbook.toJSON({pretty: true}).workflows[workflowID]).toBeUndefined(); @@ -114,14 +112,14 @@ describe('together workbook model and controller', function() { }); it('creates workflow with predefined name', function () { - $scope.addWorkflow(); + wbCtrl.addWorkflow(); expect(workbook.get('workflows').get(0).getID()).toBeGreaterThan(''); }); it('creates workflows with different names on 2 successive calls', function () { - $scope.addWorkflow(); - $scope.addWorkflow(); + wbCtrl.addWorkflow(); + wbCtrl.addWorkflow(); expect(workbook.get('workflows').get(0).getID()).not.toEqual( workbook.get('workflows').get(1).getID()) diff --git a/package.json b/package.json index 6156fe9..ebb4dcb 100644 --- a/package.json +++ b/package.json @@ -43,6 +43,6 @@ "postinstall": "bower install", "test-unit": "grunt test:unit", "test": "karma start ./karma-unit.conf.js", - "lint": "eslint --no-color ./merlin/static" + "lint": "eslint --no-color ./merlin/static ./extensions/mistral/static" } }