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
This commit is contained in:
Timur Sufiev 2015-07-13 13:29:27 +03:00
parent ac6336b5e2
commit d82d48453f
6 changed files with 697 additions and 684 deletions

View File

@ -4,10 +4,15 @@
(function() { (function() {
'use strict'; 'use strict';
angular.module('mistral', ['merlin']) angular
.run(['merlin.templates', function(templates) { .module('mistral', ['merlin'])
.run(initModule);
initModule.$inject = ['merlin.templates'];
function initModule(templates) {
templates.prefetch('/static/mistral/templates/fields/', templates.prefetch('/static/mistral/templates/fields/',
['varlist', 'yaqllist']); ['varlist', 'yaqllist']);
}]) }
})(); })();

View File

@ -4,26 +4,31 @@
(function() { (function() {
'use strict'; 'use strict';
angular.module('mistral') angular
.module('mistral')
.value('baseActionID', 'action') .value('baseActionID', 'action')
.value('baseWorkflowID', 'workflow') .value('baseWorkflowID', 'workflow')
.controller('workbookCtrl', .controller('WorkbookController', WorkbookController);
['$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);
$scope.root.set('standardActions', { WorkbookController.$inject = ['mistral.workbook.models', '$http',
'$window', 'baseActionID', 'baseWorkflowID'];
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);
vm.root.set('standardActions', {
'nova.create_server': ['image', 'flavor', 'network_id'], 'nova.create_server': ['image', 'flavor', 'network_id'],
'neutron.create_network': ['name', 'create_subnet'], 'neutron.create_network': ['name', 'create_subnet'],
'glance.create_image': ['image_url'] 'glance.create_image': ['image_url']
@ -39,47 +44,47 @@
} }
function getWorkbookNextIDSuffix(base) { function getWorkbookNextIDSuffix(base) {
var containerName = base + 's', var containerName = base + 's';
regexp = /(workflow|action)([0-9]+)/, var regexp = /(workflow|action)([0-9]+)/;
container = $scope.workbook.get(containerName); var container = vm.workbook.get(containerName);
if ( !container ) { if ( !container ) {
throw 'Base should be either "action" or "workflow"!'; throw new Error('Base should be either "action" or "workflow"!');
} }
return getNextIDSuffix(container, regexp); return getNextIDSuffix(container, regexp);
} }
$scope.addAction = function() { vm.addAction = function() {
var nextSuffix = getWorkbookNextIDSuffix(baseActionId), var nextSuffix = getWorkbookNextIDSuffix(baseActionId);
newID = baseActionId + nextSuffix; var newID = baseActionId + nextSuffix;
$scope.workbook.get('actions').push( vm.workbook.get('actions').push(
{name: 'Action ' + nextSuffix}, {id: newID}); {name: 'Action ' + nextSuffix}, {id: newID});
}; };
$scope.addWorkflow = function() { vm.addWorkflow = function() {
var nextSuffix = getWorkbookNextIDSuffix(baseWorkflowId), var nextSuffix = getWorkbookNextIDSuffix(baseWorkflowId);
newID = baseWorkflowId + nextSuffix; var newID = baseWorkflowId + nextSuffix;
$scope.workbook.get('workflows').push( vm.workbook.get('workflows').push(
{name: 'Workflow ' + nextSuffix}, {id: newID}); {name: 'Workflow ' + nextSuffix}, {id: newID});
}; };
$scope.commitWorkbook = function() { vm.commitWorkbook = function() {
var data = { var data = {
name: $scope.workbook.get('name').get(), name: vm.workbook.get('name').get(),
yaml: $scope.workbook.toYAML() yaml: vm.workbook.toYAML()
}; };
$http({ $http({
url: $scope.commitUrl, url: vm.commitUrl,
method: 'POST', method: 'POST',
data: data data: data
}).success(function(data, status, headers, config) { }).success(function() {
document.location = $scope.discardUrl; $window.location.href = vm.discardUrl;
}); });
}; };
$scope.discardWorkbook = function() { vm.discardWorkbook = function() {
document.location = $scope.discardUrl; $window.location.href = vm.discardUrl;
}; };
}]) }
})(); })();

View File

@ -4,15 +4,18 @@
(function() { (function() {
'use strict'; 'use strict';
angular.module('mistral') angular
.factory('mistral.workbook.models', .module('mistral')
['merlin.field.models', 'merlin.panel.models', 'merlin.utils', '$http', '$q', .factory('mistral.workbook.models', ModelsService);
function(fields, panel, utils, $http, $q) {
ModelsService.$inject = ['merlin.field.models', 'merlin.utils'];
function ModelsService(fields, utils) {
var models = {}; var models = {};
function varlistValueFactory(json, parameters) { function varlistValueFactory(json, parameters) {
var type = Barricade.getType(json); var type = Barricade.getType(json);
if ( json === undefined || type === String ) { if ( angular.isUndefined(json) || type === String ) {
return fields.string.create(json, parameters); return fields.string.create(json, parameters);
} else if ( type === Array ) { } else if ( type === Array ) {
return fields.list.extend({}, { return fields.list.extend({}, {
@ -35,7 +38,7 @@
if ( child === item ) { if ( child === item ) {
self.remove(index); self.remove(index);
} }
}) });
} }
}); });
return self; return self;
@ -105,8 +108,8 @@
models.Action = fields.frozendict.extend({ models.Action = fields.frozendict.extend({
create: function(json, parameters) { create: function(json, parameters) {
var self = fields.frozendict.create.call(this, json, parameters), var self = fields.frozendict.create.call(this, json, parameters);
base = self.get('base'); var base = self.get('base');
base.on('change', function(operation) { base.on('change', function(operation) {
var argsEntry, pos, entry; var argsEntry, pos, entry;
if ( operation != 'id' ) { if ( operation != 'id' ) {
@ -388,7 +391,7 @@
} }
}) })
} }
}) });
}); });
models.WorkflowTaskMixin = Barricade.Blueprint.create(function() { models.WorkflowTaskMixin = Barricade.Blueprint.create(function() {
@ -420,10 +423,10 @@
}; };
function TaskFactory(json, parameters) { function TaskFactory(json, parameters) {
var type = json.type || 'action', var type = json.type || 'action';
baseClass = taskTypes[parameters.wfType], var baseClass = taskTypes[parameters.wfType];
mixinClass = taskTypes[type], var mixinClass = taskTypes[type];
taskClass = mixinClass.call(baseClass); var taskClass = mixinClass.call(baseClass);
return taskClass.create(json, parameters); return taskClass.create(json, parameters);
} }
@ -476,10 +479,10 @@
var self = fields.dictionary.create.call(this, json, parameters); var self = fields.dictionary.create.call(this, json, parameters);
self.on('childChange', function(child, op, arg) { self.on('childChange', function(child, op, arg) {
if ( op === 'taskType' ) { if ( op === 'taskType' ) {
var taskId = child.getID(), var taskId = child.getID();
params = child._parameters, var params = child._parameters;
taskPos = self.getPosByID(taskId), var taskPos = self.getPosByID(taskId);
taskData = child.toJSON(); var taskData = child.toJSON();
params.id = taskId; params.id = taskId;
self.set(taskPos, TaskFactory(taskData, params)); self.set(taskPos, TaskFactory(taskData, params));
} else if ( op === 'taskRemove' ) { } else if ( op === 'taskRemove' ) {
@ -567,10 +570,10 @@
var self = fields.dictionary.create.call(this, json, parameters); var self = fields.dictionary.create.call(this, json, parameters);
self.on('childChange', function(child, op) { self.on('childChange', function(child, op) {
if ( op === 'workflowType' ) { if ( op === 'workflowType' ) {
var workflowId = child.getID(), var workflowId = child.getID();
workflowPos = self.getPosByID(workflowId), var workflowPos = self.getPosByID(workflowId);
params = child._parameters, var params = child._parameters;
workflowData = child.toJSON(); var workflowData = child.toJSON();
params.wfType = child.type; params.wfType = child.type;
params.id = workflowId; params.id = workflowId;
self.set(workflowPos, workflowFactory(workflowData, params)); self.set(workflowPos, workflowFactory(workflowData, params));
@ -658,5 +661,5 @@
}); });
return models; return models;
}]) }
})(); })();

View File

@ -38,34 +38,36 @@
{% block main %} {% block main %}
<h3>Create Workbook</h3> <h3>Create Workbook</h3>
<div id="create-workbook" class="fluid-container" ng-cloak ng-controller="workbookCtrl" <div id="create-workbook" class="fluid-container" ng-cloak ng-controller="WorkbookController as wb"
ng-init="init({{ id|default:'undefined' }}, '{{ yaml }}', '{{ commit_url }}', '{{ discard_url }}')"> ng-init="wb.init({{ id|default:'undefined' }}, '{{ yaml }}', '{{ commit_url }}', '{{ discard_url }}')">
<div class="well"> <div class="well">
<div class="two-panels"> <div class="two-panels">
<div class="left-panel"> <div class="left-panel">
<div class="pull-left"> <div class="pull-left">
<h4><strong>{$ workbook.get('name') $}</strong></h4> <h4><strong>{$ wb.workbook.get('name') $}</strong></h4>
</div> </div>
<div class="pull-right"> <div class="pull-right">
<div class="table-actions clearfix"> <div class="table-actions clearfix">
<button ng-click="addAction()" class="btn btn-default btn-sm"><span class="fa fa-plus">Add Action</span></button> <button ng-click="wb.addAction()" class="btn btn-default btn-sm">
<button ng-click="addWorkflow()" class="btn btn-default btn-sm"><span class="fa fa-plus">Add Workflow</span></button> <span class="fa fa-plus">Add Action</span></button>
<button ng-click="wb.addWorkflow()" class="btn btn-default btn-sm">
<span class="fa fa-plus">Add Workflow</span></button>
</div> </div>
</div> </div>
</div> </div>
<div class="right-panel"> <div class="right-panel">
<div class="btn-group btn-toggle pull-right"> <div class="btn-group btn-toggle pull-right">
<button ng-click="isGraphMode = true" class="btn btn-sm" <button ng-click="wb.isGraphMode = true" class="btn btn-sm"
ng-class="isGraphMode ? 'active btn-primary' : 'btn-default'">Graph</button> ng-class="wb.isGraphMode ? 'active btn-primary' : 'btn-default'">Graph</button>
<button ng-click="isGraphMode = false" class="btn btn-sm" <button ng-click="wb.isGraphMode = false" class="btn btn-sm"
ng-class="!isGraphMode ? 'active btn-primary' : 'btn-default'">YAML</button> ng-class="!wb.isGraphMode ? 'active btn-primary' : 'btn-default'">YAML</button>
</div> </div>
</div> </div>
</div> </div>
<!-- Data panel start --> <!-- Data panel start -->
<div class="two-panels"> <div class="two-panels">
<div class="left-panel"> <div class="left-panel">
<panel ng-repeat="panel in workbook | extractPanels track by panel.id" <panel ng-repeat="panel in wb.workbook | extractPanels track by panel.id"
content="panel"> content="panel">
<div ng-repeat="row in panel | extractRows track by row.id"> <div ng-repeat="row in panel | extractRows track by row.id">
<div ng-class="{'two-columns': row.index !== undefined }"> <div ng-class="{'two-columns': row.index !== undefined }">
@ -81,10 +83,10 @@
<!-- YAML Panel --> <!-- YAML Panel -->
<div class="right-panel"> <div class="right-panel">
<div class="panel panel-default"> <div class="panel panel-default">
<div class="panel-body" ng-show="!isGraphMode"> <div class="panel-body" ng-show="!wb.isGraphMode">
<pre>{$ workbook.toYAML() $}</pre> <pre>{$ wb.workbook.toYAML() $}</pre>
</div> </div>
<div class="panel-body" ng-show="isGraphMode"> <div class="panel-body" ng-show="wb.isGraphMode">
Here will be a fancy Graph View as soon as we implement it! Here will be a fancy Graph View as soon as we implement it!
</div> </div>
</div> </div>
@ -94,9 +96,9 @@
<div class="two-panels"> <div class="two-panels">
<div class="full-width"> <div class="full-width">
<div class="pull-right"> <div class="pull-right">
<button ng-click="discardWorkbook()" class="btn btn-default cancel">Cancel</button> <button ng-click="wb.discardWorkbook()" class="btn btn-default cancel">Cancel</button>
<button ng-click="commitWorkbook()" class="btn btn-primary"> <button ng-click="wb.commitWorkbook()" class="btn btn-primary">
{$ workbookID ? 'Modify' : 'Create' $} {$ wb.workbookID ? 'Modify' : 'Create' $}
</button> </button>
</div> </div>
</div> </div>

View File

@ -27,24 +27,22 @@ describe('together workbook model and controller', function() {
describe('define top-level actions available to user:', function () { describe('define top-level actions available to user:', function () {
var $scope; var wbCtrl;
beforeEach(inject(function (_$controller_) { beforeEach(inject(function (_$controller_) {
var $controller = _$controller_; wbCtrl = _$controller_('WorkbookController', {});
$scope = {}; wbCtrl.workbook = workbook;
$controller('workbookCtrl', {$scope: $scope});
$scope.workbook = workbook;
})); }));
describe("'Add Action' action", function () { describe("'Add Action' action", function () {
it('adds a new Action', function () { it('adds a new Action', function () {
$scope.addAction(); wbCtrl.addAction();
expect(workbook.get('actions').get(0)).toBeDefined(); expect(workbook.get('actions').get(0)).toBeDefined();
}); });
it('creates action with predefined name', function () { it('creates action with predefined name', function () {
$scope.addAction(); wbCtrl.addAction();
expect(workbook.get('actions').get(0).getID()).toBeGreaterThan(''); 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 () { it("corresponding JSON has the right key for the Action", function () {
$scope.addAction(); wbCtrl.addAction();
expect(workbook.toJSON({pretty: true}).actions[actionID]).toBeDefined(); 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 () { it("once the Action ID is changed, it's reflected in JSON", function () {
var newID = 'action10'; var newID = 'action10';
$scope.addAction(); wbCtrl.addAction();
workbook.get('actions').getByID(actionID).setID(newID); workbook.get('actions').getByID(actionID).setID(newID);
expect(workbook.toJSON({pretty: true}).actions[actionID]).toBeUndefined(); 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 () { it('creates actions with different names on 2 successive calls', function () {
$scope.addAction(); wbCtrl.addAction();
$scope.addAction(); wbCtrl.addAction();
expect(workbook.get('actions').get(0).getID()).not.toEqual( expect(workbook.get('actions').get(0).getID()).not.toEqual(
workbook.get('actions').get(1).getID()) workbook.get('actions').get(1).getID())
@ -84,7 +82,7 @@ describe('together workbook model and controller', function() {
describe("'Add Workflow' action", function () { describe("'Add Workflow' action", function () {
it('adds a new Workflow', function () { it('adds a new Workflow', function () {
$scope.addWorkflow(); wbCtrl.addWorkflow();
expect(workbook.get('workflows').get(0)).toBeDefined(); 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 () { it("corresponding JSON has the right key for the Workflow", function () {
$scope.addWorkflow(); wbCtrl.addWorkflow();
expect(workbook.toJSON({pretty: true}).workflows[workflowID]).toBeDefined(); 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 () { it("once the workflow ID is changed, it's reflected in JSON", function () {
var newID = 'workflow10'; var newID = 'workflow10';
$scope.addWorkflow(); wbCtrl.addWorkflow();
workbook.get('workflows').getByID(workflowID).setID(newID); workbook.get('workflows').getByID(workflowID).setID(newID);
expect(workbook.toJSON({pretty: true}).workflows[workflowID]).toBeUndefined(); 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 () { it('creates workflow with predefined name', function () {
$scope.addWorkflow(); wbCtrl.addWorkflow();
expect(workbook.get('workflows').get(0).getID()).toBeGreaterThan(''); expect(workbook.get('workflows').get(0).getID()).toBeGreaterThan('');
}); });
it('creates workflows with different names on 2 successive calls', function () { it('creates workflows with different names on 2 successive calls', function () {
$scope.addWorkflow(); wbCtrl.addWorkflow();
$scope.addWorkflow(); wbCtrl.addWorkflow();
expect(workbook.get('workflows').get(0).getID()).not.toEqual( expect(workbook.get('workflows').get(0).getID()).not.toEqual(
workbook.get('workflows').get(1).getID()) workbook.get('workflows').get(1).getID())

View File

@ -43,6 +43,6 @@
"postinstall": "bower install", "postinstall": "bower install",
"test-unit": "grunt test:unit", "test-unit": "grunt test:unit",
"test": "karma start ./karma-unit.conf.js", "test": "karma start ./karma-unit.conf.js",
"lint": "eslint --no-color ./merlin/static" "lint": "eslint --no-color ./merlin/static ./extensions/mistral/static"
} }
} }