diff --git a/horizon/static/angular/modal/modal.js b/horizon/static/angular/modal/modal.js new file mode 100644 index 0000000000..a3af9f9019 --- /dev/null +++ b/horizon/static/angular/modal/modal.js @@ -0,0 +1,95 @@ +(function() { + 'use strict'; + + /** + * @ngdoc overview + * @name hz.widget.modal + * + * # hz.widget.modal + * + * The `hz.widget.modal` provides modal services. + * + * Requires {@link http://angular-ui.github.io/bootstrap/ `Angular-bootstrap`} + * + * | Components | + * |--------------------------------------------------------------------------| + * | {@link hz.widget.modal.controller:simpleModalCtrl `simpleModalCtrl`} | + * | {@link hz.widget.modal.factory:simpleModalService `simpleModalService`} | + * + */ + angular.module('hz.widget.modal', ['ui.bootstrap']) + + /** + * @ngdoc controller + * @name simpleModalCtrl + * + * @param(object) scope of the controller + * @param(object) modal instance from angular-bootstrap + * @param(object) context object provided by the user + * + * @description + * Horizon's controller for confirmation dialog. + * Passes context along to the template. + * If user presses cancel button or closes dialog, modal gets dismissed. + * If user presses submit button, modal gets closed. + * This controller is automatically included in modalService. + */ + .controller('simpleModalCtrl', [ '$scope', '$modalInstance', 'context', + function($scope, $modalInstance, context) { + $scope.context = context; + $scope.submit = function(){ $modalInstance.close(); }; + $scope.cancel = function(){ $modalInstance.dismiss('cancel'); }; + } // end of function + ]) // end of controller + + /** + * @ngdoc service + * @name simpleModalService + * + * @description + * Horizon's wrapper for angular-bootstrap modal service. + * It should only be use for small confirmation dialogs. + * @param {object} the object containing title, body, submit, and cancel labels + * @param {object} the object returned from angular-bootstrap $modal + * + * @example: + * angular.controller('modalExampleCtrl', [ '$scope', 'simpleModalService', + * function($scope, simpleModalService){ + * var options = { + * title: 'Confirm Delete', + * body: 'Are you sure you want to delete this item?', + * submit: 'Yes', + * cancel: 'No', + * }; + * simpleModalService(options).result.then(function(){ + * // user clicked on submit button + * // do something useful here + * }); + * } + * ]); + */ + .factory('simpleModalService', ['$modal', 'basePath', + function($modal, path) { + return function(params) { + if (params && params.title && params.body){ + var options = { + controller: 'simpleModalCtrl', + templateUrl: path + 'modal/simple-modal.html', + resolve: { + context: function() { + return { + title: params.title? params.title: '', + body: params.body? params.body: '', + submit: params.submit? params.submit: gettext('Submit'), + cancel: gettext('Cancel') + }; + } + } + }; + return $modal.open(options); + } + }; // end of return + } // end of function + ]); // end of factory + +})(); \ No newline at end of file diff --git a/horizon/static/angular/modal/simple-modal.html b/horizon/static/angular/modal/simple-modal.html new file mode 100644 index 0000000000..39904f39c6 --- /dev/null +++ b/horizon/static/angular/modal/simple-modal.html @@ -0,0 +1,18 @@ + + + \ No newline at end of file diff --git a/horizon/static/angular/modal/simple-modal.spec.js b/horizon/static/angular/modal/simple-modal.spec.js new file mode 100644 index 0000000000..9fae12b486 --- /dev/null +++ b/horizon/static/angular/modal/simple-modal.spec.js @@ -0,0 +1,55 @@ +'use strict'; + +describe('hz.widget.modal module', function(){ + it('should have been defined', function(){ + expect(angular.module('hz.widget.modal')).toBeDefined(); + }); +}); + +describe('modal factory', function(){ + + var modal; + var modalData = { + title: 'Confirm deletion', + body: 'Are you sure?', + submit: 'Yes', + cancel: 'No' + }; + + beforeEach(module('ui.bootstrap')); + beforeEach(module('hz')); + beforeEach(module('hz.widgets')); + beforeEach(module('hz.widget.modal')); + beforeEach(inject(function($injector, simpleModalService){ + modal = simpleModalService; + })); + + it('should fail without any params', function(){ + expect(modal()).toBeUndefined(); + }); + + it('should fail without a title', function(){ + var data = angular.copy(modalData); + delete data.title; + expect(modal(data)).toBeUndefined(); + }); + + it('should fail without a body', function(){ + var data = angular.copy(modalData); + delete data.body; + expect(modal(data)).toBeUndefined(); + }); + + it('should have default submit and cancel labels', function(){ + var data = angular.copy(modalData); + delete data.submit; + delete data.cancel; + expect(modal(data)).toBeDefined(); + }); + + it('should work when all params are supplied', function(){ + var data = angular.copy(modalData); + expect(modal(data)).toBeDefined(); + }); + +}); \ No newline at end of file diff --git a/horizon/static/angular/widget.module.js b/horizon/static/angular/widget.module.js index 68f50e6e77..1be4d484cc 100644 --- a/horizon/static/angular/widget.module.js +++ b/horizon/static/angular/widget.module.js @@ -4,7 +4,8 @@ angular.module('hz.widgets', [ 'hz.widget.help-panel', 'hz.widget.wizard', - 'hz.widget.table' + 'hz.widget.table', + 'hz.widget.modal' ]) .constant('basePath', '/static/angular/'); diff --git a/horizon/templates/horizon/_scripts.html b/horizon/templates/horizon/_scripts.html index af375eb9bf..d89b255a63 100644 --- a/horizon/templates/horizon/_scripts.html +++ b/horizon/templates/horizon/_scripts.html @@ -26,6 +26,7 @@ + diff --git a/horizon/test/jasmine/jasmine_tests.py b/horizon/test/jasmine/jasmine_tests.py index 5a1de149e8..402a98080c 100644 --- a/horizon/test/jasmine/jasmine_tests.py +++ b/horizon/test/jasmine/jasmine_tests.py @@ -29,6 +29,7 @@ class ServicesTests(test.JasmineTests): 'angular/help-panel/help-panel.js', 'angular/wizard/wizard.js', 'angular/table/table.js', + 'angular/modal/modal.js', ] specs = [ 'horizon/tests/jasmine/utilsSpec.js', @@ -37,8 +38,9 @@ class ServicesTests(test.JasmineTests): 'angular/help-panel/help-panel.spec.js', 'angular/wizard/wizard.spec.js', 'angular/table/table.spec.js', + 'angular/modal/simple-modal.spec.js', ] externalTemplates = [ 'angular/help-panel/help-panel.html', - 'angular/wizard/wizard.html', + 'angular/wizard/wizard.html' ] diff --git a/openstack_dashboard/templates/_header.html b/openstack_dashboard/templates/_header.html index 386158969f..66ee0a991f 100644 --- a/openstack_dashboard/templates/_header.html +++ b/openstack_dashboard/templates/_header.html @@ -6,7 +6,7 @@