From 6f7f5450ca436b08180dc8c61e3795fb439f73c1 Mon Sep 17 00:00:00 2001 From: Kim Shepherd Date: Sun, 30 Mar 2025 16:56:12 +0200 Subject: [PATCH] Geospatial maps: Better "no points" handling * If no results for browse or search maps are available, zoom to 1 and show a i18n tooltip * Added a missing i18n for point filter * New default centre point added to configuration --- config/config.example.yml | 7 +++++++ .../geospatial-map/geospatial-map.component.ts | 16 +++++++++++++++- src/assets/i18n/en.json5 | 4 ++++ src/config/default-app-config.ts | 6 ++++++ src/config/geospatial-map-config.ts | 7 ++++++- src/environments/environment.test.ts | 4 ++++ 6 files changed, 42 insertions(+), 2 deletions(-) diff --git a/config/config.example.yml b/config/config.example.yml index 0be38e5490..bc81e5511d 100644 --- a/config/config.example.yml +++ b/config/config.example.yml @@ -578,3 +578,10 @@ geospatialMapViewer: # (see https://leaflet-extras.github.io/leaflet-providers/preview/) for a full list tileProviders: - 'OpenStreetMap.Mapnik' + # Starting centre point for the map, as lat and lng coordinates. This is useful + # to set the centre of the map when the map is first loaded and if there are no + # points, shapes or markers to display. + # Defaults to the centre of Istanbul + defaultCentrePoint: + lat: 41.015137 + lng: 28.979530 diff --git a/src/app/shared/geospatial-map/geospatial-map.component.ts b/src/app/shared/geospatial-map/geospatial-map.component.ts index b637ac91cf..8f9cc76355 100644 --- a/src/app/shared/geospatial-map/geospatial-map.component.ts +++ b/src/app/shared/geospatial-map/geospatial-map.component.ts @@ -92,6 +92,8 @@ export class GeospatialMapComponent implements AfterViewInit, OnInit, OnDestroy */ @Input() layout = 'item'; + DEFAULT_CENTRE_POINT = [environment.geospatialMapViewer.defaultCentrePoint.lat, environment.geospatialMapViewer.defaultCentrePoint.lng]; + private subs: Subscription[] = []; constructor(private elRef: ElementRef, @@ -146,7 +148,7 @@ export class GeospatialMapComponent implements AfterViewInit, OnInit, OnDestroy const el = this.elRef.nativeElement.querySelector('div.geospatial-map'); // Defaults are London - we update this after drawing markers to zoom and fit based on data this.map = L.map(el, { - center: [51.505, -0.09], + center: this.DEFAULT_CENTRE_POINT, zoom: 11, }); const tileProviders = environment.geospatialMapViewer.tileProviders; @@ -247,9 +249,15 @@ export class GeospatialMapComponent implements AfterViewInit, OnInit, OnDestroy point.url = '/search'; return point; }).filter((point) => hasValue(point) && hasValue(point.coordinates) && point.coordinates.length === 2); + // If there are no points to draw, instead zoom out and show a tooltip and return early if (isEmpty(points)) { + this.map.setZoom(1); + const marker = new L.marker(this.DEFAULT_CENTRE_POINT, { opacity: 0 }); + marker.bindTooltip('' + this.translateService.instant('search.results.geospatial-map.empty') + '', { permanent: true, offset: [0, 0], direction: 'top' }); + this.map.addLayer(marker); return; } + // We have >0 markers, so construct links and tooltips for each const markers = L.markerClusterGroup(); for (let i = 0; i < points.length; i++) { // GeoJSON coordinates are [x, y] or [longitude, latitude] or [eastings, northings] @@ -305,6 +313,12 @@ export class GeospatialMapComponent implements AfterViewInit, OnInit, OnDestroy this.map.addLayer(markers); const bounds = L.latLngBounds(points.map(point => [point.latitude, point.longitude])); this.map.fitBounds(bounds); + } else { + // If there are no points to draw, instead zoom out and show a tooltip + this.map.setZoom(1); + const marker = new L.marker(this.DEFAULT_CENTRE_POINT, { opacity: 0 }); + marker.bindTooltip('' + this.translateService.instant('search.results.geospatial-map.empty') + '', { permanent: true, offset: [0, 0], direction: 'top' }); + this.map.addLayer(marker); } } diff --git a/src/assets/i18n/en.json5 b/src/assets/i18n/en.json5 index d6ce3ee19c..27037b323f 100644 --- a/src/assets/i18n/en.json5 +++ b/src/assets/i18n/en.json5 @@ -4483,6 +4483,8 @@ "search.filters.applied.operator.query": "", + "search.filters.applied.f.point": "Coordinates", + "search.filters.filter.title.head": "Title", "search.filters.filter.title.placeholder": "Title", @@ -4731,6 +4733,8 @@ "search.results.empty": "Your search returned no results.", + "search.results.geospatial-map.empty": "No results on this page with geospatial locations", + "search.results.view-result": "View", "search.results.response.500": "An error occurred during query execution, please try again later", diff --git a/src/config/default-app-config.ts b/src/config/default-app-config.ts index 8ef1f480d3..f2ee3f1c5a 100644 --- a/src/config/default-app-config.ts +++ b/src/config/default-app-config.ts @@ -619,5 +619,11 @@ export class DefaultAppConfig implements AppConfig { tileProviders: [ 'OpenStreetMap.Mapnik', ], + // Starting centre point for maps (before drawing and zooming to markers) + // Defaults to Istanbul + defaultCentrePoint: { + lat: 41.015137, + lng: 28.979530, + }, }; } diff --git a/src/config/geospatial-map-config.ts b/src/config/geospatial-map-config.ts index 88cb186046..7922e391ce 100644 --- a/src/config/geospatial-map-config.ts +++ b/src/config/geospatial-map-config.ts @@ -38,6 +38,11 @@ export class GeospatialMapConfig implements Config { */ public tileProviders: string[]; - + /** + * Starting centre point for maps (before drawing and zooming to markers) + * Takes a lat and lng float value as coordinates + * Defaults to Istanbul + */ + public defaultCentrePoint: { lat: number, lng: number }; } diff --git a/src/environments/environment.test.ts b/src/environments/environment.test.ts index d9c29068f7..58ac61cd16 100644 --- a/src/environments/environment.test.ts +++ b/src/environments/environment.test.ts @@ -448,5 +448,9 @@ export const environment: BuildConfig = { tileProviders: [ 'OpenStreetMap.Mapnik', ], + defaultCentrePoint: { + lat: 41.015137, + lng: 28.979530, + }, }, };