Merge pull request #319 from SchrodingersGat/confirm-delete

Add a generic DeleteForm and update AjaxDeleteView
This commit is contained in:
Oliver 2019-05-13 23:06:47 +10:00 committed by GitHub
commit 5a81372ead
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 114 additions and 93 deletions

View File

@ -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'
]

View File

@ -12,11 +12,14 @@ 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
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):

View File

@ -1,3 +1,7 @@
{% extends "modal_delete_form.html" %}
{% block pre_form_content %}
Are you sure you want to unallocate these parts?
<br>
This will remove {{ item.quantity }} parts from build '{{ item.build.title }}'.
This will remove {{ item.quantity }} parts from build '{{ item.build.title }}'.
{% endblock %}

View File

@ -1,3 +1,7 @@
{% extends "modal_delete_form.html" %}
{% block pre_form_content %}
Are you sure you want to delete company '{{ company.name }}'?
<br>
@ -11,3 +15,5 @@ If this supplier is deleted, these supplier part entries will also be deleted.</
{% endfor %}
</ul>
{% endif %}
{% endblock %}

View File

@ -54,7 +54,7 @@
});
$('#delete-company').click(function() {
launchDeleteForm(
launchModalForm(
"{% url 'company-delete' company.id %}",
{
redirect: "{% url 'company-index' %}"

View File

@ -1 +1,5 @@
Are you sure you want to delete this supplier part?
{% extends "modal_delete_form.html" %}
{% block pre_form_content %}
Are you sure you want to delete this supplier part?
{% endblock %}

View File

@ -109,7 +109,7 @@ InvenTree | {{ company.name }} - Parts
});
$('#delete-part').click(function() {
launchDeleteForm(
launchModalForm(
"{% url 'supplier-part-delete' part.id %}",
{
redirect: "{% url 'company-index' %}"

View File

@ -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 {

View File

@ -1,3 +1,7 @@
{% extends "modal_delete_form.html" %}
{% block pre_form_content %}
Are you sure you wish to delete this attachment?
<br>
This will remove the file '{{ attachment.basename }}'.
This will remove the file '{{ attachment.basename }}'.
{% endblock %}

View File

@ -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();
}

View File

@ -1,3 +1,7 @@
{% extends "modal_delete_form.html" %}
{% block pre_form_content %}
Are you sure you want to delete this BOM item?
<br>
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:
<b>{{ item.part.full_name }}</b> - <i>{{ item.part.description }}</i>
</li>
</ul>
{% endblock %}

View File

@ -111,7 +111,7 @@
{% endif %}
$('#cat-delete').click(function() {
launchDeleteForm("{% url 'category-delete' category.id %}",
launchModalForm("{% url 'category-delete' category.id %}",
{
redirect: redirect
});

View File

@ -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.
<li class='list-group-item'><b>{{ part.full_name }}</b> - <i>{{ part.description }}</i></li>
{% endfor %}
</ul>
{% endif %}
{% endif %}
{% endblock %}

View File

@ -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 %}

View File

@ -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'

View File

@ -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);
}

View File

@ -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');
}

View File

@ -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

View File

@ -194,7 +194,7 @@
{% endif %}
$("#stock-delete").click(function () {
launchDeleteForm(
launchModalForm(
"{% url 'stock-item-delete' item.id %}",
{
redirect: "{% url 'part-stock' item.part.id %}"

View File

@ -1,5 +1,11 @@
{% extends "modal_delete_form.html" %}
{% block pre_form_content %}
<div class='alert alert-danger alert-block'>
Are you sure you want to delete this stock item?
<br>
This will remove <b>{{ item.quantity }}</b> units of <b>{{ item.part.full_name }}</b> from stock.
</div>
{% endblock %}

View File

@ -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' %}"
});

View File

@ -1,3 +1,6 @@
{% extends "modal_delete_form.html" %}
{% block pre_form_content %}
Are you sure you want to delete stock location '{{ location.name }}'?
<br>
@ -34,3 +37,4 @@ If this location is deleted, these items will be moved to the top level 'Stock'
{% endfor %}
</ul>
{% endif %}
{% endblock %}

View File

@ -0,0 +1 @@
{% extends "modal_form.html" %}