diff options
author | Étienne Loks <etienne.loks@iggdrasil.net> | 2019-09-13 18:37:06 +0200 |
---|---|---|
committer | Étienne Loks <etienne.loks@iggdrasil.net> | 2019-09-13 18:37:29 +0200 |
commit | bddadc1eec4f477ff85e666e009382a274ac1103 (patch) | |
tree | 81714ce5e159dcdd06faed1b44b2fa4ccdf22e1a | |
parent | 9bc04754f1a8a01cb7457c335c41a3b2fee0a68c (diff) | |
download | Ishtar-bddadc1eec4f477ff85e666e009382a274ac1103.tar.bz2 Ishtar-bddadc1eec4f477ff85e666e009382a274ac1103.zip |
Muliple person deletion wizard
-rw-r--r-- | archaeological_finds/forms.py | 4 | ||||
-rw-r--r-- | ishtar_common/forms.py | 2 | ||||
-rw-r--r-- | ishtar_common/forms_common.py | 22 | ||||
-rw-r--r-- | ishtar_common/templates/ishtar/wizard/confirm_wizard.html | 3 | ||||
-rw-r--r-- | ishtar_common/templates/ishtar/wizard/delete_wizard.html | 42 | ||||
-rw-r--r-- | ishtar_common/templates/ishtar/wizard/wizard_person_deletion.html | 4 | ||||
-rw-r--r-- | ishtar_common/views.py | 2 | ||||
-rw-r--r-- | ishtar_common/wizards.py | 109 |
8 files changed, 177 insertions, 11 deletions
diff --git a/archaeological_finds/forms.py b/archaeological_finds/forms.py index a333033c6..a08821d85 100644 --- a/archaeological_finds/forms.py +++ b/archaeological_finds/forms.py @@ -54,7 +54,7 @@ from ishtar_common import widgets from ishtar_common.forms import CustomForm, CustomFormSearch, FormSet, \ FloatField, reverse_lazy, TableSelect, get_now, FinalForm, \ ManageOldType, FieldType, IshtarForm, FormHeader, QAForm, HistorySelect, \ - PkWizardSearch + MultiSearchForm from ishtar_common.forms_common import get_town_field from ishtar_common.models import valid_id, valid_ids, get_current_profile, \ SpatialReferenceSystem, Area, OperationType, IshtarUser @@ -1452,7 +1452,7 @@ class FindDeletionForm(FinalForm): confirm_end_msg = _(u"Would you like to delete this find?") -class UpstreamFindFormSelection(PkWizardSearch, FindFormSelection): +class UpstreamFindFormSelection(MultiSearchForm, FindFormSelection): form_label = _(u"Upstream finds") current_model = models.Find pk_key = 'resulting_pk' diff --git a/ishtar_common/forms.py b/ishtar_common/forms.py index 8acd5ffcc..ae7c6ca14 100644 --- a/ishtar_common/forms.py +++ b/ishtar_common/forms.py @@ -372,7 +372,7 @@ class CustomForm(BSForm): return sorted(customs, key=lambda x: x[1]) -class PkWizardSearch(object): +class MultiSearchForm(object): current_model = None pk_key = None diff --git a/ishtar_common/forms_common.py b/ishtar_common/forms_common.py index 235138eea..42bf90691 100644 --- a/ishtar_common/forms_common.py +++ b/ishtar_common/forms_common.py @@ -44,7 +44,8 @@ from ishtar_common.templatetags.link_to_window import simple_link_to_window from .forms import FinalForm, FormSet, reverse_lazy, name_validator, \ TableSelect, ManageOldType, CustomForm, FieldType, FormHeader, \ FormSetWithDeleteSwitches, BSForm, get_data_from_formset, \ - file_size_validator, HistorySelect, CustomFormSearch, QAForm, IshtarForm + file_size_validator, HistorySelect, CustomFormSearch, QAForm, IshtarForm, \ + MultiSearchForm from ishtar_common.utils import is_downloadable, clean_session_cache, \ max_size_help @@ -515,6 +516,25 @@ class PersonFormSelection(CustomFormSearch): validators=[models.valid_id(models.Person)]) +class PersonFormMultiSelection(MultiSearchForm, PersonFormSelection): + pk_key = 'pks' + associated_models = {'pks': models.Person} + + pk = forms.CharField( + label="", + required=True, + widget=widgets.DataTable( + reverse_lazy('get-person'), PersonSelect, models.Person, + multiple_select=True, + source_full=reverse_lazy('get-person-full')), + validators=[models.valid_ids(models.Person)]) + + def __init__(self, *args, **kwargs): + super(MultiSearchForm, self).__init__(*args, **kwargs) + self.fields['pk'].required = True + self.fields[self.pk_key] = self.fields.pop('pk') + + class QAPersonFormMulti(QAForm): form_admin_name = _(u"Person - Quick action - Modify") form_slug = "person-quickaction-modify" diff --git a/ishtar_common/templates/ishtar/wizard/confirm_wizard.html b/ishtar_common/templates/ishtar/wizard/confirm_wizard.html index e78a2f4a6..56887d28b 100644 --- a/ishtar_common/templates/ishtar/wizard/confirm_wizard.html +++ b/ishtar_common/templates/ishtar/wizard/confirm_wizard.html @@ -15,6 +15,7 @@ </div> {% endblock %} {% block "detailed_informations" %} + {% block "cards" %} {% for form_label, form_data in datas %} <div class="card"> @@ -32,8 +33,8 @@ </div> </div> - {% endfor %} + {% endblock "cards" %} {{wizard.management_form}} {% if not wizard.form.is_hidden %} <table> diff --git a/ishtar_common/templates/ishtar/wizard/delete_wizard.html b/ishtar_common/templates/ishtar/wizard/delete_wizard.html new file mode 100644 index 000000000..82e074eae --- /dev/null +++ b/ishtar_common/templates/ishtar/wizard/delete_wizard.html @@ -0,0 +1,42 @@ +{% extends "ishtar/wizard/confirm_wizard.html" %} +{% load i18n %} +{% load range %} +{% block "warning_message" %} +<div class="alert alert-danger"> + <p><i class="fa fa-exclamation-triangle" aria-hidden="true"></i> + {% if current_objs and current_objs.1 %} + {% trans "Are you sure to want to delete theses items?" %} + <ul>{% for obj in current_objs %} + <li>{{obj}}</li> + {% endfor %}</ul> + {% else %} + {% trans "Are you sure to want to delete this item?" %}{% endif %} + </p> + <p>{% trans "No rollback is possible. Be careful to scroll to the end of page to check every piece of information." %}</p> +</div> +{% endblock %} + +{% block "cards" %} +{% for form_label, form_data in datas %} + +<div class="card"> + {% if form_label %} + <div class="card-header"> + {{form_label}} + </div>{% endif %} + <div class="card-body"> + {% if current_objs and current_objs.1 %}{% for current_object in current_objs %}{% if forloop.counter == forloop.parentloop.counter %} + {% block "detailled_extra_info" %} + {% endblock %} + {% endif %}{% endfor %}{% endif %} + <table class='table'> + {% for data in form_data %} + <tr{% if data.2 %} class='{{data.2}}'{%endif%}><th>{{data.0}}</th><td>{{data.1}}</td></tr> + {% endfor %} + </table> + + </div> +</div> + +{% endfor %} +{% endblock "cards" %} diff --git a/ishtar_common/templates/ishtar/wizard/wizard_person_deletion.html b/ishtar_common/templates/ishtar/wizard/wizard_person_deletion.html index 6d1f06bd1..27595286b 100644 --- a/ishtar_common/templates/ishtar/wizard/wizard_person_deletion.html +++ b/ishtar_common/templates/ishtar/wizard/wizard_person_deletion.html @@ -1,6 +1,6 @@ -{% extends "ishtar/wizard/confirm_wizard.html" %} +{% extends "ishtar/wizard/delete_wizard.html" %} {% load i18n %} -{% block "extra_informations" %} +{% block "detailled_extra_info" %} {% if current_object.file_responsability.count %} <h3>{% trans "In charge of archaeological files" %}</h3> diff --git a/ishtar_common/views.py b/ishtar_common/views.py index 0f0854720..0f2fe1276 100644 --- a/ishtar_common/views.py +++ b/ishtar_common/views.py @@ -164,7 +164,7 @@ def person_modify(request, pk): person_deletion_wizard = wizards.PersonDeletionWizard.as_view( - [('selec-person_deletion', forms.PersonFormSelection), + [('selec-person_deletion', forms.PersonFormMultiSelection), ('final-person_deletion', FinalDeleteForm)], label=_(u"Person deletion"), url_name='person_deletion',) diff --git a/ishtar_common/wizards.py b/ishtar_common/wizards.py index 3cdcbc63d..65a37a860 100644 --- a/ishtar_common/wizards.py +++ b/ishtar_common/wizards.py @@ -38,7 +38,7 @@ from django.db.models.fields import NOT_PROVIDED from django.http import HttpResponseRedirect, Http404 from django.forms import ValidationError -from django.shortcuts import redirect, render +from django.shortcuts import redirect, render, reverse from django.template import loader from django.utils.translation import ugettext_lazy as _ from django.utils.safestring import mark_safe @@ -112,6 +112,7 @@ class Wizard(IshtarWizard): storage_name = 'formtools.wizard.storage.session.SessionStorage' wizard_done_template = 'ishtar/wizard/wizard_done.html' wizard_done_window = '' + redirect_url = None wizard_confirm = 'ishtar/wizard/confirm_wizard.html' wizard_templates = {} filter_owns = {} @@ -1508,7 +1509,7 @@ class DocumentSearch(SearchWizard): class DeletionWizard(Wizard): def __init__(self, *args, **kwargs): if (not hasattr(self, 'fields') or not self.fields) and \ - (hasattr(self, 'model') and hasattr(self.model, 'TABLE_COLS')): + (hasattr(self, 'model') and hasattr(self.model, 'TABLE_COLS')): self.fields = self.model.TABLE_COLS assert self.model return super(DeletionWizard, self).__init__(*args, **kwargs) @@ -1563,6 +1564,107 @@ class DeletionWizard(Wizard): self.request, 'ishtar/wizard/wizard_delete_done.html', {}) +class MultipleItemWizard(Wizard): + main_item_select_keys = ('selec-',) + current_object_key = "pks" + + def get_current_objects(self): + current_objs = [] + for key in self.main_item_select_keys: + main_form_key = key + self.url_name + try: + pks = self.session_get_value(main_form_key, + self.current_object_key) + if pks: + for pk in pks.split(","): + current_objs.append(self.model.objects.get(pk=int(pk))) + except(TypeError, ValueError, ObjectDoesNotExist): + pass + return current_objs + + +class MultipleDeletionWizard(MultipleItemWizard): + def __init__(self, *args, **kwargs): + if (not hasattr(self, 'fields') or not self.fields) and \ + (hasattr(self, 'model') and hasattr(self.model, 'TABLE_COLS')): + self.fields = self.model.TABLE_COLS + assert self.model + return super(MultipleDeletionWizard, self).__init__(*args, **kwargs) + + def get_formated_datas(self, forms): + datas = super(MultipleDeletionWizard, self).get_formated_datas(forms) + self.current_objs = [] + for form in forms: + if not hasattr(form, "cleaned_data"): + continue + for key in form.cleaned_data: + if key == 'pks': + model = form.associated_models['pks'] + pks = form.cleaned_data["pks"].split(",") + for pk in pks: + try: + self.current_objs.append(model.objects.get(pk=pk)) + except model.DoesNotExist: + continue + if not self.current_objs: + return datas + full_res = [] + for current_obj in self.current_objs: + res = {} + for field in self.model._meta.get_fields(): + if field.name not in self.fields: + continue + value = getattr(current_obj, field.name) + if not value: + continue + label = "" + if hasattr(field, 'verbose_name'): + label = field.verbose_name + if hasattr(value, 'all'): + if not label and hasattr(field, 'related_model'): + label = field.related_model._meta.verbose_name_plural + value = ", ".join([str(item) for item in value.all()]) + if not value: + continue + else: + value = str(value) + res[field.name] = (label, value, '') + full_res.append(res) + if not datas and self.fields: + datas = [['', []]] + datas = [] + for idx, res in enumerate(full_res): + data = [] + for field in self.fields: + if field in res: + data.append(res[field]) + datas.append((str(self.current_objs[idx]), data)) + return datas + + def get_context_data(self, form, **kwargs): + data = super(MultipleDeletionWizard, self).get_context_data(form, + **kwargs) + data["current_objs"] = self.get_current_objects() + return data + + def done(self, form_list, **kwargs): + objs = self.get_current_objects() + lbls = [] + for obj in objs: + lbls.append(str(obj)) + try: + obj.delete() + except ObjectDoesNotExist: + pass + msg = '<i class="fa fa-trash" aria-hidden="true"></i> ' + msg += str(_("{} deleted.")).format(" ; ".join(lbls)) + messages.add_message(self.request, messages.INFO, msg) + if self.redirect_url: + return HttpResponseRedirect(reverse(self.redirect_url)) + return render( + self.request, 'ishtar/wizard/wizard_delete_done.html', {}) + + class ClosingWizard(Wizard): # "close" an item # to be define in the overloaded class @@ -1628,9 +1730,10 @@ class PersonModifWizard(PersonWizard): 'identity-person_modification': "ishtar/wizard/wizard_person.html"} -class PersonDeletionWizard(DeletionWizard): +class PersonDeletionWizard(MultipleDeletionWizard): model = models.Person fields = model.TABLE_COLS + redirect_url = "person_search" wizard_templates = { 'final-person_deletion': 'ishtar/wizard/wizard_person_deletion.html'} |