summaryrefslogtreecommitdiff
path: root/archaeological_context_records
diff options
context:
space:
mode:
authorÉtienne Loks <etienne.loks@iggdrasil.net>2024-09-16 12:45:00 +0200
committerÉtienne Loks <etienne.loks@iggdrasil.net>2024-09-16 12:46:09 +0200
commit12e9870e2aa0659de98a9122fbc4ab16b0877449 (patch)
tree36d375089b787fbc3649ad54bb9e7e3b2b5741e0 /archaeological_context_records
parentdb5ecbb7b69ff668ca005bd9535bf595b79e649e (diff)
downloadIshtar-12e9870e2aa0659de98a9122fbc4ab16b0877449.tar.bz2
Ishtar-12e9870e2aa0659de98a9122fbc4ab16b0877449.zip
✨ Context records relations: remove form from the wizard to put in a specific form
Diffstat (limited to 'archaeological_context_records')
-rw-r--r--archaeological_context_records/forms.py80
-rw-r--r--archaeological_context_records/models.py18
-rw-r--r--archaeological_context_records/urls.py5
-rw-r--r--archaeological_context_records/views.py122
-rw-r--r--archaeological_context_records/wizards.py12
5 files changed, 186 insertions, 51 deletions
diff --git a/archaeological_context_records/forms.py b/archaeological_context_records/forms.py
index 55f27ddcd..8d41a7888 100644
--- a/archaeological_context_records/forms.py
+++ b/archaeological_context_records/forms.py
@@ -21,6 +21,7 @@
Context records forms definitions
"""
from collections import OrderedDict
+from copy import copy
from itertools import groupby
from bootstrap_datepicker.widgets import DateField
@@ -464,37 +465,6 @@ DatingFormSet.form_admin_name = _("Context record - 030 - Dating")
DatingFormSet.form_slug = "contextrecord-030-datings"
-class RecordRelationsForm(OpeRecordRelationsForm):
- current_model = models.RelationType
- current_related_model = models.ContextRecord
- associated_models = {
- "right_record": models.ContextRecord,
- "relation_type": models.RelationType,
- }
- right_record = forms.ChoiceField(
- label=_("Context record"), choices=[], required=False
- )
-
- def __init__(self, *args, **kwargs):
- crs = None
- if "data" in kwargs and "CONTEXT_RECORDS" in kwargs["data"]:
- crs = kwargs["data"]["CONTEXT_RECORDS"]
- super(RecordRelationsForm, self).__init__(*args, **kwargs)
- self.fields["relation_type"].choices = models.RelationType.get_types(
- initial=self.init_data.get("relation_type")
- )
- if crs:
- self.fields["right_record"].choices = [("", "-" * 2)] + crs
-
-
-RecordRelationsFormSet = formset_factory(
- RecordRelationsForm, can_delete=True, formset=RecordRelationsFormSetBase
-)
-RecordRelationsFormSet.form_label = _("Relations")
-RecordRelationsFormSet.form_admin_name = _("Context record - 050 - Relations")
-RecordRelationsFormSet.form_slug = "contextrecord-050-recordrelations"
-
-
class RecordFormInterpretation(CustomForm, ManageOldType):
HEADERS = {}
form_label = _("Interpretation")
@@ -554,6 +524,54 @@ class RecordDeletionForm(FinalForm):
confirm_end_msg = _("Would you like to delete this context record?")
+class RecordRelationsForm(OpeRecordRelationsForm):
+ current_model = models.RelationType
+ current_related_model = models.ContextRecord
+ associated_models = {
+ "right_record": models.ContextRecord,
+ "relation_type": models.RelationType,
+ }
+ ERROR_MISSING = _("You should select a context record and a relation type.")
+
+ right_record = forms.ChoiceField(
+ label=_("Context record"), choices=[], required=False
+ )
+
+ def __init__(self, *args, **kwargs):
+ crs = None
+ if "data" in kwargs and "CONTEXT_RECORDS" in kwargs["data"]:
+ kwargs["data"] = copy(kwargs["data"])
+ crs = kwargs["data"].pop("CONTEXT_RECORDS")
+ # clean data if not "real" data
+ prefix_value = kwargs['prefix'] + '-relation_type'
+ if not [k for k in kwargs['data'].keys()
+ if k.startswith(prefix_value) and kwargs['data'][k]]:
+ kwargs.pop('data')
+ if 'files' in kwargs:
+ kwargs.pop('files')
+ initial = kwargs.get("initial", {})
+ if initial and initial.get("right_record", None):
+ if initial["right_record"] not in [cr_id for cr_id, cr_lbl in crs]:
+ try:
+ crs.append(
+ (initial["right_record"],
+ str(models.ContextRecord.objects.get(pk=initial["right_record"])))
+ )
+ except models.ContextRecord.DoesNotExist:
+ pass
+ super().__init__(*args, **kwargs)
+ if crs:
+ self.fields["right_record"].choices = [("", "-" * 2)] + crs
+
+
+RecordRelationsFormSet = formset_factory(
+ RecordRelationsForm, can_delete=True, formset=RecordRelationsFormSetBase
+)
+RecordRelationsFormSet.form_label = _("Relations")
+RecordRelationsFormSet.form_admin_name = _("Context record - 050 - Relations")
+RecordRelationsFormSet.form_slug = "contextrecord-050-recordrelations"
+
+
class QAOperationCR(IshtarForm):
town = forms.ChoiceField(label=_("Town"), choices=[])
archaeological_site = forms.ChoiceField(
diff --git a/archaeological_context_records/models.py b/archaeological_context_records/models.py
index ee43183eb..3867997de 100644
--- a/archaeological_context_records/models.py
+++ b/archaeological_context_records/models.py
@@ -1056,9 +1056,10 @@ class ContextRecord(
def get_extra_actions(self, request):
# url, base_text, icon, extra_text, extra css class, is a quick action
- actions = super(ContextRecord, self).get_extra_actions(request)
+ actions = super().get_extra_actions(request)
+ is_locked = hasattr(self, "is_locked") and self.is_locked(request.user)
- # is_locked = hasattr(self, "is_locked") and self.is_locked(request.user)
+ can_edit_cr = self.can_do(request, "change_contextrecord")
profile = get_current_profile()
can_add_geo = profile.mapping and self.can_do(request, "add_geovectordata")
if can_add_geo:
@@ -1075,7 +1076,18 @@ class ContextRecord(
False,
),
]
- can_edit_cr = self.can_do(request, "change_contextrecord")
+ if can_edit_cr and not is_locked:
+ actions += [
+ (
+ reverse("context-record-relation-modify", args=[self.pk]),
+ _("Modify relations"),
+ "fa fa-retweet",
+ _("relations"),
+ "",
+ True,
+ ),
+ ]
+
if can_edit_cr:
actions += [
(
diff --git a/archaeological_context_records/urls.py b/archaeological_context_records/urls.py
index 446b3fbf9..5fd360fbb 100644
--- a/archaeological_context_records/urls.py
+++ b/archaeological_context_records/urls.py
@@ -150,6 +150,11 @@ urlpatterns = [
name="get-contextrecordrelationdetail",
),
url(
+ r"^context-record-relations-modify/(?P<pk>.+)/$",
+ views.context_record_modify_relations,
+ name="context-record-relation-modify",
+ ),
+ url(
r"^operation-qa-contextrecord/(?P<pks>[0-9]+)/$",
check_rights(["add_contextrecord", "add_own_contextrecord"])(
views.QAOperationContextRecordView.as_view()
diff --git a/archaeological_context_records/views.py b/archaeological_context_records/views.py
index 9d1d285e5..3695617f9 100644
--- a/archaeological_context_records/views.py
+++ b/archaeological_context_records/views.py
@@ -21,7 +21,7 @@ import json
from django.db.models import Q
from django.http import HttpResponse, HttpResponseRedirect, Http404
-from django.shortcuts import redirect
+from django.shortcuts import render, redirect
from django.urls import reverse
from ishtar_common.utils import ugettext_lazy as _
from django.views.generic import RedirectView
@@ -32,7 +32,6 @@ from archaeological_context_records import models
from archaeological_operations.views import site_extra_context
from archaeological_context_records import forms
-from ishtar_common.utils import put_session_message
from ishtar_common.views import (
IshtarMixin,
@@ -42,7 +41,7 @@ from ishtar_common.views import (
wizard_is_available,
QAItemEditForm,
)
-from ishtar_common.views_item import display_item, get_item, show_item, revert_item
+from ishtar_common.views_item import get_item, show_item, revert_item
from archaeological_context_records import wizards
show_contextrecord = show_item(
@@ -122,7 +121,6 @@ record_creation_steps = [
("general-record_creation", forms.RecordFormGeneral),
("datings-record_creation", forms.DatingFormSet),
("interpretation-record_creation", forms.RecordFormInterpretation),
- ("relations-record_creation", forms.RecordRelationsFormSet),
("final-record_creation", forms.FinalForm),
]
@@ -138,7 +136,6 @@ record_modification_steps = [
("general-record_modification", forms.RecordFormGeneral),
("datings-record_modification", forms.DatingFormSet),
("interpretation-record_modification", forms.RecordFormInterpretation),
- ("relations-record_modification", forms.RecordRelationsFormSet),
("final-record_modification", forms.FinalForm),
]
@@ -196,6 +193,121 @@ def reset_wizards(request):
wizard_class.session_reset(request, url_name)
+RELATION_FORMSET_EXTRA_FORM = 3
+
+
+def get_relation_modify(model, model_relation, url_name):
+ def _modify_relation(request, pk):
+ formset_class = forms.RecordRelationsFormSet
+ item = model.objects.get(pk=pk)
+ relations = model_relation.objects.filter(left_record_id=pk).all()
+
+ items = [
+ (item.id, str(item))
+ for item in model.objects.filter(operation=item.operation).all()
+ ]
+ current_items = [item[0] for item in items]
+
+ initial = []
+ for relation in relations:
+ initial.append({
+ "pk": relation.pk,
+ "right_record": relation.right_record_id,
+ "relation_type": relation.relation_type_id,
+ })
+ if relation.right_record_id not in current_items:
+ items.append((relation.right_record_id, str(relation.right_record)))
+
+ data = {
+ 'form-TOTAL_FORMS': len(initial) + RELATION_FORMSET_EXTRA_FORM,
+ 'form-INITIAL_FORMS': 0,
+ 'form-MIN_NUM_FORMS': 0,
+ 'form-MAX_NUM_FORMS': 100,
+ "CONTEXT_RECORDS": items
+ }
+
+ if request.method == 'POST':
+ new_data = dict(request.POST)
+ new_data = {k: new_data[k][0] for k in new_data} # convert POST to classic dict
+
+ # remove empty lines and get deleted
+ no_values = list(range(data["form-TOTAL_FORMS"]))
+ deleted = {}
+ for k, value in new_data.items():
+ if not value or not k.startswith("form-"):
+ continue
+ try:
+ form_number = int(k.split("-")[1])
+ except (ValueError, IndexError) as __:
+ continue
+ if k.endswith("-DELETE") and new_data.get(f"form-{form_number}-pk", None):
+ deleted[form_number] = new_data[f"form-{form_number}-pk"]
+ if form_number not in no_values: # put it back in no values
+ no_values.append(form_number)
+ elif form_number in no_values and form_number not in deleted:
+ no_values.pop(no_values.index(form_number))
+ for no_value in no_values:
+ for k in list(new_data.keys()):
+ if k.startswith(f"form-{no_value}-"):
+ new_data.pop(k)
+ data["form-TOTAL_FORMS"] = data["form-TOTAL_FORMS"] - len(no_values)
+
+ new_data.update(data)
+ formset = formset_class(data=new_data)
+
+ if formset.is_valid():
+ is_valid = True
+ # delete
+ for deleted_id in deleted.values():
+ try:
+ model_relation.objects.get(pk=deleted_id).delete()
+ except model_relation.DoesNotExist:
+ continue
+
+ for idx_form, data in enumerate(formset.cleaned_data):
+ if not data.get('right_record') or not data.get('relation_type'):
+ continue
+
+ if data.get("pk"):
+ try:
+ current_relation = model_relation.objects.get(pk=data.get("pk"))
+ except model_relation.DoesNotExist:
+ continue
+ not_deleted_or_associated = True
+ for key, value in data.items():
+ if key == "DELETE" and value is True:
+ current_relation.delete()
+ not_deleted_or_associated = False
+
+ if not_deleted_or_associated:
+ current_relation.right_record_id = data.get("right_record")
+ current_relation.relation_type_id = data.get("relation_type")
+ current_relation.save()
+ else:
+ model_relation.objects.create(
+ **{
+ "left_record_id": item.pk,
+ "right_record_id": data.get("right_record"),
+ "relation_type_id": data.get("relation_type"),
+ }
+ )
+ if is_valid:
+ return redirect(reverse(url_name, args=[pk]))
+ else:
+ formset = formset_class(initial=initial, data=data)
+
+ return render(request, 'ishtar/forms/modify_relations.html', {
+ 'formset': formset,
+ "url": reverse(url_name, args=[pk])
+ })
+ return _modify_relation
+
+
+context_record_modify_relations = get_relation_modify(
+ models.ContextRecord, models.RecordRelations, "context-record-relation-modify"
+)
+
+
class GenerateRelationImage(IshtarMixin, LoginRequiredMixin, RedirectView):
upper_model = models.Operation
model = models.ContextRecord
diff --git a/archaeological_context_records/wizards.py b/archaeological_context_records/wizards.py
index e92d9587e..35b4e02b4 100644
--- a/archaeological_context_records/wizards.py
+++ b/archaeological_context_records/wizards.py
@@ -119,21 +119,9 @@ class RecordWizard(Wizard):
else:
current_object = self.get_current_object()
data["context_record"] = current_object
- elif step.startswith("relations") and hasattr(form, "management_form"):
- data["CONTEXT_RECORDS"] = self.get_other_context_records()
form = super(RecordWizard, self).get_form(step, data, files)
return form
- def get_other_context_records(self):
- operation = self.get_current_operation()
- if not operation:
- return []
- q = models.ContextRecord.objects.filter(operation_id=operation.pk)
- obj = self.get_current_object()
- if obj and obj.pk:
- q = q.exclude(pk=obj.pk)
- return [(cr.pk, cr.cached_label) for cr in q.all()]
-
class RecordModifWizard(RecordWizard):
modification = True