From e6225498cc009c362da4b90d585d613ea6dc58c3 Mon Sep 17 00:00:00 2001 From: Thai Tran Date: Tue, 9 Feb 2016 17:07:35 -0800 Subject: [PATCH] Queues create wizard This patch adds the ability to create queues with metadata. Tests will be added in subsequent patches. Co-Authored-By: Fei Long Wang Change-Id: I294f9b1cf84ad11be23e0e17b16c52a963ff235c --- zaqar_ui/api/rest/zaqar.py | 9 +- zaqar_ui/api/zaqar.py | 2 +- zaqar_ui/enabled/_1520_project_queues.py | 6 + .../openstack-service-api/zaqar.service.js | 10 +- .../queues/actions/create.action.service.js | 105 ++++++++++++++++++ .../queues/actions/create.workflow.service.js | 54 +++++++++ .../dashboard/project/queues/queues.module.js | 35 ++++-- .../queue-details/queue-details.controller.js | 62 +++++++++++ .../steps/queue-details/queue-details.html | 33 ++++++ .../queue-metadata.controller.js | 103 +++++++++++++++++ .../steps/queue-metadata/queue-metadata.html | 8 ++ .../queues/table/batch-actions.service.js | 63 +++++++++++ .../project/queues/table/table.controller.js | 31 ++++-- .../dashboard/project/queues/table/table.html | 23 +++- 14 files changed, 518 insertions(+), 26 deletions(-) create mode 100644 zaqar_ui/static/dashboard/project/queues/actions/create.action.service.js create mode 100644 zaqar_ui/static/dashboard/project/queues/actions/create.workflow.service.js create mode 100644 zaqar_ui/static/dashboard/project/queues/steps/queue-details/queue-details.controller.js create mode 100644 zaqar_ui/static/dashboard/project/queues/steps/queue-details/queue-details.html create mode 100644 zaqar_ui/static/dashboard/project/queues/steps/queue-metadata/queue-metadata.controller.js create mode 100644 zaqar_ui/static/dashboard/project/queues/steps/queue-metadata/queue-metadata.html create mode 100644 zaqar_ui/static/dashboard/project/queues/table/batch-actions.service.js diff --git a/zaqar_ui/api/rest/zaqar.py b/zaqar_ui/api/rest/zaqar.py index 65d3f12..33b8ce5 100644 --- a/zaqar_ui/api/rest/zaqar.py +++ b/zaqar_ui/api/rest/zaqar.py @@ -64,12 +64,13 @@ class Queues(generic.View): zaqar.queue_delete(request, queue_name) @rest_utils.ajax(data_required=True) - def create(self, request): + def put(self, request): """Create a new queue. Returns the new queue object on success. """ new_queue = zaqar.queue_create(request, **request.DATA) - return rest_utils.CreatedResponse( - '/api/messaging/queues/%s' % new_queue.name, - new_queue.to_dict()) + location = '/api/zaqar/queues/%s' % new_queue.name + response = {'name': new_queue.name, + 'metadata': new_queue._metadata} + return rest_utils.CreatedResponse(location, response) diff --git a/zaqar_ui/api/zaqar.py b/zaqar_ui/api/zaqar.py index c4dd55c..a3c1fd7 100644 --- a/zaqar_ui/api/zaqar.py +++ b/zaqar_ui/api/zaqar.py @@ -60,9 +60,9 @@ def queue_create(request, queue_name, metadata): # 2. ttl # 3. max message size # 4. Metadata - queue = zaqarclient(request).queue(queue_name, force_create=True) queue.metadata(new_meta=metadata) + return queue def queue_delete(request, queue_name): diff --git a/zaqar_ui/enabled/_1520_project_queues.py b/zaqar_ui/enabled/_1520_project_queues.py index 23c4044..b75cf58 100644 --- a/zaqar_ui/enabled/_1520_project_queues.py +++ b/zaqar_ui/enabled/_1520_project_queues.py @@ -28,6 +28,12 @@ ADD_ANGULAR_MODULES = [ ADD_JS_FILES = [ 'app/core/openstack-service-api/zaqar.service.js', 'dashboard/project/queues/queues.module.js', + 'dashboard/project/queues/actions/create.action.service.js', + 'dashboard/project/queues/actions/create.workflow.service.js', + 'dashboard/project/queues/steps/queue-details/queue-details.controller.js', + 'dashboard/project/queues/steps/queue-metadata/' + 'queue-metadata.controller.js', + 'dashboard/project/queues/table/batch-actions.service.js', 'dashboard/project/queues/table/table.controller.js', ] diff --git a/zaqar_ui/static/app/core/openstack-service-api/zaqar.service.js b/zaqar_ui/static/app/core/openstack-service-api/zaqar.service.js index ebeb617..ceee866 100644 --- a/zaqar_ui/static/app/core/openstack-service-api/zaqar.service.js +++ b/zaqar_ui/static/app/core/openstack-service-api/zaqar.service.js @@ -28,7 +28,8 @@ function ZaqarAPI(apiService, toastService) { var service = { - getQueues: getQueues + getQueues: getQueues, + createQueue: createQueue }; return service; @@ -42,6 +43,13 @@ }); } + function createQueue(newQueue) { + return apiService.put('/api/zaqar/queues/', newQueue) + .error(function() { + toastService.add('error', gettext('Unable to create the queue.')); + }); + } + } }()); diff --git a/zaqar_ui/static/dashboard/project/queues/actions/create.action.service.js b/zaqar_ui/static/dashboard/project/queues/actions/create.action.service.js new file mode 100644 index 0000000..bb6cf2e --- /dev/null +++ b/zaqar_ui/static/dashboard/project/queues/actions/create.action.service.js @@ -0,0 +1,105 @@ +/** + * Copyright 2016 IBM Corp. + * + * 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('horizon.dashboard.project.queues') + .factory('horizon.dashboard.project.queues.actions.createService', createService); + + createService.$inject = [ + 'horizon.app.core.metadata.service', + 'horizon.app.core.openstack-service-api.policy', + 'horizon.dashboard.project.queues.events', + 'horizon.dashboard.project.queues.actions.createWorkflow', + 'horizon.app.core.openstack-service-api.zaqar', + 'horizon.framework.widgets.modal.wizard-modal.service', + 'horizon.framework.widgets.toast.service' + ]; + + /** + * @ngDoc factory + * @name horizon.dashboard.project.queues.actions.createService + * @Description A service to open the queues wizard. + */ + function createService(meta, policy, events, createWorkflow, zaqar, wizard, toast) { + + var message = { + success: gettext('Queue %s was successfully created.') + }; + + var scope; + var model = { + queue_name: null, + metadata: {} + }; + + var service = { + initScope: initScope, + perform: perform, + allowed: allowed + }; + + return service; + + ////////////// + + // we define initScope so that the table controller + // will know when a new queue has been created + function initScope($scope) { + scope = $scope; + var queueWatcher = $scope.$on(events.DETAILS_CHANGED, onQueueChange); + var metadataWatcher = $scope.$on(events.METADATA_CHANGED, onMetadataChange); + $scope.$on('$destroy', function destroy() { + queueWatcher(); + metadataWatcher(); + }); + } + + function onQueueChange(e, queue) { + model.queue_name = queue.name; + e.stopPropagation(); + } + + function onMetadataChange(e, metadata) { + model.metadata = metadata; + e.stopPropagation(); + } + + function perform() { + wizard.modal({ + scope: scope, + workflow: createWorkflow, + submit: submit + }); + } + + function allowed() { + return policy.ifAllowed({ rules: [['queue', 'add_queue']] });; + } + + function submit() { + return zaqar.createQueue(model).then(success); + } + + function success(response) { + toast.add('success', interpolate(message.success, [response.data.name])); + scope.$emit(events.CREATE_SUCCESS, response.data); + } + + } // end of createService +})(); // end of IIFE diff --git a/zaqar_ui/static/dashboard/project/queues/actions/create.workflow.service.js b/zaqar_ui/static/dashboard/project/queues/actions/create.workflow.service.js new file mode 100644 index 0000000..0138275 --- /dev/null +++ b/zaqar_ui/static/dashboard/project/queues/actions/create.workflow.service.js @@ -0,0 +1,54 @@ +/** + * Copyright 2016 IBM Corp. + * + * 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('horizon.dashboard.project.queues') + .factory('horizon.dashboard.project.queues.actions.createWorkflow', createWorkflow); + + createWorkflow.$inject = [ + 'horizon.app.core.workflow.factory', + 'horizon.dashboard.project.queues.basePath', + 'horizon.framework.util.i18n.gettext' + ]; + + /** + * @ngdoc factory + * @name horizon.dashboard.project.queues.actions.createWorkflow + * @description A workflow for the create queue action. + */ + function createWorkflow(workflowService, basePath, gettext) { + + var workflow = workflowService({ + title: gettext('Create Queue'), + btnText: { finish: gettext('Create') }, + steps: [{ + title: gettext('Queue Details'), + templateUrl: basePath + 'steps/queue-details/queue-details.html', + formName: 'queueDetailsForm' + }, { + title: gettext('Queue Metadata'), + templateUrl: basePath + 'steps/queue-metadata/queue-metadata.html', + formName: 'queueMetadataForm' + }] + }); + + return workflow; + } + +})(); diff --git a/zaqar_ui/static/dashboard/project/queues/queues.module.js b/zaqar_ui/static/dashboard/project/queues/queues.module.js index b4dc1dd..14af2f5 100644 --- a/zaqar_ui/static/dashboard/project/queues/queues.module.js +++ b/zaqar_ui/static/dashboard/project/queues/queues.module.js @@ -1,5 +1,6 @@ /** * Copyright 2015 Catalyst IT Ltd + * Copyright 2016 IBM Corp. * * 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 @@ -19,20 +20,40 @@ /** * @ngdoc overview - * @name horizon.dashboard.project - * - * @description - * Dashboard module to host various queues panels. + * @name horizon.dashboard.project.queues + * @description Dashboard module to host various queues panels. */ angular .module('horizon.dashboard.project.queues', []) + .constant('horizon.dashboard.project.queues.events', events()) .config(config); - config.$inject = ['$provide', '$windowProvider']; + config.$inject = [ + '$provide', + '$windowProvider' + ]; + /** + * @ngdoc value + * @name horizon.dashboard.project.queues.events + * @description a list of events for queues + */ + function events() { + return { + CREATE_SUCCESS: 'horizon.dashboard.project.queues.CREATE_SUCCESS', + DETAILS_CHANGED: 'horizon.dashboard.project.queues.DETAILS_CHANGED', + METADATA_CHANGED: 'horizon.dashboard.project.queues.METADATA_CHANGED' + }; + } + + /** + * @ndoc config + * @name horizon.dashboard.project.queues.basePath + * @description Base path for the queues panel + */ function config($provide, $windowProvider) { - var path = $windowProvider.$get().STATIC_URL + 'dashboard/project/'; - $provide.constant('horizon.dashboard.project.basePath', path); + var path = $windowProvider.$get().STATIC_URL + 'dashboard/project/queues/'; + $provide.constant('horizon.dashboard.project.queues.basePath', path); } })(); \ No newline at end of file diff --git a/zaqar_ui/static/dashboard/project/queues/steps/queue-details/queue-details.controller.js b/zaqar_ui/static/dashboard/project/queues/steps/queue-details/queue-details.controller.js new file mode 100644 index 0000000..a2ddbb3 --- /dev/null +++ b/zaqar_ui/static/dashboard/project/queues/steps/queue-details/queue-details.controller.js @@ -0,0 +1,62 @@ +/** + * Copyright 2016 IBM Corp. + * + * 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('horizon.dashboard.project.queues') + .controller('horizon.dashboard.project.queues.steps.QueueDetailsController', controller); + + controller.$inject = [ + '$scope', + 'horizon.app.core.openstack-service-api.zaqar', + 'horizon.dashboard.project.queues.events' + ]; + + /** + * @ngdoc controller + * @name horizon.dashboard.project.queues.steps.QueueDetailsController + * @description This controller is use for creating a queue. + */ + function controller($scope, zaqar, events) { + + var ctrl = this; + ctrl.queue = {}; + + //////////////////////// + + // watch this object, when it changes, emit to parent listeners + var watcher = $scope.$watchCollection(getQueue, onQueneChange); + $scope.$on('$destroy', function() { + watcher(); + }) + + //////////////////////// + + function getQueue() { + return ctrl.queue; + } + + function onQueneChange(newValue, oldValue){ + if (newValue !== oldValue) { + $scope.$emit(events.DETAILS_CHANGED, newValue); + } + } + + } // end of controller + +})(); diff --git a/zaqar_ui/static/dashboard/project/queues/steps/queue-details/queue-details.html b/zaqar_ui/static/dashboard/project/queues/steps/queue-details/queue-details.html new file mode 100644 index 0000000..c861449 --- /dev/null +++ b/zaqar_ui/static/dashboard/project/queues/steps/queue-details/queue-details.html @@ -0,0 +1,33 @@ + +
+ +

Queue Details

+
+ +
+ Note that you can create a queue without defining metadata. + The metadata step is optional but recommended. +
+ +
+
+
+
+ + +

+ A user name between 1-256 characters is required. +

+
+
+
+
+ +
+
diff --git a/zaqar_ui/static/dashboard/project/queues/steps/queue-metadata/queue-metadata.controller.js b/zaqar_ui/static/dashboard/project/queues/steps/queue-metadata/queue-metadata.controller.js new file mode 100644 index 0000000..15cafa3 --- /dev/null +++ b/zaqar_ui/static/dashboard/project/queues/steps/queue-metadata/queue-metadata.controller.js @@ -0,0 +1,103 @@ +/** + * Copyright 2016 IBM Corp. + * + * 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('horizon.dashboard.project.queues') + .controller('horizon.dashboard.project.queues.steps.QueueMetadataController', controller); + + controller.$inject = [ + '$q', + '$scope', + 'horizon.app.core.metadata.service', + 'horizon.app.core.openstack-service-api.zaqar', + 'horizon.dashboard.project.queues.events', + 'horizon.framework.widgets.metadata.tree.service' + ]; + + /** + * @ngdoc controller + * @name horizon.dashboard.project.queues.steps.QueueDetailsController + * @description This controller is use for creating a queue. + */ + function controller($q, $scope, metadata, zaqar, events, metaTree) { + + var ctrl = this; + var queue = $scope.queue? $scope.queue: {}; + + ctrl.tree = new metaTree.Tree([], []); + + /* eslint-enable angular/ng_controller_as */ + $scope.$watchCollection(getTree, onMetadataChanged); + /* eslint-enable angular/ng_controller_as */ + + init(); + + //////////////////////////////// + + function init() { + $q.all({ + available: standardDefinitions(), + existing: getExistingMetdataPromise(queue) + }) + .then(onMetadataGet); + } + + function onMetadataGet(response) { + console.log(response); + ctrl.tree = new metaTree.Tree( + response.available.data.items, + response.existing.data + ); + } + + function getTree() { + return ctrl.tree.getExisting(); + } + + function standardDefinitions() { + + // TODO: currently, there is no standard metadefinitions + // should add some reserved/fixed definition here + // preferably it should come from zaqar and not hardcoded here + var deferred = $q.defer(); + deferred.resolve({data: []}); + return deferred.promise; + } + + function getExistingMetdataPromise(queue) { + + //if (angular.isDefined(queue.id)) { + // return metadata.getMetadata('queue', queue.id); + //} + //else { + var deferred = $q.defer(); + deferred.resolve({data: []}); + return deferred.promise; + //} + } + + function onMetadataChanged(newValue, oldValue) { + if (newValue !== oldValue) { + $scope.$emit(events.METADATA_CHANGED, newValue); + } + } + + } // end of controller + +})(); diff --git a/zaqar_ui/static/dashboard/project/queues/steps/queue-metadata/queue-metadata.html b/zaqar_ui/static/dashboard/project/queues/steps/queue-metadata/queue-metadata.html new file mode 100644 index 0000000..8be7688 --- /dev/null +++ b/zaqar_ui/static/dashboard/project/queues/steps/queue-metadata/queue-metadata.html @@ -0,0 +1,8 @@ + +
+ +

Queue Metadata

+
+ +
+
diff --git a/zaqar_ui/static/dashboard/project/queues/table/batch-actions.service.js b/zaqar_ui/static/dashboard/project/queues/table/batch-actions.service.js new file mode 100644 index 0000000..9244b33 --- /dev/null +++ b/zaqar_ui/static/dashboard/project/queues/table/batch-actions.service.js @@ -0,0 +1,63 @@ +/** + * Copyright 2016 IBM Corp. + * + * 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('horizon.dashboard.project.queues') + .factory('horizon.dashboard.project.queues.batch-actions.service', batchActions); + + batchActions.$inject = [ + 'horizon.dashboard.project.queues.actions.createService', + 'horizon.framework.util.i18n.gettext' + ]; + + /** + * @ngdoc factory + * @name horizon.dashboard.project.queues.batch-actions.service + * @description A list of table batch actions. + */ + function batchActions(createService, gettext) { + + var service = { + initScope: initScope, + actions: actions + }; + + return service; + + /////////////// + + function initScope(scope) { + angular.forEach([createService], setActionScope); + function setActionScope(action) { + action.initScope(scope.$new()); + } + } + + function actions() { + return [{ + service: createService, + template: { + type: 'create', + text: gettext('Create Queue') + } + }]; + } + } + +})(); \ No newline at end of file diff --git a/zaqar_ui/static/dashboard/project/queues/table/table.controller.js b/zaqar_ui/static/dashboard/project/queues/table/table.controller.js index 54273bd..cece900 100644 --- a/zaqar_ui/static/dashboard/project/queues/table/table.controller.js +++ b/zaqar_ui/static/dashboard/project/queues/table/table.controller.js @@ -29,17 +29,32 @@ queuesTableController.$inject = [ '$scope', - 'horizon.app.core.openstack-service-api.zaqar' + 'horizon.app.core.openstack-service-api.zaqar', + 'horizon.dashboard.project.queues.batch-actions.service', + 'horizon.dashboard.project.queues.events' ]; - function queuesTableController($scope, zaqar) { + function queuesTableController($scope, zaqar, batchActions, events) { var ctrl = this; - ctrl.iqueues = []; ctrl.queues = []; + ctrl.queuesSrc = []; + + ctrl.batchActions = batchActions; + ctrl.batchActions.initScope($scope); init(); + initScope(); + + ////////// + + function initScope() { + var createWatcher = $scope.$on(events.CREATE_SUCCESS, onCreateSuccess); + $scope.$on('$destroy', function destroy() { + createWatcher(); + }) + } ////////// @@ -48,12 +63,12 @@ } function getQueuesSuccess(response) { + ctrl.queuesSrc = response; + } - // TODO: If the response does not contain the id field - // then you must manually add them on the client-side - // the horizon table's checkboxes requires that the id field be present - console.log(response); - ctrl.queues = response; + function onCreateSuccess(e, newQueue) { + e.stopPropagation(); + ctrl.queuesSrc.push(newQueue); } } diff --git a/zaqar_ui/static/dashboard/project/queues/table/table.html b/zaqar_ui/static/dashboard/project/queues/table/table.html index 22dfe9a..bf59826 100644 --- a/zaqar_ui/static/dashboard/project/queues/table/table.html +++ b/zaqar_ui/static/dashboard/project/queues/table/table.html @@ -2,21 +2,34 @@ + + + + + @@ -35,7 +48,7 @@ Include action-col if you want to perform actions. rsp-p1 rsp-p2 are responsive priority as user resizes window. --> -
+ + + + +
- + Name
@@ -105,7 +118,7 @@
- {$ table.iqueues.length|itemCount $} + {$ table.queuesSrc.length|itemCount $}