2
0
mirror of https://github.com/inventree/InvenTree.git synced 2025-06-18 04:55:44 +00:00

Adds API mixin for "bulk delete" (#3146)

* Introduces a BulkDelete API mixin class

- Allows deletion of multiple items against a single API request

* Bump API version

* Adds BulkDelete mixin to StockItemTestResult API class

* refactor "multi BOM Item delete" to use new approach

* Refactor various attachment API endpoints

* Refactor multi delete for StockItem

* Convert remaining enndpoints over

* Fix for API test code
This commit is contained in:
Oliver
2022-06-07 07:25:12 +10:00
committed by GitHub
parent ea83d4b290
commit 00b75d792e
16 changed files with 218 additions and 156 deletions

View File

@ -7,7 +7,6 @@
/* exported
inventreeGet,
inventreeDelete,
inventreeMultiDelete,
inventreeFormDataUpload,
showApiError,
*/
@ -160,59 +159,20 @@ function inventreePut(url, data={}, options={}) {
}
/*
* Performs a DELETE API call to the server
*/
function inventreeDelete(url, options={}) {
/*
* Delete a record
*/
options = options || {};
options.method = 'DELETE';
return inventreePut(url, {}, options);
}
/*
* Perform a 'multi delete' operation:
*
* - Items are deleted sequentially from the database, rather than simultaneous requests
* - This prevents potential overload / transaction issues in the DB backend
*
* Notes:
* - Assumes that each item in the 'items' list has a parameter 'pk'
*/
function inventreeMultiDelete(url, items, options={}) {
if (!url.endsWith('/')) {
url += '/';
}
function doNextDelete() {
if (items.length > 0) {
var item = items.shift();
inventreeDelete(`${url}${item.pk}/`, {
complete: doNextDelete
});
} else {
if (options.modal) {
$(options.modal).modal('hide');
}
if (options.success) {
options.success();
}
}
}
if (options.modal) {
showModalSpinner(options.modal);
}
// Initiate the process
doNextDelete();
return inventreePut(
url,
options.data || {},
options
);
}

View File

@ -86,9 +86,11 @@ function deleteAttachments(attachments, url, options={}) {
}
var rows = '';
var ids = [];
attachments.forEach(function(att) {
rows += renderAttachment(att);
ids.push(att.pk);
});
var html = `
@ -105,22 +107,16 @@ function deleteAttachments(attachments, url, options={}) {
</table>
`;
constructFormBody({}, {
constructForm(url, {
method: 'DELETE',
title: '{% trans "Delete Attachments" %}',
preFormContent: html,
onSubmit: function(fields, opts) {
inventreeMultiDelete(
url,
attachments,
{
modal: opts.modal,
success: function() {
// Refresh the table once all attachments are deleted
$('#attachment-table').bootstrapTable('refresh');
}
}
);
form_data: {
items: ids,
},
onSuccess: function() {
// Refresh the table once all attachments are deleted
$('#attachment-table').bootstrapTable('refresh');
}
});
}

View File

@ -672,9 +672,11 @@ function deleteBomItems(items, options={}) {
}
var rows = '';
var ids = [];
items.forEach(function(item) {
rows += renderItem(item);
ids.push(item.pk);
});
var html = `
@ -692,22 +694,14 @@ function deleteBomItems(items, options={}) {
</table>
`;
constructFormBody({}, {
constructForm('{% url "api-bom-list" %}', {
method: 'DELETE',
title: '{% trans "Delete selected BOM items?" %}',
fields: {},
preFormContent: html,
onSubmit: function(fields, opts) {
inventreeMultiDelete(
'{% url "api-bom-list" %}',
items,
{
modal: opts.modal,
success: options.success,
}
);
form_data: {
items: ids,
},
preFormContent: html,
onSuccess: options.success,
});
}

View File

@ -3,7 +3,6 @@
/* globals
constructForm,
imageHoverIcon,
inventreeMultiDelete,
loadTableFilters,
makeIconButton,
renderLink,
@ -238,9 +237,11 @@ function deleteSupplierParts(parts, options={}) {
}
var rows = '';
var ids = [];
parts.forEach(function(sup_part) {
rows += renderPart(sup_part);
ids.push(sup_part.pk);
});
var html = `
@ -258,21 +259,14 @@ function deleteSupplierParts(parts, options={}) {
</table>
`;
constructFormBody({}, {
constructForm('{% url "api-supplier-part-list" %}', {
method: 'DELETE',
title: '{% trans "Delete Supplier Parts" %}',
preFormContent: html,
onSubmit: function(fields, opts) {
inventreeMultiDelete(
'{% url "api-supplier-part-list" %}',
parts,
{
modal: opts.modal,
success: options.success
}
);
}
form_data: {
items: ids,
},
onSuccess: options.success,
});
}
@ -472,9 +466,11 @@ function deleteManufacturerParts(selections, options={}) {
}
var rows = '';
var ids = [];
selections.forEach(function(man_part) {
rows += renderPart(man_part);
ids.push(man_part.pk);
});
var html = `
@ -491,21 +487,14 @@ function deleteManufacturerParts(selections, options={}) {
</table>
`;
constructFormBody({}, {
constructForm('{% url "api-manufacturer-part-list" %}', {
method: 'DELETE',
title: '{% trans "Delete Manufacturer Parts" %}',
preFormContent: html,
onSubmit: function(fields, opts) {
inventreeMultiDelete(
'{% url "api-manufacturer-part-list" %}',
selections,
{
modal: opts.modal,
success: options.success,
}
);
}
form_data: {
items: ids,
},
onSuccess: options.success,
});
}
@ -525,9 +514,11 @@ function deleteManufacturerPartParameters(selections, options={}) {
}
var rows = '';
var ids = [];
selections.forEach(function(param) {
rows += renderParam(param);
ids.push(param.pk);
});
var html = `
@ -543,20 +534,14 @@ function deleteManufacturerPartParameters(selections, options={}) {
</table>
`;
constructFormBody({}, {
constructForm('{% url "api-manufacturer-part-parameter-list" %}', {
method: 'DELETE',
title: '{% trans "Delete Parameters" %}',
preFormContent: html,
onSubmit: function(fields, opts) {
inventreeMultiDelete(
'{% url "api-manufacturer-part-parameter-list" %}',
selections,
{
modal: opts.modal,
success: options.success,
}
);
}
form_data: {
items: ids,
},
onSuccess: options.success,
});
}

View File

@ -725,7 +725,8 @@ function submitFormData(fields, options) {
// Only used if file / image upload is required
var form_data = new FormData();
var data = {};
// We can (optionally) provide a "starting point" for the submitted data
var data = options.form_data || {};
var has_files = false;

View File

@ -12,7 +12,6 @@
handleFormErrors,
imageHoverIcon,
inventreeGet,
inventreeMultiDelete,
inventreePut,
launchModalForm,
linkButtonsToSelection,
@ -1107,12 +1106,23 @@ function adjustStock(action, items, options={}) {
// Delete action is handled differently
if (action == 'delete') {
inventreeMultiDelete(
var ids = [];
items.forEach(function(item) {
ids.push(item.pk);
});
showModalSpinner(opts.modal, true);
inventreeDelete(
'{% url "api-stock-list" %}',
items,
{
modal: opts.modal,
success: options.success,
data: {
items: ids,
},
success: function(response) {
$(opts.modal).modal('hide');
options.success(response);
}
}
);