summaryrefslogtreecommitdiff
path: root/archaeological_operations
diff options
context:
space:
mode:
Diffstat (limited to 'archaeological_operations')
-rw-r--r--archaeological_operations/admin.py2
-rw-r--r--archaeological_operations/forms.py96
-rw-r--r--archaeological_operations/migrations/0128_add_editors.py39
-rw-r--r--archaeological_operations/migrations/0129_data_migration.json233
-rw-r--r--archaeological_operations/migrations/0129_data_migration_heritageinterest_heritageenvprotection_relsite.py24
-rw-r--r--archaeological_operations/models.py50
-rw-r--r--archaeological_operations/templates/ishtar/sheet_operation.html25
-rw-r--r--archaeological_operations/templates/ishtar/sheet_site.html14
-rw-r--r--archaeological_operations/tests.py46
-rw-r--r--archaeological_operations/urls.py8
-rw-r--r--archaeological_operations/views.py6
11 files changed, 469 insertions, 74 deletions
diff --git a/archaeological_operations/admin.py b/archaeological_operations/admin.py
index 913ed74ea..82c5c7f90 100644
--- a/archaeological_operations/admin.py
+++ b/archaeological_operations/admin.py
@@ -141,6 +141,7 @@ class RecordRelationsAdmin(admin.ModelAdmin):
admin_site.register(models.RecordRelations, RecordRelationsAdmin)
+admin_site.register(models.SiteRecordRelations, RecordRelationsAdmin)
class RelationTypeAdmin(GeneralTypeAdmin):
@@ -150,6 +151,7 @@ class RelationTypeAdmin(GeneralTypeAdmin):
admin_site.register(models.RelationType, RelationTypeAdmin)
+admin_site.register(models.SiteRelationType, RelationTypeAdmin)
class RecordQualityTypeAdmin(GeneralTypeAdmin):
diff --git a/archaeological_operations/forms.py b/archaeological_operations/forms.py
index 82f41c089..3e94e3963 100644
--- a/archaeological_operations/forms.py
+++ b/archaeological_operations/forms.py
@@ -41,7 +41,7 @@ from ishtar_common import widgets
from ishtar_common.forms import FinalForm, FormSet, \
reverse_lazy, get_data_from_formset, QAForm, CustomFormSearch,\
ManageOldType, IshtarForm, CustomForm, FieldType, FormHeader, \
- GeoItemSelect, LockForm, MultiSearchForm, DocumentItemSelect
+ GeoItemSelect, LockForm, MultiSearchForm, DocumentItemSelect, DatingSelect
from ishtar_common.forms_common import TownFormSet, get_town_field, TownForm
from ishtar_common.models import valid_id, valid_ids, Person, Town, \
DocumentTemplate, Organization, get_current_profile, \
@@ -432,6 +432,32 @@ RecordRelationsFormSet.form_admin_name = _("Operation - Relations")
RecordRelationsFormSet.form_slug = "operation-relations"
+class SiteRecordRelationsForm(RecordRelationsForm):
+ current_model = models.SiteRelationType
+ current_related_model = models.ArchaeologicalSite
+ associated_models = {
+ "right_record": models.ArchaeologicalSite,
+ "relation_type": models.SiteRelationType,
+ }
+ ERROR_MISSING = _("You should select an archaeological site and a relation type.")
+ ERROR_SAME = _("An archaeological site cannot be related to himself.")
+
+ right_record = forms.IntegerField(
+ label=_("Archaeological site"),
+ widget=widgets.JQueryAutoComplete(
+ reverse_lazy('autocomplete-archaeologicalsite'),
+ associated_model=models.ArchaeologicalSite),
+ validators=[valid_id(models.ArchaeologicalSite)], required=False)
+
+
+SiteRecordRelationsFormSet = formset_factory(
+ SiteRecordRelationsForm, can_delete=True, formset=RecordRelationsFormSetBase
+)
+SiteRecordRelationsFormSet.form_label = _("Archaeological site - Relations")
+RecordRelationsFormSet.form_admin_name = _("Archaeological site - Relations")
+RecordRelationsFormSet.form_slug = "archaeologicalsite-recordrelations"
+
+
class OpeSiteRelationsForm(ManageOldType):
associated_models = {'right_record': models.ArchaeologicalSite}
@@ -446,6 +472,7 @@ class OpeSiteRelationsForm(ManageOldType):
super().__init__(*args, **kwargs)
self.fields["right_record"].label = get_current_profile().get_site_label()
+
OpeSiteRelationsFormSet = formset_factory(
OpeSiteRelationsForm, can_delete=True, formset=RecordRelationsFormSetBase,
extra=3
@@ -628,6 +655,7 @@ class OperationFormMultiSelection(LockForm, MultiSearchForm):
class OperationCodeInput(forms.TextInput):
"""Manage auto complete when changing year in form"""
+
def render(self, *args, **kwargs):
name, value = args
base_name = '-'.join(name.split('-')[:-1])
@@ -1173,7 +1201,7 @@ class OperationDeletionForm(FinalForm):
#########
-class SiteSelect(GeoItemSelect):
+class SiteSelect(GeoItemSelect, DatingSelect):
_model = models.ArchaeologicalSite
form_admin_name = _("Archaeological site - 001 - Search")
form_slug = "archaeological_site-001-search"
@@ -1186,23 +1214,48 @@ class SiteSelect(GeoItemSelect):
name = forms.CharField(label=_("Name"), max_length=200, required=False)
other_reference = forms.CharField(label=_("Other reference"),
max_length=200, required=False)
- types = widgets.Select2MultipleField(label=_("Types"), required=False)
+ types = widgets.Select2SimpleField(label=_("Types"), required=False,
+ modal="modal-advanced-search")
+ heritage_interest = forms.ChoiceField(label=_("Heritage interests"), choices=[],
+ required=False)
+ actors = forms.IntegerField(
+ label=_("Actors"), required=False,
+ widget=widgets.JQueryAutoComplete(
+ reverse_lazy('autocomplete-qualifiedbiographicalnote')))
+ collaborators = forms.IntegerField(
+ label=_("Collaborators"), required=False,
+ widget=widgets.JQueryAutoComplete(
+ reverse_lazy('autocomplete-person')))
+ protection_id = forms.CharField(label=_("Protection ID"), required=False)
+ protection_date = DateField(label=_("Protection date"), required=False)
+ heritage_environmental_protections = forms.ChoiceField(
+ label=_("Heritage and environmental protections"), choices=[],
+ required=False)
+ details_on_protection = forms.CharField(label=_("Details on protection"),
+ required=False)
discoverer = forms.IntegerField(
- widget=widgets.JQueryAutoComplete(reverse_lazy('autocomplete-person'), associated_model=Person),
+ widget=widgets.JQueryAutoComplete(reverse_lazy('autocomplete-person'),
+ associated_model=Person),
label=_("Discoverer"))
- periods = forms.ChoiceField(label=_("Periods"), choices=[], required=False)
- remains = forms.ChoiceField(label=_("Remains"), choices=[], required=False)
- cultural_attributions = forms.ChoiceField(
- label=_("Cultural attribution"), choices=[], required=False)
- discovery_status = forms.ChoiceField(label=_("Discovery status"), choices=[], required=False)
- current_status = forms.ChoiceField(label=_("Current status"), choices=[], required=False)
- nature_of_site = forms.ChoiceField(label=_("Nature of site"), choices=[], required=False)
- interpretation_level = forms.ChoiceField(label=_("Interpretation level"), choices=[], required=False)
+ periods = widgets.Select2SimpleField(label=_("Periods"), required=False,
+ modal="modal-advanced-search")
+ remains = widgets.Select2SimpleField(label=_("Remains"), required=False,
+ modal="modal-advanced-search")
+ cultural_attributions = widgets.Select2SimpleField(
+ label=_("Cultural attributions"), required=False, modal="modal-advanced-search")
+ discovery_status = forms.ChoiceField(label=_("Discovery status"), choices=[],
+ required=False)
+ current_states = forms.ChoiceField(label=_("Current states"), required=False)
+ nature_of_site = forms.ChoiceField(label=_("Nature of site"), choices=[],
+ required=False)
+ interpretation_level = forms.ChoiceField(label=_("Interpretation level"),
+ choices=[], required=False)
+
towns = get_town_field()
towns__areas = forms.ChoiceField(label=_("Areas"), choices=[])
- description = forms.CharField(label=_("Description"), max_length=200, required=False)
- public_description = forms.CharField(label=_("Public description"), max_length=200, required=False)
- comment = forms.CharField(label=_("Comment"), max_length=200, required=False)
+ description = forms.CharField(label=_("Description"), required=False)
+ public_description = forms.CharField(label=_("Public description"), required=False)
+ comment = forms.CharField(label=_("Comment"), required=False)
top_operation = forms.IntegerField(
label=_("Top operation"), required=False,
widget=widgets.JQueryAutoComplete(
@@ -1241,17 +1294,21 @@ class SiteSelect(GeoItemSelect):
discovery_area = forms.CharField(
label=_("Discovery area"), max_length=200,
required=False)
+
TYPES = [
FieldType('periods', models.Period),
FieldType('remains', models.RemainType),
- FieldType("types", models.SiteType, is_multiple=True),
- FieldType('current_status', models.SiteCurrentStatusType),
+ FieldType("types", models.SiteType),
+ FieldType('current_states', models.SiteCurrentStatusType),
FieldType('discovery_status', models.SiteDiscoveryStatusType),
FieldType('cultural_attributions', models.CulturalAttributionType),
FieldType('nature_of_site', models.NatureOfSiteType),
FieldType('interpretation_level', models.InterpretationLevelType),
FieldType('towns__areas', Area),
- ] + GeoItemSelect.TYPES
+ FieldType('heritage_interest', models.HeritageInterestType),
+ FieldType('heritage_environmental_protections',
+ models.HeritageAndEnvironmentalProtectionType),
+ ] + GeoItemSelect.TYPES + DatingSelect.TYPES
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
@@ -1265,6 +1322,7 @@ class SiteSelect(GeoItemSelect):
'affmar_number',
'drassm_number',
))
+ self._reorder_period_fields("comment")
class SiteFormSelection(LockForm, CustomFormSearch):
@@ -1343,7 +1401,7 @@ class SiteForm(CustomForm, ManageOldType):
required=False)
actor = widgets.Select2MultipleField(
model=QualifiedBiographicalNote, label=_("Actors"), required=False,
- remote=True, new=True)
+ remote=True, new=True, remote_filter='qualification_type__S-A')
collaborator = widgets.Select2MultipleField(
model=Person, label=_("Collaborators"), required=False,
remote=True, new=True)
diff --git a/archaeological_operations/migrations/0128_add_editors.py b/archaeological_operations/migrations/0128_add_editors.py
new file mode 100644
index 000000000..d26c47f74
--- /dev/null
+++ b/archaeological_operations/migrations/0128_add_editors.py
@@ -0,0 +1,39 @@
+# Generated by Django 4.2.21 on 2026-04-02 06:36
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('ishtar_common', '0276_add_editors'),
+ ('archaeological_operations', '0127_data_migration_current_states'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='administrativeact',
+ name='editors',
+ field=models.ManyToManyField(blank=True, related_name='%(class)s_edited', to='ishtar_common.author', verbose_name='Editors'),
+ ),
+ migrations.AddField(
+ model_name='operation',
+ name='editors',
+ field=models.ManyToManyField(blank=True, related_name='%(class)s_edited', to='ishtar_common.author', verbose_name='Editors'),
+ ),
+ migrations.AddField(
+ model_name='parcel',
+ name='editors',
+ field=models.ManyToManyField(blank=True, related_name='%(class)s_edited', to='ishtar_common.author', verbose_name='Editors'),
+ ),
+ migrations.AddField(
+ model_name='parcelowner',
+ name='editors',
+ field=models.ManyToManyField(blank=True, related_name='%(class)s_edited', to='ishtar_common.author', verbose_name='Editors'),
+ ),
+ migrations.AlterField(
+ model_name='archaeologicalsite',
+ name='editors',
+ field=models.ManyToManyField(blank=True, related_name='%(class)s_edited', to='ishtar_common.author', verbose_name='Editors'),
+ ),
+ ]
diff --git a/archaeological_operations/migrations/0129_data_migration.json b/archaeological_operations/migrations/0129_data_migration.json
new file mode 100644
index 000000000..edf090689
--- /dev/null
+++ b/archaeological_operations/migrations/0129_data_migration.json
@@ -0,0 +1,233 @@
+[
+{
+ "model": "archaeological_operations.heritageandenvironmentalprotectiontype",
+ "fields": {
+ "label": "Site classé",
+ "txt_idx": "site-classe",
+ "comment": "",
+ "available": true,
+ "parent": [
+ "protection-patrimoniale"
+ ],
+ "order": 10
+ }
+},
+{
+ "model": "archaeological_operations.heritageandenvironmentalprotectiontype",
+ "fields": {
+ "label": "Site inscrit",
+ "txt_idx": "site-inscrit",
+ "comment": "",
+ "available": true,
+ "parent": [
+ "protection-patrimoniale"
+ ],
+ "order": 10
+ }
+},
+{
+ "model": "archaeological_operations.heritageandenvironmentalprotectiontype",
+ "fields": {
+ "label": "Natura 2000",
+ "txt_idx": "natura-2000",
+ "comment": "",
+ "available": true,
+ "parent": [
+ "protection-environnementale"
+ ],
+ "order": 10
+ }
+},
+{
+ "model": "archaeological_operations.heritageandenvironmentalprotectiontype",
+ "fields": {
+ "label": "Protection patrimoniale",
+ "txt_idx": "protection-patrimoniale",
+ "comment": "",
+ "available": true,
+ "parent": null,
+ "order": 10
+ }
+},
+{
+ "model": "archaeological_operations.heritageandenvironmentalprotectiontype",
+ "fields": {
+ "label": "Protection environnementale",
+ "txt_idx": "protection-environnementale",
+ "comment": "",
+ "available": true,
+ "parent": null,
+ "order": 10
+ }
+},
+{
+ "model": "archaeological_operations.heritageinteresttype",
+ "fields": {
+ "label": "Intérêt patrimonial 1",
+ "txt_idx": "interet-patrimonial-1",
+ "comment": "",
+ "available": true,
+ "parent": null,
+ "order": 10
+ }
+},
+{
+ "model": "archaeological_operations.heritageinteresttype",
+ "fields": {
+ "label": "Intérêt patrimonial 2",
+ "txt_idx": "interet-patrimonial-2",
+ "comment": "",
+ "available": true,
+ "parent": null,
+ "order": 10
+ }
+},
+ {
+ "model": "archaeological_operations.siterelationtype",
+ "fields": {
+ "label": "Voisin de",
+ "txt_idx": "voisin-de",
+ "comment": "",
+ "available": true,
+ "order": 30,
+ "symmetrical": true,
+ "tiny_label": null,
+ "inverse_relation": null,
+ "logical_relation": null
+ }
+ },
+ {
+ "model": "archaeological_operations.siterelationtype",
+ "fields": {
+ "label": "Relation indirecte",
+ "txt_idx": "relation-indirecte",
+ "comment": "",
+ "available": true,
+ "order": 40,
+ "symmetrical": true,
+ "tiny_label": null,
+ "inverse_relation": null,
+ "logical_relation": null
+ }
+ },
+ {
+ "model": "archaeological_operations.siterelationtype",
+ "fields": {
+ "label": "Parent de",
+ "txt_idx": "parent-de",
+ "comment": "",
+ "available": true,
+ "order": 10,
+ "symmetrical": false,
+ "tiny_label": null,
+ "inverse_relation": null,
+ "logical_relation": null
+ }
+ },
+ {
+ "model": "archaeological_operations.siterelationtype",
+ "fields": {
+ "label": "Enfant de",
+ "txt_idx": "enfant-de",
+ "comment": "",
+ "available": true,
+ "order": 20,
+ "symmetrical": false,
+ "tiny_label": null,
+ "inverse_relation": null,
+ "logical_relation": null
+ }
+ },
+ {
+ "model": "archaeological_operations.siterelationtype",
+ "fields": {
+ "label": "Ant\u00e9rieure \u00e0",
+ "txt_idx": "anterieure-a",
+ "comment": "",
+ "available": true,
+ "order": 50,
+ "symmetrical": false,
+ "tiny_label": null,
+ "inverse_relation": null,
+ "logical_relation": null
+ }
+ },
+ {
+ "model": "archaeological_operations.siterelationtype",
+ "fields": {
+ "label": "Post\u00e9rieure \u00e0",
+ "txt_idx": "posterieure-a",
+ "comment": "",
+ "available": true,
+ "order": 60,
+ "symmetrical": false,
+ "tiny_label": null,
+ "inverse_relation": null,
+ "logical_relation": null
+ }
+ },
+ {
+ "model": "archaeological_operations.siterelationtype",
+ "fields": {
+ "label": "Parent de",
+ "txt_idx": "parent-de",
+ "comment": "",
+ "available": true,
+ "order": 10,
+ "symmetrical": false,
+ "tiny_label": null,
+ "inverse_relation": [
+ "enfant-de"
+ ],
+ "logical_relation": null
+ }
+ },
+ {
+ "model": "archaeological_operations.siterelationtype",
+ "fields": {
+ "label": "Enfant de",
+ "txt_idx": "enfant-de",
+ "comment": "",
+ "available": true,
+ "order": 20,
+ "symmetrical": false,
+ "tiny_label": null,
+ "inverse_relation": [
+ "parent-de"
+ ],
+ "logical_relation": null
+ }
+ },
+ {
+ "model": "archaeological_operations.siterelationtype",
+ "fields": {
+ "label": "Ant\u00e9rieure \u00e0",
+ "txt_idx": "anterieure-a",
+ "comment": "",
+ "available": true,
+ "order": 50,
+ "symmetrical": false,
+ "tiny_label": null,
+ "inverse_relation": [
+ "posterieure-a"
+ ],
+ "logical_relation": null
+ }
+ },
+ {
+ "model": "archaeological_operations.siterelationtype",
+ "fields": {
+ "label": "Post\u00e9rieure \u00e0",
+ "txt_idx": "posterieure-a",
+ "comment": "",
+ "available": true,
+ "order": 60,
+ "symmetrical": false,
+ "tiny_label": null,
+ "inverse_relation": [
+ "anterieure-a"
+ ],
+ "logical_relation": null
+ }
+ }
+]
diff --git a/archaeological_operations/migrations/0129_data_migration_heritageinterest_heritageenvprotection_relsite.py b/archaeological_operations/migrations/0129_data_migration_heritageinterest_heritageenvprotection_relsite.py
new file mode 100644
index 000000000..59a884794
--- /dev/null
+++ b/archaeological_operations/migrations/0129_data_migration_heritageinterest_heritageenvprotection_relsite.py
@@ -0,0 +1,24 @@
+# Generated by Django 2.2.24 on 2024-02-10 12:07
+
+import os
+
+from django.db import migrations
+from django.core.management import call_command
+
+
+def load_data(apps, __):
+ QualifiedBiographicalNoteType = apps.get_model("archaeological_operations", "HeritageInterestType")
+ if not QualifiedBiographicalNoteType.objects.count():
+ json_path = os.sep.join(os.path.abspath(__file__).split(os.sep)[:-1] + ["0129_data_migration.json"])
+ call_command("loaddata", json_path)
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('archaeological_operations', '0128_add_editors'),
+ ]
+
+ operations = [
+ migrations.RunPython(load_data)
+ ]
diff --git a/archaeological_operations/models.py b/archaeological_operations/models.py
index 7bf654639..a3fe2ea3f 100644
--- a/archaeological_operations/models.py
+++ b/archaeological_operations/models.py
@@ -475,8 +475,8 @@ class ArchaeologicalSite(
"heritage_environmental_protections"
]
- DATED_FIELDS = BaseHistorizedItem.DATED_FIELDS + ["sinking_date"]
- NUMBER_FIELDS = GeographicTownItem.NUMBER_FIELDS[:]
+ DATED_FIELDS = BaseHistorizedItem.DATED_FIELDS + ["sinking_date", "protection_date"]
+ NUMBER_FIELDS = GeographicTownItem.NUMBER_FIELDS[:] + BaseDating.NUMBER_FIELDS
EXTRA_REQUEST_KEYS = {
"towns_label": "towns",
@@ -516,9 +516,37 @@ class ArchaeologicalSite(
pgettext_lazy("key for text search", "discovery-status"),
"discovery_status__label__iexact"
),
- "current_status": SearchAltName(
+ "current_states": SearchAltName(
pgettext_lazy("key for text search", "current-status"),
- "current_status__label__iexact"
+ "current_states__label__iexact"
+ ),
+ "actors": SearchAltName(
+ pgettext_lazy("key for text search", "actors"),
+ "actors__cached_label__iexact"
+ ),
+ "collaborators": SearchAltName(
+ pgettext_lazy("key for text search", "collaborators"),
+ "collaborators__cached_label__iexact"
+ ),
+ "protection_id": SearchAltName(
+ pgettext_lazy("key for text search", "protection-id"),
+ "protection_id__iexact"
+ ),
+ "protection_date": SearchAltName(
+ pgettext_lazy("key for text search", "protection-date"),
+ "protection_date"
+ ),
+ "details_on_protection": SearchAltName(
+ pgettext_lazy("key for text search", "protection-details"),
+ "details_on_protection__iexact"
+ ),
+ "heritage_interest": SearchAltName(
+ pgettext_lazy("key for text search", "heritage-interest"),
+ "heritage_interests__label__iexact"
+ ),
+ "heritage_environmental_protections": SearchAltName(
+ pgettext_lazy("key for text search", "heritage-environmental-protection"),
+ "heritage_environmental_protections__label__iexact"
),
"nature_of_site": SearchAltName(
pgettext_lazy("key for text search", "nature"),
@@ -606,6 +634,7 @@ class ArchaeologicalSite(
ALT_NAMES.update(DocumentItem.ALT_NAMES)
ALT_NAMES.update(GeoItem.ALT_NAMES)
ALT_NAMES.update(Imported.ALT_NAMES)
+ ALT_NAMES.update(BaseDating.ALT_NAMES)
DEFAULT_SEARCH_FORM = ("archaeological_operations.forms", "SiteSelect")
@@ -767,9 +796,6 @@ class ArchaeologicalSite(
QualifiedBiographicalNote, related_name="sites", verbose_name=_("Actors"),
blank=True
)
- editors = models.ManyToManyField(
- Author, related_name="sites", verbose_name=_("Editors"), blank=True
- )
documents = models.ManyToManyField(
Document, related_name="sites", verbose_name=_("Documents"), blank=True
)
@@ -930,6 +956,16 @@ class ArchaeologicalSite(
]
actions += [
(
+ reverse("site-relations-modify", args=[self.pk]),
+ _("Modify sites relations"),
+ "fa fa-retweet",
+ _("sites"),
+ "",
+ True,
+ ),
+ ]
+ actions += [
+ (
reverse("site-operation-relations-modify", args=[self.pk, window_id]),
_("Modify site-operation relations"),
"fa fa-retweet",
diff --git a/archaeological_operations/templates/ishtar/sheet_operation.html b/archaeological_operations/templates/ishtar/sheet_operation.html
index e290ce319..fced5457a 100644
--- a/archaeological_operations/templates/ishtar/sheet_operation.html
+++ b/archaeological_operations/templates/ishtar/sheet_operation.html
@@ -410,28 +410,9 @@
{% if display_relations %}
<div class="tab-pane fade" id="{{window_id}}-relations"
role="tabpanel" aria-labelledby="{{window_id}}-relations-tab">
-
- {% if item.right_relations.count and not item.right_relations_not_available %}
- <h3>{% trans "Relations"%}</h3>
- {% for rel in item.right_relations.all %}
- {% ifchanged rel.relation_type %}
- {% if forloop.counter0 %}</div>{% endif %}
- <h4>{{rel.relation_type}}</h4>
- <div class="row">{% endifchanged %}
- <div class="col-12">
- <a href="#" onclick="load_window('/show-operation/{{rel.right_record.pk|unlocalize}}/');" class="display_details">
- <i class="fa fa-info-circle" aria-hidden="true"></i>
- </a> {{rel.right_record}}
- </div>
- {% if forloop.last %}
- </div>{% endif %}
- {% endfor %}
- {% else %}
- <div class="alert alert-info" role="alert">
- <i class="fa fa-info-circle" aria-hidden="true"></i> &nbsp;
- {% trans "No relations" %}
- </div>
- {% endif %}
+ {% with relation_url="/show-operation/" %}
+ {% include "ishtar/blocks/sheet_relations.html" %}
+ {% endwith %}
</div>
{% endif %}
diff --git a/archaeological_operations/templates/ishtar/sheet_site.html b/archaeological_operations/templates/ishtar/sheet_site.html
index 1de4c367f..2ce9e7eaa 100644
--- a/archaeological_operations/templates/ishtar/sheet_site.html
+++ b/archaeological_operations/templates/ishtar/sheet_site.html
@@ -1,5 +1,5 @@
{% extends "ishtar/sheet.html" %}
-{% load i18n ishtar_helpers window_tables window_header window_ope_tables window_field from_dict %}
+{% load i18n l10n ishtar_helpers window_tables window_header window_ope_tables window_field from_dict %}
{% block head_title %}<strong>{{SITE_LABEL}}</strong> - {{item.cached_label}}{% endblock %}
@@ -11,6 +11,7 @@
{# trick to set to null non existing variable #}
{% with permission_view_own_archaeologicalsite=permission_view_own_archaeologicalsite %}
+{% with display_relations=item|safe_or:"right_relations.count|left_relations.count"|safe_and_not:"right_relations_not_available"|safe_and_not:"left_relations_not_available" %}
{% with can_change=permission_change_own_archaeologicalsite|or_:permission_change_archaeologicalsite %}
{% with dating_list=item|m2m_listing:"datings" %}
{% with permission_change_own_geovectordata=permission_change_own_geovectordata %}
@@ -150,19 +151,26 @@
{% endif %}
{% endif %}
+{% if display_relations %}
+ {% with relation_url="/show-site/" %}
+ {% include "ishtar/blocks/sheet_relations.html" %}
+ {% endwith %}
+{% endif %}
+
{% if not is_external and SHOW_GEO %}
<h3>{% trans "Geographic data" %}</h3>
{% with geo_item=item %}{% include "ishtar/blocks/sheet_geographic.html" %}{% endwith %}
{% endif %}
{% if not is_external %}
-{% if item.history_creator or item.last_edition_date or item.created %}
+{% if item.history_creator or item.last_edition_date or item.created or item.editors.count %}
<h3>{% trans "Sheet"%}</h3>
<div class="row">
+ {% field_flex_multiple _("Editors") item.editors %}
{% include "ishtar/blocks/sheet_creation_section.html" %}
</div>
{% endif %}
{% endif %}
-{% endwith %}{% endwith %}{% endwith %}{% endwith %}{% endwith %}{% endwith %}
+{% endwith %}{% endwith %}{% endwith %}{% endwith %}{% endwith %}{% endwith %}{% endwith %}
{% endblock %}
diff --git a/archaeological_operations/tests.py b/archaeological_operations/tests.py
index b239b789d..136f710f1 100644
--- a/archaeological_operations/tests.py
+++ b/archaeological_operations/tests.py
@@ -127,7 +127,7 @@ class FileInit:
def create_file(self):
self.extra_models, self.model_list = {}, []
self.user, created = User.objects.get_or_create(
- username="username", is_superuser=True
+ username="username", is_superuser=True, is_staff=True
)
self.user.set_password("tralala")
self.user.save()
@@ -298,7 +298,7 @@ class ImportTest(BaseImportTest):
impt = form.save(self.ishtar_user)
impt.initialize()
self.init_ope_targetkey(imp=impt)
- impt.importation()
+ impt.start_import()
def init_parcel_import(self):
self.init_ope()
@@ -327,7 +327,7 @@ class ImportTest(BaseImportTest):
importer, form = self.init_parcel_import()
impt = form.save(self.ishtar_user)
impt.initialize()
- impt.importation()
+ impt.start_import()
def init_context_record_import(self):
self.init_parcel()
@@ -364,7 +364,7 @@ class ImportTest(BaseImportTest):
impt = form.save(self.ishtar_user)
impt.initialize()
self.init_cr_targetkey(impt)
- impt.importation()
+ impt.start_import()
class ImportOperationTest(ImportTest, TestCase):
@@ -385,14 +385,14 @@ class ImportOperationTest(ImportTest, TestCase):
self.assertTrue(TargetKey.objects.count() > target_key_nb)
# first try to import
- impt.importation()
+ impt.start_import()
current_ope_nb = models.Operation.objects.count()
# no new operation imported because of a missing connection for
# operation_type value
self.assertEqual(current_ope_nb, first_ope_nb)
self.init_ope_targetkey(imp=impt)
- impt.importation()
+ impt.start_import()
# new operations have now been imported
current_ope_nb = models.Operation.objects.count()
self.assertEqual(current_ope_nb, first_ope_nb + 2)
@@ -413,7 +413,7 @@ class ImportOperationTest(ImportTest, TestCase):
# a second importation will be not possible: no two same patriarche
# code
- impt.importation()
+ impt.start_import()
self.assertEqual(last_ope, models.Operation.objects.order_by("-pk").all()[0])
def test_import_bad_encoding(self):
@@ -428,7 +428,7 @@ class ImportOperationTest(ImportTest, TestCase):
impt = form.save(self.ishtar_user)
impt.initialize()
self.init_ope_targetkey(imp=impt)
- impt.importation()
+ impt.start_import()
# new operations have now been imported
current_ope_nb = models.Operation.objects.count()
self.assertEqual(current_ope_nb, first_ope_nb + 2)
@@ -457,7 +457,7 @@ class ImportOperationTest(ImportTest, TestCase):
impt = form.save(self.ishtar_user)
impt.initialize()
self.init_ope_targetkey(imp=impt)
- impt.importation()
+ impt.start_import()
current_ope_nb = models.Operation.objects.count()
self.assertEqual(current_ope_nb, first_ope_nb + 2)
@@ -481,7 +481,7 @@ class ImportOperationTest(ImportTest, TestCase):
impt = form.save(self.ishtar_user)
impt.initialize()
self.init_ope_targetkey(imp=impt)
- impt.importation()
+ impt.start_import()
self.assertEqual(
models.Operation.objects.filter(
code_patriarche="4201",
@@ -523,7 +523,7 @@ class ImportOperationTest(ImportTest, TestCase):
impt = form.save(self.ishtar_user)
impt.initialize()
self.init_ope_targetkey(imp=impt)
- impt.importation()
+ impt.start_import()
self.assertEqual(
models.Operation.objects.filter(
code_patriarche="4201",
@@ -542,7 +542,7 @@ class ImportOperationTest(ImportTest, TestCase):
impt = form.save(self.ishtar_user)
impt.initialize()
self.init_ope_targetkey(imp=impt)
- impt.importation()
+ impt.start_import()
self.assertEqual(
models.Operation.objects.filter(code_patriarche="oa-4201").count(), 1
)
@@ -559,7 +559,7 @@ class ImportOperationTest(ImportTest, TestCase):
impt = form.save(self.ishtar_user)
impt.initialize()
self.init_ope_targetkey(imp=impt)
- impt.importation()
+ impt.start_import()
self.assertEqual(
models.Operation.objects.filter(code_patriarche="oa-42014201").count(), 1
)
@@ -595,7 +595,7 @@ class ImportOperationTest(ImportTest, TestCase):
tg.associated_import = other_imp
tg.save()
- impt.importation()
+ impt.start_import()
current_ope_nb = models.Operation.objects.count()
# no new operation
self.assertEqual(current_ope_nb, init_ope_number)
@@ -615,7 +615,7 @@ class ImportOperationTest(ImportTest, TestCase):
impt = form.save(self.ishtar_user)
impt.initialize()
self.init_ope_targetkey(imp=impt)
- impt.importation()
+ impt.start_import()
self.assertEqual(len(impt.errors), 2)
self.assertTrue("cody" in impt.errors[0]["error"])
self.assertTrue(
@@ -632,7 +632,7 @@ class ImportOperationTest(ImportTest, TestCase):
# no model defined in created_models: normal import
init_ope_number = models.Operation.objects.count()
- impt.importation()
+ impt.start_import()
current_ope_nb = models.Operation.objects.count()
self.assertEqual(current_ope_nb, init_ope_number + 2)
@@ -650,7 +650,7 @@ class ImportOperationTest(ImportTest, TestCase):
self.init_ope_targetkey(imp=impt)
# no imports
- impt.importation()
+ impt.start_import()
current_ope_nb = models.Operation.objects.count()
self.assertEqual(current_ope_nb, init_ope_number)
@@ -667,7 +667,7 @@ class ImportOperationTest(ImportTest, TestCase):
self.init_ope_targetkey(imp=impt)
# import of operations
- impt.importation()
+ impt.start_import()
current_ope_nb = models.Operation.objects.count()
self.assertEqual(current_ope_nb, init_ope_number + 2)
@@ -703,7 +703,7 @@ class ImportOperationTest(ImportTest, TestCase):
mcc_parcel, form = self.init_parcel_import()
impt = form.save(self.ishtar_user)
impt.initialize()
- impt.importation()
+ impt.start_import()
# new parcels has now been imported
current_nb = models.Parcel.objects.count()
self.assertEqual(current_nb, old_nb + 3)
@@ -752,7 +752,7 @@ class ImportOperationTest(ImportTest, TestCase):
impt = form.save(self.ishtar_user)
impt.initialize()
self.init_ope_targetkey(imp=impt)
- impt.importation()
+ impt.start_import()
ope1 = models.Operation.objects.get(code_patriarche="4200")
self.assertEqual(ope1.data, {"autre_refs": {"arbitraire": 789}})
ope2 = models.Operation.objects.get(code_patriarche="4201")
@@ -767,7 +767,7 @@ class ImportOperationTest(ImportTest, TestCase):
impt = form.save(self.ishtar_user)
impt.initialize()
self.init_ope_targetkey(imp=impt)
- impt.importation()
+ impt.start_import()
ope1 = models.Operation.objects.get(code_patriarche="4200")
self.assertEqual(ope1.data, {"autre_refs": {"arbitraire": 789}, "autre": 666})
ope2 = models.Operation.objects.get(code_patriarche="4201")
@@ -790,7 +790,7 @@ class ImportOperationTest(ImportTest, TestCase):
impt = form.save(self.ishtar_user)
impt.initialize()
self.init_ope_targetkey(imp=impt)
- impt.importation()
+ impt.start_import()
ope1 = models.Operation.objects.get(code_patriarche="4200")
self.assertEqual(ope1.data, {"code_insee": "45123"})
ope2 = models.Operation.objects.get(code_patriarche="4201")
@@ -858,7 +858,7 @@ class ImportDocumentTest(ImportTest, TestCase):
importer, form = self.init_doc_import()
self.assertTrue(form.is_valid())
impt = form.save(self.ishtar_user)
- impt.importation()
+ impt.start_import()
self.assertEqual(doc_nb + 2, Document.objects.count())
self.assertEqual(current_index + 2, Document.get_next_index() - 1)
diff --git a/archaeological_operations/urls.py b/archaeological_operations/urls.py
index 2af502f9f..31930fbd9 100644
--- a/archaeological_operations/urls.py
+++ b/archaeological_operations/urls.py
@@ -352,6 +352,14 @@ urlpatterns = [
name="operation-site-relations-modify",
),
path(
+ "site-relations-modify/<int:pk>)/",
+ check_permissions(
+ ["archaeological_operations.change_archaeologicalsite",
+ "archaeological_operations.change_own_archaeologicalsite"]
+ )(views.site_modify_relations),
+ name="site-relations-modify",
+ ),
+ path(
"site-operation-relations-modify/<int:pk>/",
check_permissions(
["archaeological_operations.change_operation",
diff --git a/archaeological_operations/views.py b/archaeological_operations/views.py
index 3449290e0..f2117c747 100644
--- a/archaeological_operations/views.py
+++ b/archaeological_operations/views.py
@@ -593,6 +593,12 @@ operation_modify_relations = get_relation_modify(
)
+site_modify_relations = get_relation_modify(
+ models.ArchaeologicalSite, models.SiteRecordRelations,
+ forms.SiteRecordRelationsFormSet, "site-relations-modify"
+)
+
+
RELATION_LIMIT = 50