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
This commit is contained in:
Kim Shepherd
2025-03-30 16:56:12 +02:00
parent 0bd93ae1d9
commit 6f7f5450ca
6 changed files with 42 additions and 2 deletions

View File

@@ -578,3 +578,10 @@ geospatialMapViewer:
# (see https://leaflet-extras.github.io/leaflet-providers/preview/) for a full list # (see https://leaflet-extras.github.io/leaflet-providers/preview/) for a full list
tileProviders: tileProviders:
- 'OpenStreetMap.Mapnik' - '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

View File

@@ -92,6 +92,8 @@ export class GeospatialMapComponent implements AfterViewInit, OnInit, OnDestroy
*/ */
@Input() layout = 'item'; @Input() layout = 'item';
DEFAULT_CENTRE_POINT = [environment.geospatialMapViewer.defaultCentrePoint.lat, environment.geospatialMapViewer.defaultCentrePoint.lng];
private subs: Subscription[] = []; private subs: Subscription[] = [];
constructor(private elRef: ElementRef, constructor(private elRef: ElementRef,
@@ -146,7 +148,7 @@ export class GeospatialMapComponent implements AfterViewInit, OnInit, OnDestroy
const el = this.elRef.nativeElement.querySelector('div.geospatial-map'); 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 // Defaults are London - we update this after drawing markers to zoom and fit based on data
this.map = L.map(el, { this.map = L.map(el, {
center: [51.505, -0.09], center: this.DEFAULT_CENTRE_POINT,
zoom: 11, zoom: 11,
}); });
const tileProviders = environment.geospatialMapViewer.tileProviders; const tileProviders = environment.geospatialMapViewer.tileProviders;
@@ -247,9 +249,15 @@ export class GeospatialMapComponent implements AfterViewInit, OnInit, OnDestroy
point.url = '/search'; point.url = '/search';
return point; return point;
}).filter((point) => hasValue(point) && hasValue(point.coordinates) && point.coordinates.length === 2); }).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)) { if (isEmpty(points)) {
this.map.setZoom(1);
const marker = new L.marker(this.DEFAULT_CENTRE_POINT, { opacity: 0 });
marker.bindTooltip('<span class="fs-4 no-results-tooltip">' + this.translateService.instant('search.results.geospatial-map.empty') + '</span>', { permanent: true, offset: [0, 0], direction: 'top' });
this.map.addLayer(marker);
return; return;
} }
// We have >0 markers, so construct links and tooltips for each
const markers = L.markerClusterGroup(); const markers = L.markerClusterGroup();
for (let i = 0; i < points.length; i++) { for (let i = 0; i < points.length; i++) {
// GeoJSON coordinates are [x, y] or [longitude, latitude] or [eastings, northings] // 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); this.map.addLayer(markers);
const bounds = L.latLngBounds(points.map(point => [point.latitude, point.longitude])); const bounds = L.latLngBounds(points.map(point => [point.latitude, point.longitude]));
this.map.fitBounds(bounds); 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('<span class="fs-4 no-results-tooltip">' + this.translateService.instant('search.results.geospatial-map.empty') + '</span>', { permanent: true, offset: [0, 0], direction: 'top' });
this.map.addLayer(marker);
} }
} }

View File

@@ -4483,6 +4483,8 @@
"search.filters.applied.operator.query": "", "search.filters.applied.operator.query": "",
"search.filters.applied.f.point": "Coordinates",
"search.filters.filter.title.head": "Title", "search.filters.filter.title.head": "Title",
"search.filters.filter.title.placeholder": "Title", "search.filters.filter.title.placeholder": "Title",
@@ -4731,6 +4733,8 @@
"search.results.empty": "Your search returned no results.", "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.view-result": "View",
"search.results.response.500": "An error occurred during query execution, please try again later", "search.results.response.500": "An error occurred during query execution, please try again later",

View File

@@ -619,5 +619,11 @@ export class DefaultAppConfig implements AppConfig {
tileProviders: [ tileProviders: [
'OpenStreetMap.Mapnik', 'OpenStreetMap.Mapnik',
], ],
// Starting centre point for maps (before drawing and zooming to markers)
// Defaults to Istanbul
defaultCentrePoint: {
lat: 41.015137,
lng: 28.979530,
},
}; };
} }

View File

@@ -38,6 +38,11 @@ export class GeospatialMapConfig implements Config {
*/ */
public tileProviders: string[]; 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 };
} }

View File

@@ -448,5 +448,9 @@ export const environment: BuildConfig = {
tileProviders: [ tileProviders: [
'OpenStreetMap.Mapnik', 'OpenStreetMap.Mapnik',
], ],
defaultCentrePoint: {
lat: 41.015137,
lng: 28.979530,
},
}, },
}; };