diff --git a/doc/source/configuration/settings.rst b/doc/source/configuration/settings.rst index 1fcd1e16d3..0ec34ddeaf 100644 --- a/doc/source/configuration/settings.rst +++ b/doc/source/configuration/settings.rst @@ -50,9 +50,10 @@ Default: 'images_panel': True, 'key_pairs_panel': False, 'flavors_panel': False, + 'domains_panel': False, 'users_panel': False, - 'roles_panel': False, - 'domains_panel': False + 'groups_panel': False, + 'roles_panel': False } A dictionary of currently available AngularJS features. This allows simple diff --git a/openstack_dashboard/dashboards/identity/groups/urls.py b/openstack_dashboard/dashboards/identity/groups/urls.py index 74d4d11ee4..96b8fe2610 100644 --- a/openstack_dashboard/dashboards/identity/groups/urls.py +++ b/openstack_dashboard/dashboards/identity/groups/urls.py @@ -12,18 +12,28 @@ # License for the specific language governing permissions and limitations # under the License. +from django.conf import settings from django.conf.urls import url +from horizon.browsers.views import AngularIndexView + +from openstack_dashboard.dashboards.identity.groups import panel from openstack_dashboard.dashboards.identity.groups import views -urlpatterns = [ - url(r'^$', views.IndexView.as_view(), name='index'), - url(r'^create$', views.CreateView.as_view(), name='create'), - url(r'^(?P[^/]+)/update/$', - views.UpdateView.as_view(), name='update'), - url(r'^(?P[^/]+)/manage_members/$', - views.ManageMembersView.as_view(), name='manage_members'), - url(r'^(?P[^/]+)/add_members/$', - views.NonMembersView.as_view(), name='add_members'), -] +if settings.ANGULAR_FEATURES.get('groups_panel', False): + title = panel.Groups.name + urlpatterns = [ + url(r'^$', AngularIndexView.as_view(title=title), name='index'), + ] +else: + urlpatterns = [ + url(r'^$', views.IndexView.as_view(), name='index'), + url(r'^create$', views.CreateView.as_view(), name='create'), + url(r'^(?P[^/]+)/update/$', + views.UpdateView.as_view(), name='update'), + url(r'^(?P[^/]+)/manage_members/$', + views.ManageMembersView.as_view(), name='manage_members'), + url(r'^(?P[^/]+)/add_members/$', + views.NonMembersView.as_view(), name='add_members'), + ] diff --git a/openstack_dashboard/dashboards/identity/static/dashboard/identity/groups/groups.module.js b/openstack_dashboard/dashboards/identity/static/dashboard/identity/groups/groups.module.js new file mode 100644 index 0000000000..579ffef354 --- /dev/null +++ b/openstack_dashboard/dashboards/identity/static/dashboard/identity/groups/groups.module.js @@ -0,0 +1,123 @@ +/** + * Copyright 2016 99Cloud + * + * 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'; + + /** + * @ngdoc overview + * @ngname horizon.dashboard.identity.groups + * + * @description + * Provides all of the services and widgets required + * to support and display groups related content. + */ + angular + .module('horizon.dashboard.identity.groups', [ + 'ngRoute' + ]) + .constant('horizon.dashboard.identity.groups.resourceType', 'OS::Keystone::Group') + .run(run) + .config(config); + + run.$inject = [ + 'horizon.framework.conf.resource-type-registry.service', + 'horizon.app.core.openstack-service-api.keystone', + 'horizon.dashboard.identity.groups.basePath', + 'horizon.dashboard.identity.groups.resourceType' + ]; + + function run(registry, keystone, basePath, groupResourceType) { + registry.getResourceType(groupResourceType) + .setNames(gettext('Group'), gettext('Groups')) + .setProperties(groupProperties()) + .setListFunction(listFunction) + .tableColumns + .append({ + id: 'name', + priority: 1, + sortDefault: true + }) + .append({ + id: 'description', + priority: 1 + }) + .append({ + id: 'id', + priority: 1 + }); + + registry.getResourceType(groupResourceType).filterFacets + .append({ + label: gettext('Name'), + name: 'name', + singleton: true + }) + .append({ + label: gettext('ID'), + name: 'id', + singleton: true + }); + + function listFunction() { + return keystone.getGroups(); + } + + /** + * @name groupProperties + * @description resource properties for group module + */ + function groupProperties() { + return { + name: { + label: gettext('Name'), + filters: ['noName'] + }, + description: { + label: gettext('Description'), + filters: ['noValue'] + }, + id: { + label: gettext('ID'), + filters: ['noValue'] + } + }; + } + } + + config.$inject = [ + '$provide', + '$windowProvider', + '$routeProvider' + ]; + + /** + * @name config + * @param {Object} $provide + * @param {Object} $windowProvider + * @param {Object} $routeProvider + * @description Routes used by this module. + * @returns {undefined} Returns nothing + */ + function config($provide, $windowProvider, $routeProvider) { + var path = $windowProvider.$get().STATIC_URL + 'dashboard/identity/groups/'; + $provide.constant('horizon.dashboard.identity.groups.basePath', path); + + $routeProvider.when('/identity/groups', { + templateUrl: path + 'panel.html' + }); + } +})(); diff --git a/openstack_dashboard/dashboards/identity/static/dashboard/identity/groups/groups.module.spec.js b/openstack_dashboard/dashboards/identity/static/dashboard/identity/groups/groups.module.spec.js new file mode 100644 index 0000000000..fc64fc35a3 --- /dev/null +++ b/openstack_dashboard/dashboards/identity/static/dashboard/identity/groups/groups.module.spec.js @@ -0,0 +1,59 @@ +/** + * Copyright 2017 SUSE Linux. + * + * 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('horizon.dashboard.identity.groups', function () { + var $scope, registry, keystone; + var groups = {data: {items: [{id: '1234', name: 'test_group1'}]}}; + + beforeEach(module('horizon.app.core.openstack-service-api')); + beforeEach(module('horizon.dashboard.identity.groups')); + beforeEach(module('horizon.framework')); + beforeEach(inject(function($injector, $q, _$rootScope_) { + $scope = _$rootScope_.$new(); + registry = + $injector.get('horizon.framework.conf.resource-type-registry.service'); + keystone = $injector.get('horizon.app.core.openstack-service-api.keystone'); + var deferredGroups = $q.defer(); + deferredGroups.resolve(groups); + spyOn(keystone, 'getGroups').and.returnValue(deferredGroups.promise); + })); + + it('registers name', function() { + expect(registry.getResourceType('OS::Keystone::Group'). + getName()).toBe("Groups"); + }); + + it('should set facets for search', function () { + var group = registry.getResourceType('OS::Keystone::Group').filterFacets + .map(getName); + expect(group).toContain('name'); + expect(group).toContain('id'); + + function getName(x) { + return x.name; + } + }); + + it('should load groups', function () { + registry.getResourceType('OS::Keystone::Group').list().then(function(responses) { + $scope.$apply(); + expect(responses).toEqual(groups); + }); + }); + }); +})(); diff --git a/openstack_dashboard/dashboards/identity/static/dashboard/identity/groups/panel.html b/openstack_dashboard/dashboards/identity/static/dashboard/identity/groups/panel.html new file mode 100644 index 0000000000..4153b98aa8 --- /dev/null +++ b/openstack_dashboard/dashboards/identity/static/dashboard/identity/groups/panel.html @@ -0,0 +1,4 @@ + + + + diff --git a/openstack_dashboard/dashboards/identity/static/dashboard/identity/identity.module.js b/openstack_dashboard/dashboards/identity/static/dashboard/identity/identity.module.js index 72b6ced5d8..e54d9f369e 100644 --- a/openstack_dashboard/dashboards/identity/static/dashboard/identity/identity.module.js +++ b/openstack_dashboard/dashboards/identity/static/dashboard/identity/identity.module.js @@ -27,8 +27,9 @@ angular .module('horizon.dashboard.identity', [ 'horizon.dashboard.identity.domains', - 'horizon.dashboard.identity.users', 'horizon.dashboard.identity.projects', + 'horizon.dashboard.identity.users', + 'horizon.dashboard.identity.groups', 'horizon.dashboard.identity.roles' ]) .config(config); diff --git a/openstack_dashboard/settings.py b/openstack_dashboard/settings.py index 4284c5e646..2d03a49735 100644 --- a/openstack_dashboard/settings.py +++ b/openstack_dashboard/settings.py @@ -326,9 +326,10 @@ ANGULAR_FEATURES = { 'images_panel': True, 'key_pairs_panel': False, 'flavors_panel': False, + 'domains_panel': False, 'users_panel': False, + 'groups_panel': False, 'roles_panel': False, - 'domains_panel': False } # Notice all customizable configurations should be above this line