diff options
Diffstat (limited to 'ishtar_common')
| -rw-r--r-- | ishtar_common/forms.py | 75 | ||||
| -rw-r--r-- | ishtar_common/migrations/0274_qualifiedbiographicalnote.py | 6 | ||||
| -rw-r--r-- | ishtar_common/models.py | 9 | ||||
| -rw-r--r-- | ishtar_common/views.py | 76 | ||||
| -rw-r--r-- | ishtar_common/views_item.py | 1 |
5 files changed, 164 insertions, 3 deletions
diff --git a/ishtar_common/forms.py b/ishtar_common/forms.py index 9558186bb..4db6a138b 100644 --- a/ishtar_common/forms.py +++ b/ishtar_common/forms.py @@ -21,6 +21,7 @@ Forms definition """ from collections import OrderedDict +from copy import copy import datetime from markdown import markdown import re @@ -534,6 +535,8 @@ class LockForm(object): if pk_key not in cleaned_data or not cleaned_data[pk_key]: raise forms.ValidationError(_("You should select an item.")) model = self.associated_models[pk_key] + if isinstance(model, tuple): + model = apps.get_model(*model) pks = self.cleaned_data[pk_key] pks = [pks] if isinstance(pks, int) else pks.split(",") for pk in pks: @@ -564,7 +567,10 @@ class MultiSearchForm(CustomFormSearch): @classmethod def get_current_model(cls): - return cls.associated_models[cls.pk_key] + model = cls.associated_models[cls.pk_key] + if isinstance(model, tuple): + model = apps.get_model(*model) + return model @classmethod def get_formated_datas(cls, cleaned_datas): @@ -691,6 +697,8 @@ class FieldType: def __init__(self, key, model, is_multiple=False, extra_args=None, empty_first=True, help_text=True): self.key = key + if isinstance(model, tuple): + model = apps.get_model(*model) self.model = model self.is_multiple = is_multiple self.extra_args = extra_args @@ -1560,3 +1568,68 @@ class GeoItemSelect(DocumentItemSelect): # all geo item can have documents FieldType("geodata__origin", models.GeoOriginType), FieldType("geodata__provider", models.GeoProviderType), ] + DocumentItemSelect.TYPES + + +class QADating(ManageOldType, forms.Form): + form_label = _("Dating") + associated_models = { + "dating_type_id": ("archaeological_context_records", "DatingType"), + "quality_id": ("archaeological_context_records", "DatingQuality"), + "period_id": ("archaeological_operations", "Period"), + } + pk = forms.IntegerField(required=False, widget=forms.HiddenInput) + reference = forms.CharField( + label=_("Reference"), validators=[validators.MaxLengthValidator(400)], + required=False + ) + period_id = widgets.Select2SimpleField( + label=_("Period"), required=False, modal="modal-dynamic-form" + ) + start_date = forms.IntegerField(label=_("Start date"), required=False) + end_date = forms.IntegerField(label=_("End date"), required=False) + quality_id = forms.ChoiceField(label=_("Quality"), required=False, choices=[]) + dating_type_id = forms.ChoiceField(label=_("Dating type"), required=False, choices=[]) + precise_dating = forms.CharField(label=_("Precise on this dating"), required=False, + widget=forms.Textarea) + + TYPES = [ + FieldType("dating_type_id", ("archaeological_context_records", "DatingType")), + FieldType("quality_id", ("archaeological_context_records", "DatingQuality")), + FieldType("period_id", ("archaeological_operations", "Period")), + ] + + def __init__(self, *args, **kwargs): + self.dating_model = kwargs.pop("dating_model") + self.current_item = kwargs.pop("current_item") + return super().__init__(*args, **kwargs) + + def clean(self): + data = self.cleaned_data + reference = data['reference'] + if reference: + q_attr = { + "reference": reference, + self.dating_model.CURRENT_MODEL_ATTR + "_id": self.current_item.pk + } + q = self.dating_model.objects.filter(**q_attr) + if data.get("pk", None): + q = q.exclude(pk=data["pk"]) + if q.count(): + raise forms.ValidationError( + _("This reference already exists for this item.") + ) + if any(1 for k in self.cleaned_data if self.cleaned_data[k]): + return data + raise forms.ValidationError(_("No data provided.")) + + def save(self): + data = copy(self.cleaned_data) + data[self.dating_model.CURRENT_MODEL_ATTR + "_id"] = self.current_item.pk + for attr in ['period_id', 'quality_id', 'dating_type_id']: + if not data.get(attr, None): + data[attr] = None + if data.get("pk", None): + pk = data.pop("pk") + self.dating_model.objects.filter(pk=pk).update(**data) + return + self.dating_model.objects.create(**data) diff --git a/ishtar_common/migrations/0274_qualifiedbiographicalnote.py b/ishtar_common/migrations/0274_qualifiedbiographicalnote.py index e27fbfdeb..7f23586c9 100644 --- a/ishtar_common/migrations/0274_qualifiedbiographicalnote.py +++ b/ishtar_common/migrations/0274_qualifiedbiographicalnote.py @@ -80,4 +80,10 @@ class Migration(migrations.Migration): name='export_format', field=models.CharField(blank=True, choices=[('docx', 'DOCX'), ('html', 'HTML'), ('pdf', 'PDF'), ('xlsx', 'XLSX')], default='', max_length=4, verbose_name='Export format'), ), + migrations.AddField( + model_name='qualifiedbiographicalnotetype', + name='model', + field=models.CharField(choices=[('S', 'Archaeological site'), ('O', 'Operation'), ('C', 'Context record'), ('F', 'Find')], default='A', max_length=1, verbose_name='Model'), + preserve_default=False, + ), ] diff --git a/ishtar_common/models.py b/ishtar_common/models.py index a6aab9416..e52d210a6 100644 --- a/ishtar_common/models.py +++ b/ishtar_common/models.py @@ -4683,9 +4683,18 @@ def author_post_save(sender, **kwargs): post_save.connect(author_post_save, sender=Author) +MODELS_FOR_QUALIFICATION = ( + ("S", _("Archaeological site")), + ("O", _("Operation")), + ("C", _("Context record")), + ("F", _("Find")), + ("A", _("All")), +) + class QualifiedBiographicalNoteType(OrderedHierarchicalType): order = models.IntegerField(_("Order"), default=10) + model = models.CharField(_("Model"), max_length=2, choices=MODELS_FOR_QUALIFICATION) class Meta: verbose_name = _("Qualification type") diff --git a/ishtar_common/views.py b/ishtar_common/views.py index 9ffd4a4eb..4f37a0938 100644 --- a/ishtar_common/views.py +++ b/ishtar_common/views.py @@ -74,8 +74,7 @@ from archaeological_operations.models import Operation, ArchaeologicalSite from archaeological_warehouse.models import Warehouse from ishtar_common import forms_common as forms from ishtar_common import wizards -from ishtar_common.data_importer import ImporterError -from ishtar_common.forms import FinalForm, FinalDeleteForm, reverse_lazy +from ishtar_common.forms import FinalForm, FinalDeleteForm, reverse_lazy, QADating from ishtar_common.models import get_current_profile from ishtar_common.models_common import QuickAction from ishtar_common.templatetags.link_to_window import simple_link_to_window @@ -3909,3 +3908,76 @@ class GeoDeleteView(IshtarMixin, LoginRequiredMixin, DeleteView): if self.request.POST.get("back_url", None): return self.request.POST.get("back_url", None) return reverse("start") + + +def get_dating_form(model, dating_model, url_name): + def _dating_form(request, pk, dating_pk=None, current_right=None): + try: + item = model.objects.get(pk=pk) + except model.DoesNotExist: + raise Http404() + # permission not provided + if not current_right: + raise PermissionDenied() + # specificaly check permission for own item, otherwise already checked + if "_own_" in current_right: + if not request.user.has_perm(current_right, item): + raise PermissionDenied() + initial = {} + if dating_pk: + try: + dating_item = dating_model.objects.get(pk=dating_pk) + initial = dict( + (attr, getattr(dating_item, attr)) + for attr in [ + "pk", "reference", "period_id", "start_date", "end_date", + "quality_id", "dating_type_id", "precise_dating"] + ) + except dating_model.DoesNotExist: + raise Http404() + if request.method == 'POST': + form = QADating(request.POST, dating_model=dating_model, + current_item=item) + if form.is_valid(): + form.save() + return HttpResponseRedirect(reverse("success")) + else: + form = QADating(dating_model=dating_model, + current_item=item, initial=initial) + button_name = _("Add") if not dating_pk else _("Modify") + icon = "fa fa-plus" if not dating_pk else "fa fa-pencil" + url_args = [pk] + if dating_pk: + url_args.append(dating_pk) + return render( + request, + "ishtar/forms/qa_form.html", { + "page_name": _("Dating"), + "icon": icon, + "action_name": button_name, + "form": form, + "url": reverse(url_name, args=url_args) + }) + return _dating_form + + +def get_dating_delete(model, dating_model, url_name): + def _dating_form(request, dating_pk, current_right=None): + try: + dating_item = dating_model.objects.get(pk=dating_pk) + except dating_model.DoesNotExist: + raise Http404() + pk = getattr(dating_item, dating_model.CURRENT_MODEL_ATTR + "_id") + try: + item = model.objects.get(pk=pk) + except model.DoesNotExist: + raise Http404() + if "_own_" in current_right: + if not request.user.has_perm(current_right, item): + raise PermissionDenied() + elif current_right: + if not request.user.has_perm(current_right): + raise PermissionDenied() + dating_item.delete() + return HttpResponseRedirect(reverse("success")) + return _dating_form diff --git a/ishtar_common/views_item.py b/ishtar_common/views_item.py index 18e3f5576..878d5361e 100644 --- a/ishtar_common/views_item.py +++ b/ishtar_common/views_item.py @@ -376,6 +376,7 @@ def modify_qa_item(model, frm, callback=None): return func + def get_default_permissions(dct): cache_key = f"{settings.PROJECT_SLUG}-default-perms" default_permissions = cache.get(cache_key) |
