From e35a9284eba500ea62b21d51e3145229ad3865a1 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Mon, 13 May 2019 22:46:47 +1000 Subject: [PATCH 01/10] Add a generic DeleteForm and update AjaxDeleteView --- InvenTree/InvenTree/forms.py | 16 +++++++ InvenTree/InvenTree/views.py | 54 ++++++++++++++++------ InvenTree/templates/modal_delete_form.html | 1 + 3 files changed, 56 insertions(+), 15 deletions(-) create mode 100644 InvenTree/templates/modal_delete_form.html diff --git a/InvenTree/InvenTree/forms.py b/InvenTree/InvenTree/forms.py index ba203b2f1b..8c86fdd7fc 100644 --- a/InvenTree/InvenTree/forms.py +++ b/InvenTree/InvenTree/forms.py @@ -17,3 +17,19 @@ class HelperForm(forms.ModelForm): self.helper = FormHelper() self.helper.form_tag = False + + +class DeleteForm(forms.Form): + """ Generic deletion form which provides simple user confirmation + """ + + confirm_delete = forms.BooleanField( + required=False, + initial=False, + help_text='Confirm item deletion' + ) + + class Meta: + fields = [ + 'confirm_delete' + ] diff --git a/InvenTree/InvenTree/views.py b/InvenTree/InvenTree/views.py index ed07318e28..994f2ed89b 100644 --- a/InvenTree/InvenTree/views.py +++ b/InvenTree/InvenTree/views.py @@ -17,6 +17,9 @@ from django.views.generic.base import TemplateView from part.models import Part +from .forms import DeleteForm +from .helpers import str2bool + from rest_framework import views @@ -300,13 +303,28 @@ class AjaxUpdateView(AjaxMixin, UpdateView): return self.renderJsonResponse(request, form, data) -class AjaxDeleteView(AjaxMixin, DeleteView): +class AjaxDeleteView(AjaxMixin, UpdateView): """ An 'AJAXified DeleteView for removing an object from the DB - Returns a HTML object (not a form!) in JSON format (for delivery to a modal window) - Handles deletion """ + form_class = DeleteForm + ajax_form_title = "Delete Item" + ajax_template_name = "modal_delete_form.html" + context_object_name = 'item' + + def get_object(self): + try: + self.object = self.model.objects.get(pk=self.kwargs['pk']) + except: + return None + return self.object + + def get_form(self): + return self.form_class(self.get_form_kwargs()) + def get(self, request, *args, **kwargs): """ Respond to GET request @@ -314,19 +332,15 @@ class AjaxDeleteView(AjaxMixin, DeleteView): - Return rendered form to client """ - super(DeleteView, self).get(request, *args, **kwargs) + super(UpdateView, self).get(request, *args, **kwargs) - data = { - 'id': self.get_object().id, - 'delete': False, - 'title': self.ajax_form_title, - 'html_data': render_to_string( - self.ajax_template_name, - self.get_context_data(), - request=request) - } + form = self.get_form() - return JsonResponse(data) + context = self.get_context_data() + + context[self.context_object_name] = self.get_object() + + return self.renderJsonResponse(request, form, context=context) def post(self, request, *args, **kwargs): """ Respond to POST request @@ -337,14 +351,24 @@ class AjaxDeleteView(AjaxMixin, DeleteView): obj = self.get_object() pk = obj.id - obj.delete() + + form = self.get_form() + + confirmed = str2bool(request.POST.get('confirm_delete', False)) + context = self.get_context_data() + + if confirmed: + obj.delete() + else: + form.errors['confirm_delete'] = ['Check box to confirm item deletion'] + context[self.context_object_name] = self.get_object() data = { 'id': pk, - 'delete': True + 'form_valid': confirmed } - return self.renderJsonResponse(request, data=data) + return self.renderJsonResponse(request, form, data=data, context=context) class IndexView(TemplateView): diff --git a/InvenTree/templates/modal_delete_form.html b/InvenTree/templates/modal_delete_form.html new file mode 100644 index 0000000000..df8553f26e --- /dev/null +++ b/InvenTree/templates/modal_delete_form.html @@ -0,0 +1 @@ +{% extends "modal_form.html" %} From a78106526a758b5dcc16eb129858ed17dbfe89f4 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Mon, 13 May 2019 22:47:36 +1000 Subject: [PATCH 02/10] Remove launchDeleteForm JS function - All should be consolidated upon launchModalForm - StockItem delete now uses this --- InvenTree/static/script/inventree/modals.js | 62 ------------------- InvenTree/stock/templates/stock/item.html | 2 +- .../stock/templates/stock/item_delete.html | 10 ++- 3 files changed, 9 insertions(+), 65 deletions(-) diff --git a/InvenTree/static/script/inventree/modals.js b/InvenTree/static/script/inventree/modals.js index 9116ba659d..67d4497674 100644 --- a/InvenTree/static/script/inventree/modals.js +++ b/InvenTree/static/script/inventree/modals.js @@ -345,68 +345,6 @@ function openModal(options) { } -function launchDeleteForm(url, options = {}) { - /* Launch a modal form to delete an object - */ - - var modal = options.modal || '#modal-delete'; - - $(modal).on('shown.bs.modal', function() { - $(modal + ' .modal-form-content').scrollTop(0); - }); - - // Un-bind any attached click listeners - $(modal).off('click', '#modal-form-delete'); - - // Request delete form data - $.ajax({ - url: url, - type: 'get', - dataType: 'json', - beforeSend: function() { - openModal({modal: modal}); - }, - success: function (response) { - if (response.title) { - modalSetTitle(modal, response.title); - } - if (response.html_data) { - modalSetContent(modal, response.html_data); - } - else { - - $(modal).modal('hide'); - showAlertDialog('Invalid form response', 'JSON response missing HTML data'); - } - }, - error: function (xhr, ajaxOptions, thrownError) { - $(modal).modal('hide'); - showAlertDialog('Error requesting form data', renderErrorMessage(xhr)); - } - }); - - $(modal).on('click', '#modal-form-delete', function() { - - var form = $(modal).find('#delete-form'); - - $.ajax({ - url: url, - data: form.serialize(), - type: 'post', - dataType: 'json', - success: function (response) { - $(modal).modal('hide'); - afterForm(response, options); - }, - error: function (xhr, ajaxOptions, thrownError) { - $(modal).modal('hide'); - showAlertDialog('Error deleting item', renderErrorMessage(xhr)); - } - }); - }); -} - - function injectModalForm(modal, form_html) { /* Inject form content into the modal. * Updates the HTML of the form content, and then applies some other updates diff --git a/InvenTree/stock/templates/stock/item.html b/InvenTree/stock/templates/stock/item.html index 8bfe5c8e4e..cb54ac6f5e 100644 --- a/InvenTree/stock/templates/stock/item.html +++ b/InvenTree/stock/templates/stock/item.html @@ -194,7 +194,7 @@ {% endif %} $("#stock-delete").click(function () { - launchDeleteForm( + launchModalForm( "{% url 'stock-item-delete' item.id %}", { redirect: "{% url 'part-stock' item.part.id %}" diff --git a/InvenTree/stock/templates/stock/item_delete.html b/InvenTree/stock/templates/stock/item_delete.html index 9f3f863d75..9e908a0d67 100644 --- a/InvenTree/stock/templates/stock/item_delete.html +++ b/InvenTree/stock/templates/stock/item_delete.html @@ -1,5 +1,11 @@ +{% extends "modal_delete_form.html" %} + +{% block pre_form_content %} + +
Are you sure you want to delete this stock item? -
- This will remove {{ item.quantity }} units of {{ item.part.full_name }} from stock. +
+ +{% endblock %} \ No newline at end of file From 0e0096467c5d172f988f2ce59282d8ba37dfa63f Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Mon, 13 May 2019 22:50:05 +1000 Subject: [PATCH 03/10] Update delete form for Company objects --- InvenTree/company/templates/company/delete.html | 6 ++++++ InvenTree/company/templates/company/detail.html | 2 +- InvenTree/company/views.py | 2 ++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/InvenTree/company/templates/company/delete.html b/InvenTree/company/templates/company/delete.html index 1069d790e3..9a94404739 100644 --- a/InvenTree/company/templates/company/delete.html +++ b/InvenTree/company/templates/company/delete.html @@ -1,3 +1,7 @@ +{% extends "modal_delete_form.html" %} + +{% block pre_form_content %} + Are you sure you want to delete company '{{ company.name }}'?
@@ -11,3 +15,5 @@ If this supplier is deleted, these supplier part entries will also be deleted. {% endif %} + +{% endblock %} \ No newline at end of file diff --git a/InvenTree/company/templates/company/detail.html b/InvenTree/company/templates/company/detail.html index 0068d150ae..8e26d85a89 100644 --- a/InvenTree/company/templates/company/detail.html +++ b/InvenTree/company/templates/company/detail.html @@ -54,7 +54,7 @@ }); $('#delete-company').click(function() { - launchDeleteForm( + launchModalForm( "{% url 'company-delete' company.id %}", { redirect: "{% url 'company-index' %}" diff --git a/InvenTree/company/views.py b/InvenTree/company/views.py index f61da1fffa..0630556946 100644 --- a/InvenTree/company/views.py +++ b/InvenTree/company/views.py @@ -93,10 +93,12 @@ class CompanyCreate(AjaxCreateView): class CompanyDelete(AjaxDeleteView): """ View for deleting a Company object """ + model = Company success_url = '/company/' ajax_template_name = 'company/delete.html' ajax_form_title = 'Delete Company' + context_object_name = 'company' def get_data(self): return { From fcdddf6bb654f409396ae6e821af4cb64974705e Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Mon, 13 May 2019 22:52:20 +1000 Subject: [PATCH 04/10] Cleaup for delete supplier part form --- InvenTree/company/templates/company/partdelete.html | 6 +++++- InvenTree/company/templates/company/partdetail.html | 2 +- InvenTree/part/views.py | 1 + 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/InvenTree/company/templates/company/partdelete.html b/InvenTree/company/templates/company/partdelete.html index 13ba71e2ca..ba6b78f841 100644 --- a/InvenTree/company/templates/company/partdelete.html +++ b/InvenTree/company/templates/company/partdelete.html @@ -1 +1,5 @@ -Are you sure you want to delete this supplier part? \ No newline at end of file +{% extends "modal_delete_form.html" %} + +{% block pre_form_content %} +Are you sure you want to delete this supplier part? +{% endblock %} \ No newline at end of file diff --git a/InvenTree/company/templates/company/partdetail.html b/InvenTree/company/templates/company/partdetail.html index 2924f05453..b2fdf8aeb9 100644 --- a/InvenTree/company/templates/company/partdetail.html +++ b/InvenTree/company/templates/company/partdetail.html @@ -109,7 +109,7 @@ InvenTree | {{ company.name }} - Parts }); $('#delete-part').click(function() { - launchDeleteForm( + launchModalForm( "{% url 'supplier-part-delete' part.id %}", { redirect: "{% url 'company-index' %}" diff --git a/InvenTree/part/views.py b/InvenTree/part/views.py index d9540035d8..b820efb592 100644 --- a/InvenTree/part/views.py +++ b/InvenTree/part/views.py @@ -804,3 +804,4 @@ class SupplierPartDelete(AjaxDeleteView): success_url = '/supplier/' ajax_template_name = 'company/partdelete.html' ajax_form_title = 'Delete Supplier Part' + context_object_name = 'supplier_part' \ No newline at end of file From ffa5a25fa9d908d0d2431ae8d661ce746a304a61 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Mon, 13 May 2019 22:53:58 +1000 Subject: [PATCH 05/10] Updated form for deleting part attachments --- InvenTree/part/templates/part/attachment_delete.html | 6 +++++- InvenTree/part/templates/part/attachments.html | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/InvenTree/part/templates/part/attachment_delete.html b/InvenTree/part/templates/part/attachment_delete.html index db98b7f6d6..1adffcc710 100644 --- a/InvenTree/part/templates/part/attachment_delete.html +++ b/InvenTree/part/templates/part/attachment_delete.html @@ -1,3 +1,7 @@ +{% extends "modal_delete_form.html" %} + +{% block pre_form_content %} Are you sure you wish to delete this attachment?
-This will remove the file '{{ attachment.basename }}'. \ No newline at end of file +This will remove the file '{{ attachment.basename }}'. +{% endblock %} \ No newline at end of file diff --git a/InvenTree/part/templates/part/attachments.html b/InvenTree/part/templates/part/attachments.html index e3bed202c4..d0ccaf122d 100644 --- a/InvenTree/part/templates/part/attachments.html +++ b/InvenTree/part/templates/part/attachments.html @@ -62,7 +62,7 @@ $("#attachment-table").on('click', '.attachment-delete-button', function() { var button = $(this); - launchDeleteForm(button.attr('url'), { + launchModalForm(button.attr('url'), { success: function() { location.reload(); } From 00b37b62dba4c76d790112ff9f958bb78c57cb82 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Mon, 13 May 2019 22:55:40 +1000 Subject: [PATCH 06/10] Updated form to delete part category --- InvenTree/part/templates/part/category.html | 2 +- InvenTree/part/templates/part/category_delete.html | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/InvenTree/part/templates/part/category.html b/InvenTree/part/templates/part/category.html index 0e83a68a9a..286b5fc418 100644 --- a/InvenTree/part/templates/part/category.html +++ b/InvenTree/part/templates/part/category.html @@ -111,7 +111,7 @@ {% endif %} $('#cat-delete').click(function() { - launchDeleteForm("{% url 'category-delete' category.id %}", + launchModalForm("{% url 'category-delete' category.id %}", { redirect: redirect }); diff --git a/InvenTree/part/templates/part/category_delete.html b/InvenTree/part/templates/part/category_delete.html index 298499ab1a..98f6ec9590 100644 --- a/InvenTree/part/templates/part/category_delete.html +++ b/InvenTree/part/templates/part/category_delete.html @@ -1,3 +1,6 @@ +{% extends "modal_delete_form.html" %} + +{% block pre_form_content %} Are you sure you want to delete category '{{ category.name }}'? {% if category.children.all|length > 0 %} @@ -30,4 +33,6 @@ the top level 'Parts' category.
  • {{ part.full_name }} - {{ part.description }}
  • {% endfor %} -{% endif %} \ No newline at end of file +{% endif %} + +{% endblock %} \ No newline at end of file From d679ee997115b7daf87fddfc459fd24675cc0312 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Mon, 13 May 2019 22:58:42 +1000 Subject: [PATCH 07/10] Update form for deleting stock location --- InvenTree/stock/templates/stock/location.html | 2 +- InvenTree/stock/templates/stock/location_delete.html | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/InvenTree/stock/templates/stock/location.html b/InvenTree/stock/templates/stock/location.html index 0faeb66216..c0212f2c5f 100644 --- a/InvenTree/stock/templates/stock/location.html +++ b/InvenTree/stock/templates/stock/location.html @@ -97,7 +97,7 @@ }); $('#location-delete').click(function() { - launchDeleteForm("{% url 'stock-location-delete' location.id %}", + launchModalForm("{% url 'stock-location-delete' location.id %}", { redirect: "{% url 'stock-index' %}" }); diff --git a/InvenTree/stock/templates/stock/location_delete.html b/InvenTree/stock/templates/stock/location_delete.html index ecb60ae1f1..ef5cee7541 100644 --- a/InvenTree/stock/templates/stock/location_delete.html +++ b/InvenTree/stock/templates/stock/location_delete.html @@ -1,3 +1,6 @@ +{% extends "modal_delete_form.html" %} + +{% block pre_form_content %} Are you sure you want to delete stock location '{{ location.name }}'?
    @@ -34,3 +37,4 @@ If this location is deleted, these items will be moved to the top level 'Stock' {% endfor %} {% endif %} +{% endblock %} \ No newline at end of file From 06e95819c945ef51b6423ca5da5659ccdc1e05fd Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Mon, 13 May 2019 23:00:04 +1000 Subject: [PATCH 08/10] Update form for deleting a BOM item --- InvenTree/part/templates/part/bom-delete.html | 6 ++++++ InvenTree/part/templates/part/detail.html | 2 +- InvenTree/static/script/inventree/bom.js | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/InvenTree/part/templates/part/bom-delete.html b/InvenTree/part/templates/part/bom-delete.html index 492a6eeeda..ffaf2c57e5 100644 --- a/InvenTree/part/templates/part/bom-delete.html +++ b/InvenTree/part/templates/part/bom-delete.html @@ -1,3 +1,7 @@ +{% extends "modal_delete_form.html" %} + +{% block pre_form_content %} + Are you sure you want to delete this BOM item?
    Deleting this entry will remove the BOM row from the following part: @@ -7,3 +11,5 @@ Deleting this entry will remove the BOM row from the following part: {{ item.part.full_name }} - {{ item.part.description }} + +{% endblock %} \ No newline at end of file diff --git a/InvenTree/part/templates/part/detail.html b/InvenTree/part/templates/part/detail.html index c352bfa7ee..c0f823ce13 100644 --- a/InvenTree/part/templates/part/detail.html +++ b/InvenTree/part/templates/part/detail.html @@ -193,7 +193,7 @@ $('#delete-part').click(function() { - launchDeleteForm( + launchModalForm( "{% url 'part-delete' part.id %}", { redirect: {% if part.category %}"{% url 'category-detail' part.category.id %}"{% else %}"{% url 'part-index' %}"{% endif %} diff --git a/InvenTree/static/script/inventree/bom.js b/InvenTree/static/script/inventree/bom.js index 6e7a33775a..eaa1d40d3d 100644 --- a/InvenTree/static/script/inventree/bom.js +++ b/InvenTree/static/script/inventree/bom.js @@ -184,7 +184,7 @@ function loadBomTable(table, options) { table.on('click', '.bom-delete-button', function() { var button = $(this); - launchDeleteForm(button.attr('url'), { + launchModalForm(button.attr('url'), { success: function() { reloadBomTable(table); } From edc2cc49c281b2365d304ecacec2a15ef4848401 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Mon, 13 May 2019 23:03:32 +1000 Subject: [PATCH 09/10] Fix deletion form for BuildItem --- InvenTree/build/templates/build/delete_build_item.html | 6 +++++- InvenTree/static/script/inventree/build.js | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/InvenTree/build/templates/build/delete_build_item.html b/InvenTree/build/templates/build/delete_build_item.html index 23993feb95..37ed0dfa32 100644 --- a/InvenTree/build/templates/build/delete_build_item.html +++ b/InvenTree/build/templates/build/delete_build_item.html @@ -1,3 +1,7 @@ +{% extends "modal_delete_form.html" %} + +{% block pre_form_content %} Are you sure you want to unallocate these parts?
    -This will remove {{ item.quantity }} parts from build '{{ item.build.title }}'. \ No newline at end of file +This will remove {{ item.quantity }} parts from build '{{ item.build.title }}'. +{% endblock %} \ No newline at end of file diff --git a/InvenTree/static/script/inventree/build.js b/InvenTree/static/script/inventree/build.js index 4ecd4214a2..c982cc254c 100644 --- a/InvenTree/static/script/inventree/build.js +++ b/InvenTree/static/script/inventree/build.js @@ -87,7 +87,7 @@ function loadAllocationTable(table, part_id, part, url, required, button) { table.on('click', '.item-del-button', function() { var button = $(this); - launchDeleteForm(button.attr('url'), { + launchModalForm(button.attr('url'), { success: function() { table.bootstrapTable('refresh'); } From 069cebb669669e86ce0591765aacaf34552fd543 Mon Sep 17 00:00:00 2001 From: Oliver Walters Date: Mon, 13 May 2019 23:03:37 +1000 Subject: [PATCH 10/10] PEP --- InvenTree/InvenTree/forms.py | 2 +- InvenTree/InvenTree/views.py | 2 +- InvenTree/part/views.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/InvenTree/InvenTree/forms.py b/InvenTree/InvenTree/forms.py index 8c86fdd7fc..7ec4401101 100644 --- a/InvenTree/InvenTree/forms.py +++ b/InvenTree/InvenTree/forms.py @@ -20,7 +20,7 @@ class HelperForm(forms.ModelForm): class DeleteForm(forms.Form): - """ Generic deletion form which provides simple user confirmation + """ Generic deletion form which provides simple user confirmation """ confirm_delete = forms.BooleanField( diff --git a/InvenTree/InvenTree/views.py b/InvenTree/InvenTree/views.py index 994f2ed89b..08ca9e0eb5 100644 --- a/InvenTree/InvenTree/views.py +++ b/InvenTree/InvenTree/views.py @@ -12,7 +12,7 @@ from django.template.loader import render_to_string from django.http import JsonResponse from django.views import View -from django.views.generic import UpdateView, CreateView, DeleteView +from django.views.generic import UpdateView, CreateView from django.views.generic.base import TemplateView from part.models import Part diff --git a/InvenTree/part/views.py b/InvenTree/part/views.py index b820efb592..8650b85fb4 100644 --- a/InvenTree/part/views.py +++ b/InvenTree/part/views.py @@ -804,4 +804,4 @@ class SupplierPartDelete(AjaxDeleteView): success_url = '/supplier/' ajax_template_name = 'company/partdelete.html' ajax_form_title = 'Delete Supplier Part' - context_object_name = 'supplier_part' \ No newline at end of file + context_object_name = 'supplier_part'