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)
|
||||
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)
|
||||
def post(self, request):
|
||||
"""Create a new Image.
|
||||
@ -238,17 +247,6 @@ class Images(generic.View):
|
||||
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
|
||||
class Hosts(generic.View):
|
||||
"""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
|
||||
.append({
|
||||
id: 'deleteImageAction',
|
||||
|
@ -19,123 +19,138 @@
|
||||
* @ngDoc factory
|
||||
* @name horizon.dashboard.container.images.actions.delete.service
|
||||
* @Description
|
||||
* restart container.
|
||||
* Brings up the delete images confirmation modal dialog.
|
||||
* On submit, delete selected resources.
|
||||
* On cancel, do nothing.
|
||||
*/
|
||||
angular
|
||||
.module('horizon.dashboard.container.images.actions')
|
||||
.module('horizon.dashboard.container.images')
|
||||
.factory('horizon.dashboard.container.images.actions.delete.service', deleteService);
|
||||
|
||||
deleteService.$inject = [
|
||||
'$location',
|
||||
'$q',
|
||||
'$rootScope',
|
||||
'horizon.app.core.openstack-service-api.zun',
|
||||
'horizon.dashboard.container.images.basePath',
|
||||
'horizon.dashboard.container.images.resourceType',
|
||||
'horizon.app.core.openstack-service-api.policy',
|
||||
'horizon.framework.util.actions.action-result.service',
|
||||
'horizon.framework.util.i18n.gettext',
|
||||
'horizon.framework.util.q.extensions',
|
||||
'horizon.framework.widgets.form.ModalFormService',
|
||||
'horizon.framework.widgets.toast.service'
|
||||
'horizon.framework.widgets.modal.deleteModalService',
|
||||
'horizon.framework.widgets.table.events',
|
||||
'horizon.framework.widgets.toast.service',
|
||||
'horizon.dashboard.container.images.resourceType',
|
||||
'horizon.dashboard.container.images.events'
|
||||
];
|
||||
|
||||
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 hosts = [{value: "", name: gettext("Select host to remove the image from.")}];
|
||||
// schema
|
||||
var schema = {
|
||||
type: "object",
|
||||
properties: {
|
||||
host: {
|
||||
title: gettext("Host"),
|
||||
type: "string"
|
||||
}
|
||||
}
|
||||
var scope;
|
||||
var context = {
|
||||
labels: null,
|
||||
deleteEntity: deleteEntity,
|
||||
successEvent: events.DELETE_SUCCESS
|
||||
};
|
||||
|
||||
// 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 = {
|
||||
initAction: initAction,
|
||||
allowed: allowed,
|
||||
perform: perform
|
||||
};
|
||||
var notAllowedMessage = gettext("You are not allowed to delete images: %s");
|
||||
|
||||
return service;
|
||||
|
||||
//////////////
|
||||
|
||||
// include this function in your service
|
||||
// if you plan to emit events to the parent controller
|
||||
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() {
|
||||
return $qExtensions.booleanAsPromise(true);
|
||||
}
|
||||
|
||||
function perform(selected) {
|
||||
model = {
|
||||
id: selected.id,
|
||||
repo: selected.repo,
|
||||
host: ""
|
||||
};
|
||||
// delete selected resource objects
|
||||
function perform(selected, newScope) {
|
||||
scope = newScope;
|
||||
selected = angular.isArray(selected) ? selected : [selected];
|
||||
context.labels = labelize(selected.length);
|
||||
return $qExtensions.allSettled(selected.map(checkPermission)).then(afterCheck);
|
||||
}
|
||||
|
||||
// modal config
|
||||
var config = {
|
||||
"title": interpolate(gettext('Delete Image %s'), [model.repo]),
|
||||
"submitText": gettext('Delete'),
|
||||
"schema": schema,
|
||||
"form": form,
|
||||
"model": model
|
||||
function labelize(count) {
|
||||
return {
|
||||
title: ngettext('Confirm Delete Image',
|
||||
'Confirm Delete Images', count),
|
||||
/* eslint-disable max-len */
|
||||
message: ngettext('You have selected "%s". Please confirm your selection. Deleted image is not recoverable.',
|
||||
'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) {
|
||||
var id = context.model.id;
|
||||
var repo = context.model.repo;
|
||||
var host = context.model.host;
|
||||
return zun.deleteImage(id, host).then(function() {
|
||||
toast.add('success', interpolate(message.success, [repo]));
|
||||
var result = actionResult.getActionResult().updated(resourceType, id);
|
||||
return result.result;
|
||||
});
|
||||
// for batch delete
|
||||
function checkPermission(selected) {
|
||||
return {promise: allowed(selected), context: selected};
|
||||
}
|
||||
|
||||
// for batch delete
|
||||
function afterCheck(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));
|
||||
}
|
||||
|
||||
function deleteImage(id, host) {
|
||||
var msg = gettext('Unable to delete the Image.');
|
||||
return apiService.delete(imagesPath + id, {host: host}).error(error(msg));
|
||||
function deleteImage(id, suppressError) {
|
||||
var promise = apiService.delete(imagesPath, [id]);
|
||||
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