Skip to content

Commit 206e8c5

Browse files
authored
Fix issue with showing marker icons in GeoJSON preview map (#9140)
* Update TileLayer URL and attribution in GeoJSONPreview Switch to the OpenStreetMap Germany tile server and adjust attribution to reflect the source accurately. Added subdomains, cross-origin, and referrer policy attributes for improved compatibility and security. * Handle tile load errors by switching OpenStreetMap sources Added an error handler to retry failed tile requests by switching between OpenStreetMap tile servers. This ensures improved robustness and prevents map failures due to unreachable sources. * Set default marker icons for Leaflet in GeoJSON preview Configured Leaflet to use default marker icons and shadow images by importing assets and merging options. This ensures consistent marker display and fixes potential issues with missing icons in the GeoJSON preview component. * Add leaflet-defaulticon-compatibility to simplify map icons Replaced manual marker icon configuration with the leaflet-defaulticon-compatibility package for better maintainability and cleaner code. Updated dependencies in package.json and adjusted GeoJSONPreview.jsx imports accordingly. This change improves code readability and ensures seamless icon handling in leaflet maps. * Refactor GeoJSON tile handling with enhanced fallback logic Improved fallback mechanisms for map tile loading in `GeoJSONPreview.jsx` by introducing error handling with retries across multiple tile servers. Added detailed comments to clarify tile source URLs, subdomains, and error handling logic for better maintainability. This ensures a more robust and seamless map loading experience.
1 parent 22452bd commit 206e8c5

File tree

3 files changed

+60
-2
lines changed

3 files changed

+60
-2
lines changed

webui/package-lock.json

Lines changed: 12 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

webui/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
"csstype": "^3.1.3",
3030
"dayjs": "^1.11.10",
3131
"leaflet": "^1.9.4",
32+
"leaflet-defaulticon-compatibility": "^0.1.2",
3233
"lodash": "^4.17.21",
3334
"p-map": "^7.0.0",
3435
"prismjs": "^1.29.0",

webui/src/lib/components/repository/GeoJSONPreview.jsx

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ import React from "react";
22
import { MapContainer, TileLayer, GeoJSON } from "react-leaflet";
33
import L from 'leaflet';
44
import "leaflet/dist/leaflet.css";
5+
import "leaflet-defaulticon-compatibility/dist/leaflet-defaulticon-compatibility.css";
6+
import "leaflet-defaulticon-compatibility";
57

68
const parseGeoJSON = data => {
79
try {
@@ -27,8 +29,51 @@ export const GeoJSONPreview = ({ data }) => {
2729
<div className="geojson-map-wrapper">
2830
<MapContainer {...mapProps} className="geojson-map-container">
2931
<TileLayer
30-
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
31-
attribution='&copy; <a href="https://openstreetmap.org/copyright">OpenStreetMap</a>'
32+
// url="https://{s}.tile.openstreetmap.de/{z}/{x}/{y}.png" tells Leaflet to load map tiles from the OpenStreetMap Germany server.
33+
// The {s} in the URL is a placeholder for a “subdomain”.
34+
// By listing ['a','b','c'], Leaflet will pick one of those letters each time it requests a tile.
35+
// That way, the requests are spread across a.tile.openstreetmap.de, b.tile… and c.tile…, which helps balance the load and speed up loading.
36+
// You’re telling the map where to get its background tiles (using three mirror subdomains for performance) and providing
37+
// fallback servers if one goes down.
38+
url="https://{s}.tile.openstreetmap.de/{z}/{x}/{y}.png"
39+
subdomains={['a', 'b', 'c']}
40+
41+
// .org credits the OpenStreetMap project and contributors (the source of the map data)
42+
// .de credits the German tile hosting server (the infrastructure serving the tiles).
43+
attribution={`
44+
&copy; <a href="https://openstreetmap.org/">OpenStreetMap</a>
45+
&copy; <a href="https://openstreetmap.de/">OSM Germany</a>
46+
`}
47+
/*
48+
This part is an error handler for when a map tile fails to load.
49+
If the request to tile.openstreetmap.de fails (the default tile server), the onTileError handler triggers.
50+
Inside the handler, we check the URL of the failed image, and replace the domain with
51+
an alternative one (tile.openstreetmap.fr/osmfr) to try loading it again.
52+
If that also fails, it retries once more - this time falling back to the main OpenStreetMap tile server (tile.openstreetmap.org).
53+
So it's basically a retry chain that tries up to three different tile sources,
54+
all using the same tile path pattern - just switching the base domain.
55+
*/
56+
onTileError={(e) => {
57+
const img = e.tile;
58+
const src = img.src;
59+
60+
// e.tile is a reference to the actual <img> DOM element that failed to load.
61+
// By updating img.src, we’re directly modifying that element’s src attribute in the DOM - so the browser will
62+
// automatically retry loading the image from the new URL.
63+
// That’s how the fallback mechanism works here: when a tile fails, we catch it and point the browser
64+
// to a backup tile server by changing the image’s src.
65+
if (src.includes("tile.openstreetmap.de")) {
66+
img.src = src.replace(
67+
"tile.openstreetmap.de",
68+
"tile.openstreetmap.fr/osmfr"
69+
);
70+
} else if (src.includes("tile.openstreetmap.fr/osmfr")) {
71+
img.src = src.replace(
72+
"tile.openstreetmap.fr/osmfr",
73+
"tile.openstreetmap.org"
74+
);
75+
}
76+
}}
3277
/>
3378
<GeoJSON data={geoJsonData} />
3479
</MapContainer>

0 commit comments

Comments
 (0)