From efaab4426a2fccc52d72464428655088286d209e Mon Sep 17 00:00:00 2001 From: Idrissa Djepa Creutz Date: Fri, 18 Aug 2023 19:28:57 +0200 Subject: [PATCH 01/19] Add CirculationEdge model --- docs/changelog.rst | 4 + docs/install/advanced-configuration.rst | 31 ++++++++ geotrek/common/mixins/views.py | 3 + geotrek/land/admin.py | 10 ++- geotrek/land/filters.py | 16 +++- geotrek/land/fixtures/basic.json | 28 +++++++ geotrek/land/forms.py | 8 +- geotrek/land/locale/fr/LC_MESSAGES/django.po | 18 +++++ .../0011_circulationedge_circulationtype.py | 44 +++++++++++ geotrek/land/models.py | 76 +++++++++++++++++++ geotrek/land/serializers.py | 21 ++++- geotrek/land/static/land/main.js | 1 + .../land/circulationedge_detail.html | 24 ++++++ .../templates/land/land_detail_fragment.html | 15 ++++ .../land/land_extrabody_fragment.html | 3 + .../land/land_preactions_fragment.html | 2 + .../land/templates/land/sql/post_10_views.sql | 9 ++- .../templates/land/sql/post_90_defaults.sql | 13 ++++ .../templates/land/sql/pre_10_cleanup.sql | 1 + geotrek/land/tests/factories.py | 14 ++++ geotrek/land/tests/test_filters.py | 6 +- geotrek/land/tests/test_models.py | 11 ++- geotrek/land/tests/test_views.py | 51 ++++++++++++- geotrek/land/urls.py | 1 + geotrek/land/views.py | 63 ++++++++++++++- 25 files changed, 460 insertions(+), 13 deletions(-) create mode 100644 geotrek/land/migrations/0011_circulationedge_circulationtype.py create mode 100644 geotrek/land/templates/land/circulationedge_detail.html diff --git a/docs/changelog.rst b/docs/changelog.rst index 94cdc72310..22a48e3e76 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -5,6 +5,10 @@ CHANGELOG 2.101.4+dev (XXXX-XX-XX) ------------------------ +**New features** + +- Add CirculationEdge model, which allows to create a traffic circulation plan on paths. Created on the model of LandEdge and PhysicalEdge (#3578) + **Improvements** - Add rules fixture on sensitive area (#3470) diff --git a/docs/install/advanced-configuration.rst b/docs/install/advanced-configuration.rst index 03c7be8a37..2f5124027d 100644 --- a/docs/install/advanced-configuration.rst +++ b/docs/install/advanced-configuration.rst @@ -1011,6 +1011,16 @@ A (nearly?) exhaustive list of attributes available for display and export as co "agreement", "uuid", ] + COLUMNS_LISTS["circulationedge_view"] = [ + "eid", + "min_elevation", + "max_elevation", + "date_update", + "length_2d", + "date_insert", + "authorized", + "uuid", + ] COLUMNS_LISTS["physicaledge_view"] = [ "eid", "date_insert", @@ -1414,6 +1424,24 @@ A (nearly?) exhaustive list of attributes available for display and export as co "slope", "uuid", ] + COLUMNS_LISTS["circulationedge_export"] = [ + "eid", + "circulation_type", + "authorized", + "date_insert", + "date_update", + "cities", + "districts", + "areas", + "length", + "length_2d", + "ascent", + "descent", + "min_elevation", + "max_elevation", + "slope", + "uuid", + ] COLUMNS_LISTS["physicaledge_export"] = [ "eid", "physical_type", @@ -2180,6 +2208,9 @@ An exhaustive list of form fields hideable in each module. "locked", "uid", "origin" + ], + HIDDEN_FORM_FIELDS["circulationedge"] = [ + "authorized", ] diff --git a/geotrek/common/mixins/views.py b/geotrek/common/mixins/views.py index c2bc7bb22c..e180d11973 100644 --- a/geotrek/common/mixins/views.py +++ b/geotrek/common/mixins/views.py @@ -34,6 +34,9 @@ class CustomColumnsMixin: 'PhysicalEdgeList': 'physicaledge_view', 'PhysicalEdgeJsonList': 'physicaledge_view', 'PhysicalEdgeFormatList': 'physicaledge_export', + 'CirculationEdgeList': 'circulationedge_view', + 'CirculationEdgeJsonList': 'circulationedge_view', + 'CirculationEdgeFormatList': 'circulationedge_export', 'CompetenceEdgeList': 'competenceedge_view', 'CompetenceEdgeJsonList': 'competenceedge_view', 'CompetenceEdgeFormatList': 'competenceedge_export', diff --git a/geotrek/land/admin.py b/geotrek/land/admin.py index d986e55102..c322039dd7 100644 --- a/geotrek/land/admin.py +++ b/geotrek/land/admin.py @@ -1,7 +1,7 @@ from django.contrib import admin from geotrek.common.mixins.actions import MergeActionMixin -from .models import PhysicalType, LandType +from .models import PhysicalType, LandType, CirculationType class PhysicalTypeAdmin(MergeActionMixin, admin.ModelAdmin): @@ -18,5 +18,13 @@ class LandTypeAdmin(MergeActionMixin, admin.ModelAdmin): merge_field = "name" +class CirculationTypeAdmin(MergeActionMixin, admin.ModelAdmin): + list_display = ('name', 'structure', ) + search_fields = ('name', 'structure') + list_filter = ('structure',) + merge_field = "name" + + admin.site.register(PhysicalType, PhysicalTypeAdmin) admin.site.register(LandType, LandTypeAdmin) +admin.site.register(CirculationType, CirculationTypeAdmin) diff --git a/geotrek/land/filters.py b/geotrek/land/filters.py index ad0a824f85..a91d3c6ace 100644 --- a/geotrek/land/filters.py +++ b/geotrek/land/filters.py @@ -13,7 +13,7 @@ from .models import ( CompetenceEdge, LandEdge, LandType, PhysicalEdge, PhysicalType, - SignageManagementEdge, WorkManagementEdge, + SignageManagementEdge, WorkManagementEdge, CirculationEdge, CirculationType ) @@ -23,6 +23,12 @@ class Meta(MapEntityFilterSet.Meta): fields = ['physical_type'] +class CirculationEdgeFilterSet(ValidTopologyFilterSet, MapEntityFilterSet): + class Meta(MapEntityFilterSet.Meta): + model = CirculationEdge + fields = ['circulation_type', 'authorized'] + + class LandEdgeFilterSet(ValidTopologyFilterSet, MapEntityFilterSet): class Meta(MapEntityFilterSet.Meta): model = LandEdge @@ -63,6 +69,13 @@ def values_to_edges(self, values): return PhysicalEdge.objects.filter(physical_type__in=values) +class TopologyFilterCirculationType(TopologyFilter): + model = CirculationType + + def values_to_edges(self, values): + return CirculationEdge.objects.filter(circulation_type__in=values) + + class TopologyFilterLandType(TopologyFilter): model = LandType @@ -95,6 +108,7 @@ def add_edge_filters(filter_set): filter_set.add_filters({ 'land_type': TopologyFilterLandType(label=_('Land edge'), required=False), 'physical_type': TopologyFilterPhysicalType(label=_('Physical edge'), required=False), + 'circulation_type': TopologyFilterCirculationType(label=_('Circulation edge'), required=False), 'competence': TopologyFilterCompetenceEdge(label=_('Competence edge'), required=False), 'signage': TopologyFilterSignageManagementEdge(label=_('Signage management edge'), required=False), 'work': TopologyFilterWorkManagementEdge(label=_('Work management edge'), required=False), diff --git a/geotrek/land/fixtures/basic.json b/geotrek/land/fixtures/basic.json index f1a0ce3f9a..93ba58ba59 100644 --- a/geotrek/land/fixtures/basic.json +++ b/geotrek/land/fixtures/basic.json @@ -135,5 +135,33 @@ "right_of_way": false, "name": "Servitude DFCI" } + }, + { + "pk": 1, + "model": "land.circulationtype", + "fields": { + "name": "Pédestre" + } + }, + { + "pk": 2, + "model": "land.circulationtype", + "fields": { + "name": "Cycliste" + } + }, + { + "pk": 3, + "model": "land.circulationtype", + "fields": { + "name": "Motorisée" + } + }, + { + "pk": 4, + "model": "land.circulationtype", + "fields": { + "name": "Équestre" + } } ] \ No newline at end of file diff --git a/geotrek/land/forms.py b/geotrek/land/forms.py index 1659d17e80..ee9ab0a3ea 100644 --- a/geotrek/land/forms.py +++ b/geotrek/land/forms.py @@ -1,7 +1,7 @@ from geotrek.core.widgets import LineTopologyWidget from geotrek.core.forms import TopologyForm from .models import (PhysicalEdge, LandEdge, CompetenceEdge, WorkManagementEdge, - SignageManagementEdge) + SignageManagementEdge, CirculationEdge) class EdgeForm(TopologyForm): @@ -24,6 +24,12 @@ class Meta(EdgeForm.Meta): fields = EdgeForm.Meta.fields + ['land_type', 'owner', 'agreement'] +class CirculationEdgeForm(EdgeForm): + class Meta(EdgeForm.Meta): + model = CirculationEdge + fields = EdgeForm.Meta.fields + ['circulation_type', 'authorized'] + + class OrganismForm(EdgeForm): class Meta(EdgeForm.Meta): fields = EdgeForm.Meta.fields + ['organization'] diff --git a/geotrek/land/locale/fr/LC_MESSAGES/django.po b/geotrek/land/locale/fr/LC_MESSAGES/django.po index 6c7ebf136e..67b370974a 100644 --- a/geotrek/land/locale/fr/LC_MESSAGES/django.po +++ b/geotrek/land/locale/fr/LC_MESSAGES/django.po @@ -23,6 +23,9 @@ msgstr "Statuts" msgid "Land edge" msgstr "Type foncier" +msgid "Circulation edge" +msgstr "Autorisation de circulation" + msgid "Physical edge" msgstr "Type de voie" @@ -74,6 +77,18 @@ msgstr "Conventionné" msgid "Land edges" msgstr "Types fonciers" +msgid "Circulation edges" +msgstr "Autorisations de circulation" + +msgid "Circulation type" +msgstr "Type d'autorisation de circulation" + +msgid "Circulation types" +msgstr "Types d'autorisation de circulation" + +msgid "Authorized" +msgstr "Autorisée" + msgid "Organism" msgstr "Organisme" @@ -89,6 +104,9 @@ msgstr "Gestionnaires signalétique" msgid "Add a new land edge" msgstr "Ajouter un type foncier" +msgid "Add a new circulation edge" +msgstr "Ajouter une nouvelle autorisation de circulation" + msgid "Add a new physical edge" msgstr "Ajouter un type de voie" diff --git a/geotrek/land/migrations/0011_circulationedge_circulationtype.py b/geotrek/land/migrations/0011_circulationedge_circulationtype.py new file mode 100644 index 0000000000..7365de2af8 --- /dev/null +++ b/geotrek/land/migrations/0011_circulationedge_circulationtype.py @@ -0,0 +1,44 @@ +# Generated by Django 3.2.18 on 2023-08-18 09:30 + +from django.db import migrations, models +import django.db.models.deletion +import mapentity.models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authent', '0011_alter_userprofile_structure'), + ('core', '0036_auto_20230503_0837'), + ('land', '0010_auto_20230503_0837'), + ] + + operations = [ + migrations.CreateModel( + name='CirculationType', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=128, verbose_name='Name')), + ('structure', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='authent.structure', verbose_name='Related structure')), + ], + options={ + 'verbose_name': 'Circulation type', + 'verbose_name_plural': 'Circulation types', + 'ordering': ['name'], + }, + ), + migrations.CreateModel( + name='CirculationEdge', + fields=[ + ('topo_object', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='core.topology')), + ('authorized', models.BooleanField(default=False, verbose_name='Authorized')), + ('eid', models.CharField(blank=True, max_length=1024, null=True, verbose_name='External id')), + ('circulation_type', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='land.circulationtype', verbose_name='Circulation type')), + ], + options={ + 'verbose_name': 'Circulation edge', + 'verbose_name_plural': 'Circulation edges', + }, + bases=(mapentity.models.DuplicateMixin, 'core.topology', models.Model), + ), + ] diff --git a/geotrek/land/models.py b/geotrek/land/models.py index c5245b4ad3..68660b4409 100644 --- a/geotrek/land/models.py +++ b/geotrek/land/models.py @@ -360,3 +360,79 @@ def log_cascade_deletion_from_signagemanagementedge_topology(sender, instance, u Project.add_property('signage_edges', lambda self: self.edges_by_attr('signage_edges'), _("Signage management edges")) if 'geotrek.signage' in settings.INSTALLED_APPS: Blade.add_property('signage_edges', lambda self: self.signage.signage_edges, _("Signage management edges")) + + +class CirculationType(StructureOrNoneRelated): + name = models.CharField(max_length=128, verbose_name=_("Name")) + + class Meta: + verbose_name = _("Circulation type") + verbose_name_plural = _("Circulation types") + ordering = ['name'] + + def __str__(self): + if self.structure: + return "{} ({})".format(self.name, self.structure.name) + return self.name + + +class CirculationEdge(GeotrekMapEntityMixin, Topology): + topo_object = models.OneToOneField(Topology, parent_link=True, on_delete=models.CASCADE) + circulation_type = models.ForeignKey(CirculationType, verbose_name=_("Circulation type"), on_delete=models.PROTECT) + authorized = models.BooleanField(verbose_name=_("Authorized"), default=None, null=True) + eid = models.CharField(verbose_name=_("External id"), max_length=1024, blank=True, null=True) + + geometry_types_allowed = ["LINESTRING"] + + class Meta: + verbose_name = _("Circulation edge") + verbose_name_plural = _("Circulation edges") + + def __str__(self): + return _("Circulation edge") + ": %s" % self.circulation_type + + @property + def color_index(self): + return self.circulation_type_id + + @property + def name(self): + return self.circulation_type_csv_display + + @property + def name_display(self): + return self.circulation_type_display + + @property + def circulation_type_display(self): + return '%s' % ( + self.pk, + self.get_detail_url(), + self.circulation_type + ) + + @property + def circulation_type_csv_display(self): + return str(self.circulation_type) + + @classmethod + def path_circulations(cls, path): + return cls.objects.existing().select_related('circulation_type').filter(aggregations__path=path).distinct('pk') + + @classmethod + def topology_circulations(cls, topology): + return cls.overlapping(topology).select_related('circulation_type') + + +@receiver(pre_delete, sender=Topology) +def log_cascade_deletion_from_circulationedge_topology(sender, instance, using, **kwargs): + # CirculationEdges are deleted when topologies are deleted + log_cascade_deletion(sender, instance, CirculationEdge, 'topo_object') + + +Path.add_property('circulation_edges', CirculationEdge.path_circulations, _("Circulation edges")) +Topology.add_property('circulation_edges', CirculationEdge.topology_circulations, _("Circulation edges")) +Intervention.add_property('circulation_edges', lambda self: self.target.circulation_edges if self.target and hasattr(self.target, 'circulation_edges') else [], _("Circulation edges")) +Project.add_property('circulation_edges', lambda self: self.edges_by_attr('circulation_edges'), _("Circulation edges")) +if 'geotrek.signage' in settings.INSTALLED_APPS: + Blade.add_property('circulation_edges', lambda self: self.signage.circulation_edges, _("Circulation edges")) diff --git a/geotrek/land/serializers.py b/geotrek/land/serializers.py index 7859d770e1..d6f257cd1f 100644 --- a/geotrek/land/serializers.py +++ b/geotrek/land/serializers.py @@ -2,7 +2,7 @@ from mapentity.serializers import MapentityGeojsonModelSerializer from rest_framework import serializers -from geotrek.land.models import LandEdge, PhysicalEdge, CompetenceEdge, SignageManagementEdge, WorkManagementEdge +from geotrek.land.models import LandEdge, PhysicalEdge, CompetenceEdge, SignageManagementEdge, WorkManagementEdge, CirculationEdge class LandEdgeSerializer(DynamicFieldsMixin, serializers.ModelSerializer): @@ -24,6 +24,25 @@ class Meta(MapentityGeojsonModelSerializer.Meta): fields = ["id", "name", "color_index"] +class CirculationEdgeSerializer(DynamicFieldsMixin, serializers.ModelSerializer): + circulation_type = serializers.CharField(source='circulation_type_display') + length = serializers.FloatField(source='length_display') + length_2d = serializers.FloatField(source='length_2d_display') + + class Meta: + model = CirculationEdge + fields = "__all__" + + +class CirculationEdgeGeojsonSerializer(MapentityGeojsonModelSerializer): + color_index = serializers.IntegerField() + name = serializers.CharField() + + class Meta(MapentityGeojsonModelSerializer.Meta): + model = CirculationEdge + fields = ["id", "name", "color_index"] + + class PhysicalEdgeSerializer(DynamicFieldsMixin, serializers.ModelSerializer): physical_type = serializers.CharField(source='physical_type_display') length = serializers.FloatField(source='length_display') diff --git a/geotrek/land/static/land/main.js b/geotrek/land/static/land/main.js index a91e815190..6b1a775ad3 100644 --- a/geotrek/land/static/land/main.js +++ b/geotrek/land/static/land/main.js @@ -4,6 +4,7 @@ $(window).on('entity:map', function (e, data) { var managementLayers = [{ url: window.SETTINGS.urls.landedge_layer, name: tr('Land type'), id: 'land' }, { url: window.SETTINGS.urls.physicaledge_layer, name: tr('Physical type'), id: 'physical' }, + { url: window.SETTINGS.urls.circulationedge_layer, name: tr('Circulation type'), id: 'circulation' }, { url: window.SETTINGS.urls.competenceedge_layer, name: tr('Competence'), id: 'competence' }, { url: window.SETTINGS.urls.signagemanagementedge_layer, name: tr('Signage management edges'), id: 'signagemanagement' }, { url: window.SETTINGS.urls.workmanagementedge_layer, name: tr('Work management edges'), id: 'workmanagement' }]; diff --git a/geotrek/land/templates/land/circulationedge_detail.html b/geotrek/land/templates/land/circulationedge_detail.html new file mode 100644 index 0000000000..ff7cf8d41b --- /dev/null +++ b/geotrek/land/templates/land/circulationedge_detail.html @@ -0,0 +1,24 @@ +{% extends "common/common_detail.html" %} +{% load i18n mapentity_tags %} + +{% block detailspanel %} + + + + + + + + + + {% include "altimetry/elevationinfo_fragment.html" %} + {% include "mapentity/trackinfo_fragment.html" %} +
{{ circulationedge|verbose:"circulation_type" }}{{ circulationedge.circulation_type }}
{{ circulationedge|verbose:"authorized" }} + {% if circulationedge.authorized %} + {% trans "Yes" %} + {% else %} + {% trans "No" %} + {% endif %} +
+ {{ block.super }} +{% endblock detailspanel %} diff --git a/geotrek/land/templates/land/land_detail_fragment.html b/geotrek/land/templates/land/land_detail_fragment.html index bfc4cd70eb..0d5a9e311e 100644 --- a/geotrek/land/templates/land/land_detail_fragment.html +++ b/geotrek/land/templates/land/land_detail_fragment.html @@ -80,6 +80,21 @@

{% trans "Status" %}

{% endif %} + + {% if modelname != "circulationedge" %} + + {% trans "Circulation edges" %} + + {% if perms.land.add_circulationedge %} +

+ {% trans "Add a new circulation edge" %} +

+ {% endif %} + + {% valuelist object.circulation_edges field='circulation_type' %} + + + {% endif %} {% endif %} diff --git a/geotrek/land/templates/land/land_extrabody_fragment.html b/geotrek/land/templates/land/land_extrabody_fragment.html index 4a9fd5fec0..425c6e3742 100644 --- a/geotrek/land/templates/land/land_extrabody_fragment.html +++ b/geotrek/land/templates/land/land_extrabody_fragment.html @@ -1,8 +1,10 @@ {% load static i18n %} diff --git a/geotrek/land/templates/land/land_preactions_fragment.html b/geotrek/land/templates/land/land_preactions_fragment.html index f290af3b9c..85af3c5ab1 100644 --- a/geotrek/land/templates/land/land_preactions_fragment.html +++ b/geotrek/land/templates/land/land_preactions_fragment.html @@ -9,6 +9,7 @@ {% if modelname == 'competenceedge' %}{% trans "Competence edges" %}{% endif %} {% if modelname == 'signagemanagementedge' %}{% trans "Signage management edges" %}{% endif %} {% if modelname == 'workmanagementedge' %}{% trans "Work management edges" %}{% endif %} + {% if modelname == 'circulationedge' %}{% trans "Circulation edges" %}{% endif %} {% endif %} diff --git a/geotrek/land/templates/land/sql/post_10_views.sql b/geotrek/land/templates/land/sql/post_10_views.sql index 01de3c4015..a82ddd0095 100644 --- a/geotrek/land/templates/land/sql/post_10_views.sql +++ b/geotrek/land/templates/land/sql/post_10_views.sql @@ -31,4 +31,11 @@ CREATE VIEW {{ schema_geotrek }}.v_workmanagements AS ( FROM core_topology AS e, land_workmanagementedge AS f, common_organism AS b WHERE f.topo_object_id = e.id AND f.organization_id = b.id AND deleted = FALSE -); \ No newline at end of file +); + +CREATE VIEW {{ schema_geotrek }}.v_circulations AS ( + SELECT e.*, b.structure_id, b.name + FROM core_topology AS e, land_circulationedge AS f, land_circulationtype AS b + WHERE f.topo_object_id = e.id AND f.circulation_type_id = b.id + AND deleted = FALSE +); diff --git a/geotrek/land/templates/land/sql/post_90_defaults.sql b/geotrek/land/templates/land/sql/post_90_defaults.sql index 76f77eb1f3..f6453b4d8d 100644 --- a/geotrek/land/templates/land/sql/post_90_defaults.sql +++ b/geotrek/land/templates/land/sql/post_90_defaults.sql @@ -24,6 +24,19 @@ ALTER TABLE land_landedge ALTER COLUMN owner SET DEFAULT ''; ALTER TABLE land_landedge ALTER COLUMN agreement SET DEFAULT False; -- eid +-- CirculationType +----------- +-- name +-- structure + + +-- CirculationEdge +----------- +-- topo_object +-- circulation_type +ALTER TABLE land_circulationedge ALTER COLUMN authorized SET DEFAULT False; +-- eid + -- CompetenceEdge ----------------- diff --git a/geotrek/land/templates/land/sql/pre_10_cleanup.sql b/geotrek/land/templates/land/sql/pre_10_cleanup.sql index 467880dc58..ebc191d932 100644 --- a/geotrek/land/templates/land/sql/pre_10_cleanup.sql +++ b/geotrek/land/templates/land/sql/pre_10_cleanup.sql @@ -2,6 +2,7 @@ DROP VIEW IF EXISTS f_v_nature; DROP VIEW IF EXISTS v_physicals; DROP VIEW IF EXISTS f_v_foncier; DROP VIEW IF EXISTS v_lands; +DROP VIEW IF EXISTS v_circulations; DROP VIEW IF EXISTS f_v_competence; DROP VIEW IF EXISTS v_competences; DROP VIEW IF EXISTS f_v_gestion_signaletique; diff --git a/geotrek/land/tests/factories.py b/geotrek/land/tests/factories.py index 0b635ab50d..a4fcda8967 100644 --- a/geotrek/land/tests/factories.py +++ b/geotrek/land/tests/factories.py @@ -35,6 +35,20 @@ class Meta: land_type = factory.SubFactory(LandTypeFactory) +class CirculationTypeFactory(factory.django.DjangoModelFactory): + class Meta: + model = models.CirculationType + + name = factory.Sequence(lambda n: "CirculationType %s" % n) + + +class CirculationEdgeFactory(TopologyFactory): + class Meta: + model = models.CirculationEdge + + circulation_type = factory.SubFactory(CirculationTypeFactory) + + class CompetenceEdgeFactory(TopologyFactory): class Meta: model = models.CompetenceEdge diff --git a/geotrek/land/tests/test_filters.py b/geotrek/land/tests/test_filters.py index 6755279856..ecc0b55084 100644 --- a/geotrek/land/tests/test_filters.py +++ b/geotrek/land/tests/test_filters.py @@ -9,7 +9,8 @@ from geotrek.core.tests.factories import PathFactory, getRandomLineStringInBounds from geotrek.land.tests.factories import ( PhysicalEdgeFactory, LandEdgeFactory, CompetenceEdgeFactory, - WorkManagementEdgeFactory, SignageManagementEdgeFactory + WorkManagementEdgeFactory, SignageManagementEdgeFactory, + CirculationEdgeFactory ) @@ -54,6 +55,9 @@ def test_filter_by_physical_edge(self): def test_filter_by_land_edge(self): self._filter_by_edge(LandEdgeFactory, 'land_type', lambda edge: edge.land_type.pk) + def test_filter_by_circulation_edge(self): + self._filter_by_edge(CirculationEdgeFactory, 'circulation_type', lambda edge: edge.circulation_type.pk) + def test_filter_by_competence_edge(self): self._filter_by_edge(CompetenceEdgeFactory, 'competence', lambda edge: edge.organization.pk) diff --git a/geotrek/land/tests/test_models.py b/geotrek/land/tests/test_models.py index 41495106c9..352b205e35 100644 --- a/geotrek/land/tests/test_models.py +++ b/geotrek/land/tests/test_models.py @@ -1,7 +1,7 @@ from django.test import TestCase from geotrek.authent.models import Structure -from geotrek.land.models import LandType, PhysicalType +from geotrek.land.models import LandType, PhysicalType, CirculationType class TestModelLand(TestCase): @@ -22,3 +22,12 @@ def test_landtype_value_default_structure(self): structure = Structure.objects.create(name="Structure_1") pt = LandType.objects.create(name='LandType_1', structure=structure) self.assertEqual(str(pt), 'LandType_1 (Structure_1)') + + def test_circulationtype_value_no_structure(self): + pt = CirculationType.objects.create(name='CirculationType_1') + self.assertEqual(str(pt), 'CirculationType_1') + + def test_circulationtype_value_default_structure(self): + structure = Structure.objects.create(name="Structure_1") + pt = CirculationType.objects.create(name='CirculationType_1', structure=structure) + self.assertEqual(str(pt), 'CirculationType_1 (Structure_1)') diff --git a/geotrek/land/tests/test_views.py b/geotrek/land/tests/test_views.py index 19aeaadd50..c3a4ad1836 100644 --- a/geotrek/land/tests/test_views.py +++ b/geotrek/land/tests/test_views.py @@ -8,11 +8,13 @@ from geotrek.core.tests.factories import PathFactory from geotrek.common.tests.factories import OrganismFactory from geotrek.land.models import (PhysicalEdge, LandEdge, CompetenceEdge, - WorkManagementEdge, SignageManagementEdge) + WorkManagementEdge, SignageManagementEdge, + CirculationEdge) from geotrek.land.tests.factories import (PhysicalEdgeFactory, LandEdgeFactory, CompetenceEdgeFactory, WorkManagementEdgeFactory, SignageManagementEdgeFactory, PhysicalTypeFactory, - LandTypeFactory) + LandTypeFactory, CirculationEdgeFactory, + CirculationTypeFactory) @skipIf(not settings.TREKKING_TOPOLOGY_ENABLED, 'Test with dynamic segmentation only') @@ -45,6 +47,13 @@ class PhysicalEdgeTest(EdgeHelperTest): helper_name = 'physical_edges' +@skipIf(not settings.TREKKING_TOPOLOGY_ENABLED, 'Test with dynamic segmentation only') +class CirculationEdgeTest(EdgeHelperTest): + + factory = CirculationEdgeFactory + helper_name = 'circulation_edges' + + @skipIf(not settings.TREKKING_TOPOLOGY_ENABLED, 'Test with dynamic segmentation only') class CompetenceEdgeTest(EdgeHelperTest): @@ -141,6 +150,44 @@ def get_expected_datatables_attrs(self): } +@skipIf(not settings.TREKKING_TOPOLOGY_ENABLED, 'Test with dynamic segmentation only') +class CirculationEdgeViewsTest(CommonTest): + model = CirculationEdge + modelfactory = CirculationEdgeFactory + userfactory = PathManagerFactory + extra_column_list = ['authorized'] + expected_column_list_extra = ['id', 'circulation_type', 'authorized'] + expected_column_formatlist_extra = ['id', 'authorized'] + expected_json_geom = {'coordinates': [[3.0013501, 46.5008686], + [3.0000461, 46.4999682]], + 'type': 'LineString'} + + def get_expected_geojson_geom(self): + return self.expected_json_geom + + def get_expected_geojson_attrs(self): + return { + 'id': self.obj.pk, + 'name': self.obj.name, + 'color_index': self.obj.circulation_type_id + } + + def get_good_data(self): + path = PathFactory.create() + return { + 'circulation_type': CirculationTypeFactory.create().pk, + 'topology': '{"paths": [%s]}' % path.pk, + } + + def get_expected_datatables_attrs(self): + return { + 'id': self.obj.pk, + 'circulation_type': self.obj.circulation_type_display, + 'length': round(self.obj.length, 1), + 'length_2d': round(self.obj.length, 1) + } + + @skipIf(not settings.TREKKING_TOPOLOGY_ENABLED, 'Test with dynamic segmentation only') class CompetenceEdgeViewsTest(CommonTest): model = CompetenceEdge diff --git a/geotrek/land/urls.py b/geotrek/land/urls.py index 608d69c3c8..9a570e3598 100644 --- a/geotrek/land/urls.py +++ b/geotrek/land/urls.py @@ -21,6 +21,7 @@ def __init__(self, model): urlpatterns = registry.register(models.PhysicalEdge, menu=False) urlpatterns += registry.register(models.LandEdge, menu=False) +urlpatterns += registry.register(models.CirculationEdge, menu=False) urlpatterns += registry.register(models.Status, options=LandEdgeOptions, menu=settings.TREKKING_TOPOLOGY_ENABLED and settings.LANDEDGE_MODEL_ENABLED) urlpatterns += registry.register(models.CompetenceEdge, menu=False) urlpatterns += registry.register(models.WorkManagementEdge, menu=False) diff --git a/geotrek/land/views.py b/geotrek/land/views.py index 20f1575480..75774885ef 100644 --- a/geotrek/land/views.py +++ b/geotrek/land/views.py @@ -8,14 +8,16 @@ from geotrek.core.models import AltimetryMixin from geotrek.core.views import CreateFromTopologyMixin from .filters import PhysicalEdgeFilterSet, LandEdgeFilterSet, CompetenceEdgeFilterSet, WorkManagementEdgeFilterSet, \ - SignageManagementEdgeFilterSet -from .forms import PhysicalEdgeForm, LandEdgeForm, CompetenceEdgeForm, WorkManagementEdgeForm, SignageManagementEdgeForm + SignageManagementEdgeFilterSet, CirculationEdgeFilterSet +from .forms import PhysicalEdgeForm, LandEdgeForm, CompetenceEdgeForm, WorkManagementEdgeForm, SignageManagementEdgeForm, \ + CirculationEdgeForm from .models import (PhysicalEdge, LandEdge, CompetenceEdge, - WorkManagementEdge, SignageManagementEdge) + WorkManagementEdge, SignageManagementEdge, + CirculationEdge) from .serializers import LandEdgeSerializer, PhysicalEdgeSerializer, CompetenceEdgeSerializer, \ SignageManagementEdgeSerializer, WorkManagementEdgeSerializer, PhysicalEdgeGeojsonSerializer, \ LandEdgeGeojsonSerializer, CompetenceEdgeGeojsonSerializer, WorkManagementEdgeGeojsonSerializer, \ - SignageManagementEdgeGeojsonSerializer + SignageManagementEdgeGeojsonSerializer, CirculationEdgeSerializer, CirculationEdgeGeojsonSerializer class PhysicalEdgeList(CustomColumnsMixin, CreateFromTopologyMixin, MapEntityList): @@ -126,6 +128,59 @@ def get_queryset(self): return qs.defer('geom', 'geom_3d') +class CirculationEdgeList(CustomColumnsMixin, MapEntityList): + queryset = CirculationEdge.objects.existing() + filterform = CirculationEdgeFilterSet + mandatory_columns = ['id', 'circulation_type'] + default_extra_columns = ['length', 'length_2d'] + + +class CirculationEdgeFormatList(MapEntityFormat, CirculationEdgeList): + mandatory_columns = ['id'] + default_extra_columns = [ + 'circulation_type', 'authorized', 'date_insert', 'date_update', + 'cities', 'districts', 'areas', 'uuid', 'length_2d' + ] + AltimetryMixin.COLUMNS + + +class CirculationEdgeDetail(MapEntityDetail): + queryset = CirculationEdge.objects.existing() + + +class CirculationEdgeDocument(MapEntityDocument): + model = CirculationEdge + + +class CirculationEdgeCreate(CreateFromTopologyMixin, MapEntityCreate): + model = CirculationEdge + form_class = CirculationEdgeForm + + +class CirculationEdgeUpdate(MapEntityUpdate): + queryset = CirculationEdge.objects.existing() + form_class = CirculationEdgeForm + + +class CirculationEdgeDelete(MapEntityDelete): + model = CirculationEdge + + +class CirculationEdgeViewSet(GeotrekMapentityViewSet): + model = CirculationEdge + serializer_class = CirculationEdgeSerializer + geojson_serializer_class = CirculationEdgeGeojsonSerializer + filterset_class = CirculationEdgeFilterSet + mapentity_list_class = CirculationEdgeList + + def get_queryset(self): + qs = self.model.objects.existing().select_related('circulation_type') + if self.format_kwarg == 'geojson': + qs = qs.annotate(api_geom=Transform('geom', settings.API_SRID)) + qs = qs.only('id', 'circulation_type') + return qs + return qs.defer('geom', 'geom_3d') + + class CompetenceEdgeList(CustomColumnsMixin, MapEntityList): queryset = CompetenceEdge.objects.existing() filterform = CompetenceEdgeFilterSet From 54be577f8860b992e751bcc58691e967db2cc959 Mon Sep 17 00:00:00 2001 From: Idrissa Djepa Creutz Date: Fri, 18 Aug 2023 19:30:02 +0200 Subject: [PATCH 02/19] Add color pool for CirculationEdge model - to fix --- docs/install/advanced-configuration.rst | 1 + geotrek/settings/base.py | 1 + 2 files changed, 2 insertions(+) diff --git a/docs/install/advanced-configuration.rst b/docs/install/advanced-configuration.rst index 2f5124027d..7f65ee42e8 100644 --- a/docs/install/advanced-configuration.rst +++ b/docs/install/advanced-configuration.rst @@ -289,6 +289,7 @@ Color of the different layers on the map COLORS_POOL = {'land': ['#f37e79', '#7998f3', '#bbf379', '#f379df', '#f3bf79', '#9c79f3', '#7af379'], 'physical': ['#f3799d', '#79c1f3', '#e4f379', '#de79f3', '#79f3ba', '#f39779', '#797ff3'], + 'circulation': ['#f3799d', '#79c1f3', '#e4f379', '#de79f3', '#79f3ba', '#f39779', '#797ff3'], 'competence': ['#a2f379', '#f379c6', '#79e9f3', '#f3d979', '#b579f3', '#79f392', '#f37984'], 'signagemanagement': ['#79a8f3', '#cbf379', '#f379ee', '#79f3e3', '#79f3d3'], 'workmanagement': ['#79a8f3', '#cbf379', '#f379ee', '#79f3e3', '#79f3d3'], diff --git a/geotrek/settings/base.py b/geotrek/settings/base.py index b051e6bee4..2cf2edf24b 100644 --- a/geotrek/settings/base.py +++ b/geotrek/settings/base.py @@ -476,6 +476,7 @@ def api_bbox(bbox, buffer): """ COLORS_POOL = {'land': ['#f37e79', '#7998f3', '#bbf379', '#f379df', '#f3bf79', '#9c79f3', '#7af379'], 'physical': ['#f3799d', '#79c1f3', '#e4f379', '#de79f3', '#79f3ba', '#f39779', '#797ff3'], + 'circulation': ['#f37e79', '#7998f3', '#bbf379', '#f379df', '#f3bf79', '#9c79f3', '#7af379'], 'competence': ['#a2f379', '#f379c6', '#79e9f3', '#f3d979', '#b579f3', '#79f392', '#f37984'], 'signagemanagement': ['#79a8f3', '#cbf379', '#f379ee', '#79f3e3', '#79f3d3'], 'workmanagement': ['#79a8f3', '#cbf379', '#f379ee', '#79f3e3', '#79f3d3'], From 0a51108a2b17675bb53dd4bed8120b77bcd6b91b Mon Sep 17 00:00:00 2001 From: Idrissa Djepa Creutz Date: Thu, 24 Aug 2023 11:25:17 +0200 Subject: [PATCH 03/19] Modification traduction Circulation --- geotrek/land/locale/fr/LC_MESSAGES/django.po | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/geotrek/land/locale/fr/LC_MESSAGES/django.po b/geotrek/land/locale/fr/LC_MESSAGES/django.po index 67b370974a..d5042a6c2f 100644 --- a/geotrek/land/locale/fr/LC_MESSAGES/django.po +++ b/geotrek/land/locale/fr/LC_MESSAGES/django.po @@ -24,7 +24,7 @@ msgid "Land edge" msgstr "Type foncier" msgid "Circulation edge" -msgstr "Autorisation de circulation" +msgstr "Circulation" msgid "Physical edge" msgstr "Type de voie" @@ -81,10 +81,10 @@ msgid "Circulation edges" msgstr "Autorisations de circulation" msgid "Circulation type" -msgstr "Type d'autorisation de circulation" +msgstr "Type de circulation" msgid "Circulation types" -msgstr "Types d'autorisation de circulation" +msgstr "Types de circulation" msgid "Authorized" msgstr "Autorisée" @@ -105,7 +105,7 @@ msgid "Add a new land edge" msgstr "Ajouter un type foncier" msgid "Add a new circulation edge" -msgstr "Ajouter une nouvelle autorisation de circulation" +msgstr "Ajouter une nouvelle circulation" msgid "Add a new physical edge" msgstr "Ajouter un type de voie" From 07fdc5bfa6c181768626d1b246802a32b9c5a0bd Mon Sep 17 00:00:00 2001 From: Idrissa Djepa Creutz Date: Thu, 24 Aug 2023 17:34:39 +0200 Subject: [PATCH 04/19] Traduction Circulation --- geotrek/land/locale/fr/LC_MESSAGES/django.po | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/geotrek/land/locale/fr/LC_MESSAGES/django.po b/geotrek/land/locale/fr/LC_MESSAGES/django.po index d5042a6c2f..b3da70860c 100644 --- a/geotrek/land/locale/fr/LC_MESSAGES/django.po +++ b/geotrek/land/locale/fr/LC_MESSAGES/django.po @@ -78,7 +78,7 @@ msgid "Land edges" msgstr "Types fonciers" msgid "Circulation edges" -msgstr "Autorisations de circulation" +msgstr "Circulations" msgid "Circulation type" msgstr "Type de circulation" From 41a19d2e3b3d2d415ae0fbfc0f79a6876e8f32ac Mon Sep 17 00:00:00 2001 From: Idrissa Djepa Creutz <73114156+IdrissaD@users.noreply.github.com> Date: Tue, 29 Aug 2023 10:24:38 +0200 Subject: [PATCH 05/19] Update geotrek/land/models.py MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Célia --- geotrek/land/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/geotrek/land/models.py b/geotrek/land/models.py index 68660b4409..aa9d062add 100644 --- a/geotrek/land/models.py +++ b/geotrek/land/models.py @@ -380,7 +380,7 @@ class CirculationEdge(GeotrekMapEntityMixin, Topology): topo_object = models.OneToOneField(Topology, parent_link=True, on_delete=models.CASCADE) circulation_type = models.ForeignKey(CirculationType, verbose_name=_("Circulation type"), on_delete=models.PROTECT) authorized = models.BooleanField(verbose_name=_("Authorized"), default=None, null=True) - eid = models.CharField(verbose_name=_("External id"), max_length=1024, blank=True, null=True) + eid = models.CharField(verbose_name=_("External id"), max_length=1024, blank=True) geometry_types_allowed = ["LINESTRING"] From bf420f1c361df5df782118cf9e6d2ad2e2adfbba Mon Sep 17 00:00:00 2001 From: Idrissa Djepa Creutz Date: Tue, 29 Aug 2023 10:52:32 +0200 Subject: [PATCH 06/19] Resolve nullable circulation authorization --- geotrek/land/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/geotrek/land/models.py b/geotrek/land/models.py index aa9d062add..932d852b6a 100644 --- a/geotrek/land/models.py +++ b/geotrek/land/models.py @@ -379,7 +379,7 @@ def __str__(self): class CirculationEdge(GeotrekMapEntityMixin, Topology): topo_object = models.OneToOneField(Topology, parent_link=True, on_delete=models.CASCADE) circulation_type = models.ForeignKey(CirculationType, verbose_name=_("Circulation type"), on_delete=models.PROTECT) - authorized = models.BooleanField(verbose_name=_("Authorized"), default=None, null=True) + authorized = models.BooleanField(verbose_name=_("Authorized"), null=True) eid = models.CharField(verbose_name=_("External id"), max_length=1024, blank=True) geometry_types_allowed = ["LINESTRING"] From 4c436e475a26c959e69c8cca40a0502460df4bd0 Mon Sep 17 00:00:00 2001 From: Idrissa Djepa Creutz Date: Tue, 29 Aug 2023 10:59:11 +0200 Subject: [PATCH 07/19] Add migrations files --- .../0012_alter_circulationedge_authorized.py | 18 ++++++++++++++++++ .../0013_alter_circulationedge_eid.py | 19 +++++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 geotrek/land/migrations/0012_alter_circulationedge_authorized.py create mode 100644 geotrek/land/migrations/0013_alter_circulationedge_eid.py diff --git a/geotrek/land/migrations/0012_alter_circulationedge_authorized.py b/geotrek/land/migrations/0012_alter_circulationedge_authorized.py new file mode 100644 index 0000000000..1bf47a4bea --- /dev/null +++ b/geotrek/land/migrations/0012_alter_circulationedge_authorized.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.20 on 2023-08-29 08:39 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('land', '0011_circulationedge_circulationtype'), + ] + + operations = [ + migrations.AlterField( + model_name='circulationedge', + name='authorized', + field=models.BooleanField(null=True, verbose_name='Authorized'), + ), + ] diff --git a/geotrek/land/migrations/0013_alter_circulationedge_eid.py b/geotrek/land/migrations/0013_alter_circulationedge_eid.py new file mode 100644 index 0000000000..67a1350911 --- /dev/null +++ b/geotrek/land/migrations/0013_alter_circulationedge_eid.py @@ -0,0 +1,19 @@ +# Generated by Django 3.2.20 on 2023-08-29 08:46 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('land', '0012_alter_circulationedge_authorized'), + ] + + operations = [ + migrations.AlterField( + model_name='circulationedge', + name='eid', + field=models.CharField(blank=True, default=5, max_length=1024, verbose_name='External id'), + preserve_default=False, + ), + ] From 314614357f763cb48cd85930c01e42d367efbf4e Mon Sep 17 00:00:00 2001 From: Idrissa Djepa Creutz <73114156+IdrissaD@users.noreply.github.com> Date: Tue, 29 Aug 2023 15:30:54 +0200 Subject: [PATCH 08/19] Update geotrek/land/templates/land/circulationedge_detail.html MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Célia --- geotrek/land/templates/land/circulationedge_detail.html | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/geotrek/land/templates/land/circulationedge_detail.html b/geotrek/land/templates/land/circulationedge_detail.html index ff7cf8d41b..2db3e2e711 100644 --- a/geotrek/land/templates/land/circulationedge_detail.html +++ b/geotrek/land/templates/land/circulationedge_detail.html @@ -10,7 +10,13 @@ {{ circulationedge|verbose:"authorized" }} - {% if circulationedge.authorized %} + {% if circulationedge.authorized is none %} + {% trans "Undefined" %} + {% elif circulationedge.authorized %} + {% trans "Yes" %} + {% else %} + {% trans "No" %} + {% endif %} {% trans "Yes" %} {% else %} {% trans "No" %} From 3584099901563e9fead997b67d4f824458a5841b Mon Sep 17 00:00:00 2001 From: Idrissa Djepa Creutz Date: Tue, 29 Aug 2023 15:34:06 +0200 Subject: [PATCH 09/19] Translation Undefined --- geotrek/land/locale/fr/LC_MESSAGES/django.po | 3 +++ 1 file changed, 3 insertions(+) diff --git a/geotrek/land/locale/fr/LC_MESSAGES/django.po b/geotrek/land/locale/fr/LC_MESSAGES/django.po index b3da70860c..7ced0f001a 100644 --- a/geotrek/land/locale/fr/LC_MESSAGES/django.po +++ b/geotrek/land/locale/fr/LC_MESSAGES/django.po @@ -127,3 +127,6 @@ msgstr "Oui" msgid "No" msgstr "Non" + +msgid "Undefined" +msgstr "Indéterminée" From 06b6548a39645561116b0c09d869764bef3e4ca9 Mon Sep 17 00:00:00 2001 From: Idrissa Djepa Creutz Date: Fri, 22 Sep 2023 16:18:21 +0200 Subject: [PATCH 10/19] Ajout de circulationedge_category --- geotrek/altimetry/tests/test_commands.py | 2 +- geotrek/land/admin.py | 10 ++++- geotrek/land/filters.py | 13 ++++++- geotrek/land/fixtures/basic.json | 21 ++++++++++ geotrek/land/forms.py | 2 +- geotrek/land/locale/fr/LC_MESSAGES/django.po | 10 ++--- .../migrations/0014_auto_20230831_0751.py | 38 +++++++++++++++++++ geotrek/land/models.py | 24 +++++++++++- geotrek/land/serializers.py | 1 + .../land/circulationedge_detail.html | 16 +------- .../land/land_extrabody_fragment.html | 1 + .../land/templates/land/sql/post_10_views.sql | 4 +- .../templates/land/sql/post_90_defaults.sql | 7 +++- geotrek/land/tests/factories.py | 8 ++++ geotrek/land/tests/test_models.py | 11 +++++- geotrek/land/tests/test_views.py | 10 +++-- 16 files changed, 145 insertions(+), 33 deletions(-) create mode 100644 geotrek/land/migrations/0014_auto_20230831_0751.py diff --git a/geotrek/altimetry/tests/test_commands.py b/geotrek/altimetry/tests/test_commands.py index 765dbafeb4..09864cec7b 100644 --- a/geotrek/altimetry/tests/test_commands.py +++ b/geotrek/altimetry/tests/test_commands.py @@ -71,7 +71,7 @@ def test_success_without_replace_update_altimetry_nds(self): output_stdout = StringIO() filename = os.path.join(os.path.dirname(__file__), 'data', 'elevation.tif') self.trek = TrekFactory.create(geom=LineString((605600, 6650000), (605900, 6650010), srid=2154)) - with self.assertNumQueries(21): # 5 for loaddem initial + 16 with selects and update geom + with self.assertNumQueries(22): # 5 for loaddem initial + 17 with selects and update geom call_command('loaddem', filename, update_altimetry=True, verbosity=2, stdout=output_stdout) self.assertIn('DEM successfully loaded.', output_stdout.getvalue()) self.assertIn('Everything looks fine, we can start loading DEM', output_stdout.getvalue()) diff --git a/geotrek/land/admin.py b/geotrek/land/admin.py index c322039dd7..d2bf7be78d 100644 --- a/geotrek/land/admin.py +++ b/geotrek/land/admin.py @@ -1,7 +1,7 @@ from django.contrib import admin from geotrek.common.mixins.actions import MergeActionMixin -from .models import PhysicalType, LandType, CirculationType +from .models import PhysicalType, LandType, CirculationType, AuthorizationType class PhysicalTypeAdmin(MergeActionMixin, admin.ModelAdmin): @@ -25,6 +25,14 @@ class CirculationTypeAdmin(MergeActionMixin, admin.ModelAdmin): merge_field = "name" +class AuthorizationTypeAdmin(MergeActionMixin, admin.ModelAdmin): + list_display = ('name', 'structure', ) + search_fields = ('name', 'structure') + list_filter = ('structure',) + merge_field = "name" + + admin.site.register(PhysicalType, PhysicalTypeAdmin) admin.site.register(LandType, LandTypeAdmin) admin.site.register(CirculationType, CirculationTypeAdmin) +admin.site.register(AuthorizationType, AuthorizationTypeAdmin) diff --git a/geotrek/land/filters.py b/geotrek/land/filters.py index a91d3c6ace..3ed513cc08 100644 --- a/geotrek/land/filters.py +++ b/geotrek/land/filters.py @@ -13,7 +13,8 @@ from .models import ( CompetenceEdge, LandEdge, LandType, PhysicalEdge, PhysicalType, - SignageManagementEdge, WorkManagementEdge, CirculationEdge, CirculationType + SignageManagementEdge, WorkManagementEdge, CirculationEdge, CirculationType, + AuthorizationType ) @@ -26,7 +27,7 @@ class Meta(MapEntityFilterSet.Meta): class CirculationEdgeFilterSet(ValidTopologyFilterSet, MapEntityFilterSet): class Meta(MapEntityFilterSet.Meta): model = CirculationEdge - fields = ['circulation_type', 'authorized'] + fields = ['circulation_type', 'authorization_type'] class LandEdgeFilterSet(ValidTopologyFilterSet, MapEntityFilterSet): @@ -76,6 +77,13 @@ def values_to_edges(self, values): return CirculationEdge.objects.filter(circulation_type__in=values) +class TopologyFilterAuthorizationType(TopologyFilter): + model = AuthorizationType + + def values_to_edges(self, values): + return CirculationEdge.objects.filter(authorization_type__in=values) + + class TopologyFilterLandType(TopologyFilter): model = LandType @@ -109,6 +117,7 @@ def add_edge_filters(filter_set): 'land_type': TopologyFilterLandType(label=_('Land edge'), required=False), 'physical_type': TopologyFilterPhysicalType(label=_('Physical edge'), required=False), 'circulation_type': TopologyFilterCirculationType(label=_('Circulation edge'), required=False), + 'authorization_type': TopologyFilterAuthorizationType(label=_('Circulation edge'), required=False), 'competence': TopologyFilterCompetenceEdge(label=_('Competence edge'), required=False), 'signage': TopologyFilterSignageManagementEdge(label=_('Signage management edge'), required=False), 'work': TopologyFilterWorkManagementEdge(label=_('Work management edge'), required=False), diff --git a/geotrek/land/fixtures/basic.json b/geotrek/land/fixtures/basic.json index 93ba58ba59..5f32573c0f 100644 --- a/geotrek/land/fixtures/basic.json +++ b/geotrek/land/fixtures/basic.json @@ -163,5 +163,26 @@ "fields": { "name": "Équestre" } + }, + { + "pk": 1, + "model": "land.authorizationtype", + "fields": { + "name": "Autorisée" + } + }, + { + "pk": 2, + "model": "land.authorizationtype", + "fields": { + "name": "Interdite" + } + }, + { + "pk": 3, + "model": "land.authorizationtype", + "fields": { + "name": "Réglementée" + } } ] \ No newline at end of file diff --git a/geotrek/land/forms.py b/geotrek/land/forms.py index ee9ab0a3ea..76e153953e 100644 --- a/geotrek/land/forms.py +++ b/geotrek/land/forms.py @@ -27,7 +27,7 @@ class Meta(EdgeForm.Meta): class CirculationEdgeForm(EdgeForm): class Meta(EdgeForm.Meta): model = CirculationEdge - fields = EdgeForm.Meta.fields + ['circulation_type', 'authorized'] + fields = EdgeForm.Meta.fields + ['circulation_type', 'authorization_type'] class OrganismForm(EdgeForm): diff --git a/geotrek/land/locale/fr/LC_MESSAGES/django.po b/geotrek/land/locale/fr/LC_MESSAGES/django.po index 7ced0f001a..fced7ea992 100644 --- a/geotrek/land/locale/fr/LC_MESSAGES/django.po +++ b/geotrek/land/locale/fr/LC_MESSAGES/django.po @@ -86,8 +86,11 @@ msgstr "Type de circulation" msgid "Circulation types" msgstr "Types de circulation" -msgid "Authorized" -msgstr "Autorisée" +msgid "Authorization type" +msgstr "Type d'autorisation" + +msgid "Authorization types" +msgstr "Types d'autorisation" msgid "Organism" msgstr "Organisme" @@ -127,6 +130,3 @@ msgstr "Oui" msgid "No" msgstr "Non" - -msgid "Undefined" -msgstr "Indéterminée" diff --git a/geotrek/land/migrations/0014_auto_20230831_0751.py b/geotrek/land/migrations/0014_auto_20230831_0751.py new file mode 100644 index 0000000000..baf94ad5d4 --- /dev/null +++ b/geotrek/land/migrations/0014_auto_20230831_0751.py @@ -0,0 +1,38 @@ +# Generated by Django 3.2.20 on 2023-08-31 07:51 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('authent', '0011_alter_userprofile_structure'), + ('land', '0013_alter_circulationedge_eid'), + ] + + operations = [ + migrations.RemoveField( + model_name='circulationedge', + name='authorized', + ), + migrations.CreateModel( + name='AuthorizationType', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=128, verbose_name='Name')), + ('structure', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='authent.structure', verbose_name='Related structure')), + ], + options={ + 'verbose_name': 'Authorization type', + 'verbose_name_plural': 'Authorization types', + 'ordering': ['name'], + }, + ), + migrations.AddField( + model_name='circulationedge', + name='authorization_type', + field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.PROTECT, to='land.authorizationtype', verbose_name='Authorization type'), + preserve_default=False, + ), + ] diff --git a/geotrek/land/models.py b/geotrek/land/models.py index 932d852b6a..4e313bd2df 100644 --- a/geotrek/land/models.py +++ b/geotrek/land/models.py @@ -376,10 +376,24 @@ def __str__(self): return self.name +class AuthorizationType(StructureOrNoneRelated): + name = models.CharField(max_length=128, verbose_name=_("Name")) + + class Meta: + verbose_name = _("Authorization type") + verbose_name_plural = _("Authorization types") + ordering = ['name'] + + def __str__(self): + if self.structure: + return "{} ({})".format(self.name, self.structure.name) + return self.name + + class CirculationEdge(GeotrekMapEntityMixin, Topology): topo_object = models.OneToOneField(Topology, parent_link=True, on_delete=models.CASCADE) circulation_type = models.ForeignKey(CirculationType, verbose_name=_("Circulation type"), on_delete=models.PROTECT) - authorized = models.BooleanField(verbose_name=_("Authorized"), null=True) + authorization_type = models.ForeignKey(AuthorizationType, verbose_name=_("Authorization type"), on_delete=models.PROTECT) eid = models.CharField(verbose_name=_("External id"), max_length=1024, blank=True) geometry_types_allowed = ["LINESTRING"] @@ -411,6 +425,14 @@ def circulation_type_display(self): self.circulation_type ) + @property + def authorization_type_display(self): + return '%s' % ( + self.pk, + self.get_detail_url(), + self.authorization_type + ) + @property def circulation_type_csv_display(self): return str(self.circulation_type) diff --git a/geotrek/land/serializers.py b/geotrek/land/serializers.py index d6f257cd1f..cffca0267b 100644 --- a/geotrek/land/serializers.py +++ b/geotrek/land/serializers.py @@ -26,6 +26,7 @@ class Meta(MapentityGeojsonModelSerializer.Meta): class CirculationEdgeSerializer(DynamicFieldsMixin, serializers.ModelSerializer): circulation_type = serializers.CharField(source='circulation_type_display') + authorization_type = serializers.CharField(source='authorization_type_display') length = serializers.FloatField(source='length_display') length_2d = serializers.FloatField(source='length_2d_display') diff --git a/geotrek/land/templates/land/circulationedge_detail.html b/geotrek/land/templates/land/circulationedge_detail.html index 2db3e2e711..05f09ded11 100644 --- a/geotrek/land/templates/land/circulationedge_detail.html +++ b/geotrek/land/templates/land/circulationedge_detail.html @@ -8,20 +8,8 @@ {{ circulationedge.circulation_type }} - {{ circulationedge|verbose:"authorized" }} - - {% if circulationedge.authorized is none %} - {% trans "Undefined" %} - {% elif circulationedge.authorized %} - {% trans "Yes" %} - {% else %} - {% trans "No" %} - {% endif %} - {% trans "Yes" %} - {% else %} - {% trans "No" %} - {% endif %} - + {{ circulationedge|verbose:"authorization_type" }} + {{ circulationedge.authorization_type }} {% include "altimetry/elevationinfo_fragment.html" %} {% include "mapentity/trackinfo_fragment.html" %} diff --git a/geotrek/land/templates/land/land_extrabody_fragment.html b/geotrek/land/templates/land/land_extrabody_fragment.html index 425c6e3742..f93840524e 100644 --- a/geotrek/land/templates/land/land_extrabody_fragment.html +++ b/geotrek/land/templates/land/land_extrabody_fragment.html @@ -5,6 +5,7 @@ MapEntity.i18n['Status'] = "{% trans "Status" %}"; MapEntity.i18n['Land type'] = "{% trans "Land type" %}"; MapEntity.i18n['Circulation type'] = "{% trans "Circulation type" %}"; + MapEntity.i18n['Authorization type'] = "{% trans "Authorization type" %}"; MapEntity.i18n['Physical type'] = "{% trans "Physical type" %}"; MapEntity.i18n['Competence'] = "{% trans "Competence" %}"; MapEntity.i18n['Signage management edge'] = "{% trans "Signage management edge" %}"; diff --git a/geotrek/land/templates/land/sql/post_10_views.sql b/geotrek/land/templates/land/sql/post_10_views.sql index a82ddd0095..679561d4db 100644 --- a/geotrek/land/templates/land/sql/post_10_views.sql +++ b/geotrek/land/templates/land/sql/post_10_views.sql @@ -35,7 +35,7 @@ CREATE VIEW {{ schema_geotrek }}.v_workmanagements AS ( CREATE VIEW {{ schema_geotrek }}.v_circulations AS ( SELECT e.*, b.structure_id, b.name - FROM core_topology AS e, land_circulationedge AS f, land_circulationtype AS b - WHERE f.topo_object_id = e.id AND f.circulation_type_id = b.id + FROM core_topology AS e, land_circulationedge AS f, land_circulationtype AS b, land_authorizationtype as c + WHERE f.topo_object_id = e.id AND f.circulation_type_id = b.id AND f.authorization_type_id = c.id AND deleted = FALSE ); diff --git a/geotrek/land/templates/land/sql/post_90_defaults.sql b/geotrek/land/templates/land/sql/post_90_defaults.sql index f6453b4d8d..ccc9c76de1 100644 --- a/geotrek/land/templates/land/sql/post_90_defaults.sql +++ b/geotrek/land/templates/land/sql/post_90_defaults.sql @@ -29,12 +29,17 @@ ALTER TABLE land_landedge ALTER COLUMN agreement SET DEFAULT False; -- name -- structure +-- AuthorizationType +----------- +-- name +-- structure + -- CirculationEdge ----------- -- topo_object -- circulation_type -ALTER TABLE land_circulationedge ALTER COLUMN authorized SET DEFAULT False; +-- authorization_type -- eid diff --git a/geotrek/land/tests/factories.py b/geotrek/land/tests/factories.py index a4fcda8967..8c9d9f32a5 100644 --- a/geotrek/land/tests/factories.py +++ b/geotrek/land/tests/factories.py @@ -42,11 +42,19 @@ class Meta: name = factory.Sequence(lambda n: "CirculationType %s" % n) +class AuthorizationTypeFactory(factory.django.DjangoModelFactory): + class Meta: + model = models.AuthorizationType + + name = factory.Sequence(lambda n: "AuthorizationType %s" % n) + + class CirculationEdgeFactory(TopologyFactory): class Meta: model = models.CirculationEdge circulation_type = factory.SubFactory(CirculationTypeFactory) + authorization_type = factory.SubFactory(AuthorizationTypeFactory) class CompetenceEdgeFactory(TopologyFactory): diff --git a/geotrek/land/tests/test_models.py b/geotrek/land/tests/test_models.py index 352b205e35..635dc8baa8 100644 --- a/geotrek/land/tests/test_models.py +++ b/geotrek/land/tests/test_models.py @@ -1,7 +1,7 @@ from django.test import TestCase from geotrek.authent.models import Structure -from geotrek.land.models import LandType, PhysicalType, CirculationType +from geotrek.land.models import LandType, PhysicalType, CirculationType, AuthorizationType class TestModelLand(TestCase): @@ -31,3 +31,12 @@ def test_circulationtype_value_default_structure(self): structure = Structure.objects.create(name="Structure_1") pt = CirculationType.objects.create(name='CirculationType_1', structure=structure) self.assertEqual(str(pt), 'CirculationType_1 (Structure_1)') + + def test_authorizationtype_value_no_structure(self): + pt = AuthorizationType.objects.create(name='AuthorizationType_1') + self.assertEqual(str(pt), 'AuthorizationType_1') + + def test_authorizationtype_value_default_structure(self): + structure = Structure.objects.create(name="Structure_1") + pt = AuthorizationType.objects.create(name='AuthorizationType_1', structure=structure) + self.assertEqual(str(pt), 'AuthorizationType_1 (Structure_1)') diff --git a/geotrek/land/tests/test_views.py b/geotrek/land/tests/test_views.py index c3a4ad1836..ec545f0e34 100644 --- a/geotrek/land/tests/test_views.py +++ b/geotrek/land/tests/test_views.py @@ -14,7 +14,7 @@ CompetenceEdgeFactory, WorkManagementEdgeFactory, SignageManagementEdgeFactory, PhysicalTypeFactory, LandTypeFactory, CirculationEdgeFactory, - CirculationTypeFactory) + CirculationTypeFactory, AuthorizationTypeFactory) @skipIf(not settings.TREKKING_TOPOLOGY_ENABLED, 'Test with dynamic segmentation only') @@ -155,9 +155,9 @@ class CirculationEdgeViewsTest(CommonTest): model = CirculationEdge modelfactory = CirculationEdgeFactory userfactory = PathManagerFactory - extra_column_list = ['authorized'] - expected_column_list_extra = ['id', 'circulation_type', 'authorized'] - expected_column_formatlist_extra = ['id', 'authorized'] + extra_column_list = ['eid'] + expected_column_list_extra = ['id', 'circulation_type', 'authorization_type', 'eid'] + expected_column_formatlist_extra = ['id', 'eid'] expected_json_geom = {'coordinates': [[3.0013501, 46.5008686], [3.0000461, 46.4999682]], 'type': 'LineString'} @@ -176,6 +176,7 @@ def get_good_data(self): path = PathFactory.create() return { 'circulation_type': CirculationTypeFactory.create().pk, + 'authorization_type': AuthorizationTypeFactory.create().pk, 'topology': '{"paths": [%s]}' % path.pk, } @@ -183,6 +184,7 @@ def get_expected_datatables_attrs(self): return { 'id': self.obj.pk, 'circulation_type': self.obj.circulation_type_display, + 'authorization_type': self.obj.authorization_type_display, 'length': round(self.obj.length, 1), 'length_2d': round(self.obj.length, 1) } From a473b537fe95fd488de2f19c02c0822fb3ec394c Mon Sep 17 00:00:00 2001 From: Idrissa Djepa Creutz Date: Tue, 26 Sep 2023 16:34:09 +0200 Subject: [PATCH 11/19] Fix permissions --- geotrek/authent/fixtures/basic.json | 30 +++++++++++++++++++++++++-- geotrek/authent/fixtures/minimal.json | 1 + geotrek/land/tests/test_views.py | 3 +-- geotrek/land/views.py | 4 ++-- 4 files changed, 32 insertions(+), 6 deletions(-) diff --git a/geotrek/authent/fixtures/basic.json b/geotrek/authent/fixtures/basic.json index 3acbffdf68..c5a057b60c 100644 --- a/geotrek/authent/fixtures/basic.json +++ b/geotrek/authent/fixtures/basic.json @@ -92,6 +92,11 @@ ["change_geom_landedge", "land", "landedge"], ["delete_landedge", "land", "landedge"], ["export_landedge", "land", "landedge"], + ["add_circulationedge", "land", "circulationedge"], + ["change_circulationedge", "land", "circulationedge"], + ["change_geom_circulationedge", "land", "circulationedge"], + ["delete_circulationedge", "land", "circulationedge"], + ["export_circulationedge", "land", "circulationedge"], ["add_physicaledge", "land", "physicaledge"], ["change_physicaledge", "land", "physicaledge"], ["change_geom_physicaledge", "land", "physicaledge"], @@ -114,8 +119,13 @@ ["add_landtype", "land", "landtype"], ["change_landtype", "land", "landtype"], ["delete_landtype", "land", "landtype"], - - + ["add_circulationtype", "land", "circulationtype"], + ["change_circulationtype", "land", "circulationtype"], + ["delete_circulationtype", "land", "circulationtype"], + ["add_authorizationtype", "land", "authorizationtype"], + ["change_authorizationtype", "land", "authorizationtype"], + ["delete_authorizationtype", "land", "authorizationtype"], + ["add_intervention", "maintenance", "intervention"], ["change_intervention", "maintenance", "intervention"], @@ -173,6 +183,7 @@ ["read_competenceedge", "land", "competenceedge"], ["read_landedge", "land", "landedge"], ["read_physicaledge", "land", "physicaledge"], + ["read_circulationedge", "land", "circulationedge"], ["read_signagemanagementedge", "land", "signagemanagementedge"], ["read_workmanagementedge", "land", "workmanagementedge"], @@ -274,6 +285,7 @@ ["read_competenceedge", "land", "competenceedge"], ["read_landedge", "land", "landedge"], ["read_physicaledge", "land", "physicaledge"], + ["read_circulationedge", "land", "circulationedge"], ["read_signagemanagementedge", "land", "signagemanagementedge"], ["read_workmanagementedge", "land", "workmanagementedge"], @@ -344,6 +356,11 @@ ["change_geom_landedge", "land", "landedge"], ["delete_landedge", "land", "landedge"], ["export_landedge", "land", "landedge"], + ["add_circulationedge", "land", "circulationedge"], + ["change_circulationedge", "land", "circulationedge"], + ["change_geom_circulationedge", "land", "circulationedge"], + ["delete_circulationedge", "land", "circulationedge"], + ["export_circulationedge", "land", "circulationedge"], ["add_physicaledge", "land", "physicaledge"], ["change_physicaledge", "land", "physicaledge"], ["change_geom_physicaledge", "land", "physicaledge"], @@ -381,6 +398,7 @@ ["read_competenceedge", "land", "competenceedge"], ["read_landedge", "land", "landedge"], ["read_physicaledge", "land", "physicaledge"], + ["read_circulationedge", "land", "circulationedge"], ["read_signagemanagementedge", "land", "signagemanagementedge"], ["read_workmanagementedge", "land", "workmanagementedge"], @@ -428,6 +446,11 @@ ["change_geom_landedge", "land", "landedge"], ["delete_landedge", "land", "landedge"], ["export_landedge", "land", "landedge"], + ["add_circulationedge", "land", "circulationedge"], + ["change_circulationedge", "land", "circulationedge"], + ["change_geom_circulationedge", "land", "circulationedge"], + ["delete_circulationedge", "land", "circulationedge"], + ["export_circulationedge", "land", "circulationedge"], ["add_physicaledge", "land", "physicaledge"], ["change_physicaledge", "land", "physicaledge"], ["change_geom_physicaledge", "land", "physicaledge"], @@ -465,6 +488,7 @@ ["read_competenceedge", "land", "competenceedge"], ["read_landedge", "land", "landedge"], ["read_physicaledge", "land", "physicaledge"], + ["read_circulationedge", "land", "circulationedge"], ["read_signagemanagementedge", "land", "signagemanagementedge"], ["read_workmanagementedge", "land", "workmanagementedge"], @@ -557,6 +581,7 @@ ["read_competenceedge", "land", "competenceedge"], ["read_landedge", "land", "landedge"], ["read_physicaledge", "land", "physicaledge"], + ["read_circulationedge", "land", "circulationedge"], ["read_signagemanagementedge", "land", "signagemanagementedge"], ["read_workmanagementedge", "land", "workmanagementedge"], @@ -672,6 +697,7 @@ ["read_competenceedge", "land", "competenceedge"], ["read_landedge", "land", "landedge"], ["read_physicaledge", "land", "physicaledge"], + ["read_circulationedge", "land", "circulationedge"], ["read_signagemanagementedge", "land", "signagemanagementedge"], ["read_workmanagementedge", "land", "workmanagementedge"], diff --git a/geotrek/authent/fixtures/minimal.json b/geotrek/authent/fixtures/minimal.json index a206593997..ebe00d178c 100644 --- a/geotrek/authent/fixtures/minimal.json +++ b/geotrek/authent/fixtures/minimal.json @@ -17,6 +17,7 @@ ["read_competenceedge", "land", "competenceedge"], ["read_landedge", "land", "landedge"], ["read_physicaledge", "land", "physicaledge"], + ["read_circulationedge", "land", "circulationedge"], ["read_signagemanagementedge", "land", "signagemanagementedge"], ["read_workmanagementedge", "land", "workmanagementedge"], diff --git a/geotrek/land/tests/test_views.py b/geotrek/land/tests/test_views.py index ec545f0e34..e3e2eb1785 100644 --- a/geotrek/land/tests/test_views.py +++ b/geotrek/land/tests/test_views.py @@ -158,8 +158,7 @@ class CirculationEdgeViewsTest(CommonTest): extra_column_list = ['eid'] expected_column_list_extra = ['id', 'circulation_type', 'authorization_type', 'eid'] expected_column_formatlist_extra = ['id', 'eid'] - expected_json_geom = {'coordinates': [[3.0013501, 46.5008686], - [3.0000461, 46.4999682]], + expected_json_geom = {'coordinates': [[3.0, 46.5], [3.001304, 46.5009004]], 'type': 'LineString'} def get_expected_geojson_geom(self): diff --git a/geotrek/land/views.py b/geotrek/land/views.py index 75774885ef..c12103828c 100644 --- a/geotrek/land/views.py +++ b/geotrek/land/views.py @@ -131,14 +131,14 @@ def get_queryset(self): class CirculationEdgeList(CustomColumnsMixin, MapEntityList): queryset = CirculationEdge.objects.existing() filterform = CirculationEdgeFilterSet - mandatory_columns = ['id', 'circulation_type'] + mandatory_columns = ['id', 'circulation_type', 'authorization_type'] default_extra_columns = ['length', 'length_2d'] class CirculationEdgeFormatList(MapEntityFormat, CirculationEdgeList): mandatory_columns = ['id'] default_extra_columns = [ - 'circulation_type', 'authorized', 'date_insert', 'date_update', + 'circulation_type', 'authorization_type', 'date_insert', 'date_update', 'cities', 'districts', 'areas', 'uuid', 'length_2d' ] + AltimetryMixin.COLUMNS From 30573fa8c77692258f444fe4bcafa412dcc26ef5 Mon Sep 17 00:00:00 2001 From: Idrissa Djepa Creutz Date: Tue, 26 Sep 2023 17:08:38 +0200 Subject: [PATCH 12/19] Rewrite migrations history --- ...ontype_circulationedge_circulationtype.py} | 21 ++++++++-- .../0012_alter_circulationedge_authorized.py | 18 --------- .../0013_alter_circulationedge_eid.py | 19 ---------- .../migrations/0014_auto_20230831_0751.py | 38 ------------------- 4 files changed, 17 insertions(+), 79 deletions(-) rename geotrek/land/migrations/{0011_circulationedge_circulationtype.py => 0011_authorizationtype_circulationedge_circulationtype.py} (65%) delete mode 100644 geotrek/land/migrations/0012_alter_circulationedge_authorized.py delete mode 100644 geotrek/land/migrations/0013_alter_circulationedge_eid.py delete mode 100644 geotrek/land/migrations/0014_auto_20230831_0751.py diff --git a/geotrek/land/migrations/0011_circulationedge_circulationtype.py b/geotrek/land/migrations/0011_authorizationtype_circulationedge_circulationtype.py similarity index 65% rename from geotrek/land/migrations/0011_circulationedge_circulationtype.py rename to geotrek/land/migrations/0011_authorizationtype_circulationedge_circulationtype.py index 7365de2af8..0d5d973db9 100644 --- a/geotrek/land/migrations/0011_circulationedge_circulationtype.py +++ b/geotrek/land/migrations/0011_authorizationtype_circulationedge_circulationtype.py @@ -1,4 +1,4 @@ -# Generated by Django 3.2.18 on 2023-08-18 09:30 +# Generated by Django 3.2.20 on 2023-09-26 14:56 from django.db import migrations, models import django.db.models.deletion @@ -8,12 +8,25 @@ class Migration(migrations.Migration): dependencies = [ - ('authent', '0011_alter_userprofile_structure'), ('core', '0036_auto_20230503_0837'), + ('authent', '0011_alter_userprofile_structure'), ('land', '0010_auto_20230503_0837'), ] operations = [ + migrations.CreateModel( + name='AuthorizationType', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=128, verbose_name='Name')), + ('structure', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='authent.structure', verbose_name='Related structure')), + ], + options={ + 'verbose_name': 'Authorization type', + 'verbose_name_plural': 'Authorization types', + 'ordering': ['name'], + }, + ), migrations.CreateModel( name='CirculationType', fields=[ @@ -31,8 +44,8 @@ class Migration(migrations.Migration): name='CirculationEdge', fields=[ ('topo_object', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='core.topology')), - ('authorized', models.BooleanField(default=False, verbose_name='Authorized')), - ('eid', models.CharField(blank=True, max_length=1024, null=True, verbose_name='External id')), + ('eid', models.CharField(blank=True, max_length=1024, verbose_name='External id')), + ('authorization_type', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='land.authorizationtype', verbose_name='Authorization type')), ('circulation_type', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='land.circulationtype', verbose_name='Circulation type')), ], options={ diff --git a/geotrek/land/migrations/0012_alter_circulationedge_authorized.py b/geotrek/land/migrations/0012_alter_circulationedge_authorized.py deleted file mode 100644 index 1bf47a4bea..0000000000 --- a/geotrek/land/migrations/0012_alter_circulationedge_authorized.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 3.2.20 on 2023-08-29 08:39 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('land', '0011_circulationedge_circulationtype'), - ] - - operations = [ - migrations.AlterField( - model_name='circulationedge', - name='authorized', - field=models.BooleanField(null=True, verbose_name='Authorized'), - ), - ] diff --git a/geotrek/land/migrations/0013_alter_circulationedge_eid.py b/geotrek/land/migrations/0013_alter_circulationedge_eid.py deleted file mode 100644 index 67a1350911..0000000000 --- a/geotrek/land/migrations/0013_alter_circulationedge_eid.py +++ /dev/null @@ -1,19 +0,0 @@ -# Generated by Django 3.2.20 on 2023-08-29 08:46 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('land', '0012_alter_circulationedge_authorized'), - ] - - operations = [ - migrations.AlterField( - model_name='circulationedge', - name='eid', - field=models.CharField(blank=True, default=5, max_length=1024, verbose_name='External id'), - preserve_default=False, - ), - ] diff --git a/geotrek/land/migrations/0014_auto_20230831_0751.py b/geotrek/land/migrations/0014_auto_20230831_0751.py deleted file mode 100644 index baf94ad5d4..0000000000 --- a/geotrek/land/migrations/0014_auto_20230831_0751.py +++ /dev/null @@ -1,38 +0,0 @@ -# Generated by Django 3.2.20 on 2023-08-31 07:51 - -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - dependencies = [ - ('authent', '0011_alter_userprofile_structure'), - ('land', '0013_alter_circulationedge_eid'), - ] - - operations = [ - migrations.RemoveField( - model_name='circulationedge', - name='authorized', - ), - migrations.CreateModel( - name='AuthorizationType', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(max_length=128, verbose_name='Name')), - ('structure', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='authent.structure', verbose_name='Related structure')), - ], - options={ - 'verbose_name': 'Authorization type', - 'verbose_name_plural': 'Authorization types', - 'ordering': ['name'], - }, - ), - migrations.AddField( - model_name='circulationedge', - name='authorization_type', - field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.PROTECT, to='land.authorizationtype', verbose_name='Authorization type'), - preserve_default=False, - ), - ] From 3228f32d57bc4e8639bdb936333d82e12cde1f40 Mon Sep 17 00:00:00 2001 From: Idrissa Djepa Creutz Date: Sun, 1 Oct 2023 15:11:15 +0200 Subject: [PATCH 13/19] Add fixtures for circulation and authorization types --- debian/postinst | 1 + docker/load_data.sh | 1 + docs/changelog.rst | 2 +- docs/install/advanced-configuration.rst | 14 +++++-- geotrek/land/fixtures/basic.json | 49 ------------------------ geotrek/land/fixtures/circulations.json | 51 +++++++++++++++++++++++++ 6 files changed, 65 insertions(+), 53 deletions(-) create mode 100644 geotrek/land/fixtures/circulations.json diff --git a/debian/postinst b/debian/postinst index 3adffb1e36..df5221b18f 100644 --- a/debian/postinst +++ b/debian/postinst @@ -118,6 +118,7 @@ if [ "$MANAGE_DB" = "true" ] && [ -z "$2" ]; then geotrek loaddata -v0 cirkwi || true geotrek loaddata -v0 basic || true geotrek loaddata -v0 licenses || true + geotrek loaddata -v0 circulations || true for dir in `ls -d /opt/geotrek-admin/lib/python3*/site-packages/geotrek/*/fixtures/upload`; do cd $dir > /dev/null cp -r * /opt/geotrek-admin/var/media/upload/ diff --git a/docker/load_data.sh b/docker/load_data.sh index 5c8e1b786b..4b150ae36f 100755 --- a/docker/load_data.sh +++ b/docker/load_data.sh @@ -8,6 +8,7 @@ cd /opt/geotrek-admin ./manage.py loaddata cirkwi ./manage.py loaddata basic ./manage.py loaddata licenses +./manage.py loaddata circulations # copy media files for fixtures for dir in `find geotrek/ -type d -name upload`; do pushd `dirname $$dir` > /dev/null && cp -R $dir/* /opt/geotrek-admin/var/media/upload/ && popd > /dev/null; done diff --git a/docs/changelog.rst b/docs/changelog.rst index 22a48e3e76..ea0745d297 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -7,7 +7,7 @@ CHANGELOG **New features** -- Add CirculationEdge model, which allows to create a traffic circulation plan on paths. Created on the model of LandEdge and PhysicalEdge (#3578) +-Land: Add ``CirculationEdge`` model to manage circulation types and authorization types in the land module (#3578) **Improvements** diff --git a/docs/install/advanced-configuration.rst b/docs/install/advanced-configuration.rst index 7f65ee42e8..3294f8921b 100644 --- a/docs/install/advanced-configuration.rst +++ b/docs/install/advanced-configuration.rst @@ -620,6 +620,16 @@ You can insert licenses of attachments with this command : sudo geotrek loaddata /opt/geotrek-admin/lib/python*/site-packages/geotrek/common/fixtures/licenses.json +Land +~~~~~~~ + +You can insert circulation and authorization types with this command : + +:: + + sudo geotrek loaddata /opt/geotrek-admin/lib/python*/site-packages/geotrek/land/fixtures/circulations.json + + Outdoor ~~~~~~~ @@ -1019,7 +1029,6 @@ A (nearly?) exhaustive list of attributes available for display and export as co "date_update", "length_2d", "date_insert", - "authorized", "uuid", ] COLUMNS_LISTS["physicaledge_view"] = [ @@ -1428,7 +1437,7 @@ A (nearly?) exhaustive list of attributes available for display and export as co COLUMNS_LISTS["circulationedge_export"] = [ "eid", "circulation_type", - "authorized", + "authorization_type", "date_insert", "date_update", "cities", @@ -2211,7 +2220,6 @@ An exhaustive list of form fields hideable in each module. "origin" ], HIDDEN_FORM_FIELDS["circulationedge"] = [ - "authorized", ] diff --git a/geotrek/land/fixtures/basic.json b/geotrek/land/fixtures/basic.json index 5f32573c0f..f1a0ce3f9a 100644 --- a/geotrek/land/fixtures/basic.json +++ b/geotrek/land/fixtures/basic.json @@ -135,54 +135,5 @@ "right_of_way": false, "name": "Servitude DFCI" } - }, - { - "pk": 1, - "model": "land.circulationtype", - "fields": { - "name": "Pédestre" - } - }, - { - "pk": 2, - "model": "land.circulationtype", - "fields": { - "name": "Cycliste" - } - }, - { - "pk": 3, - "model": "land.circulationtype", - "fields": { - "name": "Motorisée" - } - }, - { - "pk": 4, - "model": "land.circulationtype", - "fields": { - "name": "Équestre" - } - }, - { - "pk": 1, - "model": "land.authorizationtype", - "fields": { - "name": "Autorisée" - } - }, - { - "pk": 2, - "model": "land.authorizationtype", - "fields": { - "name": "Interdite" - } - }, - { - "pk": 3, - "model": "land.authorizationtype", - "fields": { - "name": "Réglementée" - } } ] \ No newline at end of file diff --git a/geotrek/land/fixtures/circulations.json b/geotrek/land/fixtures/circulations.json new file mode 100644 index 0000000000..4169aa73f2 --- /dev/null +++ b/geotrek/land/fixtures/circulations.json @@ -0,0 +1,51 @@ +[ + { + "pk": 1, + "model": "land.circulationtype", + "fields": { + "name": "Pédestre" + } + }, + { + "pk": 2, + "model": "land.circulationtype", + "fields": { + "name": "Cycliste" + } + }, + { + "pk": 3, + "model": "land.circulationtype", + "fields": { + "name": "Motorisée" + } + }, + { + "pk": 4, + "model": "land.circulationtype", + "fields": { + "name": "Équestre" + } + }, + { + "pk": 1, + "model": "land.authorizationtype", + "fields": { + "name": "Autorisée" + } + }, + { + "pk": 2, + "model": "land.authorizationtype", + "fields": { + "name": "Interdite" + } + }, + { + "pk": 3, + "model": "land.authorizationtype", + "fields": { + "name": "Réglementée" + } + } +] From 5796344e465b6bb0ef3e1e9a712a235b29ffad7a Mon Sep 17 00:00:00 2001 From: Idrissa Djepa Creutz <73114156+IdrissaD@users.noreply.github.com> Date: Sun, 8 Oct 2023 20:11:44 +0200 Subject: [PATCH 14/19] Update advanced-configuration.rst --- docs/install/advanced-configuration.rst | 610 ++++++++++++++++++++++++ 1 file changed, 610 insertions(+) diff --git a/docs/install/advanced-configuration.rst b/docs/install/advanced-configuration.rst index 3294f8921b..2631060dd4 100644 --- a/docs/install/advanced-configuration.rst +++ b/docs/install/advanced-configuration.rst @@ -974,6 +974,616 @@ Custom columns available A (nearly?) exhaustive list of attributes available for display and export as columns in each module. +:: + + LEAFLET_CONFIG['TILES'] = [ + ('Scan', '//wxs.ign.fr//wmts?LAYER=GEOGRAPHICALGRIDSYSTEMS.MAPS.SCAN-EXPRESS.STANDARD&EXCEPTIONS=image/jpeg&FORMAT=image/jpeg&SERVICE=WMTS&VERSION=1.0.0&REQUEST=GetTile&STYLE=normal&TILEMATRIXSET=PM&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}', + '© IGN - GeoPortail'), + ('Ortho', '//wxs.ign.fr//wmts?LAYER=ORTHOIMAGERY.ORTHOPHOTOS&EXCEPTIONS=image/jpeg&FORMAT=image/jpeg&SERVICE=WMTS&VERSION=1.0.0&REQUEST=GetTile&STYLE=normal&TILEMATRIXSET=PM&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}', + '© IGN - GeoPortail'), + ('Cadastre', '//wxs.ign.fr//wmts?LAYER=CADASTRALPARCELS.PARCELS&EXCEPTIONS=image/jpeg&FORMAT=image/png&SERVICE=WMTS&VERSION=1.0.0&REQUEST=GetTile&STYLE=normal&TILEMATRIXSET=PM&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}', + '© IGN - GeoPortail'), + ('OSM', 'http://{s}.tile.osm.org/{z}/{x}/{y}.png', '© OSM contributors'), + ] + + LEAFLET_CONFIG['OVERLAYS'] = [ + ('Cadastre', + '//wxs.ign.fr//wmts?LAYER=CADASTRALPARCELS.PARCELS&EXCEPTIONS=text/xml&FORMAT=image/png&SERVICE=WMTS&VERSION=1.0.0&REQUEST=GetTile&STYLE=bdparcellaire_o&TILEMATRIXSET=PM&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}', + '© IGN - GeoPortail'), + ] + +Configuration of the tiles. + + *If you want to change it,* + *Change the array like that:* + + :: + + LEAFLET_CONFIG['TILES'] = [('NAME_OF_TILE', 'URL', 'COPYRIGHT'), ...] + + *It's the same for the overlay but use only transparent tiles.* + +| + +:: + + LEAFLET_CONFIG['MAX_ZOOM'] = 19 + +You can define the max_zoom the user can zoom for all tiles. + + *It can be interesting when your tiles can't go to a zoom. For example OpenTopoMap is 17.* + +**Enable Apps** + +:: + + FLATPAGES_ENABLED = True + +Show Flatpages on menu or not. Flatpages are used in Geotrek-rando. + +| + +:: + + TOURISM_ENABLED = True + +Show TouristicContents and TouristicEvents on menu or not. + +| + +:: + + TRAIL_MODEL_ENABLED = True + +Show Trails on menu or not. + +| + +:: + + LANDEDGE_MODEL_ENABLED = True + +Show land on menu or not. + +| + +:: + + LAND_BBOX_CITIES_ENABLED = True + LAND_BBOX_DISTRICTS_ENABLED = True + LAND_BBOX_AREAS_ENABLED = False + +Show filter bbox by zoning. + +.. image:: /images/options/zoning_bboxs.png + + +| + +:: + + ACCESSIBILITY_ATTACHMENTS_ENABLED = True + +Show or not the accessibility menu for attachments + +**Translations** + +:: + + LANGUAGE_CODE = 'fr' + +Language of your interface. + +**Geographical CRUD** + +:: + + PATH_SNAPPING_DISTANCE = 2.0 + +Minimum distance to merge 2 paths in unit of SRID + + *Change the distance. Better to keep it like this. Not used when ``TREKKING_TOPOLOGY_ENABLED = True``.* + +:: + + SNAP_DISTANCE = 30 + +Distance of snapping for the cursor in pixels on Leaflet map. + + +:: + + PATH_MERGE_SNAPPING_DISTANCE = 2 + +Minimum distance to merge 2 paths. + + *Change the distance. Should be higher or the same as PATH_SNAPPING_DISTANCE* + + *Used when TREKKING_TOPOLOGY_ENABLED = True* + +:: + + MAPENTITY_CONFIG['MAP_STYLES'] = { + 'path': {'weight': 2, 'opacity': 1.0, 'color': '#FF4800'}, + 'draftpath': {'weight': 5, 'opacity': 1, 'color': 'yellow', 'dashArray': '8, 8'}, + 'city': {'weight': 4, 'color': 'orange', 'opacity': 0.3, 'fillOpacity': 0.0}, + 'district': {'weight': 6, 'color': 'orange', 'opacity': 0.3, 'fillOpacity': 0.0, 'dashArray': '12, 12'}, + 'restrictedarea': {'weight': 2, 'color': 'red', 'opacity': 0.5, 'fillOpacity': 0.5}, + 'land': {'weight': 4, 'color': 'red', 'opacity': 1.0}, + 'physical': {'weight': 6, 'color': 'red', 'opacity': 1.0}, + 'competence': {'weight': 4, 'color': 'red', 'opacity': 1.0}, + 'workmanagement': {'weight': 4, 'color': 'red', 'opacity': 1.0}, + 'signagemanagement': {'weight': 5, 'color': 'red', 'opacity': 1.0}, + 'print': {'path': {'weight': 1}, + 'trek': {'color': '#FF3300', 'weight': 7, 'opacity': 0.5, + 'arrowColor': 'black', 'arrowSize': 10},} + } + +Color of the different layers on the map + + *To change any map_style do as following:* + + :: + + MAPENTITY_CONFIG['MAP_STYLES']['path'] = {'weigth': 2, 'opacity': 2.0, 'color': 'yellow'}* + MAPENTITY_CONFIG['MAP_STYLES']['city']['opacity'] = 0.8* + + *For color: use color picker for example* + +| + +:: + + COLORS_POOL = {'land': ['#f37e79', '#7998f3', '#bbf379', '#f379df', '#f3bf79', '#9c79f3', '#7af379'], + 'physical': ['#f3799d', '#79c1f3', '#e4f379', '#de79f3', '#79f3ba', '#f39779', '#797ff3'], + 'circulation': ['#f3799d', '#79c1f3', '#e4f379', '#de79f3', '#79f3ba', '#f39779', '#797ff3'], + 'competence': ['#a2f379', '#f379c6', '#79e9f3', '#f3d979', '#b579f3', '#79f392', '#f37984'], + 'signagemanagement': ['#79a8f3', '#cbf379', '#f379ee', '#79f3e3', '#79f3d3'], + 'workmanagement': ['#79a8f3', '#cbf379', '#f379ee', '#79f3e3', '#79f3d3'], + 'restrictedarea': ['plum', 'violet', 'deeppink', 'orchid', + 'darkviolet', 'lightcoral', 'palevioletred', + 'MediumVioletRed', 'MediumOrchid', 'Magenta', + 'LightSalmon', 'HotPink', 'Fuchsia']} + +Color of the different layers on the top right for landing. + + * For land, physical, competence, signagemanagement, workmanagement should have 5 values. + * For restricted Area: add as many color as your number of restricted area type + + *To change any map_style do as following :* + + :: + + COLORS_POOL['restrictedarea'] = ['plum', 'violet', 'yellow', 'red', '#79a8f3'] + MAPENTITY_CONFIG['MAP_STYLES']['city']['opacity'] = 0.8* + + *For color: use color picker for example* + +| + +:: + + TREK_POINTS_OF_REFERENCE_ENABLED = True + +Points of reference are enabled on form of treks. + +| + +:: + + OUTDOOR_COURSE_POINTS_OF_REFERENCE_ENABLED = True + +Points of reference are enabled on form of otudoor courses. + +| + +:: + + TOPOLOGY_STATIC_OFFSETS = {'land': -5, 'physical': 0, 'competence': 5, 'signagemanagement': -10, 'workmanagement': 10} + +Land objects are added on other objects (path for example) with offset, avoiding overlay. + + *You should not change it to avoid overlay except if you want to have more overlay.* + *You can do for example for :* + + :: + + TOPOLOGY_STATIC_OFFSETS = {'land': -7, 'physical': 0, 'competence': 7, 'signagemanagement': -14, 'workmanagement': 14} + +| + +:: + + ALTIMETRIC_PROFILE_PRECISION = 25 # Sampling precision in meters + ALTIMETRIC_PROFILE_AVERAGE = 2 # nb of points for altimetry moving average + ALTIMETRIC_PROFILE_STEP = 1 # Step min precision for positive / negative altimetry gain + ALTIMETRIC_PROFILE_BACKGROUND = 'white' + ALTIMETRIC_PROFILE_COLOR = '#F77E00' + ALTIMETRIC_PROFILE_HEIGHT = 400 + ALTIMETRIC_PROFILE_WIDTH = 800 + ALTIMETRIC_PROFILE_FONTSIZE = 25 + ALTIMETRIC_PROFILE_FONT = 'ubuntu' + ALTIMETRIC_PROFILE_MIN_YSCALE = 1200 # Minimum y scale (in meters) + ALTIMETRIC_AREA_MAX_RESOLUTION = 150 # Maximum number of points (by width/height) + ALTIMETRIC_AREA_MARGIN = 0.15 + +All settings used to generate altimetric profile. + + *All these settings can be modified but you need to check the result every time* + + *The only one modified most of the time is ALTIMETRIC_PROFILE_COLOR* + +**Signage and Blade** + +``BLADE_ENABLED`` and ``LINE_ENABLED`` settings (default to ``True``) allow to enable or disable blades and lines submodules. + +``DIRECTION_ON_LINES_ENABLED`` setting (default to ``False``) allow to have the `direction` field on lines instead of blades. + +:: + + BLADE_CODE_TYPE = int + +Type of the blade code (str or int) + + *It can be str or int.* + + *If you have an integer code : int* + + *If you have an string code : str* + +| + +:: + + BLADE_CODE_FORMAT = "{signagecode}-{bladenumber}" + +Correspond to the format of blades. Show N3-1 for the blade 1 of the signage N3. + + *If you want to change : move information under bracket* + + *You can also remove one element between bracket* + + *You can do for exemple :* + *"CD99.{signagecode}.{bladenumber}"* + + *It will display : CD99.XIDNZEIU.01 (first blade of XIDNZEIU)* + + * *signagecode is the code of the signage* + * *bladenumber is the number of the blade* + +| + +:: + + LINE_CODE_FORMAT = "{signagecode}-{bladenumber}-{linenumber}" + +Correspond to the format used in export of lines. Used in csv of signage. + + *Similar with above* + *You can do for example :* + *"CD99.{signagecode}-{bladenumber}.{linenumber}"* + + *It will display : CD99.XIDNZEIU-01.02 (second line of the first blade of XIDNZEIU)* + + * *signagecode is the code of the signage* + * *bladenumber is the number of the blade* + * *linenumber is the number of the line* + + +**Screenshots** + +:: + + SHOW_SENSITIVE_AREAS_ON_MAP_SCREENSHOT = True + SHOW_POIS_ON_MAP_SCREENSHOT = True + SHOW_SERVICES_ON_MAP_SCREENSHOT = True + SHOW_SIGNAGES_ON_MAP_SCREENSHOT = True + SHOW_INFRASTRUCTURES_ON_MAP_SCREENSHOT = True + +Show objects on maps of PDF + +| + +:: + + MAP_CAPTURE_SIZE = 800 + +Size in pixels of the capture. + + *Be careful with your pdfs.* + *If you change this value, pdfs will be rendered differently* + + +**Synchro Geotrek-rando** + +:: + + SYNC_RANDO_ROOT = os.path.join(VAR_DIR, 'data') + +Path on your server where the data for Geotrek-rando website will be generated + + *If you want to modify it, do not forget to import os at the top of the file.* + *Check* `import Python `_ *, if you need any information* + +:: + + THUMBNAIL_COPYRIGHT_FORMAT = "" + +Add a thumbnail on every picture for Geotrek-rando + + + *Example :* + + *"{title}-:-{author}-:-{legend}"* + + *Will display title of the picture, author* + *and the legend :* + *Puy de Dômes-:-Paul Paul-:-Beautiful sunrise on Puy de Dômes"* + +| + +:: + + THUMBNAIL_COPYRIGHT_SIZE = 15 + +Size of the thumbnail. + +| + +:: + + TOURISM_INTERSECTION_MARGIN = 500 + +Distance to which tourist contents, tourist events, treks, pois, services will be displayed + + *This distance can be changed by practice for treks in the admin.* + +| + +:: + + DIVING_INTERSECTION_MARGIN = 500 + +Distance to which dives will be displayed. + +| + +:: + + TREK_EXPORT_POI_LIST_LIMIT = 14 + +Limit of the number of pois on treks pdf. + + *14 is already a huge amount of POI, but it's possible to add more* + +| + +:: + + TREK_EXPORT_INFORMATION_DESK_LIST_LIMIT = 2 + +Limit of the number of information desks on treks pdf. + + *You can put -1 if you want all the information desks* + +| + +:: + + SPLIT_TREKS_CATEGORIES_BY_PRACTICE = False + +On the Geotrek-rando v2 website, treks practices will be displayed separately + + *Field order for each practices in admin will be take in account* + +| + +:: + + SPLIT_TREKS_CATEGORIES_BY_ACCESSIBILITY = False + +On the Geotrek-rando v2 website, accessibilites will be displayed separately + +| + +:: + + SPLIT_TREKS_CATEGORIES_BY_ITINERANCY = False + +On the Geotrek-rando v2 website, if a trek has a children it will be displayed separately + +| + +:: + + SPLIT_DIVES_CATEGORIES_BY_PRACTICE = True + +On the Geotrek-rando v2 website, dives practices will be displayed separately + +| + +:: + + HIDE_PUBLISHED_TREKS_IN_TOPOLOGIES = False + +On the Geotrek-rando v2 website, treks near other are hidden + +| + +:: + + SYNC_RANDO_OPTIONS = {} + +Options of the sync_rando command in Geotrek-admin interface. + +| + +:: + + TREK_WITH_POIS_PICTURES = False + +It enables correlated pictures on Gotrek-rando v2 to be displayed in the slideshow + +| + +:: + + PRIMARY_COLOR = "#7b8c12" + +Primary color of your PDF + *check : "color picker"* + +| + +:: + + ONLY_EXTERNAL_PUBLIC_PDF = False + +On Geotrek-rando v2 website, only PDF imported with filetype "Topoguide" +will be used and not autogenerated. + +| + +:: + + TREK_CATEGORY_ORDER = 1 + ITINERANCY_CATEGORY_ORDER = 2 + DIVE_CATEGORY_ORDER = 10 + TOURISTIC_EVENT_CATEGORY_ORDER = 99 + +Order of all the objects without practices on Geotrek-rando website + + *All the settings about order are the order inside Geotrek-rando website.* + + *Practices of diving, treks and categories of touristic contents are taken in account* + +| + +**Synchro Geotrek-mobile** + +:: + + SYNC_MOBILE_ROOT = os.path.join(VAR_DIR, 'mobile') + +Path on your server where the datas for mobile will be saved + + *If you want to modify it, do not forget to import os at the top of the file.* + *Check* `import Python `_ *, if you need any information* + +| + +:: + + SYNC_MOBILE_OPTIONS = {'skip_tiles': False} + +Options of the sync_mobile command + +| + +:: + + MOBILE_NUMBER_PICTURES_SYNC = 3 + +Number max of pictures that will be displayed and synchronized for each object (trek, poi, etc.) in the mobile app. + +| + +:: + + MOBILE_TILES_URL = ['https://{s}.tile.opentopomap.org/{z}/{x}/{y}.png'] + +URL's Tiles used for the mobile. + + *Change for IGN:* + + :: + + MOBILE_TILES_URL = ['https://{s}.tile.opentopomap.org/{z}/{x}/{y}.png'] + +| + +:: + + MOBILE_LENGTH_INTERVALS = [ + {"id": 1, "name": "< 10 km", "interval": [0, 9999]}, + {"id": 2, "name": "10 - 30", "interval": [9999, 29999]}, + {"id": 3, "name": "30 - 50", "interval": [30000, 50000]}, + {"id": 4, "name": "> 50 km", "interval": [50000, 999999]} + ] + +Intervals of the mobile for the length filter + + *Interval key is in meters.* + *You can add new intervals* + + :: + + MOBILE_LENGTH_INTERVALS = [ + {"id": 1, "name": "< 10 km", "interval": [0, 9999]}, + {"id": 2, "name": "10 - 30 km", "interval": [9999, 29999]}, + {"id": 3, "name": "30 - 50 km", "interval": [30000, 50000]}, + {"id": 4, "name": "50 - 80 km", "interval": [50000, 80000]} + {"id": 5, "name": "> 80 km", "interval": [80000, 999999]} + ] + +| + +:: + + MOBILE_ASCENT_INTERVALS = [ + {"id": 1, "name": "< 300 m", "interval": [0, 299]}, + {"id": 2, "name": "300 - 600", "interval": [300, 599]}, + {"id": 3, "name": "600 - 1000", "interval": [600, 999]}, + {"id": 4, "name": "> 1000 m", "interval": [1000, 9999]} + ] + +Intervals of the mobile for the ascent filter + + *Do the same as above* + +:: + + MOBILE_DURATION_INTERVALS = [ + {"id": 1, "name": "< 1 heure", "interval": [0, 1]}, + {"id": 2, "name": "1h - 2h30", "interval": [1, 2.5]}, + {"id": 3, "name": "2h30 - 5h", "interval": [2.5, 5]}, + {"id": 4, "name": "5h - 9h", "interval": [5, 9]}, + {"id": 5, "name": "> 9h", "interval": [9, 9999999]} + ] + +Intervals of the mobile for the duration filter + + *Check MOBILE_LENGTH_INTERVALS comment to use it, here interval correspond to 1 unit of hour* + +| + +:: + + ENABLED_MOBILE_FILTERS = [ + 'practice', + 'difficulty', + 'durations', + 'ascent', + 'lengths', + 'themes', + 'route', + 'districts', + 'cities', + 'accessibilities', + ] + +List of all the filters enabled on mobile. + + *Remove any of the filters if you don't want one of them. It's useless to add other one.* + + +| + +**Custom columns available** + +A (nearly?) exhaustive list of attributes available for display and export as columns in each module. + + .. code-block :: python COLUMNS_LISTS["path_view"] = [ From e19801948abab0e01f3c2e57df9bab85edc77feb Mon Sep 17 00:00:00 2001 From: Idrissa Djepa Creutz Date: Sun, 8 Oct 2023 22:33:47 +0200 Subject: [PATCH 15/19] Correct test and add circulation layer to Leaflet map --- geotrek/land/tests/test_views.py | 2 +- geotrek/settings/base.py | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/geotrek/land/tests/test_views.py b/geotrek/land/tests/test_views.py index e3e2eb1785..b4665627f4 100644 --- a/geotrek/land/tests/test_views.py +++ b/geotrek/land/tests/test_views.py @@ -158,7 +158,7 @@ class CirculationEdgeViewsTest(CommonTest): extra_column_list = ['eid'] expected_column_list_extra = ['id', 'circulation_type', 'authorization_type', 'eid'] expected_column_formatlist_extra = ['id', 'eid'] - expected_json_geom = {'coordinates': [[3.0, 46.5], [3.001304, 46.5009004]], + expected_json_geom = {'coordinates': [[2.9998617, 46.5000955], [3.0011657, 46.500996]], 'type': 'LineString'} def get_expected_geojson_geom(self): diff --git a/geotrek/settings/base.py b/geotrek/settings/base.py index 2cf2edf24b..14fde455d4 100644 --- a/geotrek/settings/base.py +++ b/geotrek/settings/base.py @@ -400,6 +400,7 @@ def api_bbox(bbox, buffer): 'restrictedarea': {'weight': 2, 'color': 'red', 'opacity': 0.5, 'fillOpacity': 0.5}, 'land': {'weight': 4, 'color': 'red', 'opacity': 1.0}, 'physical': {'weight': 6, 'color': 'red', 'opacity': 1.0}, + 'circulation': {'weight': 6, 'color': 'red', 'opacity': 1.0}, 'competence': {'weight': 4, 'color': 'red', 'opacity': 1.0}, 'workmanagement': {'weight': 4, 'color': 'red', 'opacity': 1.0}, 'signagemanagement': {'weight': 5, 'color': 'red', 'opacity': 1.0}, @@ -593,6 +594,7 @@ def api_bbox(bbox, buffer): # Static offsets in projection units TOPOLOGY_STATIC_OFFSETS = {'land': -5, 'physical': 0, + 'circulation': 15, 'competence': 5, 'signagemanagement': -10, 'workmanagement': 10} From dd14d152f8f5e7b6ba98f9234b90f4c70a8953d7 Mon Sep 17 00:00:00 2001 From: Idrissa Djepa Creutz <73114156+IdrissaD@users.noreply.github.com> Date: Wed, 18 Oct 2023 17:33:39 +0200 Subject: [PATCH 16/19] Update advanced-configuration.rst --- docs/install/advanced-configuration.rst | 610 ------------------------ 1 file changed, 610 deletions(-) diff --git a/docs/install/advanced-configuration.rst b/docs/install/advanced-configuration.rst index 2631060dd4..3294f8921b 100644 --- a/docs/install/advanced-configuration.rst +++ b/docs/install/advanced-configuration.rst @@ -974,616 +974,6 @@ Custom columns available A (nearly?) exhaustive list of attributes available for display and export as columns in each module. -:: - - LEAFLET_CONFIG['TILES'] = [ - ('Scan', '//wxs.ign.fr//wmts?LAYER=GEOGRAPHICALGRIDSYSTEMS.MAPS.SCAN-EXPRESS.STANDARD&EXCEPTIONS=image/jpeg&FORMAT=image/jpeg&SERVICE=WMTS&VERSION=1.0.0&REQUEST=GetTile&STYLE=normal&TILEMATRIXSET=PM&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}', - '© IGN - GeoPortail'), - ('Ortho', '//wxs.ign.fr//wmts?LAYER=ORTHOIMAGERY.ORTHOPHOTOS&EXCEPTIONS=image/jpeg&FORMAT=image/jpeg&SERVICE=WMTS&VERSION=1.0.0&REQUEST=GetTile&STYLE=normal&TILEMATRIXSET=PM&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}', - '© IGN - GeoPortail'), - ('Cadastre', '//wxs.ign.fr//wmts?LAYER=CADASTRALPARCELS.PARCELS&EXCEPTIONS=image/jpeg&FORMAT=image/png&SERVICE=WMTS&VERSION=1.0.0&REQUEST=GetTile&STYLE=normal&TILEMATRIXSET=PM&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}', - '© IGN - GeoPortail'), - ('OSM', 'http://{s}.tile.osm.org/{z}/{x}/{y}.png', '© OSM contributors'), - ] - - LEAFLET_CONFIG['OVERLAYS'] = [ - ('Cadastre', - '//wxs.ign.fr//wmts?LAYER=CADASTRALPARCELS.PARCELS&EXCEPTIONS=text/xml&FORMAT=image/png&SERVICE=WMTS&VERSION=1.0.0&REQUEST=GetTile&STYLE=bdparcellaire_o&TILEMATRIXSET=PM&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}', - '© IGN - GeoPortail'), - ] - -Configuration of the tiles. - - *If you want to change it,* - *Change the array like that:* - - :: - - LEAFLET_CONFIG['TILES'] = [('NAME_OF_TILE', 'URL', 'COPYRIGHT'), ...] - - *It's the same for the overlay but use only transparent tiles.* - -| - -:: - - LEAFLET_CONFIG['MAX_ZOOM'] = 19 - -You can define the max_zoom the user can zoom for all tiles. - - *It can be interesting when your tiles can't go to a zoom. For example OpenTopoMap is 17.* - -**Enable Apps** - -:: - - FLATPAGES_ENABLED = True - -Show Flatpages on menu or not. Flatpages are used in Geotrek-rando. - -| - -:: - - TOURISM_ENABLED = True - -Show TouristicContents and TouristicEvents on menu or not. - -| - -:: - - TRAIL_MODEL_ENABLED = True - -Show Trails on menu or not. - -| - -:: - - LANDEDGE_MODEL_ENABLED = True - -Show land on menu or not. - -| - -:: - - LAND_BBOX_CITIES_ENABLED = True - LAND_BBOX_DISTRICTS_ENABLED = True - LAND_BBOX_AREAS_ENABLED = False - -Show filter bbox by zoning. - -.. image:: /images/options/zoning_bboxs.png - - -| - -:: - - ACCESSIBILITY_ATTACHMENTS_ENABLED = True - -Show or not the accessibility menu for attachments - -**Translations** - -:: - - LANGUAGE_CODE = 'fr' - -Language of your interface. - -**Geographical CRUD** - -:: - - PATH_SNAPPING_DISTANCE = 2.0 - -Minimum distance to merge 2 paths in unit of SRID - - *Change the distance. Better to keep it like this. Not used when ``TREKKING_TOPOLOGY_ENABLED = True``.* - -:: - - SNAP_DISTANCE = 30 - -Distance of snapping for the cursor in pixels on Leaflet map. - - -:: - - PATH_MERGE_SNAPPING_DISTANCE = 2 - -Minimum distance to merge 2 paths. - - *Change the distance. Should be higher or the same as PATH_SNAPPING_DISTANCE* - - *Used when TREKKING_TOPOLOGY_ENABLED = True* - -:: - - MAPENTITY_CONFIG['MAP_STYLES'] = { - 'path': {'weight': 2, 'opacity': 1.0, 'color': '#FF4800'}, - 'draftpath': {'weight': 5, 'opacity': 1, 'color': 'yellow', 'dashArray': '8, 8'}, - 'city': {'weight': 4, 'color': 'orange', 'opacity': 0.3, 'fillOpacity': 0.0}, - 'district': {'weight': 6, 'color': 'orange', 'opacity': 0.3, 'fillOpacity': 0.0, 'dashArray': '12, 12'}, - 'restrictedarea': {'weight': 2, 'color': 'red', 'opacity': 0.5, 'fillOpacity': 0.5}, - 'land': {'weight': 4, 'color': 'red', 'opacity': 1.0}, - 'physical': {'weight': 6, 'color': 'red', 'opacity': 1.0}, - 'competence': {'weight': 4, 'color': 'red', 'opacity': 1.0}, - 'workmanagement': {'weight': 4, 'color': 'red', 'opacity': 1.0}, - 'signagemanagement': {'weight': 5, 'color': 'red', 'opacity': 1.0}, - 'print': {'path': {'weight': 1}, - 'trek': {'color': '#FF3300', 'weight': 7, 'opacity': 0.5, - 'arrowColor': 'black', 'arrowSize': 10},} - } - -Color of the different layers on the map - - *To change any map_style do as following:* - - :: - - MAPENTITY_CONFIG['MAP_STYLES']['path'] = {'weigth': 2, 'opacity': 2.0, 'color': 'yellow'}* - MAPENTITY_CONFIG['MAP_STYLES']['city']['opacity'] = 0.8* - - *For color: use color picker for example* - -| - -:: - - COLORS_POOL = {'land': ['#f37e79', '#7998f3', '#bbf379', '#f379df', '#f3bf79', '#9c79f3', '#7af379'], - 'physical': ['#f3799d', '#79c1f3', '#e4f379', '#de79f3', '#79f3ba', '#f39779', '#797ff3'], - 'circulation': ['#f3799d', '#79c1f3', '#e4f379', '#de79f3', '#79f3ba', '#f39779', '#797ff3'], - 'competence': ['#a2f379', '#f379c6', '#79e9f3', '#f3d979', '#b579f3', '#79f392', '#f37984'], - 'signagemanagement': ['#79a8f3', '#cbf379', '#f379ee', '#79f3e3', '#79f3d3'], - 'workmanagement': ['#79a8f3', '#cbf379', '#f379ee', '#79f3e3', '#79f3d3'], - 'restrictedarea': ['plum', 'violet', 'deeppink', 'orchid', - 'darkviolet', 'lightcoral', 'palevioletred', - 'MediumVioletRed', 'MediumOrchid', 'Magenta', - 'LightSalmon', 'HotPink', 'Fuchsia']} - -Color of the different layers on the top right for landing. - - * For land, physical, competence, signagemanagement, workmanagement should have 5 values. - * For restricted Area: add as many color as your number of restricted area type - - *To change any map_style do as following :* - - :: - - COLORS_POOL['restrictedarea'] = ['plum', 'violet', 'yellow', 'red', '#79a8f3'] - MAPENTITY_CONFIG['MAP_STYLES']['city']['opacity'] = 0.8* - - *For color: use color picker for example* - -| - -:: - - TREK_POINTS_OF_REFERENCE_ENABLED = True - -Points of reference are enabled on form of treks. - -| - -:: - - OUTDOOR_COURSE_POINTS_OF_REFERENCE_ENABLED = True - -Points of reference are enabled on form of otudoor courses. - -| - -:: - - TOPOLOGY_STATIC_OFFSETS = {'land': -5, 'physical': 0, 'competence': 5, 'signagemanagement': -10, 'workmanagement': 10} - -Land objects are added on other objects (path for example) with offset, avoiding overlay. - - *You should not change it to avoid overlay except if you want to have more overlay.* - *You can do for example for :* - - :: - - TOPOLOGY_STATIC_OFFSETS = {'land': -7, 'physical': 0, 'competence': 7, 'signagemanagement': -14, 'workmanagement': 14} - -| - -:: - - ALTIMETRIC_PROFILE_PRECISION = 25 # Sampling precision in meters - ALTIMETRIC_PROFILE_AVERAGE = 2 # nb of points for altimetry moving average - ALTIMETRIC_PROFILE_STEP = 1 # Step min precision for positive / negative altimetry gain - ALTIMETRIC_PROFILE_BACKGROUND = 'white' - ALTIMETRIC_PROFILE_COLOR = '#F77E00' - ALTIMETRIC_PROFILE_HEIGHT = 400 - ALTIMETRIC_PROFILE_WIDTH = 800 - ALTIMETRIC_PROFILE_FONTSIZE = 25 - ALTIMETRIC_PROFILE_FONT = 'ubuntu' - ALTIMETRIC_PROFILE_MIN_YSCALE = 1200 # Minimum y scale (in meters) - ALTIMETRIC_AREA_MAX_RESOLUTION = 150 # Maximum number of points (by width/height) - ALTIMETRIC_AREA_MARGIN = 0.15 - -All settings used to generate altimetric profile. - - *All these settings can be modified but you need to check the result every time* - - *The only one modified most of the time is ALTIMETRIC_PROFILE_COLOR* - -**Signage and Blade** - -``BLADE_ENABLED`` and ``LINE_ENABLED`` settings (default to ``True``) allow to enable or disable blades and lines submodules. - -``DIRECTION_ON_LINES_ENABLED`` setting (default to ``False``) allow to have the `direction` field on lines instead of blades. - -:: - - BLADE_CODE_TYPE = int - -Type of the blade code (str or int) - - *It can be str or int.* - - *If you have an integer code : int* - - *If you have an string code : str* - -| - -:: - - BLADE_CODE_FORMAT = "{signagecode}-{bladenumber}" - -Correspond to the format of blades. Show N3-1 for the blade 1 of the signage N3. - - *If you want to change : move information under bracket* - - *You can also remove one element between bracket* - - *You can do for exemple :* - *"CD99.{signagecode}.{bladenumber}"* - - *It will display : CD99.XIDNZEIU.01 (first blade of XIDNZEIU)* - - * *signagecode is the code of the signage* - * *bladenumber is the number of the blade* - -| - -:: - - LINE_CODE_FORMAT = "{signagecode}-{bladenumber}-{linenumber}" - -Correspond to the format used in export of lines. Used in csv of signage. - - *Similar with above* - *You can do for example :* - *"CD99.{signagecode}-{bladenumber}.{linenumber}"* - - *It will display : CD99.XIDNZEIU-01.02 (second line of the first blade of XIDNZEIU)* - - * *signagecode is the code of the signage* - * *bladenumber is the number of the blade* - * *linenumber is the number of the line* - - -**Screenshots** - -:: - - SHOW_SENSITIVE_AREAS_ON_MAP_SCREENSHOT = True - SHOW_POIS_ON_MAP_SCREENSHOT = True - SHOW_SERVICES_ON_MAP_SCREENSHOT = True - SHOW_SIGNAGES_ON_MAP_SCREENSHOT = True - SHOW_INFRASTRUCTURES_ON_MAP_SCREENSHOT = True - -Show objects on maps of PDF - -| - -:: - - MAP_CAPTURE_SIZE = 800 - -Size in pixels of the capture. - - *Be careful with your pdfs.* - *If you change this value, pdfs will be rendered differently* - - -**Synchro Geotrek-rando** - -:: - - SYNC_RANDO_ROOT = os.path.join(VAR_DIR, 'data') - -Path on your server where the data for Geotrek-rando website will be generated - - *If you want to modify it, do not forget to import os at the top of the file.* - *Check* `import Python `_ *, if you need any information* - -:: - - THUMBNAIL_COPYRIGHT_FORMAT = "" - -Add a thumbnail on every picture for Geotrek-rando - - - *Example :* - - *"{title}-:-{author}-:-{legend}"* - - *Will display title of the picture, author* - *and the legend :* - *Puy de Dômes-:-Paul Paul-:-Beautiful sunrise on Puy de Dômes"* - -| - -:: - - THUMBNAIL_COPYRIGHT_SIZE = 15 - -Size of the thumbnail. - -| - -:: - - TOURISM_INTERSECTION_MARGIN = 500 - -Distance to which tourist contents, tourist events, treks, pois, services will be displayed - - *This distance can be changed by practice for treks in the admin.* - -| - -:: - - DIVING_INTERSECTION_MARGIN = 500 - -Distance to which dives will be displayed. - -| - -:: - - TREK_EXPORT_POI_LIST_LIMIT = 14 - -Limit of the number of pois on treks pdf. - - *14 is already a huge amount of POI, but it's possible to add more* - -| - -:: - - TREK_EXPORT_INFORMATION_DESK_LIST_LIMIT = 2 - -Limit of the number of information desks on treks pdf. - - *You can put -1 if you want all the information desks* - -| - -:: - - SPLIT_TREKS_CATEGORIES_BY_PRACTICE = False - -On the Geotrek-rando v2 website, treks practices will be displayed separately - - *Field order for each practices in admin will be take in account* - -| - -:: - - SPLIT_TREKS_CATEGORIES_BY_ACCESSIBILITY = False - -On the Geotrek-rando v2 website, accessibilites will be displayed separately - -| - -:: - - SPLIT_TREKS_CATEGORIES_BY_ITINERANCY = False - -On the Geotrek-rando v2 website, if a trek has a children it will be displayed separately - -| - -:: - - SPLIT_DIVES_CATEGORIES_BY_PRACTICE = True - -On the Geotrek-rando v2 website, dives practices will be displayed separately - -| - -:: - - HIDE_PUBLISHED_TREKS_IN_TOPOLOGIES = False - -On the Geotrek-rando v2 website, treks near other are hidden - -| - -:: - - SYNC_RANDO_OPTIONS = {} - -Options of the sync_rando command in Geotrek-admin interface. - -| - -:: - - TREK_WITH_POIS_PICTURES = False - -It enables correlated pictures on Gotrek-rando v2 to be displayed in the slideshow - -| - -:: - - PRIMARY_COLOR = "#7b8c12" - -Primary color of your PDF - *check : "color picker"* - -| - -:: - - ONLY_EXTERNAL_PUBLIC_PDF = False - -On Geotrek-rando v2 website, only PDF imported with filetype "Topoguide" -will be used and not autogenerated. - -| - -:: - - TREK_CATEGORY_ORDER = 1 - ITINERANCY_CATEGORY_ORDER = 2 - DIVE_CATEGORY_ORDER = 10 - TOURISTIC_EVENT_CATEGORY_ORDER = 99 - -Order of all the objects without practices on Geotrek-rando website - - *All the settings about order are the order inside Geotrek-rando website.* - - *Practices of diving, treks and categories of touristic contents are taken in account* - -| - -**Synchro Geotrek-mobile** - -:: - - SYNC_MOBILE_ROOT = os.path.join(VAR_DIR, 'mobile') - -Path on your server where the datas for mobile will be saved - - *If you want to modify it, do not forget to import os at the top of the file.* - *Check* `import Python `_ *, if you need any information* - -| - -:: - - SYNC_MOBILE_OPTIONS = {'skip_tiles': False} - -Options of the sync_mobile command - -| - -:: - - MOBILE_NUMBER_PICTURES_SYNC = 3 - -Number max of pictures that will be displayed and synchronized for each object (trek, poi, etc.) in the mobile app. - -| - -:: - - MOBILE_TILES_URL = ['https://{s}.tile.opentopomap.org/{z}/{x}/{y}.png'] - -URL's Tiles used for the mobile. - - *Change for IGN:* - - :: - - MOBILE_TILES_URL = ['https://{s}.tile.opentopomap.org/{z}/{x}/{y}.png'] - -| - -:: - - MOBILE_LENGTH_INTERVALS = [ - {"id": 1, "name": "< 10 km", "interval": [0, 9999]}, - {"id": 2, "name": "10 - 30", "interval": [9999, 29999]}, - {"id": 3, "name": "30 - 50", "interval": [30000, 50000]}, - {"id": 4, "name": "> 50 km", "interval": [50000, 999999]} - ] - -Intervals of the mobile for the length filter - - *Interval key is in meters.* - *You can add new intervals* - - :: - - MOBILE_LENGTH_INTERVALS = [ - {"id": 1, "name": "< 10 km", "interval": [0, 9999]}, - {"id": 2, "name": "10 - 30 km", "interval": [9999, 29999]}, - {"id": 3, "name": "30 - 50 km", "interval": [30000, 50000]}, - {"id": 4, "name": "50 - 80 km", "interval": [50000, 80000]} - {"id": 5, "name": "> 80 km", "interval": [80000, 999999]} - ] - -| - -:: - - MOBILE_ASCENT_INTERVALS = [ - {"id": 1, "name": "< 300 m", "interval": [0, 299]}, - {"id": 2, "name": "300 - 600", "interval": [300, 599]}, - {"id": 3, "name": "600 - 1000", "interval": [600, 999]}, - {"id": 4, "name": "> 1000 m", "interval": [1000, 9999]} - ] - -Intervals of the mobile for the ascent filter - - *Do the same as above* - -:: - - MOBILE_DURATION_INTERVALS = [ - {"id": 1, "name": "< 1 heure", "interval": [0, 1]}, - {"id": 2, "name": "1h - 2h30", "interval": [1, 2.5]}, - {"id": 3, "name": "2h30 - 5h", "interval": [2.5, 5]}, - {"id": 4, "name": "5h - 9h", "interval": [5, 9]}, - {"id": 5, "name": "> 9h", "interval": [9, 9999999]} - ] - -Intervals of the mobile for the duration filter - - *Check MOBILE_LENGTH_INTERVALS comment to use it, here interval correspond to 1 unit of hour* - -| - -:: - - ENABLED_MOBILE_FILTERS = [ - 'practice', - 'difficulty', - 'durations', - 'ascent', - 'lengths', - 'themes', - 'route', - 'districts', - 'cities', - 'accessibilities', - ] - -List of all the filters enabled on mobile. - - *Remove any of the filters if you don't want one of them. It's useless to add other one.* - - -| - -**Custom columns available** - -A (nearly?) exhaustive list of attributes available for display and export as columns in each module. - - .. code-block :: python COLUMNS_LISTS["path_view"] = [ From a492b241f22ba194c34f1975aca9f52e2e3c3189 Mon Sep 17 00:00:00 2001 From: Chatewgne Date: Tue, 28 Nov 2023 17:09:41 +0100 Subject: [PATCH 17/19] =?UTF-8?q?=F0=9F=92=AB=20[IMPR]=20Improve=20SQL=20v?= =?UTF-8?q?iew=20for=20circulations?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../land/templates/land/sql/post_10_views.sql | 2 +- .../templates/land/sql/post_90_defaults.sql | 17 ----------------- 2 files changed, 1 insertion(+), 18 deletions(-) diff --git a/geotrek/land/templates/land/sql/post_10_views.sql b/geotrek/land/templates/land/sql/post_10_views.sql index 679561d4db..786d3a2fdf 100644 --- a/geotrek/land/templates/land/sql/post_10_views.sql +++ b/geotrek/land/templates/land/sql/post_10_views.sql @@ -34,7 +34,7 @@ CREATE VIEW {{ schema_geotrek }}.v_workmanagements AS ( ); CREATE VIEW {{ schema_geotrek }}.v_circulations AS ( - SELECT e.*, b.structure_id, b.name + SELECT e.*, b.structure_id, b.name AS "Type", c.name AS "Authorization" FROM core_topology AS e, land_circulationedge AS f, land_circulationtype AS b, land_authorizationtype as c WHERE f.topo_object_id = e.id AND f.circulation_type_id = b.id AND f.authorization_type_id = c.id AND deleted = FALSE diff --git a/geotrek/land/templates/land/sql/post_90_defaults.sql b/geotrek/land/templates/land/sql/post_90_defaults.sql index ccc9c76de1..d985b0e0ed 100644 --- a/geotrek/land/templates/land/sql/post_90_defaults.sql +++ b/geotrek/land/templates/land/sql/post_90_defaults.sql @@ -68,20 +68,3 @@ ALTER TABLE land_landedge ALTER COLUMN agreement SET DEFAULT False; ------------------------------------- -- label -- structure - - --- Infrastructure ------------------ --- type --- maintenance_difficulty --- usage_difficulty -ALTER TABLE infrastructure_infrastructure ALTER COLUMN accessibility SET DEFAULT ''; --- topo_object --- name -ALTER TABLE infrastructure_infrastructure ALTER COLUMN description SET DEFAULT ''; --- condition --- implantation_year --- eid -ALTER TABLE infrastructure_infrastructure ALTER COLUMN published SET DEFAULT FALSE; --- publication_date --- structure From 79198e8354bc739267aab4339321c84306396140 Mon Sep 17 00:00:00 2001 From: Chatewgne Date: Tue, 28 Nov 2023 17:42:11 +0100 Subject: [PATCH 18/19] =?UTF-8?q?=E2=9C=85=20[TEST]=20Test=20circulation?= =?UTF-8?q?=20edge=20display=20name?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- geotrek/land/tests/test_models.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/geotrek/land/tests/test_models.py b/geotrek/land/tests/test_models.py index 635dc8baa8..1cdf5bca9b 100644 --- a/geotrek/land/tests/test_models.py +++ b/geotrek/land/tests/test_models.py @@ -2,6 +2,7 @@ from geotrek.authent.models import Structure from geotrek.land.models import LandType, PhysicalType, CirculationType, AuthorizationType +from geotrek.land.tests.factories import CirculationEdgeFactory class TestModelLand(TestCase): @@ -40,3 +41,7 @@ def test_authorizationtype_value_default_structure(self): structure = Structure.objects.create(name="Structure_1") pt = AuthorizationType.objects.create(name='AuthorizationType_1', structure=structure) self.assertEqual(str(pt), 'AuthorizationType_1 (Structure_1)') + + def test_circulationedge_display(self): + circulation_edge = CirculationEdgeFactory() + self.assertEqual(circulation_edge.name_display, f'{circulation_edge.circulation_type}') From 81b9a371fee7c5ca37c5c656586151b1451b7ea9 Mon Sep 17 00:00:00 2001 From: Chatewgne Date: Tue, 28 Nov 2023 18:35:51 +0100 Subject: [PATCH 19/19] =?UTF-8?q?=E2=9C=85=20[TEST]=20Test=20circulation?= =?UTF-8?q?=20edge=20filtered=20by=20authorization=20type?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- geotrek/land/tests/test_filters.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/geotrek/land/tests/test_filters.py b/geotrek/land/tests/test_filters.py index ecc0b55084..cb4c974e1a 100644 --- a/geotrek/land/tests/test_filters.py +++ b/geotrek/land/tests/test_filters.py @@ -55,9 +55,12 @@ def test_filter_by_physical_edge(self): def test_filter_by_land_edge(self): self._filter_by_edge(LandEdgeFactory, 'land_type', lambda edge: edge.land_type.pk) - def test_filter_by_circulation_edge(self): + def test_filter_by_circulation_type(self): self._filter_by_edge(CirculationEdgeFactory, 'circulation_type', lambda edge: edge.circulation_type.pk) + def test_filter_by_authorization_type(self): + self._filter_by_edge(CirculationEdgeFactory, 'authorization_type', lambda edge: edge.authorization_type.pk) + def test_filter_by_competence_edge(self): self._filter_by_edge(CompetenceEdgeFactory, 'competence', lambda edge: edge.organization.pk)