Merge "Reproduce navigations on refreshing ngdetails view"
This commit is contained in:
commit
febb96507b
@ -100,7 +100,10 @@ class AngularDetailsView(generic.TemplateView):
|
|||||||
title = _("Horizon")
|
title = _("Horizon")
|
||||||
context["title"] = title
|
context["title"] = title
|
||||||
context["page_title"] = title
|
context["page_title"] = title
|
||||||
|
# set default dashboard and panel
|
||||||
dashboard = horizon.get_default_dashboard()
|
dashboard = horizon.get_default_dashboard()
|
||||||
self.request.horizon['dashboard'] = dashboard
|
self.request.horizon['dashboard'] = dashboard
|
||||||
self.request.horizon['panel'] = dashboard.get_panels()[0]
|
self.request.horizon['panel'] = dashboard.get_panels()[0]
|
||||||
|
# set flag that means routed by django
|
||||||
|
context['routed_by_django'] = True
|
||||||
return context
|
return context
|
||||||
|
@ -139,6 +139,10 @@
|
|||||||
self.summaryTemplateUrl = false;
|
self.summaryTemplateUrl = false;
|
||||||
self.setSummaryTemplateUrl = setSummaryTemplateUrl;
|
self.setSummaryTemplateUrl = setSummaryTemplateUrl;
|
||||||
|
|
||||||
|
self.defaultIndexUrl = false;
|
||||||
|
self.setDefaultIndexUrl = setDefaultIndexUrl;
|
||||||
|
self.getDefaultIndexUrl = getDefaultIndexUrl;
|
||||||
|
|
||||||
// Function declarations
|
// Function declarations
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -503,6 +507,35 @@
|
|||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ngdoc function
|
||||||
|
* @name setDefaultIndexUrl
|
||||||
|
* @param url
|
||||||
|
* @description
|
||||||
|
* This sets the defaultIndexUrl property on the resourceType.
|
||||||
|
*
|
||||||
|
* That URL points to a index view that shows table view for the
|
||||||
|
* resource type. The defaultIndexUrl will be used when details view
|
||||||
|
* should redirect to index view (e.g. after deletion of the resource
|
||||||
|
* itself) or should reset navigations (e.g. after refreshing details
|
||||||
|
* view by browser).
|
||||||
|
*/
|
||||||
|
function setDefaultIndexUrl(url) {
|
||||||
|
self.defaultIndexUrl = url;
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ngdoc function
|
||||||
|
* @name setDefaultIndexUrl
|
||||||
|
* @param url
|
||||||
|
* @description
|
||||||
|
* This returns the defaultIndexUrl property on the resourceType.
|
||||||
|
*/
|
||||||
|
function getDefaultIndexUrl() {
|
||||||
|
return self.defaultIndexUrl;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ngdoc function
|
* @ngdoc function
|
||||||
* @name setItemNameFunction
|
* @name setItemNameFunction
|
||||||
|
@ -0,0 +1,19 @@
|
|||||||
|
/*
|
||||||
|
* 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.framework.util.navigations', []);
|
||||||
|
|
||||||
|
})();
|
109
horizon/static/framework/util/navigations/navigations.service.js
Normal file
109
horizon/static/framework/util/navigations/navigations.service.js
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
/*
|
||||||
|
* 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.framework.util.navigations')
|
||||||
|
.factory('horizon.framework.util.navigations.service', navigationsService);
|
||||||
|
|
||||||
|
function navigationsService() {
|
||||||
|
|
||||||
|
return {
|
||||||
|
getActivePanelUrl: getActivePanelUrl,
|
||||||
|
collapseAllNavigation: collapseAllNavigation,
|
||||||
|
expandNavigationByUrl: expandNavigationByUrl,
|
||||||
|
setBreadcrumb: setBreadcrumb
|
||||||
|
};
|
||||||
|
|
||||||
|
/* get URL for active panel on navigation side bar */
|
||||||
|
function getActivePanelUrl() {
|
||||||
|
return angular.element('a.openstack-panel.active').attr('href');
|
||||||
|
}
|
||||||
|
|
||||||
|
/* collapse all nodes on navigation side bar */
|
||||||
|
function collapseAllNavigation() {
|
||||||
|
// collapse all dashboards
|
||||||
|
var dashboards = angular.element(".openstack-dashboard").children("a");
|
||||||
|
dashboards.addClass("collapsed").attr("aria-expanded", false);
|
||||||
|
dashboards.siblings("ul").removeClass("in").attr("style", "height: 0px");
|
||||||
|
|
||||||
|
// collapse all panelgroups
|
||||||
|
var panelgroups = angular.element(".openstack-panel-group").children("a");
|
||||||
|
panelgroups.addClass("collapsed").attr("aria-expanded", false);
|
||||||
|
panelgroups.siblings("div").removeClass("in").attr("style", "height: 0px");
|
||||||
|
|
||||||
|
// remove active from all panels
|
||||||
|
angular.element("a.openstack-panel").removeClass("active");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* expand specified node on navigation side bar */
|
||||||
|
function expandNavigationByUrl(url) {
|
||||||
|
// collapse all navigation
|
||||||
|
collapseAllNavigation();
|
||||||
|
|
||||||
|
var labels = [];
|
||||||
|
|
||||||
|
// get panel on nav_bar
|
||||||
|
var panel = angular.element("a.openstack-panel[href='" + url + "']");
|
||||||
|
|
||||||
|
// get panelgroup on nav_bar
|
||||||
|
var panelgroup = panel.parents(".openstack-panel-group").children("a");
|
||||||
|
|
||||||
|
// get dashboard on nav_bar
|
||||||
|
var dashboard = panel.parents(".openstack-dashboard").children("a");
|
||||||
|
|
||||||
|
// open dashboard nav
|
||||||
|
dashboard.removeClass("collapsed").attr("aria-expanded", true);
|
||||||
|
dashboard.siblings("ul").addClass("in").attr("style", null);
|
||||||
|
// get dashboard label
|
||||||
|
labels.push(dashboard.text().trim());
|
||||||
|
|
||||||
|
// open panelgroup on nav_bar if exists
|
||||||
|
if (panelgroup.length) {
|
||||||
|
panelgroup.removeClass("collapsed").attr("aria-expanded", true);
|
||||||
|
// get panelgroup label
|
||||||
|
labels.push(panelgroup.text().trim());
|
||||||
|
}
|
||||||
|
|
||||||
|
// open container for panels
|
||||||
|
panel.parent().addClass("in").attr("style", null);
|
||||||
|
|
||||||
|
// set panel active
|
||||||
|
panel.addClass("active");
|
||||||
|
// get panel label
|
||||||
|
labels.push(panel.text().trim());
|
||||||
|
|
||||||
|
return labels;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* set breadcrumb items by array. The last item will be set as active */
|
||||||
|
function setBreadcrumb(items) {
|
||||||
|
var breadcrumb = angular.element("div.page-breadcrumb ol.breadcrumb");
|
||||||
|
|
||||||
|
// remove all items
|
||||||
|
breadcrumb.empty();
|
||||||
|
|
||||||
|
// add items
|
||||||
|
items.forEach(function (item, index, array) {
|
||||||
|
var newItem = angular.element("<li>").addClass("breadcrumb-item-truncate");
|
||||||
|
if (array.length - 1 === index) {
|
||||||
|
newItem.addClass("active");
|
||||||
|
}
|
||||||
|
newItem.text(item);
|
||||||
|
breadcrumb.append(newItem);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})();
|
@ -0,0 +1,163 @@
|
|||||||
|
/*
|
||||||
|
* (c) Copyright 2016 Hewlett Packard Enterprise Development Company LP
|
||||||
|
*
|
||||||
|
* 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.framework.util.navigations.service', function() {
|
||||||
|
var service, navigations, spyElement;
|
||||||
|
var imagesUrl = '/project/images/';
|
||||||
|
var breadcrumb = ['Project', 'Compute', 'Images'];
|
||||||
|
var breadcrumbWithoutGroup = ['Project', 'Images'];
|
||||||
|
|
||||||
|
function getNavsElement (selector) {
|
||||||
|
try {
|
||||||
|
// for searching element
|
||||||
|
return navigations.find(selector);
|
||||||
|
} catch (e) {
|
||||||
|
// for creating element
|
||||||
|
return $(selector);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
beforeEach(module('horizon.framework.util.navigations'));
|
||||||
|
|
||||||
|
beforeEach(inject(function($injector) {
|
||||||
|
service = $injector.get('horizon.framework.util.navigations.service');
|
||||||
|
navigations = angular.element(
|
||||||
|
'<div>' +
|
||||||
|
' <!-- navigation side bar -->' +
|
||||||
|
' <li class="openstack-dashboard">' +
|
||||||
|
' <a class="" aria-expanded="true">' +
|
||||||
|
' Project' +
|
||||||
|
' </a>' +
|
||||||
|
' <ul class="in" style="">' +
|
||||||
|
' <li class="openstack-panel-group">' +
|
||||||
|
' <a class="" area-expanded="true">' +
|
||||||
|
' Compute' +
|
||||||
|
' </a>' +
|
||||||
|
' <div class="in" style="">' +
|
||||||
|
' <a class="openstack-panel active" href="/project/images/">' +
|
||||||
|
' Images' +
|
||||||
|
' </a>' +
|
||||||
|
' </div>' +
|
||||||
|
' </li>' +
|
||||||
|
' </ul>' +
|
||||||
|
' </li>' +
|
||||||
|
' <!-- breadcrumb -->' +
|
||||||
|
' <div class="page-breadcrumb">' +
|
||||||
|
' <ol class="breadcrumb">' +
|
||||||
|
' <li>Project</li>' +
|
||||||
|
' <li>Compute</li>' +
|
||||||
|
' <li class="active">Images</li>' +
|
||||||
|
' </ol>' +
|
||||||
|
' </div>' +
|
||||||
|
'</div>');
|
||||||
|
spyElement = spyOn(angular, 'element').and.callFake(getNavsElement);
|
||||||
|
}));
|
||||||
|
|
||||||
|
afterEach(function() {
|
||||||
|
spyElement.and.callThrough();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('getActivePanelUrl', function() {
|
||||||
|
it('returns an empty array if no items', function() {
|
||||||
|
var activeUrl = service.getActivePanelUrl();
|
||||||
|
|
||||||
|
expect(activeUrl).toBe(imagesUrl);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('collapseAllNavigation', function() {
|
||||||
|
it('collapse all nodes on navigation side bar', function() {
|
||||||
|
service.collapseAllNavigation();
|
||||||
|
|
||||||
|
var hasIn = navigations.find('.in');
|
||||||
|
expect(hasIn.length).toBe(0);
|
||||||
|
var collapsed = navigations.find('a.collapsed[aria-expanded=false]');
|
||||||
|
expect(collapsed.length).toBe(2);
|
||||||
|
var hasActive = navigations.find('a.openstack-panel.active');
|
||||||
|
expect(hasActive.length).toBe(0);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('expandNavigationByUrl', function() {
|
||||||
|
it('expands navigation side bar and return their label of selected nodes', function() {
|
||||||
|
spyOn(service, 'collapseAllNavigation').and.callThrough();
|
||||||
|
var list = service.expandNavigationByUrl(imagesUrl);
|
||||||
|
|
||||||
|
expect(list).toEqual(breadcrumb);
|
||||||
|
|
||||||
|
var hasIn = navigations.find('.in');
|
||||||
|
expect(hasIn.length).toBe(2);
|
||||||
|
var expanded = navigations.find('a[aria-expanded=true]');
|
||||||
|
expect(expanded.length).toBe(2);
|
||||||
|
var hasActive = navigations.find('a.openstack-panel.active');
|
||||||
|
expect(hasActive.length).toBe(1);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('expandNavigationByUrl', function() {
|
||||||
|
it('expands navigation side bar without panelgroup' +
|
||||||
|
'and return their label of selected nodes', function() {
|
||||||
|
navigations = angular.element(
|
||||||
|
'<div>' +
|
||||||
|
' <!-- navigation side bar -->' +
|
||||||
|
' <li class="openstack-dashboard">' +
|
||||||
|
' <a class="" aria-expanded="true">' +
|
||||||
|
' Project' +
|
||||||
|
' </a>' +
|
||||||
|
' <ul class="in" style="">' +
|
||||||
|
' <div class="in" style="">' +
|
||||||
|
' <a class="openstack-panel active" href="/project/images/">' +
|
||||||
|
' Images' +
|
||||||
|
' </a>' +
|
||||||
|
' </div>' +
|
||||||
|
' </ul>' +
|
||||||
|
' </li>' +
|
||||||
|
' <!-- breadcrumb -->' +
|
||||||
|
' <div class="page-breadcrumb">' +
|
||||||
|
' <ol class="breadcrumb">' +
|
||||||
|
' <li>Project</li>' +
|
||||||
|
' <li>Compute</li>' +
|
||||||
|
' <li class="active">Images</li>' +
|
||||||
|
' </ol>' +
|
||||||
|
' </div>' +
|
||||||
|
'</div>');
|
||||||
|
|
||||||
|
spyOn(service, 'collapseAllNavigation').and.callThrough();
|
||||||
|
var list = service.expandNavigationByUrl(imagesUrl);
|
||||||
|
|
||||||
|
expect(list).toEqual(breadcrumbWithoutGroup);
|
||||||
|
|
||||||
|
var hasIn = navigations.find('.in');
|
||||||
|
expect(hasIn.length).toBe(2);
|
||||||
|
var expanded = navigations.find('a[aria-expanded=true]');
|
||||||
|
expect(expanded.length).toBe(1);
|
||||||
|
var hasActive = navigations.find('a.openstack-panel.active');
|
||||||
|
expect(hasActive.length).toBe(1);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('setBreadcrumb', function() {
|
||||||
|
it('sets breadcrumb items from specified array', function() {
|
||||||
|
service.setBreadcrumb(breadcrumb);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
})();
|
@ -23,6 +23,7 @@
|
|||||||
'horizon.framework.util.filters',
|
'horizon.framework.util.filters',
|
||||||
'horizon.framework.util.http',
|
'horizon.framework.util.http',
|
||||||
'horizon.framework.util.i18n',
|
'horizon.framework.util.i18n',
|
||||||
|
'horizon.framework.util.navigations',
|
||||||
'horizon.framework.util.promise-toggle',
|
'horizon.framework.util.promise-toggle',
|
||||||
'horizon.framework.util.q',
|
'horizon.framework.util.q',
|
||||||
'horizon.framework.util.tech-debt',
|
'horizon.framework.util.tech-debt',
|
||||||
|
@ -23,7 +23,9 @@
|
|||||||
controller.$inject = [
|
controller.$inject = [
|
||||||
'horizon.framework.conf.resource-type-registry.service',
|
'horizon.framework.conf.resource-type-registry.service',
|
||||||
'horizon.framework.util.actions.action-result.service',
|
'horizon.framework.util.actions.action-result.service',
|
||||||
|
'horizon.framework.util.navigations.service',
|
||||||
'horizon.framework.widgets.modal-wait-spinner.service',
|
'horizon.framework.widgets.modal-wait-spinner.service',
|
||||||
|
'$location',
|
||||||
'$q',
|
'$q',
|
||||||
'$routeParams'
|
'$routeParams'
|
||||||
];
|
];
|
||||||
@ -31,7 +33,9 @@
|
|||||||
function controller(
|
function controller(
|
||||||
registry,
|
registry,
|
||||||
resultService,
|
resultService,
|
||||||
|
navigationsService,
|
||||||
spinnerService,
|
spinnerService,
|
||||||
|
$location,
|
||||||
$q,
|
$q,
|
||||||
$routeParams
|
$routeParams
|
||||||
) {
|
) {
|
||||||
@ -45,6 +49,34 @@
|
|||||||
ctrl.defaultTemplateUrl = registry.getDefaultDetailsTemplateUrl();
|
ctrl.defaultTemplateUrl = registry.getDefaultDetailsTemplateUrl();
|
||||||
ctrl.resultHandler = actionResultHandler;
|
ctrl.resultHandler = actionResultHandler;
|
||||||
|
|
||||||
|
checkRoutedByDjango(ctrl.resourceType);
|
||||||
|
|
||||||
|
function checkRoutedByDjango(resourceType) {
|
||||||
|
// get flag that means routed once by django.
|
||||||
|
var routedByDjango = angular.element("ngdetails").attr("routed-by-django");
|
||||||
|
if (routedByDjango === "True") {
|
||||||
|
// If django routed to ngdetails view, navigations (i.e. side bar and
|
||||||
|
// breadcrumbs) are set as default dashboard and panel by django side
|
||||||
|
// AngularDetailsView.
|
||||||
|
// So reset navigations properly using defaultIndexUrl parameter for
|
||||||
|
// resource-type-service.
|
||||||
|
|
||||||
|
// get defaultIndexUrl
|
||||||
|
var url = resourceType.getDefaultIndexUrl();
|
||||||
|
// if querystring has 'nav' parameter, overwrite the url
|
||||||
|
var query = $location.search();
|
||||||
|
if (query.hasOwnProperty("nav")) {
|
||||||
|
url = query.nav;
|
||||||
|
}
|
||||||
|
// set navigations (side bar and breadcrumb)
|
||||||
|
var labels = navigationsService.expandNavigationByUrl(url);
|
||||||
|
navigationsService.setBreadcrumb(labels);
|
||||||
|
|
||||||
|
// clear flag
|
||||||
|
angular.element("ngdetails").removeAttr("routed-by-django");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function actionResultHandler(returnValue) {
|
function actionResultHandler(returnValue) {
|
||||||
return $q.when(returnValue, actionSuccessHandler);
|
return $q.when(returnValue, actionSuccessHandler);
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
describe('RoutedDetailsViewController', function() {
|
describe('RoutedDetailsViewController', function() {
|
||||||
var ctrl, deferred, $timeout, $q, actionResultService;
|
var ctrl, deferred, $timeout, $q, actionResultService, navigationsService;
|
||||||
|
|
||||||
beforeEach(module('horizon.framework.widgets.details'));
|
beforeEach(module('horizon.framework.widgets.details'));
|
||||||
beforeEach(inject(function($injector, $controller, _$q_, _$timeout_) {
|
beforeEach(inject(function($injector, $controller, _$q_, _$timeout_) {
|
||||||
@ -32,7 +32,8 @@
|
|||||||
load: function() { return deferred.promise; },
|
load: function() { return deferred.promise; },
|
||||||
parsePath: function() { return 'my-context'; },
|
parsePath: function() { return 'my-context'; },
|
||||||
itemName: function() { return 'A name'; },
|
itemName: function() { return 'A name'; },
|
||||||
initActions: angular.noop
|
initActions: angular.noop,
|
||||||
|
getDefaultIndexUrl: function() { return '/project/images/'; }
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
getDefaultDetailsTemplateUrl: angular.noop
|
getDefaultDetailsTemplateUrl: angular.noop
|
||||||
@ -42,9 +43,15 @@
|
|||||||
getIdsOfType: function() { return []; }
|
getIdsOfType: function() { return []; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
navigationsService = {
|
||||||
|
expandNavigationByUrl: function() { return ['Project', 'Compute', 'Images']; },
|
||||||
|
setBreadcrumb: angular.noop
|
||||||
|
};
|
||||||
|
|
||||||
ctrl = $controller("RoutedDetailsViewController", {
|
ctrl = $controller("RoutedDetailsViewController", {
|
||||||
'horizon.framework.conf.resource-type-registry.service': service,
|
'horizon.framework.conf.resource-type-registry.service': service,
|
||||||
'horizon.framework.util.actions.action-result.service': actionResultService,
|
'horizon.framework.util.actions.action-result.service': actionResultService,
|
||||||
|
'horizon.framework.util.navigations.service': navigationsService,
|
||||||
'horizon.framework.widgets.modal-wait-spinner.service': {
|
'horizon.framework.widgets.modal-wait-spinner.service': {
|
||||||
showModalSpinner: angular.noop,
|
showModalSpinner: angular.noop,
|
||||||
hideModalSpinner: angular.noop
|
hideModalSpinner: angular.noop
|
||||||
|
@ -45,6 +45,7 @@
|
|||||||
registry.getResourceType(domainResourceType)
|
registry.getResourceType(domainResourceType)
|
||||||
.setNames(gettext('Domain'), gettext('Domains'))
|
.setNames(gettext('Domain'), gettext('Domains'))
|
||||||
.setSummaryTemplateUrl(basePath + 'details/drawer.html')
|
.setSummaryTemplateUrl(basePath + 'details/drawer.html')
|
||||||
|
.setDefaultIndexUrl('/identity/domains/')
|
||||||
.setProperties(domainProperties())
|
.setProperties(domainProperties())
|
||||||
.setListFunction(domainService.listDomains)
|
.setListFunction(domainService.listDomains)
|
||||||
.tableColumns
|
.tableColumns
|
||||||
|
@ -48,6 +48,7 @@
|
|||||||
registry.getResourceType(userResourceType)
|
registry.getResourceType(userResourceType)
|
||||||
.setNames(gettext('User'), gettext('Users'))
|
.setNames(gettext('User'), gettext('Users'))
|
||||||
.setSummaryTemplateUrl(basePath + 'details/drawer.html')
|
.setSummaryTemplateUrl(basePath + 'details/drawer.html')
|
||||||
|
.setDefaultIndexUrl('/identity/users/')
|
||||||
.setProperties(userProperties())
|
.setProperties(userProperties())
|
||||||
.setListFunction(usersService.getUsersPromise)
|
.setListFunction(usersService.getUsersPromise)
|
||||||
.setNeedsFilterFirstFunction(usersService.getFilterFirstSettingPromise)
|
.setNeedsFilterFirstFunction(usersService.getFilterFirstSettingPromise)
|
||||||
|
@ -73,6 +73,7 @@
|
|||||||
registry.getResourceType(imageResourceType)
|
registry.getResourceType(imageResourceType)
|
||||||
.setNames(gettext('Image'), gettext('Images'))
|
.setNames(gettext('Image'), gettext('Images'))
|
||||||
.setSummaryTemplateUrl(basePath + 'details/drawer.html')
|
.setSummaryTemplateUrl(basePath + 'details/drawer.html')
|
||||||
|
.setDefaultIndexUrl('/project/images/')
|
||||||
.setItemInTransitionFunction(imagesService.isInTransition)
|
.setItemInTransitionFunction(imagesService.isInTransition)
|
||||||
.setProperties(imageProperties(imagesService, statuses))
|
.setProperties(imageProperties(imagesService, statuses))
|
||||||
.setListFunction(imagesService.getImagesPromise)
|
.setListFunction(imagesService.getImagesPromise)
|
||||||
|
@ -66,7 +66,11 @@
|
|||||||
* view.
|
* view.
|
||||||
*/
|
*/
|
||||||
function getDetailsPath(item) {
|
function getDetailsPath(item) {
|
||||||
return detailRoute + 'OS::Glance::Image/' + item.id;
|
var detailsPath = detailRoute + 'OS::Glance::Image/' + item.id;
|
||||||
|
if ($location.url() === '/admin/images') {
|
||||||
|
detailsPath = detailsPath + "?nav=/admin/images/";
|
||||||
|
}
|
||||||
|
return detailsPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -48,6 +48,7 @@
|
|||||||
.setNames(gettext('Key Pair'), gettext('Key Pairs'))
|
.setNames(gettext('Key Pair'), gettext('Key Pairs'))
|
||||||
// for detail summary view on table row.
|
// for detail summary view on table row.
|
||||||
.setSummaryTemplateUrl(basePath + 'details/drawer.html')
|
.setSummaryTemplateUrl(basePath + 'details/drawer.html')
|
||||||
|
.setDefaultIndexUrl('/project/key_pairs/')
|
||||||
.setProperties(keypairProperties())
|
.setProperties(keypairProperties())
|
||||||
.setListFunction(keypairsService.getKeypairsPromise)
|
.setListFunction(keypairsService.getKeypairsPromise)
|
||||||
.tableColumns
|
.tableColumns
|
||||||
|
@ -46,6 +46,7 @@
|
|||||||
registry.getResourceType(qosResourceType)
|
registry.getResourceType(qosResourceType)
|
||||||
.setNames(gettext('QoS Policy'), gettext('QoS Policies'))
|
.setNames(gettext('QoS Policy'), gettext('QoS Policies'))
|
||||||
.setSummaryTemplateUrl(basePath + 'details/drawer.html')
|
.setSummaryTemplateUrl(basePath + 'details/drawer.html')
|
||||||
|
.setDefaultIndexUrl('/project/network_qos/')
|
||||||
.setProperties(qosProperties(qosService))
|
.setProperties(qosProperties(qosService))
|
||||||
.setListFunction(qosService.getPoliciesPromise)
|
.setListFunction(qosService.getPoliciesPromise)
|
||||||
.tableColumns
|
.tableColumns
|
||||||
|
@ -54,6 +54,7 @@
|
|||||||
registry.getResourceType(trunkResourceType)
|
registry.getResourceType(trunkResourceType)
|
||||||
.setNames(gettext('Trunk'), gettext('Trunks'))
|
.setNames(gettext('Trunk'), gettext('Trunks'))
|
||||||
.setSummaryTemplateUrl(basePath + 'summary.html')
|
.setSummaryTemplateUrl(basePath + 'summary.html')
|
||||||
|
.setDefaultIndexUrl('/project/trunks/')
|
||||||
.setProperties(trunkProperties())
|
.setProperties(trunkProperties())
|
||||||
.setListFunction(trunksService.getTrunksPromise)
|
.setListFunction(trunksService.getTrunksPromise)
|
||||||
.tableColumns
|
.tableColumns
|
||||||
|
@ -11,4 +11,5 @@
|
|||||||
|
|
||||||
{% block main %}
|
{% block main %}
|
||||||
<div ng-view></div>
|
<div ng-view></div>
|
||||||
|
<ngdetails routed-by-django="{{ routed_by_django }}">
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
6
releasenotes/notes/bug-1746706-8d2f982c514f22b1.yaml
Normal file
6
releasenotes/notes/bug-1746706-8d2f982c514f22b1.yaml
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
fixes:
|
||||||
|
- |
|
||||||
|
[:bug:`1746706`] Fixed a bug the navigation menu and breadcrumb list
|
||||||
|
are not reproduced properly when reloading or opening Angular-based
|
||||||
|
detail page directly.
|
Loading…
Reference in New Issue
Block a user