From 309169ceedb7ba6f346f9bc1573c3a376d086134 Mon Sep 17 00:00:00 2001 From: xaralis <filip.varecha@fragaria.cz> Date: Mon, 20 Jun 2022 11:40:54 +0200 Subject: [PATCH] refactor(district): fix/unify js map handling for both block and page-based approach --- district/models.py | 14 ++---- maps_utils/blocks.py | 45 +++++++++---------- .../maps_utils/geo-feature-collection.js | 32 +++++++------ 3 files changed, 44 insertions(+), 47 deletions(-) diff --git a/district/models.py b/district/models.py index 19cff274..715f307b 100644 --- a/district/models.py +++ b/district/models.py @@ -1647,7 +1647,7 @@ class DistrictGeoFeatureDetailPage( def as_geojson_object(self, request): collection = json.loads(self.geojson) image = ( - self.image.get_rendition("fill-800x450|jpegquality-80").url + self.image.get_rendition("fill-1200x675|jpegquality-80").url if self.image else None ) @@ -1667,23 +1667,15 @@ class DistrictGeoFeatureDetailPage( } ) - feature["properties"]["selfTitle"] = feature["properties"].get("title") - - feature["properties"]["title"] = ( - feature["properties"]["title"] + " - " + self.title - if feature["properties"]["selfTitle"] - else self.title - ) - if not "description" in feature["properties"]: feature["properties"]["description"] = None # This extends GeoJSON spec to pass down more context to the map. collection["properties"] = {} collection["properties"]["slug"] = f"{self.pk}-{self.slug}" - collection["properties"]["title"] = self.title - collection["properties"]["category"] = self.category.name + collection["properties"]["collectionTitle"] = self.title collection["properties"]["collectionDescription"] = self.perex + collection["properties"]["category"] = self.category.name collection["properties"]["index"] = self.index collection["properties"]["image"] = image collection["properties"]["link"] = url diff --git a/maps_utils/blocks.py b/maps_utils/blocks.py index 8c8086a1..161cb8f6 100644 --- a/maps_utils/blocks.py +++ b/maps_utils/blocks.py @@ -50,6 +50,8 @@ class MapPointBlock(blocks.StructBlock): "properties": { "slug": feature_id, "title": None, + "collectionTitle": None, + "collectionDescription": None, }, "features": [ { @@ -66,6 +68,7 @@ class MapPointBlock(blocks.StructBlock): "slug": feature_id, "title": None, "description": None, + "collectionTitle": None, "collectionDescription": None, "image": None, "color": value["hex_color"], @@ -139,11 +142,14 @@ class MapFeatureCollectionBlock(blocks.StructBlock): fwp["properties"].update( { "id": feature_id, - "slug": f"{feature_id}-{slugify(feature['title'])}", - "collectionTItle": feature["title"], + "slug": f"0-{feature_id}-{slugify(feature['title'])}", + # Individual features are suppressed to emulate collection-like style. + "title": None, + "description": None, + "collectionTitle": feature["title"], "collectionDescription": feature["description"], "image": feature["image"] - .get_rendition("fill-800x450|jpegquality-80") + .get_rendition("fill-1200x675|jpegquality-80") .url if feature["image"] else None, @@ -151,38 +157,31 @@ class MapFeatureCollectionBlock(blocks.StructBlock): "color": feature["hex_color"], } ) - - fwp["properties"]["selfTitle"] = fwp["properties"].get("title") - - fwp["properties"]["title"] = ( - fwp["properties"]["title"] + " - " + feature["title"] - if fwp["properties"]["selfTitle"] - else self.title - ) - - if not "description" in fwp["properties"]: - fwp["properties"]["description"] = None - return fwp + features = [ + _geojson_feature_with_props(i, f) for i, f in enumerate(value["features"]) + ] + context = super().get_context(value, parent_context) - collection_id = str(uuid4()) context["js_map"] = { "tile_server_config": json.dumps(TILE_SERVER_CONFIG), "geojson": json.dumps( [ + # Each feature dumped as individual collection to make things consistent. { - # Dump individual features in collection "type": "FeatureCollection", "properties": { - "slug": collection_id, - "title": None, + "slug": f"{f['properties']['id']}-{slugify(f['properties']['collectionTitle'])}", + "collectionTitle": f["properties"]["collectionTitle"], + "collectionDescription": f["properties"][ + "collectionDescription" + ], + "image": f["properties"]["image"], }, - "features": [ - _geojson_feature_with_props(i, f) - for i, f in enumerate(value["features"]) - ], + "features": [f], } + for f in features ] ), } diff --git a/maps_utils/static/maps_utils/geo-feature-collection.js b/maps_utils/static/maps_utils/geo-feature-collection.js index c466987a..4edbf101 100644 --- a/maps_utils/static/maps_utils/geo-feature-collection.js +++ b/maps_utils/static/maps_utils/geo-feature-collection.js @@ -372,6 +372,8 @@ const GeoFeatureCollection = Vue.component("GeoFeatureCollection", { : buildMarkerIcon("000000", number); const addMarker = (feature, markerPosLatLng, onClick) => { + const tooltipTitle = [feature.properties.title, feature.properties.collectionTitle].filter(i => !!i).join(' - '); + // add marker const featureMarker = new L.marker(markerPosLatLng, { icon: feature.properties.color @@ -385,7 +387,7 @@ const GeoFeatureCollection = Vue.component("GeoFeatureCollection", { ), }) .on("click", onClick) - .bindTooltip(feature.properties.title, { + .bindTooltip(tooltipTitle, { className: "geo-feature-collection-tooltip", direction: "top", offset: [0, -64], @@ -573,14 +575,17 @@ const GeoFeatureCollection = Vue.component("GeoFeatureCollection", { */ setMuted(featureCollection, muted) { featureCollection.properties.muted = muted; - // Update muted flag on category this featureCollection belongs to. - // Category is muted when all featureCollections in it are muted. - featureCollection.properties.categoryObj.muted = featureCollection - .properties - .categoryObj - .featureCollections - .map(featureCollection => featureCollection.properties.muted) - .reduce((a, b) => a && b, true); + + if (featureCollection.properties.categoryObj) { + // Update muted flag on category this featureCollection belongs to. + // Category is muted when all featureCollections in it are muted. + featureCollection.properties.categoryObj.muted = featureCollection + .properties + .categoryObj + .featureCollections + .map(featureCollection => featureCollection.properties.muted) + .reduce((a, b) => a && b, true); + } if (featureCollection.properties.muted) { if (this.featureGroup.hasLayer(featureCollection.properties.geoJSONLayer)) { @@ -747,7 +752,7 @@ const GeoFeatureCollection = Vue.component("GeoFeatureCollection", { <button class="text-left leading-tight text-xs flex justify-between w-full items-center space-x-2" :class="{'opacity-50': featureCollection.properties.muted}"> <div @click="toggleSolo(featureCollection)" class="flex items-center space-x-2" style="min-width: 0;"> <span v-if="featureCollection.properties.index" class="rounded-full inline-flex items-center justify-center bg-grey-125 font-bold text-center text-2xs w-4 h-4" style="min-width: 1rem">{{ featureCollection.properties.index }}</span> - <span class="geo-feature-collection__legend-item">{{ featureCollection.properties.title }}</span> + <span class="geo-feature-collection__legend-item">{{ featureCollection.properties.collectionTitle }}</span> </div> <i @click="setMuted(featureCollection, !featureCollection.properties.muted)" class="text-xs" :class="{'ico--eye': !featureCollection.properties.muted, 'ico--eye-off': featureCollection.properties.muted}"></i> </button> @@ -773,13 +778,14 @@ const GeoFeatureCollection = Vue.component("GeoFeatureCollection", { </div> <div class="card-headline flex items-center mb-2"> <span v-if="!currentItem.image && currentItem.index" class="rounded-full inline-flex items-center justify-center bg-grey-125 font-bold text-center text-sm w-6 h-6 mr-2">{{ currentItem.index }}</span> - <span class="flex-1">{{ currentItem.title }}</span> + <span class="flex-1" v-if="currentItem.collectionTitle">{{ currentItem.collectionTitle }}</span> + <span class="flex-1" v-else>{{ currentItem.title }}</span> </div> <div class="card-body-text space-y-4"> <div v-if="currentItem.collectionDescription">{{ currentItem.collectionDescription }}</div> - <div v-if="currentItem.selfTitle && currentItem.description"> - <h2 class="head-allcaps-4xs">{{ currentItem.selfTitle }}</h2> + <div v-if="currentItem.title && currentItem.description"> + <h2 class="head-allcaps-4xs">{{ currentItem.title }}</h2> <div v-if="currentItem.description">{{ currentItem.description }}</div> </div> </div> -- GitLab