Remove 'host' parameter from deleting image
'host' parameter for deleting image has removed from client. Zun UI should remove this parameter. Now, due to only 'id' is necessary for deleting image, we can use 'delete-selected' type action and common deletion confirmation dialog. Using the common deletion action, we can also implement deletion action as batch action. Change-Id: I2adae5cb466e620177c3788ac340f6464711e21d Closes-Bug: #1799125
This commit is contained in:
parent
0022f4a0ba
commit
3f8cb502b6
@ -226,6 +226,15 @@ class Images(generic.View):
|
|||||||
result = client.image_list(request)
|
result = client.image_list(request)
|
||||||
return {'items': [change_to_id(i.to_dict()) for i in result]}
|
return {'items': [change_to_id(i.to_dict()) for i in result]}
|
||||||
|
|
||||||
|
@rest_utils.ajax(data_required=True)
|
||||||
|
def delete(self, request):
|
||||||
|
"""Delete one or more Images by id.
|
||||||
|
|
||||||
|
Returns HTTP 204 (no content) on successful deletion.
|
||||||
|
"""
|
||||||
|
for id in request.DATA:
|
||||||
|
client.image_delete(request, id)
|
||||||
|
|
||||||
@rest_utils.ajax(data_required=True)
|
@rest_utils.ajax(data_required=True)
|
||||||
def post(self, request):
|
def post(self, request):
|
||||||
"""Create a new Image.
|
"""Create a new Image.
|
||||||
@ -238,17 +247,6 @@ class Images(generic.View):
|
|||||||
new_image.to_dict())
|
new_image.to_dict())
|
||||||
|
|
||||||
|
|
||||||
@urls.register
|
|
||||||
class Image(generic.View):
|
|
||||||
"""API for operate a single image"""
|
|
||||||
url_regex = r'zun/images/(?P<id>[^/]+)$'
|
|
||||||
|
|
||||||
@rest_utils.ajax(data_required=True)
|
|
||||||
def delete(self, request, id):
|
|
||||||
"""Delete a specific image"""
|
|
||||||
client.image_delete(request, id, **request.DATA)
|
|
||||||
|
|
||||||
|
|
||||||
@urls.register
|
@urls.register
|
||||||
class Hosts(generic.View):
|
class Hosts(generic.View):
|
||||||
"""API for Zun Hosts"""
|
"""API for Zun Hosts"""
|
||||||
|
@ -56,6 +56,16 @@
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
imagesResourceType.batchActions
|
||||||
|
.append({
|
||||||
|
id: 'deleteImageAction',
|
||||||
|
service: deleteImageService,
|
||||||
|
template: {
|
||||||
|
type: 'delete-selected',
|
||||||
|
text: gettext('Delete Images')
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
imagesResourceType.itemActions
|
imagesResourceType.itemActions
|
||||||
.append({
|
.append({
|
||||||
id: 'deleteImageAction',
|
id: 'deleteImageAction',
|
||||||
|
@ -19,123 +19,138 @@
|
|||||||
* @ngDoc factory
|
* @ngDoc factory
|
||||||
* @name horizon.dashboard.container.images.actions.delete.service
|
* @name horizon.dashboard.container.images.actions.delete.service
|
||||||
* @Description
|
* @Description
|
||||||
* restart container.
|
* Brings up the delete images confirmation modal dialog.
|
||||||
|
* On submit, delete selected resources.
|
||||||
|
* On cancel, do nothing.
|
||||||
*/
|
*/
|
||||||
angular
|
angular
|
||||||
.module('horizon.dashboard.container.images.actions')
|
.module('horizon.dashboard.container.images')
|
||||||
.factory('horizon.dashboard.container.images.actions.delete.service', deleteService);
|
.factory('horizon.dashboard.container.images.actions.delete.service', deleteService);
|
||||||
|
|
||||||
deleteService.$inject = [
|
deleteService.$inject = [
|
||||||
|
'$location',
|
||||||
|
'$q',
|
||||||
|
'$rootScope',
|
||||||
'horizon.app.core.openstack-service-api.zun',
|
'horizon.app.core.openstack-service-api.zun',
|
||||||
'horizon.dashboard.container.images.basePath',
|
'horizon.app.core.openstack-service-api.policy',
|
||||||
'horizon.dashboard.container.images.resourceType',
|
|
||||||
'horizon.framework.util.actions.action-result.service',
|
'horizon.framework.util.actions.action-result.service',
|
||||||
'horizon.framework.util.i18n.gettext',
|
'horizon.framework.util.i18n.gettext',
|
||||||
'horizon.framework.util.q.extensions',
|
'horizon.framework.util.q.extensions',
|
||||||
'horizon.framework.widgets.form.ModalFormService',
|
'horizon.framework.widgets.modal.deleteModalService',
|
||||||
'horizon.framework.widgets.toast.service'
|
'horizon.framework.widgets.table.events',
|
||||||
|
'horizon.framework.widgets.toast.service',
|
||||||
|
'horizon.dashboard.container.images.resourceType',
|
||||||
|
'horizon.dashboard.container.images.events'
|
||||||
];
|
];
|
||||||
|
|
||||||
function deleteService(
|
function deleteService(
|
||||||
zun, basePath, resourceType, actionResult, gettext, $qExtensions, modal, toast
|
$location, $q, $rootScope, zun, policy, actionResult, gettext, $qExtensions, deleteModal,
|
||||||
|
tableEvents, toast, resourceType, events
|
||||||
) {
|
) {
|
||||||
var push = Array.prototype.push;
|
var scope;
|
||||||
var hosts = [{value: "", name: gettext("Select host to remove the image from.")}];
|
var context = {
|
||||||
// schema
|
labels: null,
|
||||||
var schema = {
|
deleteEntity: deleteEntity,
|
||||||
type: "object",
|
successEvent: events.DELETE_SUCCESS
|
||||||
properties: {
|
|
||||||
host: {
|
|
||||||
title: gettext("Host"),
|
|
||||||
type: "string"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// form
|
|
||||||
var form = [
|
|
||||||
{
|
|
||||||
type: 'section',
|
|
||||||
htmlClass: 'row',
|
|
||||||
items: [
|
|
||||||
{
|
|
||||||
type: 'section',
|
|
||||||
htmlClass: 'col-sm-12',
|
|
||||||
items: [
|
|
||||||
{
|
|
||||||
key: 'host',
|
|
||||||
type: "select",
|
|
||||||
titleMap: hosts,
|
|
||||||
required: true
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
// model
|
|
||||||
var model;
|
|
||||||
|
|
||||||
var message = {
|
|
||||||
success: gettext('Container %s was successfully restarted.')
|
|
||||||
};
|
|
||||||
|
|
||||||
var service = {
|
var service = {
|
||||||
initAction: initAction,
|
initAction: initAction,
|
||||||
allowed: allowed,
|
allowed: allowed,
|
||||||
perform: perform
|
perform: perform
|
||||||
};
|
};
|
||||||
|
var notAllowedMessage = gettext("You are not allowed to delete images: %s");
|
||||||
|
|
||||||
return service;
|
return service;
|
||||||
|
|
||||||
//////////////
|
//////////////
|
||||||
|
|
||||||
// include this function in your service
|
|
||||||
// if you plan to emit events to the parent controller
|
|
||||||
function initAction() {
|
function initAction() {
|
||||||
// get hosts for zun
|
|
||||||
zun.getHosts().then(onGetZunHosts);
|
|
||||||
function onGetZunHosts(response) {
|
|
||||||
var hs = [];
|
|
||||||
response.data.items.forEach(function (host) {
|
|
||||||
hs.push({value: host.id, name: host.hostname});
|
|
||||||
});
|
|
||||||
push.apply(hosts, hs);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function allowed() {
|
function allowed() {
|
||||||
return $qExtensions.booleanAsPromise(true);
|
return $qExtensions.booleanAsPromise(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
function perform(selected) {
|
// delete selected resource objects
|
||||||
model = {
|
function perform(selected, newScope) {
|
||||||
id: selected.id,
|
scope = newScope;
|
||||||
repo: selected.repo,
|
selected = angular.isArray(selected) ? selected : [selected];
|
||||||
host: ""
|
context.labels = labelize(selected.length);
|
||||||
};
|
return $qExtensions.allSettled(selected.map(checkPermission)).then(afterCheck);
|
||||||
|
}
|
||||||
|
|
||||||
// modal config
|
function labelize(count) {
|
||||||
var config = {
|
return {
|
||||||
"title": interpolate(gettext('Delete Image %s'), [model.repo]),
|
title: ngettext('Confirm Delete Image',
|
||||||
"submitText": gettext('Delete'),
|
'Confirm Delete Images', count),
|
||||||
"schema": schema,
|
/* eslint-disable max-len */
|
||||||
"form": form,
|
message: ngettext('You have selected "%s". Please confirm your selection. Deleted image is not recoverable.',
|
||||||
"model": model
|
'You have selected "%s". Please confirm your selection. Deleted images are not recoverable.', count),
|
||||||
|
/* eslint-enable max-len */
|
||||||
|
submit: ngettext('Delete Image',
|
||||||
|
'Delete Images', count),
|
||||||
|
success: ngettext('Deleted Image: %s.',
|
||||||
|
'Deleted Images: %s.', count),
|
||||||
|
error: ngettext('Unable to delete Image: %s.',
|
||||||
|
'Unable to delete Images: %s.', count)
|
||||||
};
|
};
|
||||||
return modal.open(config).then(submit);
|
}
|
||||||
|
|
||||||
function submit(context) {
|
// for batch delete
|
||||||
var id = context.model.id;
|
function checkPermission(selected) {
|
||||||
var repo = context.model.repo;
|
return {promise: allowed(selected), context: selected};
|
||||||
var host = context.model.host;
|
}
|
||||||
return zun.deleteImage(id, host).then(function() {
|
|
||||||
toast.add('success', interpolate(message.success, [repo]));
|
// for batch delete
|
||||||
var result = actionResult.getActionResult().updated(resourceType, id);
|
function afterCheck(result) {
|
||||||
return result.result;
|
var outcome = $q.reject(); // Reject the promise by default
|
||||||
});
|
if (result.fail.length > 0) {
|
||||||
|
toast.add('error', getMessage(notAllowedMessage, result.fail));
|
||||||
|
outcome = $q.reject(result.fail);
|
||||||
}
|
}
|
||||||
|
if (result.pass.length > 0) {
|
||||||
|
outcome = deleteModal.open(scope, result.pass.map(getEntity), context).then(createResult);
|
||||||
|
}
|
||||||
|
return outcome;
|
||||||
|
}
|
||||||
|
|
||||||
|
function createResult(deleteModalResult) {
|
||||||
|
// To make the result of this action generically useful, reformat the return
|
||||||
|
// from the deleteModal into a standard form
|
||||||
|
var result = actionResult.getActionResult();
|
||||||
|
deleteModalResult.pass.forEach(function markDeleted(item) {
|
||||||
|
result.updated(resourceType, getEntity(item).id);
|
||||||
|
});
|
||||||
|
deleteModalResult.fail.forEach(function markFailed(item) {
|
||||||
|
result.failed(resourceType, getEntity(item).id);
|
||||||
|
});
|
||||||
|
var indexPath = '/admin/container/images';
|
||||||
|
var currentPath = $location.path();
|
||||||
|
if (result.result.failed.length === 0 && result.result.updated.length > 0 &&
|
||||||
|
currentPath !== indexPath) {
|
||||||
|
$location.path(indexPath);
|
||||||
|
} else {
|
||||||
|
$rootScope.$broadcast(tableEvents.CLEAR_SELECTIONS);
|
||||||
|
return result.result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getMessage(message, entities) {
|
||||||
|
return interpolate(message, [entities.map(getName).join(", ")]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getName(result) {
|
||||||
|
return getEntity(result).name;
|
||||||
|
}
|
||||||
|
|
||||||
|
// for batch delete
|
||||||
|
function getEntity(result) {
|
||||||
|
return result.context;
|
||||||
|
}
|
||||||
|
|
||||||
|
// call delete REST API
|
||||||
|
function deleteEntity(id) {
|
||||||
|
return zun.deleteImage(id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
@ -243,9 +243,12 @@
|
|||||||
return apiService.get(imagesPath).error(error(msg));
|
return apiService.get(imagesPath).error(error(msg));
|
||||||
}
|
}
|
||||||
|
|
||||||
function deleteImage(id, host) {
|
function deleteImage(id, suppressError) {
|
||||||
var msg = gettext('Unable to delete the Image.');
|
var promise = apiService.delete(imagesPath, [id]);
|
||||||
return apiService.delete(imagesPath + id, {host: host}).error(error(msg));
|
return suppressError ? promise : promise.error(function() {
|
||||||
|
var msg = gettext('Unable to delete the Image with id: %(id)s');
|
||||||
|
toastService.add('error', interpolate(msg, { id: id }, true));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////
|
///////////
|
||||||
|
Loading…
Reference in New Issue
Block a user