diff --git a/django-mapentity b/django-mapentity
new file mode 160000
index 0000000000..07aaa2728d
--- /dev/null
+++ b/django-mapentity
@@ -0,0 +1 @@
+Subproject commit 07aaa2728d578f28c00ae39d9fb875c21e1c6505
diff --git a/docker-compose.yml b/docker-compose.yml
index 79d1c47782..80cd89b9e6 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -16,7 +16,7 @@ x-images:
services:
postgres:
- image: ${POSTGRES_IMAGE:-pgrouting/pgrouting:12-3.0-3.0.0}
+ image: ${POSTGRES_IMAGE:-pgrouting/pgrouting:17-3.5-3.6}
env_file:
- .env
ports:
diff --git a/docker/Dockerfile b/docker/Dockerfile
index d010522240..a8c05c00c2 100644
--- a/docker/Dockerfile
+++ b/docker/Dockerfile
@@ -92,6 +92,7 @@ ENV UV_PYTHON=/opt/venv/bin/python
ENV UV_LINK_MODE=copy
ENV UV_CACHE_DIR=/opt/geotrek-admin/var/cache/
+COPY --chown=geotrek:geotrek django-mapentity/ django-mapentity/
RUN --mount=type=bind,src=./requirements.txt,dst=/requirements.txt \
--mount=type=cache,target=/opt/geotrek-admin/var/cache/,sharing=locked,uid=1001,gid=1001 \
uv pip install -r /requirements.txt
diff --git a/geotrek/altimetry/templates/altimetry/altimetric_profile_fragment.html b/geotrek/altimetry/templates/altimetry/altimetric_profile_fragment.html
index 61d13788dd..b7637bce67 100644
--- a/geotrek/altimetry/templates/altimetry/altimetric_profile_fragment.html
+++ b/geotrek/altimetry/templates/altimetry/altimetric_profile_fragment.html
@@ -10,7 +10,7 @@
});
});
- $(window).on('detailmap:ready', function () {
+ $(window).on('entity:map:detail', function (e) {
$('#altitudegraph').append('');
});
\ No newline at end of file
diff --git a/geotrek/common/static/common/style.css b/geotrek/common/static/common/css/style.css
similarity index 100%
rename from geotrek/common/static/common/style.css
rename to geotrek/common/static/common/css/style.css
diff --git a/geotrek/common/templates/common/attachment_accessibility_list.html b/geotrek/common/templates/common/attachment_accessibility_list.html
index b14ab96a9e..eb804e6071 100644
--- a/geotrek/common/templates/common/attachment_accessibility_list.html
+++ b/geotrek/common/templates/common/attachment_accessibility_list.html
@@ -91,4 +91,5 @@
Geometry:
{% endif %} + diff --git a/geotrek/core/widgets.py b/geotrek/core/widgets.py index 39dec7fe6a..770bc1a11f 100644 --- a/geotrek/core/widgets.py +++ b/geotrek/core/widgets.py @@ -1,51 +1,34 @@ """ - -We distinguish two types of widgets : Geometry and Topology. - -Geometry widgets receive a WKT string, deserialized by GEOS. -Leaflet.Draw is used for edition. - -Topology widgets receive a JSON string, deserialized by Topology.deserialize(). -Geotrek custom code is used for edition. +Widgets de topologie indépendants avec leur propre logique de rendu. +Basés sur BaseGeometryWidget, complètement séparés de MapWidget. """ import json - +from django.core import validators +from django.template.defaultfilters import slugify +from django.contrib.gis.forms.widgets import BaseGeometryWidget from mapentity.widgets import MapWidget from .models import Topology -class SnappedLineStringWidget(MapWidget): - geometry_field_class = "MapEntity.GeometryField.GeometryFieldSnap" - - def serialize(self, value): - geojson = super().serialize(value) - snaplist = [] - if value: - snaplist = [None for c in range(len(value.coords))] - value = {"geom": geojson, "snap": snaplist} - return json.dumps(value) - - def deserialize(self, value): - if isinstance(value, str) and value: - value = json.loads(value) - value = value["geom"] - return super().deserialize(value) - - -class BaseTopologyWidget(MapWidget): - """A widget allowing to create topologies on a map.""" - +class BaseTopologyWidget(BaseGeometryWidget): + """ + Widget de base pour les topologies, complètement indépendant de MapWidget. + Utilise uniquement le template topology_widget_fragment.html. + """ template_name = "core/topology_widget_fragment.html" - geometry_field_class = "MapEntity.GeometryField.TopologyField" + display_raw = False + modifiable = True is_line_topology = False is_point_topology = False def serialize(self, value): + """Sérialise une topologie en JSON.""" return value.serialize() if value else "" def deserialize(self, value): + """Désérialise une valeur en objet Topology.""" if isinstance(value, int): return Topology.objects.get(pk=value) try: @@ -53,31 +36,98 @@ def deserialize(self, value): except ValueError: return None + def _get_topology_attrs(self, name, attrs=None): + """ + Prépare les attributs nécessaires pour le rendu du template de topologie. + Reprend la logique de MapWidget mais pour les topologies. + """ + attrs = attrs or {} + + # Génération des IDs pour les éléments HTML et JavaScript + map_id_css = slugify(attrs.get('id', name)) + map_id = map_id_css.replace('-', '_') + + attrs.update({ + 'id': map_id, + 'id_css': map_id_css, + 'id_map': map_id_css + '_map', + 'modifiable': self.modifiable, + 'is_line_topology': self.is_line_topology, + 'is_point_topology': self.is_point_topology, + 'target_map': attrs.get('target_map', getattr(self, 'target_map', None)), + }) + return attrs + + def get_context(self, name, value, attrs): + """ + Prépare le contexte pour le rendu du template topology_widget_fragment.html. + """ + # Gestion des valeurs vides + value = None if value in validators.EMPTY_VALUES else value + + # Récupération du contexte parent + context = super().get_context(name, value, attrs) + + # Ajout des attributs spécifiques à la topologie + topology_attrs = self._get_topology_attrs(name, attrs) + context.update(topology_attrs) + + # Ajout de la valeur sérialisée pour le template + context['serialized'] = self.serialize(value) + + return context + def render(self, name, value, attrs=None, renderer=None): - """Renders the fields. Parent class calls `serialize()` with the value.""" + """ + Rendu du widget de topologie. + Gère la conversion des valeurs entières en objets Topology. + """ if isinstance(value, int): - value = Topology.objects.get(pk=value) + try: + value = Topology.objects.get(pk=value) + except Topology.DoesNotExist: + value = None + + # Mise à jour des attributs avec les flags de topologie attrs = attrs or {} - attrs.update( - is_line_topology=self.is_line_topology, - is_point_topology=self.is_point_topology, - ) + attrs.update({ + 'is_line_topology': self.is_line_topology, + 'is_point_topology': self.is_point_topology, + }) + return super().render(name, value, attrs, renderer) class LineTopologyWidget(BaseTopologyWidget): - """A widget allowing to select a list of paths.""" is_line_topology = True class PointTopologyWidget(BaseTopologyWidget): - """A widget allowing to point a position with a marker.""" is_point_topology = True -class PointLineTopologyWidget(PointTopologyWidget, LineTopologyWidget): - """A widget allowing to point a position with a marker or a list of paths.""" +class PointLineTopologyWidget(BaseTopologyWidget): + + is_line_topology = True + is_point_topology = True + + +# Garder SnappedLineStringWidget tel quel - pas de modification +class SnappedLineStringWidget(BaseTopologyWidget): + # geometry_field_class = "MapEntity.GeometryField.GeometryFieldSnap" - pass + def serialize(self, value): + geojson = super().serialize(value) + snaplist = [] + if value: + snaplist = [None for c in range(len(value.coords))] + value = {"geom": geojson, "snap": snaplist} + return json.dumps(value) + + def deserialize(self, value): + if isinstance(value, str) and value: + value = json.loads(value) + value = value["geom"] + return super().deserialize(value) \ No newline at end of file diff --git a/geotrek/diving/static/diving/advice.svg b/geotrek/diving/static/diving/img/advice.svg similarity index 100% rename from geotrek/diving/static/diving/advice.svg rename to geotrek/diving/static/diving/img/advice.svg diff --git a/geotrek/diving/static/diving/dive.svg b/geotrek/diving/static/diving/img/dive.svg similarity index 100% rename from geotrek/diving/static/diving/dive.svg rename to geotrek/diving/static/diving/img/dive.svg diff --git a/geotrek/diving/static/diving/js/maplibreDivingMain.js b/geotrek/diving/static/diving/js/maplibreDivingMain.js new file mode 100644 index 0000000000..3d9520308a --- /dev/null +++ b/geotrek/diving/static/diving/js/maplibreDivingMain.js @@ -0,0 +1,26 @@ +window.addEventListener("entity:map", () => { + const map = window.MapEntity.currentMap.map; + const modelname = 'dive'; + const layername = `${modelname}_layer`; + const layerUrl = window.SETTINGS.urls[layername]; + + const nameHTML = tr('Diving'); + const category = tr('Diving'); + const primaryKey = generateUniqueId(); + + const style = window.SETTINGS.map.styles[modelname] ?? window.SETTINGS.map.styles['autres']; + + const objectsLayer = new MaplibreObjectsLayer(null, { + style: style, + modelname: modelname, + readonly: true, + nameHTML: nameHTML, + category: category, + primaryKey: primaryKey, + dataUrl: layerUrl, + isLazy: true + }); + + objectsLayer.initialize(map.getMap()); + objectsLayer.registerLazyLayer(modelname, category, nameHTML, primaryKey, layerUrl); +}); \ No newline at end of file diff --git a/geotrek/diving/static/diving/main.js b/geotrek/diving/static/diving/main.js deleted file mode 100644 index 54bf37cef8..0000000000 --- a/geotrek/diving/static/diving/main.js +++ /dev/null @@ -1,28 +0,0 @@ -$(window).on('entity:map', function (e, data) { - var modelname = 'dive'; - var layername = `${modelname}_layer`; - var url = window.SETTINGS.urls[layername]; - var loaded_dive = false; - var map = data.map; - var style = L.Util.extend({ clickable: false }, - window.SETTINGS.map.styles[modelname] || {}); - // Show dive layer in application maps - var layer = new L.ObjectsLayer(null, { - modelname: modelname, - style: style, - }); - - if (data.modelname != modelname){ - map.layerscontrol.addOverlay(layer, tr('Diving'), tr('Diving')); - }; - - map.on('layeradd', function (e) { - var options = e.layer.options || { 'modelname': 'None' }; - if (! loaded_dive) { - if (options.modelname == modelname && options.modelname != data.modelname) { - e.layer.load(url); - loaded_dive = true; - } - } - }); -}); diff --git a/geotrek/diving/templates/diving/diving_extrabody_fragment.html b/geotrek/diving/templates/diving/diving_extrabody_fragment.html index fd184fabf8..3ea53301a9 100644 --- a/geotrek/diving/templates/diving/diving_extrabody_fragment.html +++ b/geotrek/diving/templates/diving/diving_extrabody_fragment.html @@ -1,6 +1,7 @@ {% load static i18n %} diff --git a/geotrek/diving/templates/diving/diving_extrajs_fragment.html b/geotrek/diving/templates/diving/diving_extrajs_fragment.html index 518c396397..2f7134e99c 100644 --- a/geotrek/diving/templates/diving/diving_extrajs_fragment.html +++ b/geotrek/diving/templates/diving/diving_extrajs_fragment.html @@ -1,3 +1,3 @@ {% load static %} - + diff --git a/geotrek/feedback/static/feedback/style.css b/geotrek/feedback/static/feedback/css/style.css similarity index 100% rename from geotrek/feedback/static/feedback/style.css rename to geotrek/feedback/static/feedback/css/style.css diff --git a/geotrek/feedback/static/feedback/js/maplibreFeedbackMain.js b/geotrek/feedback/static/feedback/js/maplibreFeedbackMain.js new file mode 100644 index 0000000000..eda3209f43 --- /dev/null +++ b/geotrek/feedback/static/feedback/js/maplibreFeedbackMain.js @@ -0,0 +1,29 @@ +// +// Feedback / reports +// + +window.addEventListener('entity:map', function () { + const map = window.MapEntity.currentMap.map; + const modelname = 'report'; + const layername = `${modelname}_layer`; + const layerUrl = window.SETTINGS.urls[layername]; + + const nameHTML = tr('Report'); + const category = tr('Feedback'); + const primaryKey = generateUniqueId(); + const style = window.SETTINGS.map.styles[modelname] ?? window.SETTINGS.map.styles['autres']; + + const objectsLayer = new MaplibreObjectsLayer(null, { + style: style, + modelname: modelname, + readonly: true, + nameHTML: nameHTML, + category: category, + primaryKey: primaryKey, + dataUrl: layerUrl, + isLazy: true + }); + + objectsLayer.initialize(map.getMap()); + objectsLayer.registerLazyLayer(modelname, category, nameHTML, primaryKey, layerUrl); +}); \ No newline at end of file diff --git a/geotrek/feedback/static/feedback/status_colors.js b/geotrek/feedback/static/feedback/js/status_colors.js similarity index 100% rename from geotrek/feedback/static/feedback/status_colors.js rename to geotrek/feedback/static/feedback/js/status_colors.js diff --git a/geotrek/feedback/static/feedback/workflow.js b/geotrek/feedback/static/feedback/js/workflow.js similarity index 100% rename from geotrek/feedback/static/feedback/workflow.js rename to geotrek/feedback/static/feedback/js/workflow.js diff --git a/geotrek/feedback/static/feedback/main.js b/geotrek/feedback/static/feedback/main.js deleted file mode 100644 index 101a5a8e8c..0000000000 --- a/geotrek/feedback/static/feedback/main.js +++ /dev/null @@ -1,33 +0,0 @@ -// -// Feedback / reports -// - -$(window).on('entity:map', function (e, data) { - var modelname = 'report'; - var layername = `${modelname}_layer`; - var url = window.SETTINGS.urls[layername]; - var loaded_infrastructure = false; - var map = data.map; - - // Show report layer in application maps - var style = L.Util.extend({ clickable: false }, - window.SETTINGS.map.styles[modelname] || {}); - var layer = new L.ObjectsLayer(null, { - modelname: modelname, - style: style, - }); - - if (data.modelname != modelname) { - map.layerscontrol.addOverlay(layer, tr('Report'), tr('Feedback')); - }; - - map.on('layeradd', function (e) { - var options = e.layer.options || { 'modelname': 'None' }; - if (!loaded_infrastructure) { - if (options.modelname == modelname && options.modelname != data.modelname) { - e.layer.load(url); - loaded_infrastructure = true; - } - } - }); -}); diff --git a/geotrek/feedback/templates/feedback/feedback_extrabody_fragment.html b/geotrek/feedback/templates/feedback/feedback_extrabody_fragment.html index cb3475f790..897dfff073 100644 --- a/geotrek/feedback/templates/feedback/feedback_extrabody_fragment.html +++ b/geotrek/feedback/templates/feedback/feedback_extrabody_fragment.html @@ -11,17 +11,18 @@ {% endif %} {% if enable_report_colors_per_status %} - - - +{# #} + +{# #} + {% endif %} diff --git a/geotrek/feedback/templates/feedback/feedback_extrajs_fragment.html b/geotrek/feedback/templates/feedback/feedback_extrajs_fragment.html index 4ef0af3599..693a3d1ae5 100644 --- a/geotrek/feedback/templates/feedback/feedback_extrajs_fragment.html +++ b/geotrek/feedback/templates/feedback/feedback_extrajs_fragment.html @@ -1,3 +1,3 @@ {% load static %} - + diff --git a/geotrek/feedback/templates/feedback/report_detail_pdf.html b/geotrek/feedback/templates/feedback/report_detail_pdf.html index 0a1423bcda..d463529335 100644 --- a/geotrek/feedback/templates/feedback/report_detail_pdf.html +++ b/geotrek/feedback/templates/feedback/report_detail_pdf.html @@ -4,7 +4,7 @@ {% block style %} - diff --git a/geotrek/feedback/templates/feedback/report_form.html b/geotrek/feedback/templates/feedback/report_form.html index 10b750bcf7..45d08ec7da 100644 --- a/geotrek/feedback/templates/feedback/report_form.html +++ b/geotrek/feedback/templates/feedback/report_form.html @@ -7,7 +7,8 @@ {{ block.super }} {% if suricate_workflow_enabled %} - + + diff --git a/geotrek/infrastructure/templates/infrastructure/infrastructure_extracss_fragment.html b/geotrek/infrastructure/templates/infrastructure/infrastructure_extracss_fragment.html index 9620873f96..0888ac1f7e 100644 --- a/geotrek/infrastructure/templates/infrastructure/infrastructure_extracss_fragment.html +++ b/geotrek/infrastructure/templates/infrastructure/infrastructure_extracss_fragment.html @@ -1,3 +1,3 @@ {% load static %} {# loaded by MapEntity, used to inject custom CSS at project level #} - + diff --git a/geotrek/infrastructure/templates/infrastructure/infrastructure_extrajs_fragment.html b/geotrek/infrastructure/templates/infrastructure/infrastructure_extrajs_fragment.html index 873b6997c3..bc96060974 100644 --- a/geotrek/infrastructure/templates/infrastructure/infrastructure_extrajs_fragment.html +++ b/geotrek/infrastructure/templates/infrastructure/infrastructure_extrajs_fragment.html @@ -1,3 +1,3 @@ {% load static %} - + diff --git a/geotrek/land/static/land/style.css b/geotrek/land/static/land/css/style.css similarity index 100% rename from geotrek/land/static/land/style.css rename to geotrek/land/static/land/css/style.css diff --git a/geotrek/land/static/land/js/maplibreLandMain.js b/geotrek/land/static/land/js/maplibreLandMain.js new file mode 100644 index 0000000000..de1af7807c --- /dev/null +++ b/geotrek/land/static/land/js/maplibreLandMain.js @@ -0,0 +1,44 @@ +window.addEventListener("entity:map", () => { + const map = window.MapEntity.currentMap.map; + + + const 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' } + ]; + + const colorspools = window.SETTINGS.map?.colorspool || {}; + const category = tr('Status'); + + for (const managementLayer of managementLayers) { + let nameHTML = ''; + const colors = colorspools[managementLayer.id] || []; + + // Génère un petit symbole coloré de légende (limité à 4 max) + for (let j = 0; j < Math.min(colors.length, 4); j++) { + nameHTML += `|`; + } + + nameHTML += ` ${managementLayer.name}`; + let primaryKey = generateUniqueId(); + + let style = window.SETTINGS.map.styles[managementLayer.id] ?? window.SETTINGS.map.styles['autres']; + const layer = new MaplibreObjectsLayer(null, { + modelname: managementLayer.name, + style: style, + nameHTML: nameHTML, + category: category, + readonly: true, + primaryKey: primaryKey, + dataUrl: managementLayer.url, + isLazy: true + }); + + layer.initialize(map.getMap()); + layer.registerLazyLayer(managementLayer.name, category, nameHTML, primaryKey, managementLayer.url); + } +}); \ No newline at end of file diff --git a/geotrek/land/templates/land/land_extrabody_fragment.html b/geotrek/land/templates/land/land_extrabody_fragment.html index f93840524e..fe41f71778 100644 --- a/geotrek/land/templates/land/land_extrabody_fragment.html +++ b/geotrek/land/templates/land/land_extrabody_fragment.html @@ -1,18 +1,18 @@ {% load static i18n %} - + + diff --git a/geotrek/land/templates/land/land_extracss_fragment.html b/geotrek/land/templates/land/land_extracss_fragment.html index 38863e68f3..4333c6c316 100644 --- a/geotrek/land/templates/land/land_extracss_fragment.html +++ b/geotrek/land/templates/land/land_extracss_fragment.html @@ -1,3 +1,3 @@ {% load static %} {# loaded by MapEntity, used to inject custom CSS at project level #} - + diff --git a/geotrek/maintenance/static/maintenance/style.css b/geotrek/maintenance/static/maintenance/css/style.css similarity index 100% rename from geotrek/maintenance/static/maintenance/style.css rename to geotrek/maintenance/static/maintenance/css/style.css diff --git a/geotrek/maintenance/static/maintenance/js/maplibreMaintenanceMain.js b/geotrek/maintenance/static/maintenance/js/maplibreMaintenanceMain.js new file mode 100644 index 0000000000..9ab4843f70 --- /dev/null +++ b/geotrek/maintenance/static/maintenance/js/maplibreMaintenanceMain.js @@ -0,0 +1,59 @@ +// +// Maintenance / interventions +// +window.addEventListener("entity:map", () => { + const map = window.MapEntity.currentMap.map; + const modelname = 'intervention'; + const layername = 'intervention_layer'; + const layerUrl = window.SETTINGS.urls[layername]; + + const style = window.SETTINGS.map.styles[modelname] ?? window.SETTINGS.map.styles['autres']; + + const nameHTML = tr('Intervention'); + const category = tr('Maintenance'); + const primaryKey = generateUniqueId(); + + const objectsLayer = new MaplibreObjectsLayer(null, { + style: style, + modelname: modelname, + readonly: true, + nameHTML: nameHTML, + category: category, + primaryKey: primaryKey, + dataUrl: layerUrl, + isLazy: true + }); + + objectsLayer.initialize(map.getMap()); + objectsLayer.registerLazyLayer(modelname, category, nameHTML, primaryKey, layerUrl); +}); + +// Date picker with placeholder on input +function setDatePickerConfig(idList) { + $(idList).datepicker({ + autoclose: true, + language: window.SETTINGS.languages.default, + format: window.SETTINGS.date_format + }); +} + +document.addEventListener('entity:view:add', function (e, data) { + console.log('entity:view:add', data); + if (data.modelname === "intervention"){ + setDatePickerConfig('#id_begin_date, #id_end_date'); + }; +}); + +document.addEventListener('entity:view:filter', function (e, data) { + console.log('entity:view:filter', data); + if (data.modelname === "intervention"){ + setDatePickerConfig('#id_begin_date_0, #id_begin_date_1, #id_end_date_0, #id_end_date_1'); + }; +}); + +document.addEventListener('entity:view:update', function (e, data) { + console.log('entity:view:update', data); + if (data.modelname === "intervention"){ + setDatePickerConfig('#id_begin_date, #id_end_date'); + }; +}); \ No newline at end of file diff --git a/geotrek/maintenance/static/maintenance/main.js b/geotrek/maintenance/static/maintenance/main.js deleted file mode 100644 index df97ce7696..0000000000 --- a/geotrek/maintenance/static/maintenance/main.js +++ /dev/null @@ -1,61 +0,0 @@ -// -// Maintenance / interventions -// - -$(window).on('entity:map', function (e, data) { - var modelname = 'intervention'; - var layername = `${modelname}_layer`; - var url = window.SETTINGS.urls[layername]; - var loaded_infrastructure = false; - var map = data.map; - - // Show infrastructure layer in application maps - var style = L.Util.extend({ clickable: false }, - window.SETTINGS.map.styles[modelname] || {}); - - var layer = new L.ObjectsLayer(null, { - modelname: modelname, - style: style, - }); - - if (data.modelname != modelname){ - map.layerscontrol.addOverlay(layer, tr('Intervention'), tr('Maintenance')); - }; - - map.on('layeradd', function (e) { - var options = e.layer.options || { 'modelname': 'None' }; - if (! loaded_infrastructure) { - if (options.modelname == modelname && options.modelname != data.modelname) { - e.layer.load(url); - loaded_infrastructure = true; - } - } - }); -}); - - -// Date picker with placeholder on input -function setDatePickerConfig(idList) { - $(idList).datepicker({ - autoclose: true, - language: window.SETTINGS.languages.default, - format: window.SETTINGS.date_format - }); -} -$(window).on('entity:view:add', function (e, data) { - if (data.modelname === "intervention"){ - setDatePickerConfig('#id_begin_date, #id_end_date'); - }; -}); - -$(window).on('entity:view:filter', function (e, data) { - if (data.modelname === "intervention"){ - setDatePickerConfig('#id_begin_date_0, #id_begin_date_1, #id_end_date_0, #id_end_date_1'); - }; -}); - -$(window).on('entity:view:update', function (e, data) { - if (data.modelname === "intervention"){ - setDatePickerConfig('#id_begin_date, #id_end_date'); - }; -}); diff --git a/geotrek/maintenance/templates/maintenance/maintenance_extrabody_fragment.html b/geotrek/maintenance/templates/maintenance/maintenance_extrabody_fragment.html index d3ae1336be..e5b2e896a4 100644 --- a/geotrek/maintenance/templates/maintenance/maintenance_extrabody_fragment.html +++ b/geotrek/maintenance/templates/maintenance/maintenance_extrabody_fragment.html @@ -1,8 +1,8 @@ {% load i18n %} diff --git a/geotrek/maintenance/templates/maintenance/maintenance_extracss_fragment.html b/geotrek/maintenance/templates/maintenance/maintenance_extracss_fragment.html index f1d4178bed..87ca20245e 100644 --- a/geotrek/maintenance/templates/maintenance/maintenance_extracss_fragment.html +++ b/geotrek/maintenance/templates/maintenance/maintenance_extracss_fragment.html @@ -1,3 +1,3 @@ {% load static %} {# loaded by MapEntity, used to inject custom CSS at project level #} - + diff --git a/geotrek/maintenance/templates/maintenance/maintenance_extrajs_fragment.html b/geotrek/maintenance/templates/maintenance/maintenance_extrajs_fragment.html index 9244f1fda8..c687811a3d 100644 --- a/geotrek/maintenance/templates/maintenance/maintenance_extrajs_fragment.html +++ b/geotrek/maintenance/templates/maintenance/maintenance_extrajs_fragment.html @@ -1,3 +1,3 @@ {% load static %} - + diff --git a/geotrek/maintenance/templates/maintenance/project_detail.html b/geotrek/maintenance/templates/maintenance/project_detail.html index db3a89b083..07cacde497 100644 --- a/geotrek/maintenance/templates/maintenance/project_detail.html +++ b/geotrek/maintenance/templates/maintenance/project_detail.html @@ -99,37 +99,37 @@ {% block extrabody %} {{ block.super }} - +{# #} {% endblock extrabody %} diff --git a/geotrek/outdoor/static/outdoor/main.js b/geotrek/outdoor/static/outdoor/js/maplibreOutdoorMain.js similarity index 86% rename from geotrek/outdoor/static/outdoor/main.js rename to geotrek/outdoor/static/outdoor/js/maplibreOutdoorMain.js index 2566d7228a..d0781ab8dc 100644 --- a/geotrek/outdoor/static/outdoor/main.js +++ b/geotrek/outdoor/static/outdoor/js/maplibreOutdoorMain.js @@ -1,38 +1,32 @@ -$(window).on('entity:map', function (e, data) { +window.addEventListener('entity:map', () => { + const map = window.MapEntity.currentMap.map; - var map = data.map; - var loaded_site = false; - var loaded_course = false; - // Show outdoor layers in application maps - $.each(['site', 'course'], function (i, modelname) { - var style = L.Util.extend({ clickable: false }, - window.SETTINGS.map.styles[modelname] || {}); - var layer = new L.ObjectsLayer(null, { - modelname: modelname, + ['site', 'course'].forEach((modelname) => { + const layername = `${modelname}_layer`; + const layerUrl = window.SETTINGS.urls[layername]; + let style = window.SETTINGS.map.styles[modelname] ?? window.SETTINGS.map.styles['autres']; + const nameHTML = tr(modelname); + const category = tr('Outdoor'); + let primaryKey = generateUniqueId(); + + // Show site and course layers in application maps + const objectsLayer = new MaplibreObjectsLayer(null, { style: style, + modelname: modelname, + readonly: false, + nameHTML: nameHTML, + category: category, + primaryKey: primaryKey, + dataUrl: layerUrl, + isLazy: true }); - if (data.modelname != modelname) { - map.layerscontrol.addOverlay(layer, tr(modelname), tr('Outdoor')); - }; - map.on('layeradd', function (e) { - var options = e.layer.options || { 'modelname': 'None' }; - if (!loaded_site) { - if (options.modelname == 'site' && options.modelname != data.modelname) { - e.layer.load(window.SETTINGS.urls.site_layer); - loaded_site = true; - } - } - if (!loaded_course) { - if (options.modelname == 'course' && options.modelname != data.modelname) { - e.layer.load(window.SETTINGS.urls.course_layer); - loaded_course = true; - } - } - }); + + objectsLayer.initialize(map.getMap()); + objectsLayer.registerLazyLayer(modelname, category, nameHTML, primaryKey, layerUrl); + }); }); - $(window).on('entity:view:add entity:view:update', function (e, data) { if (data.modelname == 'site') { // Refresh site types by practice @@ -207,4 +201,4 @@ function update_course_types() { } // Hide type field if there exists no type for this site's practice $('#div_id_type').toggle(Object.keys(types).length > 0); -} +} \ No newline at end of file diff --git a/geotrek/outdoor/templates/outdoor/outdoor_extrabody_fragment.html b/geotrek/outdoor/templates/outdoor/outdoor_extrabody_fragment.html index 651f436bbe..7a9fce946c 100644 --- a/geotrek/outdoor/templates/outdoor/outdoor_extrabody_fragment.html +++ b/geotrek/outdoor/templates/outdoor/outdoor_extrabody_fragment.html @@ -4,9 +4,9 @@ {% if enabled %} + + {% endif %} + {% endif %} diff --git a/geotrek/sensitivity/static/sensitivity/js/maplibreSensitivityMain.js b/geotrek/sensitivity/static/sensitivity/js/maplibreSensitivityMain.js new file mode 100644 index 0000000000..8eb28626c2 --- /dev/null +++ b/geotrek/sensitivity/static/sensitivity/js/maplibreSensitivityMain.js @@ -0,0 +1,31 @@ +// +// Sensitivity +// + +window.addEventListener('entity:map', () => { + const map = window.MapEntity.currentMap.map; + const modelname = 'sensitivearea'; + const layername = `${modelname}_layer`; + const layerUrl = window.SETTINGS.urls[layername]; + + // Show sensitivearea layer in application maps + const style = window.SETTINGS.map.styles[modelname] ?? window.SETTINGS.map.styles['autres']; + + const nameHTML = tr('sensitivearea'); + const category = tr('Sensitivity'); + const primaryKey = generateUniqueId(); + + const objectsLayer = new MaplibreObjectsLayer(null, { + style: style, + modelname: modelname, + readonly: true, + nameHTML: nameHTML, + category: category, + primaryKey: primaryKey, + dataUrl: layerUrl, + isLazy: true + }); + + objectsLayer.initialize(map.getMap()); + objectsLayer.registerLazyLayer(modelname, category, nameHTML, primaryKey, layerUrl); +}); \ No newline at end of file diff --git a/geotrek/sensitivity/static/sensitivity/main.js b/geotrek/sensitivity/static/sensitivity/main.js deleted file mode 100644 index 364c09a8ce..0000000000 --- a/geotrek/sensitivity/static/sensitivity/main.js +++ /dev/null @@ -1,34 +0,0 @@ -// -// Sensitivity -// - -$(window).on('entity:map', function (e, data) { - var modelname = 'sensitivearea'; - var layername = `${modelname}_layer`; - var url = window.SETTINGS.urls[layername]; - var loaded_sensitivearea = false; - var map = data.map; - - // Show sensitiveare layer in application maps - var style = L.Util.extend({clickable: false}, - window.SETTINGS.map.styles[modelname] || {}) - - var layer = new L.ObjectsLayer(null, { - modelname: modelname, - style: style, - }); - - if (data.modelname != modelname) { - map.layerscontrol.addOverlay(layer, tr('sensitivearea'), tr('Sensitivity')); - }; - - map.on('layeradd', function (e) { - var options = e.layer.options || {'modelname': 'None'}; - if (!loaded_sensitivearea) { - if (options.modelname == modelname && options.modelname != data.modelname) { - e.layer.load(url); - loaded_sensitivearea = true; - } - } - }); -}); diff --git a/geotrek/sensitivity/templates/sensitivity/sensitivearea_detail.html b/geotrek/sensitivity/templates/sensitivity/sensitivearea_detail.html index 7781841491..9c6fea1b1b 100644 --- a/geotrek/sensitivity/templates/sensitivity/sensitivearea_detail.html +++ b/geotrek/sensitivity/templates/sensitivity/sensitivearea_detail.html @@ -18,9 +18,11 @@ {% block extrabody %} {{ block.super }} - +{# l'affichage devrait normalement se faire depuis maplibreObjectsLayer comme un cercle et avec un rayon bien spécifique #} + +{# #} {% endblock extrabody %} diff --git a/geotrek/sensitivity/templates/sensitivity/sensitivearea_form.html b/geotrek/sensitivity/templates/sensitivity/sensitivearea_form.html index 22b8a923bd..6e7beb9107 100644 --- a/geotrek/sensitivity/templates/sensitivity/sensitivearea_form.html +++ b/geotrek/sensitivity/templates/sensitivity/sensitivearea_form.html @@ -5,83 +5,83 @@ {% block extrabody %} {{ block.super }} - +{# #} {% endblock extrabody %} diff --git a/geotrek/sensitivity/templates/sensitivity/sensitivity_extrabody_fragment.html b/geotrek/sensitivity/templates/sensitivity/sensitivity_extrabody_fragment.html index e25c2ffa1a..222bdf0586 100644 --- a/geotrek/sensitivity/templates/sensitivity/sensitivity_extrabody_fragment.html +++ b/geotrek/sensitivity/templates/sensitivity/sensitivity_extrabody_fragment.html @@ -1,7 +1,8 @@ {% load i18n %} diff --git a/geotrek/sensitivity/templates/sensitivity/sensitivity_extrajs_fragment.html b/geotrek/sensitivity/templates/sensitivity/sensitivity_extrajs_fragment.html index 11cf83eacc..03202eb161 100644 --- a/geotrek/sensitivity/templates/sensitivity/sensitivity_extrajs_fragment.html +++ b/geotrek/sensitivity/templates/sensitivity/sensitivity_extrajs_fragment.html @@ -1,3 +1,3 @@ {% load static %} - + diff --git a/geotrek/settings/base.py b/geotrek/settings/base.py index 8dc0d1d78d..f13fc91529 100644 --- a/geotrek/settings/base.py +++ b/geotrek/settings/base.py @@ -450,7 +450,8 @@ def api_bbox(bbox, buffer): "radius": 5, }, "detail": {"color": "#ffff00"}, - "others": {"color": "#ffff00"}, + "others": {"color": "#ffff00"}, # renvoie une fonction posant problème dans le template + "autres": {"color": "#ffff00"}, "print": { "path": {"weight": 1}, "trek": { @@ -491,48 +492,48 @@ def api_bbox(bbox, buffer): # Let this be defined at instance-level LEAFLET_CONFIG = { - "SRID": 3857, - "TILES": [ - ( - "OpenTopoMap", - "https://{s}.tile.opentopomap.org/{z}/{x}/{y}.png", - { - "attribution": 'map data: © OpenStreetMap contributors, SRTM | map style: © OpenTopoMap (CC-BY-SA)', - "maxNativeZoom": 17, - "maxZoom": 22, - }, - ), - ( - "OpenStreetMap", - "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", - { - "attribution": '© Contributeurs d\'OpenStreetMap', - "maxNativeZoom": 19, - "maxZoom": 22, - }, - ), - ], - "TILES_EXTENT": SPATIAL_EXTENT, - # Extent in API projection (Leaflet view default extent) - "SPATIAL_EXTENT": api_bbox(SPATIAL_EXTENT, VIEWPORT_MARGIN), - "NO_GLOBALS": False, - "PLUGINS": { - "geotrek": { - "js": [ - "vendor/leaflet.lineextremities.v0.1.1.js", - "vendor/leaflet.textpath.v1.1.0.js", - "common/points_reference.js", - "trekking/parking_location.js", - ] - }, - "topofields": { - "js": [ - "core/geotrek.forms.snap.js", - "core/geotrek.forms.topology.js", - "core/multipath.js", - ] - }, - }, + # "SRID": 3857, + # "TILES": [ + # ( + # "OpenTopoMap", + # "https://{s}.tile.opentopomap.org/{z}/{x}/{y}.png", + # { + # "attribution": 'map data: © OpenStreetMap contributors, SRTM | map style: © OpenTopoMap (CC-BY-SA)', + # "maxNativeZoom": 17, + # "maxZoom": 22, + # }, + # ), + # ( + # "OpenStreetMap", + # "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", + # { + # "attribution": '© Contributeurs d\'OpenStreetMap', + # "maxNativeZoom": 19, + # "maxZoom": 22, + # }, + # ), + # ], + # "TILES_EXTENT": SPATIAL_EXTENT, + # # Extent in API projection (Leaflet view default extent) + # "SPATIAL_EXTENT": api_bbox(SPATIAL_EXTENT, VIEWPORT_MARGIN), + # "NO_GLOBALS": False, + # "PLUGINS": { + # "geotrek": { + # "js": [ + # "vendor/leaflet.lineextremities.v0.1.1.js", + # "vendor/leaflet.textpath.v1.1.0.js", + # "common/points_reference.js", + # "trekking/parking_location.js", + # ] + # }, + # "topofields": { + # "js": [ + # "core/geotrek.forms.snap.js", + # "core/geotrek.forms.topology.js", + # "core/multipath.js", + # ] + # }, + # }, } # define forced layers from LEAFLET_CONFIG when map center in polygon @@ -1016,8 +1017,8 @@ def api_bbox(bbox, buffer): MAPENTITY_CONFIG["TRANSLATED_LANGUAGES"] = [ language for language in LANGUAGES_LIST if language[0] in MODELTRANSLATION_LANGUAGES ] -LEAFLET_CONFIG["TILES_EXTENT"] = SPATIAL_EXTENT -LEAFLET_CONFIG["SPATIAL_EXTENT"] = api_bbox(SPATIAL_EXTENT, VIEWPORT_MARGIN) +# LEAFLET_CONFIG["TILES_EXTENT"] = SPATIAL_EXTENT +# LEAFLET_CONFIG["SPATIAL_EXTENT"] = api_bbox(SPATIAL_EXTENT, VIEWPORT_MARGIN) if ( SURICATE_WORKFLOW_ENABLED diff --git a/geotrek/signage/static/signage/style.css b/geotrek/signage/static/signage/css/style.css similarity index 100% rename from geotrek/signage/static/signage/style.css rename to geotrek/signage/static/signage/css/style.css diff --git a/geotrek/signage/static/signage/picto-signage.png b/geotrek/signage/static/signage/img/picto-signage.png similarity index 100% rename from geotrek/signage/static/signage/picto-signage.png rename to geotrek/signage/static/signage/img/picto-signage.png diff --git a/geotrek/signage/static/signage/js/maplibreSignageMain.js b/geotrek/signage/static/signage/js/maplibreSignageMain.js new file mode 100644 index 0000000000..6e735be055 --- /dev/null +++ b/geotrek/signage/static/signage/js/maplibreSignageMain.js @@ -0,0 +1,31 @@ +// +// Signage +// + +window.addEventListener('entity:map', () => { + const map = window.MapEntity.currentMap.map; + const modelname = 'signage'; + const layername = `${modelname}_layer`; + const layerUrl = window.SETTINGS.urls[layername]; + + // Show signage layer in application maps + const style = window.SETTINGS.map.styles[modelname] ?? window.SETTINGS.map.styles['autres']; + + const nameHTML = tr('Signage'); + const category = tr('Signage'); + const primaryKey = generateUniqueId(); + + const objectsLayer = new MaplibreObjectsLayer(null, { + style: style, + modelname: modelname, + readonly: true, + nameHTML: nameHTML, + category: category, + primaryKey: primaryKey, + dataUrl: layerUrl, + isLazy: true + }); + + objectsLayer.initialize(map.getMap()); + objectsLayer.registerLazyLayer(modelname, category, nameHTML, primaryKey, layerUrl); +}); \ No newline at end of file diff --git a/geotrek/signage/static/signage/main.js b/geotrek/signage/static/signage/main.js deleted file mode 100644 index dc3470a6ac..0000000000 --- a/geotrek/signage/static/signage/main.js +++ /dev/null @@ -1,32 +0,0 @@ -// -// Infrastructure -// - -$(window).on('entity:map', function (e, data) { - var modelname = 'signage'; - var layername = `${modelname}_layer`; - var url = window.SETTINGS.urls[layername]; - var loaded_infrastructure = false; - var map = data.map; - var style = L.Util.extend({ clickable: false }, - window.SETTINGS.map.styles[modelname] || {}); - // Show infrastructure layer in application maps - var layer = new L.ObjectsLayer(null, { - modelname: modelname, - style: style, - }); - - if (data.modelname != modelname){ - map.layerscontrol.addOverlay(layer, tr('Signages'), tr('Signage')); - }; - - map.on('layeradd', function (e) { - var options = e.layer.options || { 'modelname': 'None' }; - if (! loaded_infrastructure) { - if (options.modelname == modelname && options.modelname != data.modelname) { - e.layer.load(url); - loaded_infrastructure = true; - } - } - }); -}); diff --git a/geotrek/signage/templates/signage/signage_extrabody_fragment.html b/geotrek/signage/templates/signage/signage_extrabody_fragment.html index 8026b0bcb8..20c581c7b4 100644 --- a/geotrek/signage/templates/signage/signage_extrabody_fragment.html +++ b/geotrek/signage/templates/signage/signage_extrabody_fragment.html @@ -1,8 +1,8 @@ {% load i18n %} diff --git a/geotrek/signage/templates/signage/signage_extracss_fragment.html b/geotrek/signage/templates/signage/signage_extracss_fragment.html index 6a6dc8d6ae..6c533bf004 100644 --- a/geotrek/signage/templates/signage/signage_extracss_fragment.html +++ b/geotrek/signage/templates/signage/signage_extracss_fragment.html @@ -1,3 +1,3 @@ {% load static %} {# loaded by MapEntity, used to inject custom CSS at project level #} - + diff --git a/geotrek/signage/templates/signage/signage_extrajs_fragment.html b/geotrek/signage/templates/signage/signage_extrajs_fragment.html index 26da0dbcc6..fe25bf0a5d 100644 --- a/geotrek/signage/templates/signage/signage_extrajs_fragment.html +++ b/geotrek/signage/templates/signage/signage_extrajs_fragment.html @@ -1,3 +1,3 @@ {% load static %} - + diff --git a/geotrek/templates/mapentity/base_site.html b/geotrek/templates/mapentity/base_site.html index 61be5a84dc..a3a4060552 100644 --- a/geotrek/templates/mapentity/base_site.html +++ b/geotrek/templates/mapentity/base_site.html @@ -12,76 +12,76 @@ - +{# #} {% else %} {% endif %} diff --git a/geotrek/tourism/static/tourism/style.css b/geotrek/tourism/static/tourism/css/style.css similarity index 100% rename from geotrek/tourism/static/tourism/style.css rename to geotrek/tourism/static/tourism/css/style.css diff --git a/geotrek/tourism/static/tourism/touristicevent.svg b/geotrek/tourism/static/tourism/img/touristicevent.svg similarity index 100% rename from geotrek/tourism/static/tourism/touristicevent.svg rename to geotrek/tourism/static/tourism/img/touristicevent.svg diff --git a/geotrek/tourism/static/tourism/main.js b/geotrek/tourism/static/tourism/js/maplibreTourismMain.js similarity index 53% rename from geotrek/tourism/static/tourism/main.js rename to geotrek/tourism/static/tourism/js/maplibreTourismMain.js index 54d6ff0215..20c49259ef 100644 --- a/geotrek/tourism/static/tourism/main.js +++ b/geotrek/tourism/static/tourism/js/maplibreTourismMain.js @@ -1,92 +1,33 @@ -// -// Touristic Content -// -var drawnItems; -PublicLayerGeometryField = L.GeometryField.extend({ - // override _editionLayer to get the feature group (drawItems) global and make it accessible outside the leaflet draw event - _editionLayer: function () { - var type = 'featureGroup', - constructor = L[type]; - if (typeof (constructor) != 'function') { - throw 'Unsupported geometry type: ' + type; - } - drawnItems = constructor([], {}) - return drawnItems; - } -}); +window.addEventListener('entity:map', (event) => { + const map = window.MapEntity.currentMap.map; -$(window).on('entity:map:update entity:map:add', function (e, data) { - var map = data.map; - var placeLayer = null; - $("#id_place").change(function () { - // remove leaflet draw marker - drawnItems.eachLayer((layer) => { - drawnItems.removeLayer(layer); - }); - // if change place remove previous one - if (placeLayer) { - map.removeLayer(placeLayer); - } - var placesCoords = JSON.parse($('#places-coords').text()); - var currentCoordsPlace = placesCoords[this.value]; - if (currentCoordsPlace) { - placeLayer = L.marker(currentCoordsPlace.reverse()); - placeLayer.addTo(map); - // TODO : parametrize zoom level ? - map.setView(placeLayer.getLatLng(), 12); - // synchronize place geom with the form - L.FieldStore.prototype.initialize("id_geom"); - L.FieldStore.prototype.save(placeLayer); - } - }) + ['touristiccontent', 'touristicevent'].forEach((modelname) => { + const layername = `${modelname}_layer`; + const layerUrl = window.SETTINGS.urls[layername]; - map.on('draw:created', function (e) { - // on leaflet draw event : delete previous place marker - if (placeLayer) { - map.removeLayer(placeLayer); - } - // empty the place input - $("#id_place").val(null); + let style = window.SETTINGS.map.styles[modelname] ?? window.SETTINGS.map.styles['autres']; - }); -}); + const nameHTML = tr(modelname); + const category = tr('Tourism'); + let primaryKey = generateUniqueId(); -$(window).on('entity:map', function (e, data) { - - var map = data.map; - var loaded_event = false; - var loaded_touristic = false; - - // Show tourism layer in application maps - $.each(['touristiccontent', 'touristicevent'], function (i, modelname) { - var style = L.Util.extend({ clickable: false }, - window.SETTINGS.map.styles[modelname] || {}); - var layer = new L.ObjectsLayer(null, { + // Show touristic content and events layers in application maps + const objectsLayer = new MaplibreObjectsLayer(null, { + style, modelname: modelname, - style: style, + readonly: true, + nameHTML: nameHTML, + category: category, + primaryKey: primaryKey, + dataUrl: layerUrl, + isLazy: true }); - if (data.modelname != modelname){ - map.layerscontrol.addOverlay(layer, tr(modelname), tr('Tourism')); - }; - map.on('layeradd', function(e){ - var options = e.layer.options || {'modelname': 'None'}; - if (! loaded_event){ - if (options.modelname == 'touristicevent' && options.modelname != data.modelname){ - e.layer.load(window.SETTINGS.urls.touristicevent_layer); - loaded_event = true; - } - } - if (! loaded_touristic){ - if (options.modelname == 'touristiccontent' && options.modelname != data.modelname){ - e.layer.load(window.SETTINGS.urls.touristiccontent_layer); - loaded_touristic = true; - } - } - }); + + objectsLayer.initialize(map.getMap()); + objectsLayer.registerLazyLayer(modelname, category, nameHTML, primaryKey, layerUrl); }); }); - $(window).on('entity:view:filter', function (e, data) { // Date picker @@ -104,7 +45,6 @@ $(window).on('entity:view:filter', function (e, data) { var addUrl = $addButton.attr('href'); }); - $(window).on('entity:view:add entity:view:update', function (e, data) { // Date picker $('#id_begin_date, #id_end_date').datepicker({ @@ -154,7 +94,6 @@ $(window).on('entity:view:add entity:view:update', function (e, data) { $('#id_category').trigger('change'); }); - function update_touristiccontent_types(n) { var categories = JSON.parse($('#categories-types').text()); var category = $('#id_category').val(); diff --git a/geotrek/tourism/templates/tourism/tourism_extrabody_fragment.html b/geotrek/tourism/templates/tourism/tourism_extrabody_fragment.html index 7f187b27ec..42261a5745 100644 --- a/geotrek/tourism/templates/tourism/tourism_extrabody_fragment.html +++ b/geotrek/tourism/templates/tourism/tourism_extrabody_fragment.html @@ -10,14 +10,14 @@ + {% endif %} diff --git a/geotrek/tourism/templates/tourism/touristicevent_public_pdf_base.html b/geotrek/tourism/templates/tourism/touristicevent_public_pdf_base.html index 09678da6b5..b3748eb70a 100644 --- a/geotrek/tourism/templates/tourism/touristicevent_public_pdf_base.html +++ b/geotrek/tourism/templates/tourism/touristicevent_public_pdf_base.html @@ -6,7 +6,7 @@ {% block style %} -