From 1e1b1d1f3f394c8421508848bd2f46995e284a4b Mon Sep 17 00:00:00 2001 From: Helge Jung <hej@c3pb.de> Date: Sun, 22 Dec 2024 01:53:19 +0100 Subject: [PATCH] assemblyteam positioning: show all current assemblies in edit view --- src/backoffice/urls.py | 1 + src/backoffice/views/assemblies/__init__.py | 4 ++ src/backoffice/views/assemblies/map.py | 51 +++++++++++++++++++++ src/core/templates/core/map.html | 44 +++++++++++++++++- 4 files changed, 99 insertions(+), 1 deletion(-) create mode 100644 src/backoffice/views/assemblies/map.py diff --git a/src/backoffice/urls.py b/src/backoffice/urls.py index b3ceb9af6..c7f1201d8 100644 --- a/src/backoffice/urls.py +++ b/src/backoffice/urls.py @@ -62,6 +62,7 @@ urlpatterns = [ path('wiki/page/<uuid:pk>/delete', wiki.PageDeleteView.as_view(), name='wiki-page-delete'), path('wiki/page/<uuid:pk>/delete-revision', wiki.PageRevisionDeleteView.as_view(), name='wiki-page-revision-delete'), path('assemblies', assemblyteam.AssembliesView.as_view(), name='assemblies'), + path('assemblies/floor.geojson', assemblies.AssemblyGeoJsonExportView.as_view(), name='assemblies-floor-geojson'), path('assemblies/list/<str:variant>', assemblyteam.AssembliesListsView.as_view(), name='assemblieslist'), path('assemblyteam/<uuid:pk>', assemblyteam.AssemblyView.as_view(), name='assemblyteam-detail'), path('assemblyteam/<uuid:pk>/state', assemblyteam.AssemblyEditStateView.as_view(), name='assemblyteam-editstate'), diff --git a/src/backoffice/views/assemblies/__init__.py b/src/backoffice/views/assemblies/__init__.py index 3cc45e5da..718271192 100644 --- a/src/backoffice/views/assemblies/__init__.py +++ b/src/backoffice/views/assemblies/__init__.py @@ -13,6 +13,9 @@ from backoffice.views.assemblies.auth import ( AuthView, VouchersView, ) +from backoffice.views.assemblies.map import ( + AssemblyGeoJsonExportView, +) from backoffice.views.assemblies.members import ( MemberCreateView, MemberListView, @@ -31,6 +34,7 @@ __all__ = [ 'AssemblyChildrenUpdateView', 'AssemblyCreateView', 'AssemblyDetailView', + 'AssemblyGeoJsonExportView', 'AssemblyLinksUpdateView', 'AssemblyListView', 'AssemblyParentLeaveView', diff --git a/src/backoffice/views/assemblies/map.py b/src/backoffice/views/assemblies/map.py new file mode 100644 index 000000000..27f563ae6 --- /dev/null +++ b/src/backoffice/views/assemblies/map.py @@ -0,0 +1,51 @@ +from django.http import HttpResponseBadRequest, JsonResponse +from django.views import View + +from core.models import Assembly + +from backoffice.views.mixins import ConferenceLoginRequiredMixin + + +def flip_coordinates(coordinates): + """Flips the coordinates' tuples' items as latitude/longitude in GeoJSON represents to Y/X instead of X/Y.""" + result = [] + for polygon in coordinates: + p = [] + for coord in polygon: + p.append((coord[1], coord[0])) + result.append(p) + return result + + +class AssemblyGeoJsonExportView(ConferenceLoginRequiredMixin, View): + def get(self, request): + floor = request.GET.get('floor') + if floor is None: + return HttpResponseBadRequest('Missing "floor" parameter.') + + features = [] + + qs = Assembly.objects.conference_accessible(self.conference, self.conferencemember).filter(location_floor__index=floor) + qs = qs.exclude(location_data__point=None, location_data__boundaries=None) + + for assembly in qs: + if coords := assembly.location_data.get('boundaries'): + feature = { + 'type': 'Feature', + 'geometry': { + 'type': 'Polygon', + 'coordinates': flip_coordinates(coords), + }, + 'properties': { + 'name': assembly.name, + 'slug': assembly.slug, + 'published': assembly.is_placed, + }, + } + features.append(feature) + + result = { + 'type': 'FeatureCollection', + 'features': features, + } + return JsonResponse(result, content_type='application/vnd.geo+json', json_dumps_params={'indent': 2}) diff --git a/src/core/templates/core/map.html b/src/core/templates/core/map.html index 8b976f4f8..0d2b5aa1d 100644 --- a/src/core/templates/core/map.html +++ b/src/core/templates/core/map.html @@ -45,7 +45,15 @@ "{{ floor.name }}": floor{{ floor.code_slug }}, {% endfor %} }; - var overlays = {}; + + var assemblies = L.geoJSON().addTo(map); + + var overlays = { + assemblies, + }; + + loadAssemblies(initial_floor_idx); + const layerOptions = { collapsed: false, hideSingleBase: true, @@ -123,10 +131,44 @@ } {% endif %} + function styleAssemblies(feature) { + return {color: 'red'}; + } + + function handleAssemblyFeature (feature, layer) { + layer.bindTooltip('<b>' + feature.properties.slug + '</b><br>' + feature.properties.name, {permanent: false, opacity: 0.75}) + } + + function loadAssemblies(activeFloor) { + map.removeLayer(assemblies); + //overlays = overlays.filter(item => item !== assemblies); // overlays.remove(assemblies); + + var url = "{% url "backoffice:assemblies-floor-geojson" %}?floor=" + activeFloor + fetch(url).then((response) => { + if (!response.ok) { + throw new Error(`HTTP error! Status: ${response.status}`); + } + return response.json(); + }) + .then((data) => { + console.log('got GeoJSON for assemblies on floor', activeFloor, '=', data); + assemblies = L.geoJSON(data, { + onEachFeature: handleAssemblyFeature, + style: styleAssemblies, + }).addTo(map); + console.log('new assemblies layer:', assemblies); + overlays.push(assemblies); + + boundariesLayer.bringToFront(); + poiLayer.bringToFront(); + }); + } + function updateFloor(idx) { activeFloor = idx; const floor_elem = document.getElementById('{{ floor_id }}'); floor_elem.value = idx != null ? idx.toString() : ""; + loadAssemblies(activeFloor); } function updatePoiPosition(latLng) { -- GitLab