Merge "Add delete load balancer actions"
This commit is contained in:
commit
988bd51b2e
@ -420,6 +420,14 @@ class LoadBalancer(generic.View):
|
||||
kwargs = {'loadbalancer_id': loadbalancer_id}
|
||||
update_loadbalancer(request, **kwargs)
|
||||
|
||||
@rest_utils.ajax()
|
||||
def delete(self, request, loadbalancer_id):
|
||||
"""Delete a specific load balancer.
|
||||
|
||||
http://localhost/api/lbaas/loadbalancers/cc758c90-3d98-4ea1-af44-aab405c9c915
|
||||
"""
|
||||
neutronclient(request).delete_loadbalancer(loadbalancer_id)
|
||||
|
||||
|
||||
@urls.register
|
||||
class Listeners(generic.View):
|
||||
|
@ -38,6 +38,7 @@
|
||||
var service = {
|
||||
getLoadBalancers: getLoadBalancers,
|
||||
getLoadBalancer: getLoadBalancer,
|
||||
deleteLoadBalancer: deleteLoadBalancer,
|
||||
createLoadBalancer: createLoadBalancer,
|
||||
editLoadBalancer: editLoadBalancer,
|
||||
getListeners: getListeners,
|
||||
@ -86,6 +87,22 @@
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @name horizon.app.core.openstack-service-api.lbaasv2.deleteLoadBalancer
|
||||
* @description
|
||||
* Delete a single load balancer by ID
|
||||
* @param {string} id
|
||||
* @param {boolean} quiet
|
||||
* Specifies the id of the load balancer to delete.
|
||||
*/
|
||||
|
||||
function deleteLoadBalancer(id, quiet) {
|
||||
var promise = apiService.delete('/api/lbaas/loadbalancers/' + id);
|
||||
return quiet ? promise : promise.error(function () {
|
||||
toastService.add('error', gettext('Unable to delete load balancer.'));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @name horizon.app.core.openstack-service-api.lbaasv2.createLoadBalancer
|
||||
* @description
|
||||
|
@ -51,6 +51,15 @@
|
||||
'1234'
|
||||
]
|
||||
},
|
||||
{
|
||||
"func": "deleteLoadBalancer",
|
||||
"method": "delete",
|
||||
"path": "/api/lbaas/loadbalancers/1234",
|
||||
"error": "Unable to delete load balancer.",
|
||||
"testInput": [
|
||||
'1234'
|
||||
]
|
||||
},
|
||||
{
|
||||
"func": "getListeners",
|
||||
"method": "get",
|
||||
@ -177,6 +186,11 @@
|
||||
});
|
||||
});
|
||||
|
||||
it('supresses the error if instructed for deleteLoadBalancer', function() {
|
||||
spyOn(apiService, 'delete').and.returnValue("promise");
|
||||
expect(service.deleteLoadBalancer("whatever", true)).toBe("promise");
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
})();
|
||||
|
@ -106,3 +106,12 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
TODO(jpomero): The float property is being set to "none" in _debt.scss apparently
|
||||
to work around a known bootstrap bug, but this appears to break the actions menu
|
||||
only in angular tables. Setting back to the original value ("left") here for now.
|
||||
*/
|
||||
td .btn-group.ng-scope > .btn {
|
||||
float: left;
|
||||
}
|
@ -34,7 +34,7 @@
|
||||
|
||||
///////////////////////
|
||||
|
||||
beforeEach(module('horizon.framework.widgets.toast'));
|
||||
beforeEach(module('horizon.framework.widgets'));
|
||||
beforeEach(module('horizon.framework.conf'));
|
||||
beforeEach(module('horizon.framework.util'));
|
||||
beforeEach(module('horizon.app.core.openstack-service-api'));
|
||||
|
@ -57,7 +57,7 @@
|
||||
|
||||
<td class="select-col">
|
||||
<input type="checkbox"
|
||||
ng-model="selected[item.id].checked"
|
||||
ng-model="tCtrl.selections[item.id].checked"
|
||||
hz-select="item">
|
||||
</td>
|
||||
<td class="expander">
|
||||
|
@ -25,6 +25,7 @@
|
||||
'$location',
|
||||
'horizon.dashboard.project.lbaasv2.workflow.modal',
|
||||
'horizon.dashboard.project.lbaasv2.basePath',
|
||||
'horizon.dashboard.project.lbaasv2.loadbalancers.actions.delete',
|
||||
'horizon.app.core.openstack-service-api.policy',
|
||||
'horizon.framework.util.i18n.gettext'
|
||||
];
|
||||
@ -39,12 +40,13 @@
|
||||
* @param $location The angular $location service.
|
||||
* @param workflowModal The LBaaS workflow modal service.
|
||||
* @param basePath The lbaasv2 module base path.
|
||||
* @param deleteService The load balancer delete service.
|
||||
* @param policy The horizon policy service.
|
||||
* @param gettext The horizon gettext function for translation.
|
||||
* @returns Load balancers table batch actions service object.
|
||||
*/
|
||||
|
||||
function tableBatchActions($location, workflowModal, basePath, policy, gettext) {
|
||||
function tableBatchActions($location, workflowModal, basePath, deleteService, policy, gettext) {
|
||||
|
||||
var create = workflowModal.init({
|
||||
controller: 'CreateLoadBalancerWizardController',
|
||||
@ -68,6 +70,12 @@
|
||||
type: 'create',
|
||||
text: gettext('Create Load Balancer')
|
||||
}
|
||||
}, {
|
||||
service: deleteService,
|
||||
template: {
|
||||
type: 'delete-selected',
|
||||
text: gettext('Delete Load Balancers')
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
|
@ -21,7 +21,7 @@
|
||||
|
||||
beforeEach(module('horizon.framework.util'));
|
||||
beforeEach(module('horizon.framework.conf'));
|
||||
beforeEach(module('horizon.framework.widgets.toast'));
|
||||
beforeEach(module('horizon.framework.widgets'));
|
||||
beforeEach(module('horizon.app.core.openstack-service-api'));
|
||||
beforeEach(module('horizon.dashboard.project.lbaasv2'));
|
||||
|
||||
@ -54,8 +54,9 @@
|
||||
}));
|
||||
|
||||
it('should define correct table batch actions', function() {
|
||||
expect(actions.length).toBe(1);
|
||||
expect(actions.length).toBe(2);
|
||||
expect(actions[0].template.text).toBe('Create Load Balancer');
|
||||
expect(actions[1].template.text).toBe('Delete Load Balancers');
|
||||
});
|
||||
|
||||
it('should have the "allowed" and "perform" functions', function() {
|
||||
|
@ -0,0 +1,147 @@
|
||||
/*
|
||||
* 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.lbaasv2.loadbalancers')
|
||||
.factory('horizon.dashboard.project.lbaasv2.loadbalancers.actions.delete', deleteService);
|
||||
|
||||
deleteService.$inject = [
|
||||
'$q',
|
||||
'$location',
|
||||
'$route',
|
||||
'horizon.framework.widgets.modal.deleteModalService',
|
||||
'horizon.app.core.openstack-service-api.lbaasv2',
|
||||
'horizon.app.core.openstack-service-api.policy',
|
||||
'horizon.framework.widgets.toast.service',
|
||||
'horizon.framework.util.q.extensions',
|
||||
'horizon.framework.util.i18n.gettext'
|
||||
];
|
||||
|
||||
/**
|
||||
* @ngDoc factory
|
||||
* @name horizon.dashboard.project.lbaasv2.loadbalancers.actions.deleteService
|
||||
* @description
|
||||
* Brings up the delete load balancers confirmation modal dialog.
|
||||
* On submit, deletes selected load balancers.
|
||||
* On cancel, does nothing.
|
||||
* @param $q The angular service for promises.
|
||||
* @param $location The angular $location service.
|
||||
* @param $route The angular $route service.
|
||||
* @param deleteModal The horizon delete modal service.
|
||||
* @param api The LBaaS v2 API service.
|
||||
* @param policy The horizon policy service.
|
||||
* @param toast The horizon message service.
|
||||
* @param qExtensions Horizon extensions to the $q service.
|
||||
* @param gettext The horizon gettext function for translation.
|
||||
* @returns The load balancers table delete service.
|
||||
*/
|
||||
|
||||
function deleteService(
|
||||
$q, $location, $route, deleteModal, api, policy, toast, qExtensions, gettext
|
||||
) {
|
||||
// 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 ' +
|
||||
'deleted: %s.');
|
||||
var context = {
|
||||
labels: {
|
||||
title: gettext('Confirm Delete Load Balancers'),
|
||||
message: gettext('You have selected "%s". Please confirm your selection. Deleted load ' +
|
||||
'balancers are not recoverable.'),
|
||||
submit: gettext('Delete Load Balancers'),
|
||||
success: gettext('Deleted load balancers: %s.'),
|
||||
error: gettext('The following load balancers could not be deleted, possibly due to ' +
|
||||
'existing listeners: %s.')
|
||||
},
|
||||
deleteEntity: deleteItem
|
||||
};
|
||||
|
||||
var service = {
|
||||
perform: perform,
|
||||
allowed: allowed
|
||||
};
|
||||
|
||||
return service;
|
||||
|
||||
//////////////
|
||||
|
||||
function perform(items) {
|
||||
if (angular.isArray(items)) {
|
||||
qExtensions.allSettled(items.map(checkPermission)).then(afterCheck);
|
||||
} else {
|
||||
deleteModal.open({ $emit: actionComplete }, [items], context);
|
||||
}
|
||||
}
|
||||
|
||||
function allowed(item) {
|
||||
// This rule is made up and should therefore always pass. I assume at some point there
|
||||
// will be a valid rule similar to this that we will want to use.
|
||||
var promises = [policy.ifAllowed({ rules: [['neutron', 'delete_loadbalancer']] })];
|
||||
if (item) {
|
||||
var status = item.provisioning_status;
|
||||
promises.push(qExtensions.booleanAsPromise(status === 'ACTIVE' || status === 'ERROR'));
|
||||
}
|
||||
return $q.all(promises);
|
||||
}
|
||||
|
||||
function canBeDeleted(item) {
|
||||
var status = item.provisioning_status;
|
||||
return qExtensions.booleanAsPromise(status === 'ACTIVE' || status === 'ERROR');
|
||||
}
|
||||
|
||||
function checkPermission(item) {
|
||||
return { promise: canBeDeleted(item), context: item };
|
||||
}
|
||||
|
||||
function afterCheck(result) {
|
||||
if (result.fail.length > 0) {
|
||||
toast.add('error', getMessage(notAllowedMessage, result.fail));
|
||||
}
|
||||
if (result.pass.length > 0) {
|
||||
deleteModal.open({ $emit: actionComplete }, result.pass.map(getEntity), context);
|
||||
}
|
||||
}
|
||||
|
||||
function deleteItem(id) {
|
||||
return api.deleteLoadBalancer(id, true);
|
||||
}
|
||||
|
||||
function getMessage(message, entities) {
|
||||
return interpolate(message, [entities.map(getName).join(", ")]);
|
||||
}
|
||||
|
||||
function getName(result) {
|
||||
return getEntity(result).name;
|
||||
}
|
||||
|
||||
function getEntity(result) {
|
||||
return result.context;
|
||||
}
|
||||
|
||||
function actionComplete() {
|
||||
// If the user is on the load balancers table then just reload the page, otherwise they
|
||||
// are on the details page and we return to the table.
|
||||
if (/\/ngloadbalancersv2(\/)?$/.test($location.path())) {
|
||||
$route.reload();
|
||||
} else {
|
||||
$location.path('project/ngloadbalancersv2');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
})();
|
@ -0,0 +1,177 @@
|
||||
/*
|
||||
* 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';
|
||||
|
||||
describe('LBaaS v2 Load Balancers Table Row Delete Service', function() {
|
||||
var service, policy, modal, lbaasv2Api, $scope, $route, $location, $q, toast, items, path;
|
||||
|
||||
function allowed(item) {
|
||||
spyOn(policy, 'ifAllowed').and.returnValue(true);
|
||||
var promise = service.allowed(item);
|
||||
var allowed;
|
||||
promise.then(function() {
|
||||
allowed = true;
|
||||
}, function() {
|
||||
allowed = false;
|
||||
});
|
||||
$scope.$apply();
|
||||
expect(policy.ifAllowed).toHaveBeenCalledWith({rules: [['neutron', 'delete_loadbalancer']]});
|
||||
return allowed;
|
||||
}
|
||||
|
||||
function makePromise(reject) {
|
||||
var def = $q.defer();
|
||||
def[reject ? 'reject' : 'resolve']();
|
||||
return def.promise;
|
||||
}
|
||||
|
||||
beforeEach(module('horizon.framework.util'));
|
||||
beforeEach(module('horizon.framework.conf'));
|
||||
beforeEach(module('horizon.framework.widgets'));
|
||||
beforeEach(module('horizon.app.core.openstack-service-api'));
|
||||
beforeEach(module('horizon.dashboard.project.lbaasv2'));
|
||||
|
||||
beforeEach(function() {
|
||||
items = [{ id: '1', name: 'First', provisioning_status: 'ACTIVE' },
|
||||
{ id: '2', name: 'Second', provisioning_status: 'ACTIVE' }];
|
||||
});
|
||||
|
||||
beforeEach(module(function($provide) {
|
||||
$provide.value('$modal', {
|
||||
open: function() {
|
||||
return {
|
||||
result: makePromise()
|
||||
};
|
||||
}
|
||||
});
|
||||
$provide.value('horizon.app.core.openstack-service-api.lbaasv2', {
|
||||
deleteLoadBalancer: function() {
|
||||
return makePromise();
|
||||
}
|
||||
});
|
||||
$provide.value('$location', {
|
||||
path: function() {
|
||||
return path;
|
||||
}
|
||||
});
|
||||
}));
|
||||
|
||||
beforeEach(inject(function ($injector) {
|
||||
policy = $injector.get('horizon.app.core.openstack-service-api.policy');
|
||||
lbaasv2Api = $injector.get('horizon.app.core.openstack-service-api.lbaasv2');
|
||||
modal = $injector.get('horizon.framework.widgets.modal.deleteModalService');
|
||||
$scope = $injector.get('$rootScope').$new();
|
||||
$route = $injector.get('$route');
|
||||
$location = $injector.get('$location');
|
||||
$q = $injector.get('$q');
|
||||
toast = $injector.get('horizon.framework.widgets.toast.service');
|
||||
service = $injector.get('horizon.dashboard.project.lbaasv2.loadbalancers.actions.delete');
|
||||
}));
|
||||
|
||||
it('should have the "allowed" and "perform" functions', function() {
|
||||
expect(service.allowed).toBeDefined();
|
||||
expect(service.perform).toBeDefined();
|
||||
});
|
||||
|
||||
it('should check policy to allow deleting a load balancer (single)', function() {
|
||||
expect(allowed(items[0])).toBe(true);
|
||||
});
|
||||
|
||||
it('should check policy to allow deleting a load balancer (batch)', function() {
|
||||
expect(allowed()).toBe(true);
|
||||
});
|
||||
|
||||
it('should not allow deleting load balancers if state check fails (single)', function() {
|
||||
items[0].provisioning_status = 'PENDING_UPDATE';
|
||||
expect(allowed(items[0])).toBe(false);
|
||||
});
|
||||
|
||||
it('should allow batch delete even if state check fails (batch)', function() {
|
||||
items[0].provisioning_status = 'PENDING_UPDATE';
|
||||
expect(allowed()).toBe(true);
|
||||
});
|
||||
|
||||
it('should open the delete modal', function() {
|
||||
spyOn(modal, 'open');
|
||||
service.perform(items[0]);
|
||||
$scope.$apply();
|
||||
expect(modal.open.calls.count()).toBe(1);
|
||||
var args = modal.open.calls.argsFor(0);
|
||||
expect(args.length).toBe(3);
|
||||
expect(args[0]).toEqual({ $emit: jasmine.any(Function) });
|
||||
expect(args[1]).toEqual([jasmine.objectContaining({ id: '1' })]);
|
||||
expect(args[2]).toEqual(jasmine.objectContaining({
|
||||
labels: jasmine.any(Object),
|
||||
deleteEntity: jasmine.any(Function)
|
||||
}));
|
||||
expect(args[2].labels.title).toBe('Confirm Delete Load Balancers');
|
||||
});
|
||||
|
||||
it('should pass function to modal that deletes load balancers', function() {
|
||||
spyOn(modal, 'open').and.callThrough();
|
||||
spyOn(lbaasv2Api, 'deleteLoadBalancer').and.callThrough();
|
||||
service.perform(items[0]);
|
||||
$scope.$apply();
|
||||
expect(lbaasv2Api.deleteLoadBalancer.calls.count()).toBe(1);
|
||||
expect(lbaasv2Api.deleteLoadBalancer).toHaveBeenCalledWith('1', true);
|
||||
});
|
||||
|
||||
it('should show message if any selected items do not allow for delete (batch)', function() {
|
||||
spyOn(modal, 'open');
|
||||
spyOn(toast, 'add');
|
||||
items[0].provisioning_status = 'PENDING_UPDATE';
|
||||
items[1].provisioning_status = 'PENDING_DELETE';
|
||||
service.perform(items);
|
||||
$scope.$apply();
|
||||
expect(modal.open).not.toHaveBeenCalled();
|
||||
expect(toast.add).toHaveBeenCalledWith('error',
|
||||
'The following load balancers are pending and cannot be deleted: First, Second.');
|
||||
});
|
||||
|
||||
it('should show message if any items fail to be deleted', function() {
|
||||
spyOn(modal, 'open').and.callThrough();
|
||||
spyOn(lbaasv2Api, 'deleteLoadBalancer').and.returnValue(makePromise(true));
|
||||
spyOn(toast, 'add');
|
||||
items.splice(1, 1);
|
||||
service.perform(items);
|
||||
$scope.$apply();
|
||||
expect(modal.open).toHaveBeenCalled();
|
||||
expect(lbaasv2Api.deleteLoadBalancer.calls.count()).toBe(1);
|
||||
expect(toast.add).toHaveBeenCalledWith('error', 'The following load balancers could not ' +
|
||||
'be deleted, possibly due to existing listeners: First.');
|
||||
});
|
||||
|
||||
it('should reload table after delete', function() {
|
||||
path = 'project/ngloadbalancersv2';
|
||||
spyOn($route, 'reload');
|
||||
service.perform(items);
|
||||
$scope.$apply();
|
||||
expect($route.reload).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should return to table after delete if on detail page', function() {
|
||||
path = 'project/ngloadbalancersv2/1';
|
||||
spyOn($location, 'path');
|
||||
spyOn(toast, 'add');
|
||||
service.perform(items[0]);
|
||||
$scope.$apply();
|
||||
expect($location.path).toHaveBeenCalledWith('project/ngloadbalancersv2');
|
||||
expect(toast.add).toHaveBeenCalledWith('success', 'Deleted load balancers: First.');
|
||||
});
|
||||
|
||||
});
|
||||
})();
|
@ -25,6 +25,7 @@
|
||||
'$q',
|
||||
'$route',
|
||||
'horizon.dashboard.project.lbaasv2.workflow.modal',
|
||||
'horizon.dashboard.project.lbaasv2.loadbalancers.actions.delete',
|
||||
'horizon.app.core.openstack-service-api.policy',
|
||||
'horizon.framework.util.q.extensions',
|
||||
'horizon.framework.util.i18n.gettext'
|
||||
@ -40,13 +41,14 @@
|
||||
* @param $q The angular service for promises.
|
||||
* @param $route The angular $route service.
|
||||
* @param workflowModal The LBaaS workflow modal service.
|
||||
* @param deleteService The load balancer delete service.
|
||||
* @param policy The horizon policy service.
|
||||
* @param qExtensions Horizon extensions to the $q service.
|
||||
* @param gettext The horizon gettext function for translation.
|
||||
* @returns Load balancers table batch actions service object.
|
||||
*/
|
||||
|
||||
function tableRowActions($q, $route, workflowModal, policy, qExtensions, gettext) {
|
||||
function tableRowActions($q, $route, workflowModal, deleteService, policy, qExtensions, gettext) {
|
||||
|
||||
var edit = workflowModal.init({
|
||||
controller: 'EditLoadBalancerWizardController',
|
||||
@ -69,6 +71,12 @@
|
||||
template: {
|
||||
text: gettext('Edit')
|
||||
}
|
||||
}, {
|
||||
service: deleteService,
|
||||
template: {
|
||||
text: gettext('Delete Load Balancer'),
|
||||
type: 'delete'
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
|
@ -35,7 +35,7 @@
|
||||
|
||||
beforeEach(module('horizon.framework.util'));
|
||||
beforeEach(module('horizon.framework.conf'));
|
||||
beforeEach(module('horizon.framework.widgets.toast'));
|
||||
beforeEach(module('horizon.framework.widgets'));
|
||||
beforeEach(module('horizon.app.core.openstack-service-api'));
|
||||
beforeEach(module('horizon.dashboard.project.lbaasv2'));
|
||||
|
||||
@ -69,8 +69,9 @@
|
||||
}));
|
||||
|
||||
it('should define correct table row actions', function() {
|
||||
expect(actions.length).toBe(1);
|
||||
expect(actions.length).toBe(2);
|
||||
expect(actions[0].template.text).toBe('Edit');
|
||||
expect(actions[1].template.text).toBe('Delete Load Balancer');
|
||||
});
|
||||
|
||||
it('should allow editing an ACTIVE load balancer', function() {
|
||||
|
@ -29,7 +29,7 @@
|
||||
|
||||
///////////////////////
|
||||
|
||||
beforeEach(module('horizon.framework.widgets.toast'));
|
||||
beforeEach(module('horizon.framework.widgets'));
|
||||
beforeEach(module('horizon.framework.conf'));
|
||||
beforeEach(module('horizon.framework.util'));
|
||||
beforeEach(module('horizon.app.core.openstack-service-api'));
|
||||
|
@ -30,7 +30,7 @@
|
||||
|
||||
///////////////////////
|
||||
|
||||
beforeEach(module('horizon.framework.widgets.toast'));
|
||||
beforeEach(module('horizon.framework.widgets'));
|
||||
beforeEach(module('horizon.framework.conf'));
|
||||
beforeEach(module('horizon.framework.util'));
|
||||
beforeEach(module('horizon.app.core.openstack-service-api'));
|
||||
|
@ -62,7 +62,7 @@
|
||||
|
||||
<td class="select-col">
|
||||
<input type="checkbox"
|
||||
ng-model="selected[item.id].checked"
|
||||
ng-model="tCtrl.selections[item.id].checked"
|
||||
hz-select="item">
|
||||
</td>
|
||||
<td class="expander">
|
||||
|
@ -55,7 +55,7 @@
|
||||
|
||||
<td class="select-col">
|
||||
<input type="checkbox"
|
||||
ng-model="selected[item.id].checked"
|
||||
ng-model="tCtrl.selections[item.id].checked"
|
||||
hz-select="item">
|
||||
</td>
|
||||
<td class="rsp-p1"><a ng-href="project/ngloadbalancersv2/{$ ::table.loadbalancerId $}/listeners/{$ ::table.listenerId $}/pools/{$ ::table.poolId $}/members/{$ ::item.id $}">{$ ::item.id $}</a></td>
|
||||
|
Loading…
x
Reference in New Issue
Block a user