diff --git a/openstack_dashboard/dashboards/project/images/images/tables.py b/openstack_dashboard/dashboards/project/images/images/tables.py
index a18733ebc4..06f6961689 100644
--- a/openstack_dashboard/dashboards/project/images/images/tables.py
+++ b/openstack_dashboard/dashboards/project/images/images/tables.py
@@ -65,7 +65,7 @@ class LaunchImageNG(LaunchImage):
def __init__(self, attrs=None, **kwargs):
if attrs is None:
- attrs = {"ng-controller": "LaunchInstanceModalCtrl"}
+ attrs = {"ng-controller": "LaunchInstanceModalController"}
kwargs['preempt'] = True
super(LaunchImage, self).__init__(attrs, **kwargs)
diff --git a/openstack_dashboard/dashboards/project/instances/tables.py b/openstack_dashboard/dashboards/project/instances/tables.py
index 71e97005dc..95f51c05b5 100644
--- a/openstack_dashboard/dashboards/project/instances/tables.py
+++ b/openstack_dashboard/dashboards/project/instances/tables.py
@@ -354,7 +354,7 @@ class LaunchLinkNG(LaunchLink):
def __init__(self,
attrs={
- "ng-controller": "LaunchInstanceModalCtrl",
+ "ng-controller": "LaunchInstanceModalController",
"ng-click": "openLaunchInstanceWizard(" +
"{successUrl: '/project/instances/'})"
},
diff --git a/openstack_dashboard/dashboards/project/network_topology/templates/network_topology/index.html b/openstack_dashboard/dashboards/project/network_topology/templates/network_topology/index.html
index efcc228cb0..95ecb33150 100644
--- a/openstack_dashboard/dashboards/project/network_topology/templates/network_topology/index.html
+++ b/openstack_dashboard/dashboards/project/network_topology/templates/network_topology/index.html
@@ -29,7 +29,7 @@
{% if launch_instance_allowed %}
{% if show_ng_launch %}
-
{% if instance_quota_exceeded %}{% trans "Launch Instance (Quota exceeded)"%}{% else %}{% trans "Launch Instance"%}{% endif %}
+
{% if instance_quota_exceeded %}{% trans "Launch Instance (Quota exceeded)"%}{% else %}{% trans "Launch Instance"%}{% endif %}
{% endif %}
{% if instance_quota_exceeded %}{% trans "Launch Instance (Quota exceeded)"%}{% else %}{% trans "Launch Instance"%}{% endif %}
{% endif %}
diff --git a/openstack_dashboard/enabled/_10_project.py b/openstack_dashboard/enabled/_10_project.py
index 9a7df090fa..a768372d08 100644
--- a/openstack_dashboard/enabled/_10_project.py
+++ b/openstack_dashboard/enabled/_10_project.py
@@ -31,8 +31,11 @@ ADD_JS_FILES = [
'dashboard/workflow/decorator.service.js',
'dashboard/workflow/workflow.service.js',
'dashboard/cloud-services/cloud-services.js',
- LAUNCH_INST + 'launch-instance.js',
- LAUNCH_INST + 'launch-instance.model.js',
+ LAUNCH_INST + 'launch-instance.module.js',
+ LAUNCH_INST + 'launch-instance-workflow.service.js',
+ LAUNCH_INST + 'launch-instance-modal.controller.js',
+ LAUNCH_INST + 'launch-instance-wizard.controller.js',
+ LAUNCH_INST + 'launch-instance-model.js',
LAUNCH_INST + 'source/source.controller.js',
LAUNCH_INST + 'source/source-help.controller.js',
LAUNCH_INST + 'flavor/flavor.controller.js',
@@ -54,8 +57,11 @@ ADD_JS_SPEC_FILES = [
'dashboard/dashboard.module.spec.js',
'dashboard/workflow/workflow.module.spec.js',
'dashboard/cloud-services/cloud-services.spec.js',
- LAUNCH_INST + 'launch-instance.spec.js',
- LAUNCH_INST + 'launch-instance.model.spec.js',
+ LAUNCH_INST + 'launch-instance.module.spec.js',
+ LAUNCH_INST + 'launch-instance-workflow.service.spec.js',
+ LAUNCH_INST + 'launch-instance-modal.controller.spec.js',
+ LAUNCH_INST + 'launch-instance-wizard.controller.spec.js',
+ LAUNCH_INST + 'launch-instance-model.spec.js',
LAUNCH_INST + 'source/source.spec.js',
LAUNCH_INST + 'flavor/flavor.spec.js',
LAUNCH_INST + 'network/network.spec.js',
diff --git a/openstack_dashboard/karma.conf.js b/openstack_dashboard/karma.conf.js
index b4bf321f6e..aa1baa4be0 100644
--- a/openstack_dashboard/karma.conf.js
+++ b/openstack_dashboard/karma.conf.js
@@ -91,7 +91,6 @@ module.exports = function (config) {
* not significant.
*/
'**/*.module.js',
- '**/launch-instance.js',
/**
* Followed by other JavaScript files that defines angular providers
diff --git a/openstack_dashboard/static/dashboard/launch-instance/launch-instance-modal.controller.js b/openstack_dashboard/static/dashboard/launch-instance/launch-instance-modal.controller.js
new file mode 100644
index 0000000000..99080354f3
--- /dev/null
+++ b/openstack_dashboard/static/dashboard/launch-instance/launch-instance-modal.controller.js
@@ -0,0 +1,57 @@
+/*
+ * (c) Copyright 2015 Hewlett-Packard Development Company, L.P.
+ *
+ * Licensed under the Apache License, Version 2.0 (the 'License');
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an 'AS IS' BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+(function () {
+ 'use strict';
+
+ angular
+ .module('hz.dashboard.launch-instance')
+ .controller('LaunchInstanceModalController', LaunchInstanceModalController);
+
+ LaunchInstanceModalController.$inject = [
+ '$scope',
+ '$modal',
+ '$window',
+ 'hz.dashboard.launch-instance.modal-spec'
+ ];
+
+ function LaunchInstanceModalController($scope, $modal, $window, modalSpec) {
+ $scope.openLaunchInstanceWizard = openLaunchInstanceWizard;
+
+ function openLaunchInstanceWizard(launchContext) {
+ var localSpec = {
+ resolve: {
+ launchContext: function () {
+ return launchContext;
+ }
+ }
+ };
+ angular.extend(localSpec, modalSpec);
+ var launchInstanceModal = $modal.open(localSpec);
+ var handleModalClose = function (redirectPropertyName) {
+ return function () {
+ if (launchContext && launchContext[redirectPropertyName]) {
+ $window.location.href = launchContext[redirectPropertyName];
+ }
+ };
+ };
+ launchInstanceModal.result.then(
+ handleModalClose('successUrl'),
+ handleModalClose('dismissUrl')
+ );
+ }
+ }
+
+})();
diff --git a/openstack_dashboard/static/dashboard/launch-instance/launch-instance-modal.controller.spec.js b/openstack_dashboard/static/dashboard/launch-instance/launch-instance-modal.controller.spec.js
new file mode 100644
index 0000000000..f72ef18680
--- /dev/null
+++ b/openstack_dashboard/static/dashboard/launch-instance/launch-instance-modal.controller.spec.js
@@ -0,0 +1,118 @@
+/*
+ * (c) Copyright 2015 Hewlett-Packard Development Company, L.P.
+ *
+ * Licensed under the Apache License, Version 2.0 (the 'License');
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an 'AS IS' BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+(function () {
+ 'use strict';
+
+ describe('LaunchInstanceModalController tests', function() {
+ var ctrl;
+ var modal;
+ var scope;
+ var $window;
+
+ beforeEach(module('hz.dashboard'));
+ beforeEach(module(function($provide) {
+ modal = {
+ open: function() {
+ return {
+ result: {
+ then: angular.noop
+ }
+ };
+ }
+ };
+ $window = { location: { href: '/' } };
+ $provide.value('$modal', modal);
+ $provide.value('$modalSpec', {});
+ $provide.value('$window', $window);
+ }));
+
+ beforeEach(inject(function($controller) {
+ scope = {};
+ ctrl = $controller('LaunchInstanceModalController', { $scope: scope });
+ }));
+
+ it('defines the controller', function() {
+ expect(ctrl).toBeDefined();
+ });
+
+ it('defines openLaunchInstanceWizard', function() {
+ expect(scope.openLaunchInstanceWizard).toBeDefined();
+ });
+
+ describe('openLaunchInstanceWizard function tests', function() {
+ var func;
+ var launchContext;
+
+ beforeEach(function() {
+ func = scope.openLaunchInstanceWizard;
+ launchContext = {};
+ });
+
+ it('calls modal.open', function() {
+ spyOn(modal, 'open').and.returnValue({ result: { then: angular.noop } });
+ func(launchContext);
+ expect(modal.open).toHaveBeenCalled();
+ });
+
+ it('calls modal.open with expected values', function() {
+ spyOn(modal, 'open').and.returnValue({ result: { then: angular.noop } });
+ launchContext = { info: 'information' };
+ func(launchContext);
+
+ var resolve = modal.open.calls.argsFor(0)[0].resolve;
+ expect(resolve).toBeDefined();
+ expect(resolve.launchContext).toBeDefined();
+ expect(resolve.launchContext()).toEqual({ info: 'information' });
+ });
+
+ it('sets up the correct success and failure paths', function() {
+ var successFunc;
+ var errFunc;
+
+ launchContext = { successUrl: '/good/path', dismissUrl: '/bad/path' };
+ spyOn(modal, 'open').and
+ .returnValue({
+ result: {
+ then: function(x, y) { successFunc = x; errFunc = y; }
+ }
+ });
+ func(launchContext);
+ successFunc('successUrl');
+ expect($window.location.href).toBe('/good/path');
+ errFunc('dismissUrl');
+ expect($window.location.href).toBe('/bad/path');
+ });
+
+ it("doesn't redirect if not configured to", function() {
+ var successFunc;
+ var errFunc;
+ launchContext = {};
+ spyOn(modal, 'open').and
+ .returnValue({
+ result: {
+ then: function(x, y) { successFunc = x; errFunc = y; }
+ }
+ });
+ func(launchContext);
+ successFunc('successUrl');
+ expect($window.location.href).toBe('/');
+ errFunc('dismissUrl');
+ expect($window.location.href).toBe('/');
+ });
+ });
+ });
+
+})();
diff --git a/openstack_dashboard/static/dashboard/launch-instance/launch-instance.model.js b/openstack_dashboard/static/dashboard/launch-instance/launch-instance-model.js
similarity index 100%
rename from openstack_dashboard/static/dashboard/launch-instance/launch-instance.model.js
rename to openstack_dashboard/static/dashboard/launch-instance/launch-instance-model.js
diff --git a/openstack_dashboard/static/dashboard/launch-instance/launch-instance.model.spec.js b/openstack_dashboard/static/dashboard/launch-instance/launch-instance-model.spec.js
similarity index 100%
rename from openstack_dashboard/static/dashboard/launch-instance/launch-instance.model.spec.js
rename to openstack_dashboard/static/dashboard/launch-instance/launch-instance-model.spec.js
diff --git a/openstack_dashboard/static/dashboard/launch-instance/launch-instance-wizard.controller.js b/openstack_dashboard/static/dashboard/launch-instance/launch-instance-wizard.controller.js
new file mode 100644
index 0000000000..c657b65b96
--- /dev/null
+++ b/openstack_dashboard/static/dashboard/launch-instance/launch-instance-wizard.controller.js
@@ -0,0 +1,36 @@
+/*
+ * (c) Copyright 2015 Hewlett-Packard Development Company, L.P.
+ *
+ * Licensed under the Apache License, Version 2.0 (the 'License');
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an 'AS IS' BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+(function () {
+ 'use strict';
+
+ angular
+ .module('hz.dashboard.launch-instance')
+ .controller('LaunchInstanceWizardController', LaunchInstanceWizardController);
+
+ LaunchInstanceWizardController.$inject = [
+ '$scope',
+ 'launchInstanceModel',
+ 'hz.dashboard.launch-instance.workflow'
+ ];
+
+ function LaunchInstanceWizardController($scope, launchInstanceModel, launchInstanceWorkflow) {
+ $scope.workflow = launchInstanceWorkflow;
+ $scope.model = launchInstanceModel;
+ $scope.model.initialize(true);
+ $scope.submit = $scope.model.createInstance;
+ }
+
+})();
diff --git a/openstack_dashboard/static/dashboard/launch-instance/launch-instance-wizard.controller.spec.js b/openstack_dashboard/static/dashboard/launch-instance/launch-instance-wizard.controller.spec.js
new file mode 100644
index 0000000000..dc48cb464d
--- /dev/null
+++ b/openstack_dashboard/static/dashboard/launch-instance/launch-instance-wizard.controller.spec.js
@@ -0,0 +1,61 @@
+/*
+ * (c) Copyright 2015 Hewlett-Packard Development Company, L.P.
+ *
+ * Licensed under the Apache License, Version 2.0 (the 'License');
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an 'AS IS' BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+(function () {
+ 'use strict';
+
+ describe('LaunchInstanceWizardController tests', function() {
+ var ctrl;
+ var model = {
+ createInstance: function() {
+ return 'created';
+ },
+ initialize: angular.noop
+ };
+ var scope = {};
+
+ beforeEach(module('hz.dashboard'));
+ beforeEach(module(function ($provide) {
+ $provide.value('serviceCatalog', {});
+ $provide.value('launchInstanceModel', model);
+ $provide.value('hz.dashboard.launch-instance.workflow', { thing: true });
+ }));
+ beforeEach(inject(function ($controller) {
+ spyOn(model, 'initialize');
+ var locals = {
+ $scope: scope
+ };
+ ctrl = $controller('LaunchInstanceWizardController', locals);
+ }));
+
+ it('defines the controller', function() {
+ expect(ctrl).toBeDefined();
+ });
+
+ it('calls initialize on the given model', function() {
+ expect(scope.model.initialize).toHaveBeenCalled();
+ });
+
+ it('sets scope.workflow to the given workflow', function() {
+ expect(scope.workflow).toEqual({ thing: true });
+ });
+
+ it('defines scope.submit', function() {
+ expect(scope.submit).toBeDefined();
+ expect(scope.submit()).toBe('created');
+ });
+ });
+
+})();
diff --git a/openstack_dashboard/static/dashboard/launch-instance/launch-instance-workflow.service.js b/openstack_dashboard/static/dashboard/launch-instance/launch-instance-workflow.service.js
new file mode 100644
index 0000000000..bb00d1274f
--- /dev/null
+++ b/openstack_dashboard/static/dashboard/launch-instance/launch-instance-workflow.service.js
@@ -0,0 +1,82 @@
+/*
+ * (c) Copyright 2015 Hewlett-Packard Development Company, L.P.
+ *
+ * Licensed under the Apache License, Version 2.0 (the 'License');
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an 'AS IS' BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+(function () {
+ 'use strict';
+
+ angular
+ .module('hz.dashboard.launch-instance')
+ .factory('hz.dashboard.launch-instance.workflow', launchInstanceWorkflow);
+
+ launchInstanceWorkflow.$inject = [
+ 'dashboardBasePath',
+ 'hz.dashboard.workflow.factory'
+ ];
+
+ function launchInstanceWorkflow(path, dashboardWorkflow) {
+ return dashboardWorkflow({
+ title: gettext('Launch Instance'),
+
+ steps: [
+ {
+ title: gettext('Select Source'),
+ templateUrl: path + 'launch-instance/source/source.html',
+ helpUrl: path + 'launch-instance/source/source.help.html',
+ formName: 'launchInstanceSourceForm'
+ },
+ {
+ title: gettext('Flavor'),
+ templateUrl: path + 'launch-instance/flavor/flavor.html',
+ helpUrl: path + 'launch-instance/flavor/flavor.help.html',
+ formName: 'launchInstanceFlavorForm'
+ },
+ {
+ title: gettext('Networks'),
+ templateUrl: path + 'launch-instance/network/network.html',
+ helpUrl: path + 'launch-instance/network/network.help.html',
+ formName: 'launchInstanceNetworkForm',
+ requiredServiceTypes: ['network']
+ },
+ {
+ title: gettext('Security Groups'),
+ templateUrl: path + 'launch-instance/security-groups/security-groups.html',
+ helpUrl: path + 'launch-instance/security-groups/security-groups.help.html',
+ formName: 'launchInstanceAccessAndSecurityForm'
+ },
+ {
+ title: gettext('Key Pair'),
+ templateUrl: path + 'launch-instance/keypair/keypair.html',
+ helpUrl: path + 'launch-instance/keypair/keypair.help.html',
+ formName: 'launchInstanceKeypairForm'
+ },
+ {
+ title: gettext('Configuration'),
+ templateUrl: path + 'launch-instance/configuration/configuration.html',
+ helpUrl: path + 'launch-instance/configuration/configuration.help.html',
+ formName: 'launchInstanceConfigurationForm'
+ }
+ ],
+
+ btnText: {
+ finish: gettext('Launch Instance')
+ },
+
+ btnIcon: {
+ finish: 'fa fa-cloud-download'
+ }
+ });
+ }
+
+})();
diff --git a/openstack_dashboard/static/dashboard/launch-instance/launch-instance-workflow.service.spec.js b/openstack_dashboard/static/dashboard/launch-instance/launch-instance-workflow.service.spec.js
new file mode 100644
index 0000000000..9ee5a3ecaf
--- /dev/null
+++ b/openstack_dashboard/static/dashboard/launch-instance/launch-instance-workflow.service.spec.js
@@ -0,0 +1,70 @@
+/*
+ * (c) Copyright 2015 Hewlett-Packard Development Company, L.P.
+ *
+ * Licensed under the Apache License, Version 2.0 (the 'License');
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an 'AS IS' BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+(function() {
+ 'use strict';
+
+ describe('hz.dashboard.launch-instance.workflow tests', function () {
+ var launchInstanceWorkflow;
+
+ beforeEach(module('hz.dashboard'));
+ beforeEach(module(function($provide) {
+ // Need to mock hz.framework.workflow from 'horizon'
+ var workflow = function(spec, decorators) {
+ angular.forEach(decorators, function(decorator) {
+ decorator(spec);
+ });
+ return spec;
+ };
+ $provide.value('horizon.openstack-service-api.serviceCatalog', {});
+ $provide.value('horizon.framework.util.workflow.service', workflow);
+ }));
+
+ beforeEach(inject(function ($injector) {
+ launchInstanceWorkflow = $injector.get('hz.dashboard.launch-instance.workflow');
+ }));
+
+ it('should be defined', function () {
+ expect(launchInstanceWorkflow).toBeDefined();
+ });
+
+ it('should have a title property', function () {
+ expect(launchInstanceWorkflow.title).toBeDefined();
+ });
+
+ it('should have the six steps defined', function () {
+ expect(launchInstanceWorkflow.steps).toBeDefined();
+ expect(launchInstanceWorkflow.steps.length).toBe(6);
+
+ var forms = [
+ 'launchInstanceSourceForm',
+ 'launchInstanceFlavorForm',
+ 'launchInstanceNetworkForm',
+ 'launchInstanceAccessAndSecurityForm',
+ 'launchInstanceKeypairForm',
+ 'launchInstanceConfigurationForm'
+ ];
+
+ forms.forEach(function(expectedForm, idx) {
+ expect(launchInstanceWorkflow.steps[idx].formName).toBe(expectedForm);
+ });
+ });
+
+ it('specifies that the network step requires the network service type', function() {
+ expect(launchInstanceWorkflow.steps[2].requiredServiceTypes).toEqual(['network']);
+ });
+ });
+
+})();
diff --git a/openstack_dashboard/static/dashboard/launch-instance/launch-instance.js b/openstack_dashboard/static/dashboard/launch-instance/launch-instance.js
deleted file mode 100644
index 7ff351bd1b..0000000000
--- a/openstack_dashboard/static/dashboard/launch-instance/launch-instance.js
+++ /dev/null
@@ -1,153 +0,0 @@
-(function () {
- 'use strict';
-
- var module = angular.module('hz.dashboard.launch-instance', [ 'ngSanitize' ]);
-
- module.factory('launchInstanceWorkflow', [
- 'dashboardBasePath',
- 'hz.dashboard.workflow.factory',
-
- function (path, dashboardWorkflow) {
-
- return dashboardWorkflow({
- title: gettext('Launch Instance'),
-
- steps: [
- {
- title: gettext('Select Source'),
- templateUrl: path + 'launch-instance/source/source.html',
- helpUrl: path + 'launch-instance/source/source.help.html',
- formName: 'launchInstanceSourceForm'
- },
- {
- title: gettext('Flavor'),
- templateUrl: path + 'launch-instance/flavor/flavor.html',
- helpUrl: path + 'launch-instance/flavor/flavor.help.html',
- formName: 'launchInstanceFlavorForm'
- },
- {
- title: gettext('Networks'),
- templateUrl: path + 'launch-instance/network/network.html',
- helpUrl: path + 'launch-instance/network/network.help.html',
- formName: 'launchInstanceNetworkForm',
- requiredServiceTypes: ['network']
- },
- {
- title: gettext('Security Groups'),
- templateUrl: path + 'launch-instance/security-groups/security-groups.html',
- helpUrl: path + 'launch-instance/security-groups/security-groups.help.html',
- formName: 'launchInstanceAccessAndSecurityForm'
- },
- {
- title: gettext('Key Pair'),
- templateUrl: path + 'launch-instance/keypair/keypair.html',
- helpUrl: path + 'launch-instance/keypair/keypair.help.html',
- formName: 'launchInstanceKeypairForm'
- },
- {
- title: gettext('Configuration'),
- templateUrl: path + 'launch-instance/configuration/configuration.html',
- helpUrl: path + 'launch-instance/configuration/configuration.help.html',
- formName: 'launchInstanceConfigurationForm'
- }
- ],
-
- btnText: {
- finish: gettext('Launch Instance')
- },
-
- btnIcon: {
- finish: 'fa fa-cloud-download'
- }
- });
- }
- ]);
-
- // Using bootstrap-ui modal widget
- module.constant('launchInstanceWizardModalSpec', {
- backdrop: 'static',
- controller: 'ModalContainerCtrl',
- template: '
',
- windowClass: 'modal-dialog-wizard'
- });
-
- /**
- * @name bootSourceTypes
- * @description Boot source types
- */
- module.constant('bootSourceTypes', {
- IMAGE: 'image',
- INSTANCE_SNAPSHOT: 'snapshot',
- VOLUME: 'volume',
- VOLUME_SNAPSHOT: 'volume_snapshot'
- });
-
- /**
- * @ngdoc filter
- * @name diskFormat
- * @description
- * Expects object and returns disk_format property value.
- * Returns empty string if input is null or not an object.
- * Uniquely required for the source step implementation of transfer tables
- */
- module.filter('diskFormat', function() {
- return function(input) {
- if (input === null || !angular.isObject(input) ||
- !angular.isDefined(input.disk_format) || input.disk_format === null) {
- return '';
- } else {
- return input.disk_format.toUpperCase();
- }
- };
- });
-
- module.controller('LaunchInstanceWizardCtrl', [
- '$scope',
- 'launchInstanceModel',
- 'launchInstanceWorkflow',
- LaunchInstanceWizardCtrl
- ]);
-
- module.controller('LaunchInstanceModalCtrl', [
- '$scope',
- '$modal',
- '$window',
- 'launchInstanceWizardModalSpec',
- LaunchInstanceModalCtrl
- ]);
-
- function LaunchInstanceWizardCtrl($scope, launchInstanceModel, launchInstanceWorkflow) {
- $scope.workflow = launchInstanceWorkflow;
- $scope.model = launchInstanceModel;
- $scope.model.initialize(true);
- $scope.submit = $scope.model.createInstance;
- }
-
- function LaunchInstanceModalCtrl($scope, $modal, $window, modalSpec) {
- $scope.openLaunchInstanceWizard = function (launchContext) {
-
- var localSpec = {
- resolve: {
- launchContext: function() { return launchContext; }
- }
- };
-
- angular.extend(localSpec, modalSpec);
-
- var launchInstanceModal = $modal.open(localSpec);
-
- var handleModalClose = function(redirectPropertyName) {
- return function() {
- if (launchContext && launchContext[redirectPropertyName]) {
- $window.location.href = launchContext[redirectPropertyName];
- }
- };
- };
-
- launchInstanceModal.result.then(handleModalClose('successUrl'),
- handleModalClose('dismissUrl'));
-
- };
- }
-
-})();
diff --git a/openstack_dashboard/static/dashboard/launch-instance/launch-instance.module.js b/openstack_dashboard/static/dashboard/launch-instance/launch-instance.module.js
new file mode 100644
index 0000000000..c3d8bb8cc3
--- /dev/null
+++ b/openstack_dashboard/static/dashboard/launch-instance/launch-instance.module.js
@@ -0,0 +1,64 @@
+/*
+ * (c) Copyright 2015 Hewlett-Packard Development Company, L.P.
+ *
+ * Licensed under the Apache License, Version 2.0 (the 'License');
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an 'AS IS' BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+(function () {
+ 'use strict';
+
+ angular
+ .module('hz.dashboard.launch-instance', [
+ 'ngSanitize'
+ ])
+ .constant('hz.dashboard.launch-instance.modal-spec', {
+ backdrop: 'static',
+ controller: 'ModalContainerCtrl',
+ template: '
',
+ windowClass: 'modal-dialog-wizard'
+ })
+
+ /**
+ * @name hz.dashboard.launch-instance.boot-source-types
+ * @description Boot source types
+ */
+ .constant('hz.dashboard.launch-instance.boot-source-types', {
+ IMAGE: 'image',
+ INSTANCE_SNAPSHOT: 'snapshot',
+ VOLUME: 'volume',
+ VOLUME_SNAPSHOT: 'volume_snapshot'
+ })
+
+ /**
+ * @ngdoc filter
+ * @name diskFormat
+ * @description
+ * Expects object and returns disk_format property value.
+ * Returns empty string if input is null or not an object.
+ * Uniquely required for the source step implementation of transfer tables
+ */
+ .filter('diskFormat', diskFormat);
+
+ function diskFormat() {
+ return filter;
+
+ function filter(input) {
+ if (input === null || !angular.isObject(input) ||
+ !angular.isDefined(input.disk_format) || input.disk_format === null) {
+ return '';
+ } else {
+ return input.disk_format.toUpperCase();
+ }
+ }
+ }
+
+})();
diff --git a/openstack_dashboard/static/dashboard/launch-instance/launch-instance.module.spec.js b/openstack_dashboard/static/dashboard/launch-instance/launch-instance.module.spec.js
new file mode 100644
index 0000000000..52f429540c
--- /dev/null
+++ b/openstack_dashboard/static/dashboard/launch-instance/launch-instance.module.spec.js
@@ -0,0 +1,40 @@
+/*
+ * (c) Copyright 2015 Hewlett-Packard Development Company, L.P.
+ *
+ * Licensed under the Apache License, Version 2.0 (the 'License');
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an 'AS IS' BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+(function () {
+ 'use strict';
+
+ describe('hz.dashboard.launch-instance module', function() {
+
+ beforeEach(module('hz.dashboard'));
+
+ it('should be defined.', function () {
+ expect(angular.module('hz.dashboard.launch-instance')).toBeDefined();
+ });
+
+ describe('hz.dashboard.launch-instance.modal-spec', function () {
+ var launchInstancedModalSpec;
+
+ beforeEach(inject(function ($injector) {
+ launchInstancedModalSpec = $injector.get('hz.dashboard.launch-instance.modal-spec');
+ }));
+
+ it('should be defined', function () {
+ expect(launchInstancedModalSpec).toBeDefined();
+ });
+ });
+ });
+
+})();
diff --git a/openstack_dashboard/static/dashboard/launch-instance/launch-instance.spec.js b/openstack_dashboard/static/dashboard/launch-instance/launch-instance.spec.js
deleted file mode 100644
index 2444891d19..0000000000
--- a/openstack_dashboard/static/dashboard/launch-instance/launch-instance.spec.js
+++ /dev/null
@@ -1,233 +0,0 @@
-/*
- * (c) Copyright 2015 Hewlett-Packard Development Company, L.P.
- *
- * Licensed under the Apache License, Version 2.0 (the 'License');
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an 'AS IS' BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-(function() {
- 'use strict';
-
- describe('Launch Instance Tests', function() {
-
- beforeEach(module('hz.dashboard'));
-
- it('should be defined.', function () {
- expect(angular.module('hz.dashboard.launch-instance')).toBeDefined();
- });
-
- describe('launchInstanceWorkflow', function () {
- var launchInstanceWorkflow;
-
- beforeEach(module(function($provide) {
- // Need to mock hz.framework.workflow from 'horizon'
- var workflow = function(spec, decorators) {
- angular.forEach(decorators, function(decorator) {
- decorator(spec);
- });
- return spec;
- };
-
- $provide.value('horizon.openstack-service-api.serviceCatalog', {});
- $provide.value('horizon.framework.util.workflow.service', workflow);
- }));
-
- beforeEach(inject(function ($injector) {
- launchInstanceWorkflow = $injector.get('launchInstanceWorkflow');
- }));
-
- it('should be defined', function () {
- expect(launchInstanceWorkflow).toBeDefined();
- });
-
- it('should have a title property', function () {
- expect(launchInstanceWorkflow.title).toBeDefined();
- });
-
- it('should have the six steps defined', function () {
- expect(launchInstanceWorkflow.steps).toBeDefined();
- expect(launchInstanceWorkflow.steps.length).toBe(6);
-
- var forms = [
- 'launchInstanceSourceForm',
- 'launchInstanceFlavorForm',
- 'launchInstanceNetworkForm',
- 'launchInstanceAccessAndSecurityForm',
- 'launchInstanceKeypairForm',
- 'launchInstanceConfigurationForm'
- ];
-
- forms.forEach(function(expectedForm, idx) {
- expect(launchInstanceWorkflow.steps[idx].formName).toBe(expectedForm);
- });
- });
-
- it('specifies that the network step requires the network service type', function() {
- expect(launchInstanceWorkflow.steps[2].requiredServiceTypes).toEqual(['network']);
- });
- });
-
- describe('launchInstanceWizardModalSpec', function () {
- var launchInstanceWizardModalSpec;
-
- beforeEach(inject(function ($injector) {
- launchInstanceWizardModalSpec = $injector.get('launchInstanceWizardModalSpec');
- }));
-
- it('should be defined', function () {
- expect(launchInstanceWizardModalSpec).toBeDefined();
- });
- });
-
- describe('LaunchInstanceWizardCtrl', function() {
- var ctrl;
- var model = {
- createInstance: function() {
- return 'created';
- },
- initialize: angular.noop
- };
-
- var scope = {};
-
- beforeEach(module(function ($provide) {
- $provide.value('serviceCatalog', {});
- $provide.value('launchInstanceModel', model);
- }));
-
- beforeEach(inject(function ($controller) {
- spyOn(model, 'initialize');
- var locals = {
- $scope: scope,
- launchInstanceWorkflow: { thing: true }
- };
- ctrl = $controller('LaunchInstanceWizardCtrl', locals);
- }));
-
- it('defines the controller', function() {
- expect(ctrl).toBeDefined();
- });
-
- it('calls initialize on the given model', function() {
- expect(scope.model.initialize).toHaveBeenCalled();
- });
-
- it('sets scope.workflow to the given workflow', function() {
- expect(scope.workflow).toEqual({ thing: true });
- });
-
- it('defines scope.submit', function() {
- expect(scope.submit).toBeDefined();
- expect(scope.submit()).toBe('created');
- });
-
- });
-
- describe('LaunchInstanceModalCtrl', function() {
- var ctrl;
- var modal;
- var scope;
- var $window;
-
- beforeEach(module(function($provide) {
- modal = {
- open: function() {
- return {
- result: {
- then: angular.noop
- }
- };
- }
- };
- $window = { location: { href: '/' } };
-
- $provide.value('$modal', modal);
- $provide.value('$modalSpec', {});
- $provide.value('$window', $window);
- }));
-
- beforeEach(inject(function($controller) {
- scope = {};
- ctrl = $controller('LaunchInstanceModalCtrl', { $scope: scope });
- }));
-
- it('defines the controller', function() {
- expect(ctrl).toBeDefined();
- });
-
- it('defines openLaunchInstanceWizard', function() {
- expect(scope.openLaunchInstanceWizard).toBeDefined();
- });
-
- describe('openLaunchInstanceWizard function tests', function() {
- var func;
- var launchContext;
-
- beforeEach(function() {
- func = scope.openLaunchInstanceWizard;
- launchContext = {};
- });
-
- it('calls modal.open', function() {
- spyOn(modal, 'open').and.returnValue({ result: { then: angular.noop } });
- func(launchContext);
- expect(modal.open).toHaveBeenCalled();
- });
-
- it('calls modal.open with expected values', function() {
- spyOn(modal, 'open').and.returnValue({ result: { then: angular.noop } });
- launchContext = { info: 'information' };
- func(launchContext);
-
- var resolve = modal.open.calls.argsFor(0)[0].resolve;
- expect(resolve).toBeDefined();
- expect(resolve.launchContext).toBeDefined();
- expect(resolve.launchContext()).toEqual({ info: 'information' });
- });
-
- it('sets up the correct success and failure paths', function() {
- var successFunc;
- var errFunc;
-
- launchContext = { successUrl: '/good/path', dismissUrl: '/bad/path' };
- spyOn(modal, 'open').and
- .returnValue({
- result: {
- then: function(x, y) { successFunc = x; errFunc = y; }
- }
- });
- func(launchContext);
- successFunc('successUrl');
- expect($window.location.href).toBe('/good/path');
- errFunc('dismissUrl');
- expect($window.location.href).toBe('/bad/path');
- });
-
- it("doesn't redirect if not configured to", function() {
- var successFunc;
- var errFunc;
- launchContext = {};
- spyOn(modal, 'open').and
- .returnValue({
- result: {
- then: function(x, y) { successFunc = x; errFunc = y; }
- }
- });
- func(launchContext);
- successFunc('successUrl');
- expect($window.location.href).toBe('/');
- errFunc('dismissUrl');
- expect($window.location.href).toBe('/');
- });
- });
- });
- });
-})();
diff --git a/openstack_dashboard/static/dashboard/launch-instance/source/source.controller.js b/openstack_dashboard/static/dashboard/launch-instance/source/source.controller.js
index 6da10a3c7f..6b12d38ab3 100644
--- a/openstack_dashboard/static/dashboard/launch-instance/source/source.controller.js
+++ b/openstack_dashboard/static/dashboard/launch-instance/source/source.controller.js
@@ -32,7 +32,7 @@
LaunchInstanceSourceController.$inject = [
'$scope',
- 'bootSourceTypes',
+ 'hz.dashboard.launch-instance.boot-source-types',
'bytesFilter',
'horizon.framework.widgets.charts.donutChartSettings',
'dateFilter',
diff --git a/openstack_dashboard/static/dashboard/launch-instance/source/source.spec.js b/openstack_dashboard/static/dashboard/launch-instance/source/source.spec.js
index b1110b9e73..3efe3a6020 100644
--- a/openstack_dashboard/static/dashboard/launch-instance/source/source.spec.js
+++ b/openstack_dashboard/static/dashboard/launch-instance/source/source.spec.js
@@ -25,7 +25,7 @@
var scope, ctrl, $browser, deferred;
beforeEach(module(function($provide) {
- $provide.value('bootSourceTypes', noop);
+ $provide.value('hz.dashboard.launch-instance.boot-source-types', noop);
$provide.value('bytesFilter', noop);
$provide.value('horizon.framework.widgets.charts.donutChartSettings', noop);
$provide.value('dateFilter', noop);