Aligning with OSM usage policies

Added 24 hours cache on Nominatim requests
Added rate limiting on Nominatim requests
Added OpenStreetMap attribution on leaflet map
pull/5122/head
Tiny Paws 3 weeks ago
parent 7ab57f8ed2
commit 726f919609

@ -34,6 +34,7 @@ const LocationMarker = (props: MarkerProps) => {
useEffect(() => {
map.attributionControl.setPrefix("");
map.attributionControl.addAttribution("<a href='https://www.openstreetmap.org/copyright'>OpenStreetMap</a>");
map.locate();
}, []);

@ -1,6 +1,6 @@
import { LatLng } from "leaflet";
import { MapPinIcon, XIcon } from "lucide-react";
import { useEffect, useState } from "react";
import { useEffect, useState, useRef } from "react";
import toast from "react-hot-toast";
import LeafletMap from "@/components/LeafletMap";
import { Button } from "@/components/ui/button";
@ -21,6 +21,12 @@ interface State {
position?: LatLng;
}
interface NomatimRateLimit {
lastNominatimFetch: Date;
nominatimTimeoutId: number | undefined;
timeBetweenFetch: number;
}
const LocationSelector = (props: Props) => {
const t = useTranslate();
const [state, setState] = useState<State>({
@ -28,6 +34,12 @@ const LocationSelector = (props: Props) => {
placeholder: props.location?.placeholder || "",
position: props.location ? new LatLng(props.location.latitude, props.location.longitude) : undefined,
});
const rateLimit = useRef<NomatimRateLimit>({
lastNominatimFetch: new Date(0),
nominatimTimeoutId: undefined,
timeBetweenFetch: 1300,
});
const [popoverOpen, setPopoverOpen] = useState<boolean>(false);
useEffect(() => {
@ -63,14 +75,16 @@ const LocationSelector = (props: Props) => {
}
}, [popoverOpen]);
useEffect(() => {
const updateReverseGeocoding = () => {
if (!state.position) {
setState({ ...state, placeholder: "" });
return;
}
// Fetch reverse geocoding data.
fetch(`https://nominatim.openstreetmap.org/reverse?lat=${state.position.lat}&lon=${state.position.lng}&format=json`)
fetch(`https://nominatim.openstreetmap.org/reverse?lat=${state.position.lat}&lon=${state.position.lng}&format=json`, {
cache: "default",
headers: new Headers({ "Cache-Control": "max-age=86400" }),
})
.then((response) => response.json())
.then((data) => {
if (data && data.display_name) {
@ -81,6 +95,16 @@ const LocationSelector = (props: Props) => {
toast.error("Failed to fetch reverse geocoding data");
console.error("Failed to fetch reverse geocoding data:", error);
});
}
useEffect(() => {
// Fetch reverse geocoding with rate limits
clearTimeout(rateLimit.current.nominatimTimeoutId);
const timeLeft = rateLimit.current.timeBetweenFetch - (new Date().getTime() - rateLimit.current.lastNominatimFetch.getTime());
rateLimit.current.nominatimTimeoutId = setTimeout(() => {
updateReverseGeocoding();
rateLimit.current.lastNominatimFetch = new Date();
}, timeLeft);
}, [state.position]);
const onPositionChanged = (position: LatLng) => {

Loading…
Cancel
Save