Reload route after performing actions

This removes any special handler functions being used by some tables
and detail pages to refresh the data after performing an action and
just reloads the angular route instead. It's simpler and consistent.

Partially-Implements: blueprint horizon-lbaas-v2-ui
Change-Id: I6b696f51cf709e11bd027f8a10038874479c51db
This commit is contained in:
Justin Pomeroy 2016-03-07 21:24:11 -06:00
parent e208757a24
commit 1240c01a84
23 changed files with 99 additions and 111 deletions

View File

@ -51,7 +51,7 @@
function tableBatchActions(
$q, $location, workflowModal, policy, gettext, loadBalancersService, deleteService
) {
var loadBalancerIsActionable, loadBalancerId, handler;
var loadBalancerIsActionable, loadBalancerId;
var create = workflowModal.init({
controller: 'CreateListenerWizardController',
@ -69,9 +69,8 @@
///////////////
function init(_loadBalancerId_, _handler_) {
function init(_loadBalancerId_) {
loadBalancerId = _loadBalancerId_;
handler = _handler_;
loadBalancerIsActionable = loadBalancersService.isActionable(loadBalancerId);
return service;
}
@ -84,7 +83,7 @@
text: gettext('Create Listener')
}
},{
service: deleteService.init(loadBalancerId, loadBalancerIsActionable, handler),
service: deleteService.init(loadBalancerId, loadBalancerIsActionable),
template: {
text: gettext('Delete Listeners'),
type: 'delete-selected'

View File

@ -54,7 +54,7 @@
function deleteService(
$q, $location, $route, deleteModal, api, policy, toast, qExtensions, gettext
) {
var loadbalancerId, statePromise, handler;
var loadbalancerId, statePromise;
var context = {
labels: {
title: gettext('Confirm Delete Listeners'),
@ -80,10 +80,9 @@
//////////////
function init(_loadbalancerId_, _statePromise_, _handler_) {
function init(_loadbalancerId_, _statePromise_) {
loadbalancerId = _loadbalancerId_;
statePromise = _statePromise_;
handler = _handler_;
return service;
}
@ -108,9 +107,7 @@
}
function actionComplete(eventType) {
if (angular.isFunction(handler)) {
handler();
} else if (eventType === context.failedEvent) {
if (eventType === context.failedEvent) {
// Action failed, reload the page
$route.reload();
} else {

View File

@ -157,14 +157,5 @@
expect(toast.add).toHaveBeenCalledWith('success', 'Deleted listeners: First.');
});
it('should call handler function if provided', function() {
var handler = { handler: angular.noop };
spyOn(handler, 'handler');
service.init('1', null, handler.handler);
service.perform(items);
$scope.$apply();
expect(handler.handler).toHaveBeenCalled();
});
});
})();

View File

@ -54,7 +54,7 @@
$q, $route, workflowModal, policy, gettext, loadBalancersService, deleteService,
createPoolService
) {
var loadbalancerId, loadBalancerIsActionable, handler;
var loadbalancerId, loadBalancerIsActionable;
var edit = workflowModal.init({
controller: 'EditListenerWizardController',
@ -72,9 +72,8 @@
///////////////
function init(_loadbalancerId_, _handler_) {
function init(_loadbalancerId_) {
loadbalancerId = _loadbalancerId_;
handler = _handler_;
loadBalancerIsActionable = loadBalancersService.isActionable(loadbalancerId);
return service;
}
@ -91,7 +90,7 @@
text: gettext('Create Pool')
}
},{
service: deleteService.init(loadbalancerId, loadBalancerIsActionable, handler),
service: deleteService.init(loadbalancerId, loadBalancerIsActionable),
template: {
text: gettext('Delete Listener'),
type: 'delete'

View File

@ -48,8 +48,8 @@
ctrl.src = [];
ctrl.checked = {};
ctrl.loadbalancerId = $routeParams.loadbalancerId;
ctrl.batchActions = batchActions.init(ctrl.loadbalancerId, init);
ctrl.rowActions = rowActions.init(ctrl.loadbalancerId, init);
ctrl.batchActions = batchActions.init(ctrl.loadbalancerId);
ctrl.rowActions = rowActions.init(ctrl.loadbalancerId);
init();

View File

@ -66,7 +66,7 @@
expect(ctrl.src).toEqual(items);
expect(ctrl.checked).toEqual({});
expect(ctrl.loadbalancerId).toEqual('1234');
expect(rowActions.init).toHaveBeenCalledWith(ctrl.loadbalancerId, jasmine.any(Function));
expect(rowActions.init).toHaveBeenCalledWith(ctrl.loadbalancerId);
expect(ctrl.rowActions).toBeDefined();
expect(ctrl.rowActions).toEqual(rowActions);
expect(ctrl.batchActions).toBeDefined();

View File

@ -47,7 +47,6 @@
*/
function tableBatchActions($location, workflowModal, basePath, deleteService, policy, gettext) {
var handler;
var create = workflowModal.init({
controller: 'CreateLoadBalancerWizardController',
@ -57,19 +56,13 @@
});
var service = {
actions: actions,
init: init
actions: actions
};
return service;
///////////////
function init(_handler_) {
handler = _handler_;
return service;
}
function actions() {
return [{
service: create,
@ -78,7 +71,7 @@
text: gettext('Create Load Balancer')
}
}, {
service: deleteService.init(handler),
service: deleteService,
template: {
type: 'delete-selected',
text: gettext('Delete Load Balancers')

View File

@ -54,8 +54,6 @@
function deleteService(
$q, $location, $route, deleteModal, api, policy, toast, qExtensions, gettext
) {
var handler;
// If a batch delete, then this message is displayed for any selected load balancers not in
// ACTIVE or ERROR state.
var notAllowedMessage = gettext('The following load balancers are pending and cannot be ' +
@ -77,19 +75,13 @@
var service = {
perform: perform,
allowed: allowed,
init: init
allowed: allowed
};
return service;
//////////////
function init(_handler_) {
handler = _handler_;
return service;
}
function perform(items) {
if (angular.isArray(items)) {
qExtensions.allSettled(items.map(checkPermission)).then(afterCheck);
@ -144,9 +136,7 @@
}
function actionComplete(eventType) {
if (angular.isFunction(handler)) {
handler();
} else if (eventType === context.failedEvent) {
if (eventType === context.failedEvent) {
// Action failed, reload the page
$route.reload();
} else {

View File

@ -173,14 +173,5 @@
expect(toast.add).toHaveBeenCalledWith('success', 'Deleted load balancers: First.');
});
it('should call handler function if provided', function() {
var handler = { handler: angular.noop };
spyOn(handler, 'handler');
service.init(handler.handler);
service.perform(items);
$scope.$apply();
expect(handler.handler).toHaveBeenCalled();
});
});
})();

View File

@ -66,8 +66,6 @@
qExtensions,
gettext
) {
var handler;
var edit = workflowModal.init({
controller: 'EditLoadBalancerWizardController',
message: gettext('The load balancer has been updated.'),
@ -76,19 +74,13 @@
});
var service = {
actions: actions,
init: init
actions: actions
};
return service;
///////////////
function init(_handler_) {
handler = _handler_;
return service;
}
function actions() {
return [{
service: edit,
@ -106,7 +98,7 @@
text: gettext('Disassociate Floating IP')
}
},{
service: deleteService.init(handler),
service: deleteService,
template: {
text: gettext('Delete Load Balancer'),
type: 'delete'

View File

@ -24,7 +24,9 @@
'horizon.app.core.openstack-service-api.lbaasv2',
'horizon.dashboard.project.lbaasv2.loadbalancers.actions.rowActions',
'horizon.dashboard.project.lbaasv2.loadbalancers.service',
'$routeParams'
'$routeParams',
'$window',
'$scope'
];
/**
@ -38,15 +40,20 @@
* @param rowActions The load balancer row actions service.
* @param loadBalancersService The LBaaS v2 load balancers service.
* @param $routeParams The angular $routeParams service.
* @param $window Angular's reference to the browser window object.
* @param $scope The angular scope object.
* @returns undefined
*/
function LoadBalancerDetailController(api, rowActions, loadBalancersService, $routeParams) {
function LoadBalancerDetailController(
api, rowActions, loadBalancersService, $routeParams, $window, $scope
) {
var ctrl = this;
ctrl.actions = rowActions.actions;
ctrl.operatingStatus = loadBalancersService.operatingStatus;
ctrl.provisioningStatus = loadBalancersService.provisioningStatus;
ctrl.listenersTabActive = $window.listenersTabActive;
init();
@ -60,6 +67,14 @@
ctrl.loadbalancer = response;
}
// Save the active state of the listeners tab in the global window object so it can stay
// active after reloading the route following an action.
$scope.$watch(function() {
return ctrl.listenersTabActive;
}, function(active) {
$window.listenersTabActive = active;
});
}
})();

View File

@ -17,12 +17,12 @@
'use strict';
describe('LBaaS v2 Load Balancer Detail Controller', function() {
var controller, lbaasv2API, loadbalancer;
var lbaasv2API, ctrl, $scope, $window;
function fakeAPI() {
return {
success: function(callback) {
callback(loadbalancer);
callback({ id: '1234' });
}
};
}
@ -40,24 +40,33 @@
}));
beforeEach(inject(function($injector) {
loadbalancer = { id: '1234' };
lbaasv2API = $injector.get('horizon.app.core.openstack-service-api.lbaasv2');
controller = $injector.get('$controller');
spyOn(lbaasv2API, 'getLoadBalancer').and.callFake(fakeAPI);
}));
function createController() {
return controller('LoadBalancerDetailController', {
api: lbaasv2API,
$scope = $injector.get('$rootScope').$new();
$window = {};
var controller = $injector.get('$controller');
ctrl = controller('LoadBalancerDetailController', {
$scope: $scope,
$window: $window,
$routeParams: { loadbalancerId: '1234' }
});
}
}));
it('should invoke lbaasv2 apis', function() {
createController();
expect(lbaasv2API.getLoadBalancer).toHaveBeenCalledWith('1234', true);
});
it('should save changes to listeners tab active state', function() {
expect($window.listenersTabActive).toBeUndefined();
expect(ctrl.listenersTabActive).toBeUndefined();
ctrl.listenersTabActive = true;
$scope.$apply();
expect($window.listenersTabActive).toBe(true);
ctrl.listenersTabActive = false;
$scope.$apply();
expect($window.listenersTabActive).toBe(false);
});
});
})();

View File

@ -47,7 +47,7 @@
</div>
</div>
</tab>
<tab heading="{$ 'Listeners' | translate $}">
<tab heading="{$ 'Listeners' | translate $}" active="ctrl.listenersTabActive">
<ng-include src="'static/dashboard/project/lbaasv2/listeners/table.html'"></ng-include>
</tab>
</tabset>

View File

@ -47,8 +47,8 @@
ctrl.items = [];
ctrl.src = [];
ctrl.checked = {};
ctrl.batchActions = batchActions.init(init);
ctrl.rowActions = rowActions.init(init);
ctrl.batchActions = batchActions;
ctrl.rowActions = rowActions;
ctrl.operatingStatus = loadBalancersService.operatingStatus;
ctrl.provisioningStatus = loadBalancersService.provisioningStatus;

View File

@ -58,7 +58,7 @@
toastService,
gettext
) {
var poolId, statePromise, handler;
var poolId, statePromise;
var service = {
perform: open,
@ -70,10 +70,9 @@
////////////
function init(_poolId_, _statePromise_, _handler_) {
function init(_poolId_, _statePromise_) {
poolId = _poolId_;
statePromise = _statePromise_;
handler = _handler_;
return service;
}
@ -116,11 +115,7 @@
function onModalClose() {
toastService.add('success', gettext('Pool member weight has been updated.'));
if (angular.isFunction(handler)) {
handler();
} else {
$route.reload();
}
$route.reload();
}
}

View File

@ -105,15 +105,6 @@
expect($route.reload).toHaveBeenCalled();
});
it('should call handler function upon closing modal if provided', function() {
var handler = { handler: angular.noop };
spyOn(handler, 'handler');
service.init('1', fakePromise(), handler.handler);
service.perform(member);
$scope.$apply();
expect(handler.handler).toHaveBeenCalled();
});
});
})();

View File

@ -40,7 +40,7 @@
*/
function rowActions(gettext, loadBalancersService, editWeight) {
var loadBalancerIsActionable, poolId, handler;
var loadBalancerIsActionable, poolId;
var service = {
actions: actions,
@ -51,16 +51,15 @@
///////////////
function init(loadbalancerId, _poolId_, _handler_) {
function init(loadbalancerId, _poolId_) {
loadBalancerIsActionable = loadBalancersService.isActionable(loadbalancerId);
poolId = _poolId_;
handler = _handler_;
return service;
}
function actions() {
return [{
service: editWeight.init(poolId, loadBalancerIsActionable, handler),
service: editWeight.init(poolId, loadBalancerIsActionable),
template: {
text: gettext('Update Weight')
}

View File

@ -42,7 +42,7 @@
function MemberDetailController(api, rowActions, $routeParams) {
var ctrl = this;
ctrl.actions = rowActions.init($routeParams.loadbalancerId, $routeParams.poolId, init).actions;
ctrl.actions = rowActions.init($routeParams.loadbalancerId, $routeParams.poolId).actions;
init();

View File

@ -90,7 +90,7 @@
it('should have actions', function() {
expect(ctrl.actions).toBe('member-actions');
expect(actions.init).toHaveBeenCalledWith('loadbalancerId', 'poolId', jasmine.any(Function));
expect(actions.init).toHaveBeenCalledWith('loadbalancerId', 'poolId');
});
});

View File

@ -48,7 +48,7 @@
ctrl.loadbalancerId = $routeParams.loadbalancerId;
ctrl.listenerId = $routeParams.listenerId;
ctrl.poolId = $routeParams.poolId;
ctrl.rowActions = rowActions.init(ctrl.loadbalancerId, ctrl.poolId, init);
ctrl.rowActions = rowActions.init(ctrl.loadbalancerId, ctrl.poolId);
init();

View File

@ -24,7 +24,9 @@
'horizon.app.core.openstack-service-api.lbaasv2',
'horizon.dashboard.project.lbaasv2.pools.actions.rowActions',
'$routeParams',
'horizon.framework.util.i18n.gettext'
'horizon.framework.util.i18n.gettext',
'$window',
'$scope'
];
/**
@ -38,10 +40,12 @@
* @param rowActions The LBaaS v2 pool row actions service.
* @param $routeParams The angular $routeParams service.
* @param gettext The horizon gettext function for translation.
* @param $window Angular's reference to the browser window object.
* @param $scope The angular scope object.
* @returns undefined
*/
function PoolDetailController(api, rowActions, $routeParams, gettext) {
function PoolDetailController(api, rowActions, $routeParams, gettext, $window, $scope) {
var ctrl = this;
ctrl.loadBalancerAlgorithm = {
@ -49,8 +53,8 @@
'LEAST_CONNECTIONS': gettext('Least Connections'),
'SOURCE_IP': gettext('Source IP')
};
ctrl.actions = rowActions.init($routeParams.loadbalancerId, $routeParams.listenerId).actions;
ctrl.membersTabActive = $window.membersTabActive;
init();
@ -68,6 +72,14 @@
}, property);
}
// Save the active state of the members tab in the global window object so it can stay
// active after reloading the route following an action.
$scope.$watch(function() {
return ctrl.membersTabActive;
}, function(active) {
$window.membersTabActive = active;
});
}
})();

View File

@ -17,7 +17,7 @@
'use strict';
describe('LBaaS v2 Pool Detail Controller', function() {
var lbaasv2API, ctrl;
var lbaasv2API, ctrl, $scope, $window;
function fakeAPI() {
return {
@ -52,8 +52,12 @@
spyOn(lbaasv2API, 'getPool').and.callFake(fakeAPI);
spyOn(lbaasv2API, 'getListener').and.callFake(fakeAPI);
spyOn(lbaasv2API, 'getLoadBalancer').and.callFake(loadbalancerAPI);
$scope = $injector.get('$rootScope').$new();
$window = {};
var controller = $injector.get('$controller');
ctrl = controller('PoolDetailController', {
$scope: $scope,
$window: $window,
$routeParams: {
loadbalancerId: 'loadbalancerId',
listenerId: 'listenerId',
@ -75,6 +79,17 @@
expect(ctrl.loadBalancerAlgorithm).toBeDefined();
});
it('should save changes to members tab active state', function() {
expect($window.membersTabActive).toBeUndefined();
expect(ctrl.membersTabActive).toBeUndefined();
ctrl.membersTabActive = true;
$scope.$apply();
expect($window.membersTabActive).toBe(true);
ctrl.membersTabActive = false;
$scope.$apply();
expect($window.membersTabActive).toBe(false);
});
});
})();

View File

@ -40,7 +40,7 @@
</div>
</div>
</tab>
<tab heading="{$ 'Members' | translate $}">
<tab heading="{$ 'Members' | translate $}" active="ctrl.membersTabActive">
<ng-include src="'static/dashboard/project/lbaasv2/members/table.html'"></ng-include>
</tab>
</tabset>