Angularize Key Pairs index view
This patch adds Angularized index view. Actions and details view will be implemented in subsequent patches. To use Angularized Key Pairs index view, copy following file: openstack_dashboard/local/local_settings.d/ _11_toggle_angular_features.py.example to: _11_toggle_angular_features.py and add following line into _11_toggle_angular_features.py: ANGULAR_FEATURES.update({'key_pairs_panel': True}) Change-Id: Ie1bf555430f77fc6bc95deedb8328caa5a2287aa Partial-Implements: blueprint ng-keypairs
This commit is contained in:
parent
ffd9140ae8
commit
4982dc3cda
|
@ -48,6 +48,7 @@ Default:
|
|||
|
||||
{
|
||||
'images_panel': True,
|
||||
'key_pairs_panel': False,
|
||||
'flavors_panel': False,
|
||||
'users_panel': False,
|
||||
'roles_panel': False,
|
||||
|
|
|
@ -16,12 +16,23 @@
|
|||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from django.conf import settings
|
||||
from django.conf.urls import url
|
||||
from openstack_dashboard.dashboards.project.key_pairs import views
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
urlpatterns = [
|
||||
url(r'^$', views.IndexView.as_view(), name='index'),
|
||||
url(r'^import/$', views.ImportView.as_view(), name='import'),
|
||||
url(r'^(?P<keypair_name>[^/]+)/$', views.DetailView.as_view(),
|
||||
name='detail'),
|
||||
]
|
||||
from horizon.browsers import views
|
||||
from openstack_dashboard.dashboards.project.key_pairs import views as \
|
||||
legacy_views
|
||||
|
||||
if settings.ANGULAR_FEATURES.get('key_pairs_panel'):
|
||||
title = _("Key Pairs")
|
||||
urlpatterns = [
|
||||
url('', views.AngularIndexView.as_view(title=title), name='index'),
|
||||
]
|
||||
else:
|
||||
urlpatterns = [
|
||||
url(r'^$', legacy_views.IndexView.as_view(), name='index'),
|
||||
url(r'^import/$', legacy_views.ImportView.as_view(), name='import'),
|
||||
url(r'^(?P<keypair_name>[^/]+)/$', legacy_views.DetailView.as_view(),
|
||||
name='detail'),
|
||||
]
|
||||
|
|
|
@ -324,6 +324,7 @@ COMPRESS_OFFLINE_CONTEXT = 'horizon.themes.offline_context'
|
|||
# Dictionary of currently available angular features
|
||||
ANGULAR_FEATURES = {
|
||||
'images_panel': True,
|
||||
'key_pairs_panel': False,
|
||||
'flavors_panel': False,
|
||||
'users_panel': False,
|
||||
'roles_panel': False,
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
@import "images/images";
|
||||
@import "keypairs/keypairs";
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
hz-resource-property-list[resource-type-name="OS::Nova::Keypair"] {
|
||||
hz-resource-property[prop-name="public_key"] dd {
|
||||
overflow-wrap: break-word;
|
||||
width: calc(100vw - 61px);
|
||||
@media (min-width: 992px) {
|
||||
width: calc(100vw - 281px);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
<hz-resource-property-list
|
||||
resource-type-name="OS::Nova::Keypair"
|
||||
item="item"
|
||||
property-groups="[['fingerprint', 'public_key']]">
|
||||
</hz-resource-property-list>
|
|
@ -27,7 +27,79 @@
|
|||
*/
|
||||
angular
|
||||
.module('horizon.app.core.keypairs', [
|
||||
'ngRoute',
|
||||
'horizon.app.core',
|
||||
'horizon.framework.conf'
|
||||
])
|
||||
;
|
||||
.constant('horizon.app.core.keypairs.resourceType', 'OS::Nova::Keypair')
|
||||
.run(run)
|
||||
.config(config);
|
||||
|
||||
run.$inject = [
|
||||
'horizon.framework.conf.resource-type-registry.service',
|
||||
'horizon.app.core.openstack-service-api.nova',
|
||||
'horizon.app.core.keypairs.basePath',
|
||||
'horizon.app.core.keypairs.resourceType',
|
||||
'horizon.app.core.keypairs.service'
|
||||
];
|
||||
|
||||
function run(registry, nova, basePath, resourceType, keypairsService) {
|
||||
registry.getResourceType(resourceType)
|
||||
.setNames(gettext('Key Pair'), gettext('Key Pairs'))
|
||||
// for detail summary view on table row.
|
||||
.setSummaryTemplateUrl(basePath + 'details/drawer.html')
|
||||
.setProperties(keypairProperties())
|
||||
.setListFunction(keypairsService.getKeypairsPromise)
|
||||
.tableColumns
|
||||
.append({
|
||||
id: 'name',
|
||||
priority: 1,
|
||||
sortDefault: true
|
||||
})
|
||||
.append({
|
||||
id: 'fingerprint',
|
||||
priority: 2
|
||||
});
|
||||
|
||||
// for magic-search
|
||||
registry.getResourceType(resourceType).filterFacets
|
||||
.append({
|
||||
'label': gettext('Name'),
|
||||
'name': 'name',
|
||||
'singleton': true
|
||||
});
|
||||
}
|
||||
|
||||
function keypairProperties() {
|
||||
return {
|
||||
'id': {label: gettext('ID'), filters: ['noValue'] },
|
||||
'name': {label: gettext('Name'), filters: ['noName'] },
|
||||
'fingerprint': {label: gettext('Fingerprint'), filters: ['noValue'] },
|
||||
'created_at': {label: gettext('Created'), filters: ['simpleDate'] },
|
||||
'user_id': {label: gettext('User ID'), filters: ['noValue'] },
|
||||
'public_key': {label: gettext('Public Key'), 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 + 'app/core/keypairs/';
|
||||
$provide.constant('horizon.app.core.keypairs.basePath', path);
|
||||
$routeProvider.when('/project/key_pairs', {
|
||||
templateUrl: path + 'panel.html'
|
||||
});
|
||||
}
|
||||
})();
|
||||
|
|
|
@ -22,4 +22,27 @@
|
|||
});
|
||||
});
|
||||
|
||||
describe('loading the module', function () {
|
||||
var registry;
|
||||
|
||||
beforeEach(module('horizon.app.core.keypairs'));
|
||||
beforeEach(inject(function($injector) {
|
||||
registry = $injector.get('horizon.framework.conf.resource-type-registry.service');
|
||||
}));
|
||||
|
||||
it('registers names', function() {
|
||||
expect(registry.getResourceType('OS::Nova::Keypair').getName()).toBe("Key Pairs");
|
||||
});
|
||||
|
||||
it('should set facets for search', function () {
|
||||
var names = registry.getResourceType('OS::Nova::Keypair').filterFacets
|
||||
.map(getName);
|
||||
expect(names).toContain('name');
|
||||
|
||||
function getName(x) {
|
||||
// underscore.js and .pluck() would be great here.
|
||||
return x.name;
|
||||
}
|
||||
});
|
||||
});
|
||||
})();
|
||||
|
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* 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.app.core.keypairs')
|
||||
.factory('horizon.app.core.keypairs.service', keypairsService);
|
||||
|
||||
keypairsService.$inject = [
|
||||
'$filter',
|
||||
'horizon.app.core.openstack-service-api.nova'
|
||||
];
|
||||
|
||||
/*
|
||||
* @ngdoc factory
|
||||
* @name horizon.app.core.keypairs.service
|
||||
*
|
||||
* @description
|
||||
* This service provides functions that are used through the key pair
|
||||
* features. These are primarily used in the module registrations
|
||||
* but do not need to be restricted to such use. Each exposed function
|
||||
* is documented below.
|
||||
*/
|
||||
function keypairsService($filter, nova) {
|
||||
return {
|
||||
getKeypairsPromise: getKeypairsPromise
|
||||
};
|
||||
|
||||
/*
|
||||
* @ngdoc function
|
||||
* @name getKeypairsPromise
|
||||
* @description
|
||||
* Given filter/query parameters, returns a promise for the matching
|
||||
* key pairs. This is used in displaying lists of key pairs. In this
|
||||
* case, we need to modify the API's response by adding a composite value
|
||||
* called 'trackBy' to assist the display mechanism when updating rows.
|
||||
*/
|
||||
function getKeypairsPromise(params) {
|
||||
return nova.getKeypairs(params).then(modifyResponse);
|
||||
|
||||
function modifyResponse(response) {
|
||||
return {data: {items: response.data.items.map(modifyItems)}};
|
||||
|
||||
function modifyItems(item) {
|
||||
item = item.keypair;
|
||||
item.trackBy = item.name;
|
||||
return item;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
})();
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* 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.app.core.keypairs', function () {
|
||||
it('should exist', function () {
|
||||
expect(angular.module('horizon.app.core.keypairs')).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('keypairsService', function() {
|
||||
var service;
|
||||
beforeEach(module('horizon.app.core'));
|
||||
beforeEach(inject(function($injector) {
|
||||
service = $injector.get('horizon.app.core.keypairs.service');
|
||||
}));
|
||||
|
||||
describe('getKeypairsPromise', function() {
|
||||
it("provides a promise that gets translated", inject(function($q, $injector, $timeout) {
|
||||
var nova = $injector.get('horizon.app.core.openstack-service-api.nova');
|
||||
var session = $injector.get('horizon.app.core.openstack-service-api.userSession');
|
||||
var deferred = $q.defer();
|
||||
var deferredSession = $q.defer();
|
||||
spyOn(nova, 'getKeypairs').and.returnValue(deferred.promise);
|
||||
spyOn(session, 'get').and.returnValue(deferredSession.promise);
|
||||
var result = service.getKeypairsPromise({});
|
||||
deferredSession.resolve({});
|
||||
deferred.resolve({
|
||||
data: {
|
||||
items: [{keypair: {name: 'keypair1'}}]
|
||||
}
|
||||
});
|
||||
$timeout.flush();
|
||||
expect(nova.getKeypairs).toHaveBeenCalled();
|
||||
expect(result.$$state.value.data.items[0].name).toBe('keypair1');
|
||||
expect(result.$$state.value.data.items[0].trackBy).toBe('keypair1');
|
||||
}));
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
})();
|
|
@ -0,0 +1,5 @@
|
|||
<hz-resource-panel resource-type-name="OS::Nova::Keypair">
|
||||
<hz-resource-table resource-type-name="OS::Nova::Keypair"
|
||||
track-by="trackBy">
|
||||
</hz-resource-table>
|
||||
</hz-resource-panel>
|
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
features:
|
||||
- |
|
||||
[`blueprint ng-keypairs <https://blueprints.launchpad.net/horizon/+spec/ng-keypairs>`_]
|
||||
Add Angular Key Pairs panel. The Key Pairs panel allows users to view
|
||||
a list of created or imported key pairs. This panel displays a table
|
||||
view of the name and fingerprint of each key pair. Also, public key
|
||||
is shown in expanded row.
|
Loading…
Reference in New Issue