summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorÉtienne Loks <etienne.loks@iggdrasil.net>2024-09-17 11:10:30 +0200
committerÉtienne Loks <etienne.loks@iggdrasil.net>2024-09-17 11:29:18 +0200
commit9430e8577cff4995c310f5675ea5d2a619554ccf (patch)
treee809cc61d746115afa703042591e8f7cc696bfdb
parent0e22d62ec2cacfe501bdb7a4f3afde9081366d55 (diff)
downloadIshtar-9430e8577cff4995c310f5675ea5d2a619554ccf.tar.bz2
Ishtar-9430e8577cff4995c310f5675ea5d2a619554ccf.zip
✨ Operations: remove form from the wizard to put in a specific form
-rw-r--r--archaeological_context_records/forms.py18
-rw-r--r--archaeological_context_records/views.py123
-rw-r--r--archaeological_operations/forms.py68
-rw-r--r--archaeological_operations/models.py12
-rw-r--r--archaeological_operations/urls.py7
-rw-r--r--archaeological_operations/views.py128
-rw-r--r--ishtar_common/templates/ishtar/forms/modify_relations.html2
7 files changed, 173 insertions, 185 deletions
diff --git a/archaeological_context_records/forms.py b/archaeological_context_records/forms.py
index f4176b619..e5d34117c 100644
--- a/archaeological_context_records/forms.py
+++ b/archaeological_context_records/forms.py
@@ -578,6 +578,7 @@ class RecordRelationsForm(OpeRecordRelationsForm):
"relation_type": models.RelationType,
}
ERROR_MISSING = _("You should select a context record and a relation type.")
+ ERROR_SAME = _("A context record cannot be related to himself.")
right_record = forms.ChoiceField(
label=_("Context record"), choices=[], required=False
@@ -585,16 +586,9 @@ class RecordRelationsForm(OpeRecordRelationsForm):
def __init__(self, *args, **kwargs):
crs = None
- if "data" in kwargs and "CONTEXT_RECORDS" in kwargs["data"]:
+ if "data" in kwargs and "CURRENT_ITEMS" 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')
+ crs = kwargs["data"].pop("CURRENT_ITEMS")
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]:
@@ -613,9 +607,9 @@ class RecordRelationsForm(OpeRecordRelationsForm):
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"
+RecordRelationsFormSet.form_label = _("Context records - Relations")
+RecordRelationsFormSet.form_admin_name = _("Context record - Relations")
+RecordRelationsFormSet.form_slug = "contextrecord-recordrelations"
class QAOperationCR(IshtarForm):
diff --git a/archaeological_context_records/views.py b/archaeological_context_records/views.py
index eba1ae8c0..98236dcd6 100644
--- a/archaeological_context_records/views.py
+++ b/archaeological_context_records/views.py
@@ -19,7 +19,6 @@
import json
-from django.core.exceptions import PermissionDenied
from django.db.models import Q
from django.http import HttpResponse, HttpResponseRedirect, Http404
from django.shortcuts import render, redirect
@@ -31,7 +30,7 @@ from ishtar_common.models import QuickAction
from archaeological_operations.models import Operation
from archaeological_context_records import models
-from archaeological_operations.views import site_extra_context
+from archaeological_operations.views import site_extra_context, get_relation_modify
from archaeological_context_records import forms
from ishtar_common.views import (
@@ -194,124 +193,10 @@ 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, current_right=None):
- try:
- item = model.objects.get(pk=pk)
- except model.DoesNotExist:
- raise Http404()
- if "_own_" in current_right:
- if not item.is_own(request.user):
- raise PermissionDenied()
- formset_class = forms.RecordRelationsFormSet
- 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"
+ models.ContextRecord, models.RecordRelations,
+ "context-record-relation-modify", forms.RecordRelationsFormSet,
+ filter_operations=True
)
diff --git a/archaeological_operations/forms.py b/archaeological_operations/forms.py
index d3c797ff2..9cc73e63b 100644
--- a/archaeological_operations/forms.py
+++ b/archaeological_operations/forms.py
@@ -20,6 +20,7 @@
"""
Operations forms definitions
"""
+from copy import copy
import datetime
from collections import OrderedDict
from itertools import groupby
@@ -371,12 +372,13 @@ class ParcelFormSet(FormSet):
class RecordRelationsForm(ManageOldType):
base_model = 'right_relation'
- ERROR_MISSING = _("You should select an operation.")
current_model = models.RelationType
current_related_model = models.Operation
-
associated_models = {'right_record': models.Operation,
'relation_type': models.RelationType}
+ ERROR_MISSING = _("You should select an operation.")
+ ERROR_SAME = _("An operation cannot be related to herself.")
+
pk = forms.IntegerField(required=False, widget=forms.HiddenInput)
relation_type = forms.ChoiceField(label=_("Relation type"),
choices=[], required=False)
@@ -391,23 +393,20 @@ class RecordRelationsForm(ManageOldType):
self.left_record = None
if 'left_record' in kwargs:
self.left_record = kwargs.pop('left_record')
+ if "data" in kwargs:
+ kwargs["data"] = copy(kwargs["data"])
+ # 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')
super().__init__(*args, **kwargs)
self.fields['relation_type'].choices = \
self.current_model.get_types(
initial=self.init_data.get('relation_type'))
- @classmethod
- def _format_lst(cls, current):
- nc = []
- for rel, ope in sorted(current):
- if not nc or nc[-1][0] != rel:
- nc.append([rel, []])
- nc[-1][1].append(ope)
- rendered = ";".join(
- ["{}{} {}".format(rel, _(":"), " ; ".join(opes))
- for rel, opes in nc])
- return rendered
-
def clean(self):
cleaned_data = self.cleaned_data
if (cleaned_data.get('relation_type', None) and
@@ -420,42 +419,9 @@ class RecordRelationsForm(ManageOldType):
if self.left_record and \
str(cleaned_data.get('right_record', None)) == str(
self.left_record.pk):
- raise forms.ValidationError(
- _("An operation cannot be related to herself."))
+ raise forms.ValidationError(self.ERROR_SAME)
return cleaned_data
- @classmethod
- def get_formated_datas(cls, cleaned_datas):
- result, current, deleted = [], [], []
- for data in cleaned_datas:
- if not data:
- continue
- try:
- relation_type = cls.current_model.objects.get(
- pk=data.get('relation_type'))
- except cls.current_model.DoesNotExist:
- continue
- try:
- right_record = cls.current_related_model.objects.get(
- pk=data.get('right_record'))
- except cls.current_related_model.DoesNotExist:
- continue
- values = [str(relation_type), right_record.reference]
- if data.get('DELETE'):
- deleted.append(values)
- else:
- current.append(values)
- if current:
- nc = []
- for rel, ope in sorted(current):
- if not nc or nc[-1][0] != rel:
- nc.append([rel, []])
- nc[-1][1].append(ope)
- result.append((_("Current relations"), cls._format_lst(current)))
- if deleted:
- result.append((_("Deleted relations"), " ; ".join(deleted)))
- return result
-
class RecordRelationsFormSetBase(FormSet):
delete_widget = forms.CheckboxInput
@@ -478,9 +444,9 @@ class RecordRelationsFormSetBase(FormSet):
RecordRelationsFormSet = formset_factory(
RecordRelationsForm, can_delete=True, formset=RecordRelationsFormSetBase)
-RecordRelationsFormSet.form_label = _("Relations")
-RecordRelationsFormSet.form_admin_name = _("Operation - 080 - Relations")
-RecordRelationsFormSet.form_slug = "operation-080-relations"
+RecordRelationsFormSet.form_label = _("Operations - Relations")
+RecordRelationsFormSet.form_admin_name = _("Operation - Relations")
+RecordRelationsFormSet.form_slug = "operation-relations"
class OperationSelect(GeoItemSelect):
diff --git a/archaeological_operations/models.py b/archaeological_operations/models.py
index 4220e6cc2..d17e529a7 100644
--- a/archaeological_operations/models.py
+++ b/archaeological_operations/models.py
@@ -2017,6 +2017,18 @@ class Operation(
False,
),
]
+ if can_edit_operation and not is_locked:
+ actions += [
+ (
+ reverse("operation-relation-modify", args=[self.pk]),
+ _("Modify relations"),
+ "fa fa-retweet",
+ _("relations"),
+ "",
+ True,
+ ),
+ ]
+
if can_edit_operation:
actions += [
(
diff --git a/archaeological_operations/urls.py b/archaeological_operations/urls.py
index 05c03bc51..b87d6c5fd 100644
--- a/archaeological_operations/urls.py
+++ b/archaeological_operations/urls.py
@@ -305,6 +305,13 @@ urlpatterns = [
name="operation-parcels-modify",
),
url(
+ r"^operation-relations-modify/(?P<pk>.+)/$",
+ check_rights(["change_operation", "change_own_operation"])(
+ views.operation_modify_relations
+ ),
+ name="operation-relation-modify",
+ ),
+ url(
r"^operation-qa-bulk-update/(?P<pks>[0-9-]+)?/$",
check_rights(["change_operation", "change_own_operation"])(
views.QAOperationForm.as_view()
diff --git a/archaeological_operations/views.py b/archaeological_operations/views.py
index 028f311e6..93fb1864b 100644
--- a/archaeological_operations/views.py
+++ b/archaeological_operations/views.py
@@ -21,6 +21,7 @@ import json
from jinja2 import TemplateSyntaxError
from django.conf import settings
+from django.core.exceptions import PermissionDenied
from django.db.models import Q
from django.forms.utils import ErrorDict, ErrorList
from django.http import HttpResponse, HttpResponseRedirect, Http404
@@ -204,7 +205,6 @@ wizard_steps = [
("judiciary-operation_creation", forms.CourtOrderedSeizureForm),
("preventive-operation_creation", forms.OperationFormPreventive),
("preventivediag-operation_creation", forms.OperationFormPreventiveDiag),
- ("relations-operation_creation", forms.RecordRelationsFormSet),
("final-operation_creation", FinalForm),
]
@@ -269,7 +269,6 @@ operation_modif_wizard_steps = [
("judiciary-operation_modification", forms.CourtOrderedSeizureForm),
("preventive-operation_modification", forms.OperationFormPreventive),
("preventivediag-operation_modification", forms.OperationFormPreventiveDiag),
- ("relations-operation_modification", forms.RecordRelationsFormSet),
("final-operation_modification", FinalForm),
]
@@ -500,6 +499,131 @@ operation_modify_parcels = get_parcel_modify(
)
+RELATION_FORMSET_EXTRA_FORM = 3
+
+
+def get_relation_modify(model, model_relation, url_name, formset_class, filter_operations=False):
+ def _modify_relation(request, pk, current_right=None):
+ try:
+ item = model.objects.get(pk=pk)
+ except model.DoesNotExist:
+ raise Http404()
+ if "_own_" in current_right:
+ if not item.is_own(request.user):
+ raise PermissionDenied()
+ relations = model_relation.objects.filter(left_record_id=pk).all()
+
+ items, current_items = [], []
+ if filter_operations:
+ 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 filter_operations and 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,
+ }
+ if filter_operations:
+ data["CURRENT_ITEMS"] = 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 list(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"):
+ if 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)
+ else:
+ new_data.pop(k)
+ 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
+
+
+operation_modify_relations = get_relation_modify(
+ models.Operation, models.RecordRelations,
+ "operation-relation-modify", forms.RecordRelationsFormSet
+)
+
+
# archaeological sites
diff --git a/ishtar_common/templates/ishtar/forms/modify_relations.html b/ishtar_common/templates/ishtar/forms/modify_relations.html
index faec8b3fc..1dcf02b0c 100644
--- a/ishtar_common/templates/ishtar/forms/modify_relations.html
+++ b/ishtar_common/templates/ishtar/forms/modify_relations.html
@@ -3,7 +3,7 @@
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
- <h2>{{ formset.form_label }}</h2>
+ <h2><i class="fa fa-retweet"></i> &nbsp;{{ formset.form_label }}</h2>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>