Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update the whole leaflet ecosystem #1258

Merged
merged 22 commits into from
Oct 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
0c2b7dd
Bump @20tab/react-leaflet-resetview from 1.0.1 to 1.1.0
dtrucs Sep 18, 2024
a47f218
Bump leaflet.offline from 3.0.1 to 3.1.0
dtrucs Sep 18, 2024
fedd24e
Send tileSize instead of full layer to getStoredTilesAsJson function
dtrucs Sep 18, 2024
002597c
Use correct type for HoverableMarker
dtrucs Sep 18, 2024
ee01bed
Bump @raruto/leaflet-elevation from 1.7.0 to 1.9.0
dtrucs Sep 18, 2024
539fb74
Refacto AltimetricProfil component
dtrucs Sep 18, 2024
f528f62
Collapse import in one line
dtrucs Sep 18, 2024
35a792f
Rename ambigues "center" variable by "bounds"
dtrucs Sep 18, 2024
daf607f
Make sure the map is loaded before saving it
dtrucs Sep 19, 2024
2b9425a
Reduce the size of map BackButton
dtrucs Sep 18, 2024
3b5641e
Add locateControl and fullscreencontrol to touristic content map
dtrucs Sep 18, 2024
4d81418
Define explicit import for map components
dtrucs Sep 18, 2024
ce313c4
Bump @types/leaflet from 1.7.5 to 1.9.12
dtrucs Sep 18, 2024
2a5bdaf
Add next-leaflet-cluster package
dtrucs Sep 18, 2024
0537105
Use next-leaflet-cluster instead of react-leaflet-markercluster
dtrucs Sep 18, 2024
48e27c9
Remove react-leaflet-markercluster package
dtrucs Sep 18, 2024
ecf7b5d
Bump react-leaflet from 3.1.0 to 4.2.1
dtrucs Sep 18, 2024
10c380b
Use ref instead of obsolete whenReady prop for MapContainer
dtrucs Sep 18, 2024
0318f5d
Use useMapEvent for attaching events on map popup
dtrucs Sep 19, 2024
f737bca
Create React-leaflet mock
dtrucs Sep 19, 2024
0baca5c
Update test for MapLayerTypeToggleButton
dtrucs Sep 19, 2024
f2b07a5
Remove useless leaflet declaration from package.json
dtrucs Sep 19, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 6 additions & 7 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,11 @@
}
},
"dependencies": {
"@20tab/react-leaflet-resetview": "^1.0.1",
"@20tab/react-leaflet-resetview": "^1.1.0",
"@hcaptcha/react-hcaptcha": "^1.4.4",
"@makina-corpus/rando3d": "^1.3.3",
"@radix-ui/react-dialog": "^1.1.1",
"@raruto/leaflet-elevation": "1.7.0",
"@raruto/leaflet-elevation": "1.9.0",
"@react-hook/resize-observer": "^1.2.6",
"@sentry/nextjs": "^7.12.1",
"@tanstack/react-query": "^5.51.1",
Expand All @@ -55,13 +55,13 @@
"dotenv-flow": "^3.2.0",
"express": "^4.17.1",
"html-react-parser": "^2.0.0",
"leaflet": "^1.7.1",
"leaflet-boundary-canvas": "^1.0.0",
"leaflet-rastercoords": "^1.0.5",
"leaflet.locatecontrol": "^0.81.1",
"leaflet.offline": "^3.0.1",
"leaflet.offline": "^3.1.0",
"next": "^13.1.6",
"next-compose-plugins": "^2.2.1",
"next-leaflet-cluster": "^1.0.0",
"next-pwa": "^5.6.0",
"orejime": "^2.3.0",
"postcss": "8.3.6",
Expand All @@ -72,9 +72,8 @@
"react-infinite-scroll-component": "6.1.0",
"react-inlinesvg": "^4.0.4",
"react-intl": "^6.2.1",
"react-leaflet": "3.1.0",
"react-leaflet": "^4.2.1",
"react-leaflet-fullscreen": "^4.1.0",
"react-leaflet-markercluster": "^3.0.0-rc1",
"react-leaflet-textpath": "2.1.0",
"react-media-hook": "^0.5.0",
"react-select": "^5.7.2",
Expand All @@ -101,7 +100,7 @@
"@testing-library/react": "^16.0.0",
"@types/debounce": "^1.2.1",
"@types/jest": "27.0.2",
"@types/leaflet": "1.7.5",
"@types/leaflet": "^1.9.12",
"@types/node": "22.5.4",
"@types/react": "^18.0.25",
"@types/react-dom": "^18.0.9",
Expand Down
11 changes: 11 additions & 0 deletions frontend/src/__mocks__/react-leaflet.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
const MapContainer = ({ children }) => <div data-testid="MapContainer">{children}</div>;

const useMap = () => ({ fitBounds: () => {} });

const TileLayer = () => <div data-testid="TileLayer" />;

const Marker = ({ children }) => <div data-testid="Marker">{children}</div>;

const Popup = () => <div data-testid="Popup" />;

export { MapContainer, TileLayer, Marker, Popup, useMap };
33 changes: 17 additions & 16 deletions frontend/src/components/Map/DetailsMap/DetailsMap.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,22 +32,23 @@
import { OutdoorCourseResult } from 'modules/outdoorCourse/interface';
import { cn } from 'services/utils/cn';
import { BackToMapButton } from 'components/BackToMapButton';
import { BackButton } from '../components/BackButton';

import { TrekMarkersAndCourse } from './TrekMarkersAndCourse';
import { getMapConfig } from '../config';
import { AltimetricProfile } from '../components/AltimetricProfile';
import { ControlSection } from '../components/ControlSection';
import { useDetailsMap } from './useDetailsMap';
import { BackButton } from 'components/Map/components/BackButton';
import { AltimetricProfile } from 'components/Map/components/AltimetricProfile';
import { ControlSection } from 'components/Map/components/ControlSection';
import DetailsMapDrawer from 'components/Map/components/DetailsMapDrawer';
import { ResetView } from 'components/Map/components/ResetView';
import TileLayerManager from 'components/Map/components/TileLayerManager';
import FullscreenControl from 'components/Map/components/FullScreenControl';
import ViewPointHD from 'components/Map/components/ViewPointHD';
import { CRSPixel } from 'components/Map/components/ViewPointHD/CRSPixel';
import { AnnotationList } from 'components/Map/components/ViewPointHD/AnnotationList';
import LocateControl from 'components/Map/components/LocateControl';

import { MapChildren, PointWithIcon } from './MapChildren';
import DetailsMapDrawer from '../components/DetailsMapDrawer';
import { ResetView } from '../components/ResetView';
import TileLayerManager from '../components/TileLayerManager';
import FullscreenControl from '../components/FullScreenControl';
import ViewPointHD from '../components/ViewPointHD';
import { CRSPixel } from '../components/ViewPointHD/CRSPixel';
import { AnnotationList } from '../components/ViewPointHD/AnnotationList';
import LocateControl from '../components/LocateControl';
import { useDetailsMap } from './useDetailsMap';
import { getMapConfig } from '../config';
import { TrekMarkersAndCourse } from './TrekMarkersAndCourse';

export interface GeometryListProps {
geometry:
Expand Down Expand Up @@ -160,7 +161,7 @@
if (visibleSection === 'report' && reportVisibility) {
props.setMapId?.('default');
}
}, [visibleSection, props.setMapId]);

Check warning on line 164 in frontend/src/components/Map/DetailsMap/DetailsMap.tsx

View workflow job for this annotation

GitHub Actions / install-and-test

React Hook useEffect has missing dependencies: 'props' and 'reportVisibility'. Either include them or remove the dependency array. However, 'props' will change when *any* prop changes, so the preferred fix is to destructure the 'props' object outside of the useEffect call and refer to those specific props inside useEffect

const hasTitle = Boolean(props.title);

Expand Down Expand Up @@ -189,7 +190,7 @@
navigator.onLine ? undefined : Math.min(...(mapConfig?.zoomAvailableOffline ?? []))
}
zoomControl={props.hasZoomControl}
whenCreated={setMapInstance}
ref={setMapInstance}
bounds={bounds}
{...(mapToDisplay !== 'default' && { crs: CRSPixel(mapToDisplay) })}
>
Expand All @@ -198,7 +199,7 @@
<FormattedMessage id="report.mapButton.validate" />
</BackButton>
) : (
<BackButton icon={<ArrowLeft size={24} />} onClick={hideMap} />
<BackButton icon={<ArrowLeft size={18} />} onClick={hideMap} />
)}
{props.hasZoomControl && <FullscreenControl />}
{mapToDisplay !== 'default' && (
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/Map/SearchMap/MapContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ const MapContainer: React.FC<Props> = ({ children, whenCreated, hasZoomControl =
center={mapConfig.searchMapCenter as [number, number]}
zoom={mapConfig.searchMapZoom}
maxZoom={mapConfig.maximumZoomLevel}
whenCreated={whenCreated}
ref={whenCreated}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't it kinda weird having a function as ref props?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, since Leaflet 1.9 (I'm not sure of the version), the whenCreated prop has been replaced by whenReady but it's not really the same callback function.
When React-leaflet shipped version 4, the release note explicitly wrote:

Removed whenCreated property from the MapContainer component (a ref callback can be used instead).

scrollWheelZoom
zoomControl={hasZoomControl}
id="search_map"
Expand Down
21 changes: 10 additions & 11 deletions frontend/src/components/Map/SearchMap/index.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
import MapContainer from 'components/Map/SearchMap/MapContainer';
import MoveHandler from 'components/Map/SearchMap/MoveHandler';
import SearchMapChildrens from 'components/Map/SearchMap/SearchMapChildrens';
import { LatLngBounds } from 'leaflet';
import React from 'react';
import { ScaleControl } from 'react-leaflet';
import 'leaflet/dist/leaflet.css';

import MapContainer from 'components/Map/SearchMap/MapContainer';
import MoveHandler from 'components/Map/SearchMap/MoveHandler';
import SearchMapChildrens from 'components/Map/SearchMap/SearchMapChildrens';
import { ArrowLeft } from 'components/Icons/ArrowLeft';
import { useTileLayer } from 'hooks/useTileLayer';
import { BackButton } from '../components/BackButton';
import { FilterButton } from '../components/FilterButton';
import { ResetView } from '../components/ResetView';
import TileLayerManager from '../components/TileLayerManager';
import FullscreenControl from '../components/FullScreenControl';
import LocateControl from '../components/LocateControl';
import { BackButton } from 'components/Map/components/BackButton';
import { FilterButton } from 'components/Map/components/FilterButton';
import { ResetView } from 'components/Map/components/ResetView';
import TileLayerManager from 'components/Map/components/TileLayerManager';
import FullscreenControl from 'components/Map/components/FullScreenControl';
import LocateControl from 'components/Map/components/LocateControl';

Comment on lines +5 to +15
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Switching from relative paths to aliased path do not seams directly related to "Leaflet ecosystem".
Maybe should it have been done in a another dedicated PR?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes maybe 👀 😅

export type PropsType = {
segments?: { x: number; y: number }[];
Expand Down Expand Up @@ -41,7 +40,7 @@ const SearchMap: React.FC<PropsType> = props => {
<MapContainer whenCreated={setMapInstance} hasZoomControl={props.hasZoomControl}>
{props.onMove && <MoveHandler onMove={props.onMove} />}
<TileLayerManager />
<BackButton icon={<ArrowLeft size={24} />} onClick={hideMap} />
<BackButton icon={<ArrowLeft size={18} />} onClick={hideMap} />
<FilterButton openFilterMenu={props.openFilterMenu} />
{props.hasZoomControl === true && <FullscreenControl />}
<ResetView />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import React from 'react';
import { MapContainer, ScaleControl } from 'react-leaflet';
import 'leaflet/dist/leaflet.css';

import { ArrowLeft } from 'components/Icons/ArrowLeft';
import { Bbox } from 'modules/details/interface';
import {
GeometryCollection,
Expand All @@ -15,13 +14,16 @@ import {
PolygonGeometry,
} from 'modules/interface';
import { useTileLayer } from 'hooks/useTileLayer';
import { BackButton } from '../components/BackButton';
import { ArrowLeft } from 'components/Icons/ArrowLeft';
import { BackButton } from 'components/Map/components/BackButton';

import { GeometryList } from '../DetailsMap/GeometryList';
import { getMapConfig } from '../config';
import { GeometryListProps } from '../DetailsMap/DetailsMap';
import { ResetView } from '../components/ResetView';
import TileLayerManager from '../components/TileLayerManager';
import { GeometryList } from 'components/Map/DetailsMap/GeometryList';
import { getMapConfig } from 'components/Map/config';
import { GeometryListProps } from 'components/Map/DetailsMap/DetailsMap';
import { ResetView } from 'components/Map/components/ResetView';
import TileLayerManager from 'components/Map/components/TileLayerManager';
import LocateControl from 'components/Map/components/LocateControl';
import FullscreenControl from 'components/Map/components/FullScreenControl';

interface TouristicContentGeometryNullable {
geometry:
Expand All @@ -46,12 +48,12 @@ export type PropsType = {
};

export const TouristicContentMap: React.FC<PropsType> = props => {
const center: LatLngBoundsExpression = [
const bounds: LatLngBoundsExpression = [
[props.bbox.corner1.y, props.bbox.corner1.x],
[props.bbox.corner2.y, props.bbox.corner2.x],
];

const { setMapInstance } = useTileLayer(Number(props.touristicContentGeometry.id), center);
const { setMapInstance } = useTileLayer(Number(props.touristicContentGeometry.id), bounds);

const hideMap = () => {
if (props.hideMap) {
Expand All @@ -61,32 +63,30 @@ export const TouristicContentMap: React.FC<PropsType> = props => {

const mapConfig = getMapConfig();
return (
<>
<MapContainer
className="size-full"
scrollWheelZoom
maxZoom={
navigator.onLine
? mapConfig.maximumZoomLevel
: Math.max(...(mapConfig?.zoomAvailableOffline ?? []))
}
minZoom={
navigator.onLine ? undefined : Math.min(...(mapConfig?.zoomAvailableOffline ?? []))
}
whenCreated={setMapInstance}
zoomControl={props.hasZoomControl}
bounds={center}
attributionControl={false}
>
<BackButton className="desktop:hidden" icon={<ArrowLeft size={24} />} onClick={hideMap} />
<ResetView />
<TileLayerManager />
<ScaleControl />
{props.touristicContentGeometry !== null && (
<GeometryList contents={[props.touristicContentGeometry as GeometryListProps]} />
)}
</MapContainer>
</>
<MapContainer
className="size-full"
scrollWheelZoom
maxZoom={
navigator.onLine
? mapConfig.maximumZoomLevel
: Math.max(...(mapConfig?.zoomAvailableOffline ?? []))
}
minZoom={navigator.onLine ? undefined : Math.min(...(mapConfig?.zoomAvailableOffline ?? []))}
ref={setMapInstance}
zoomControl={props.hasZoomControl}
bounds={bounds}
attributionControl={false}
>
<BackButton icon={<ArrowLeft size={18} />} onClick={hideMap} />
{props.hasZoomControl === true && <FullscreenControl />}
<ResetView />
<TileLayerManager />
<LocateControl />
<ScaleControl />
{props.touristicContentGeometry !== null && (
<GeometryList contents={[props.touristicContentGeometry as GeometryListProps]} />
)}
</MapContainer>
);
};

Expand Down
20 changes: 11 additions & 9 deletions frontend/src/components/Map/components/AltimetricProfile/index.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import React, { useEffect } from 'react';
import '@raruto/leaflet-elevation';
import '@raruto/leaflet-elevation/dist/leaflet-elevation.min.css';
import { useEffect } from 'react';
import L from 'leaflet';
import '@raruto/leaflet-elevation/src/index.js';
import '@raruto/leaflet-elevation/src/index.css';
import { useMap } from 'react-leaflet';
import { useIntl } from 'react-intl';
import { useRouter } from 'next/router';
import { getDefaultLanguage } from 'modules/header/utills';
import useHasMounted from 'hooks/useHasMounted';

interface AltimetricProfileProps {
trekGeoJSON: string;
Expand All @@ -17,14 +16,11 @@ export const AltimetricProfile: React.FC<AltimetricProfileProps> = ({ trekGeoJSO
const map = useMap();
const intl = useIntl();
const language = useRouter().locale ?? getDefaultLanguage();
const isMounted = useHasMounted();

useEffect(() => {
if (!isMounted) {
if (!map) {
return;
}
const div = document.getElementById(id);
if (div) div.innerHTML = '';

// @ts-expect-error the lib is not typed
const elevationControl = L.control.elevation({
Expand Down Expand Up @@ -56,7 +52,13 @@ export const AltimetricProfile: React.FC<AltimetricProfileProps> = ({ trekGeoJSO
L.setLocale(language);

elevationControl.load(trekGeoJSON);
}, [id, intl, isMounted, language, map, trekGeoJSON]);

return () => {
elevationControl.clear();
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
map.removeControl(elevationControl);
};
}, [id, intl, language, map, trekGeoJSON]);

return null;
};
42 changes: 17 additions & 25 deletions frontend/src/components/Map/components/ClusterContainer/index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import ClusterGroup from 'next-leaflet-cluster';
import { getMapConfig } from 'components/Map/config';
import React from 'react';
import MarkerClusterGroup from 'react-leaflet-markercluster';
import { ClusterMarker } from '../../Markers/Cluster';
import { ClusterMarker } from 'components/Map/Markers/Cluster';

interface ClusterContainerProps {
children: React.ReactNode;
Expand All @@ -21,25 +20,18 @@ const clusteringMaxZoom = getMapConfig().maximumZoomLevel;
/**
* Wraps MarkerClusterGroup to enable/disable it easily
*/
export const ClusterContainer: React.FC<ClusterContainerProps> = ({ children, enabled }) => {
// All MarkerClusterGroup props options are here: (the lib is not properly typed yet)
// https://github.com/Leaflet/Leaflet.markercluster#all-options

// The issue: https://github.com/yuzhva/react-leaflet-markercluster/issues

return (
<MarkerClusterGroup
iconCreateFunction={ClusterMarker}
maxClusterRadius={
enabled
? (zoom: number) =>
zoom <= clusterRadiusThreshold ? lowZoomClusterRadius : highZoomClusterRadius
: 0
}
disableClusteringAtZoom={clusteringMaxZoom}
spiderfyOnMaxZoom={true}
>
{children}
</MarkerClusterGroup>
);
};
export const ClusterContainer: React.FC<ClusterContainerProps> = ({ children, enabled }) => (
<ClusterGroup
iconCreateFunction={ClusterMarker}
maxClusterRadius={
enabled
? (zoom: number) =>
zoom <= clusterRadiusThreshold ? lowZoomClusterRadius : highZoomClusterRadius
: 0
}
disableClusteringAtZoom={clusteringMaxZoom}
spiderfyOnMaxZoom
>
{children}
</ClusterGroup>
);
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { useMap } from 'react-leaflet';
import L, { ControlPosition } from 'leaflet';
import ReactDOM from 'react-dom';

interface CustomControlProps {
export interface CustomControlProps {
children: React.ReactNode;
position?: ControlPosition;
name?: string;
Expand Down
3 changes: 2 additions & 1 deletion frontend/src/components/Map/components/HoverableMarker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@
import { useListAndMapContext } from 'modules/map/ListAndMapContext';
import React, { ReactNode, useMemo } from 'react';
import { Marker } from 'react-leaflet';
import { LatLngTuple } from 'leaflet';
import { TrekChildMarker } from '../Markers/TrekChildMarker';
import { TrekMarker } from '../Markers/TrekMarker';

const ZOOM_RATIO = 1.5;

interface BaseProps {
id: string;
position: [number, number];
position: LatLngTuple;
children?: ReactNode;
onMouseOver?: () => void;
onMouseOut?: () => void;
Expand Down Expand Up @@ -50,6 +51,6 @@
{props.children}
</Marker>
),
[props.id, isCorrespondingCardHovered, color],

Check warning on line 54 in frontend/src/components/Map/components/HoverableMarker.tsx

View workflow job for this annotation

GitHub Actions / install-and-test

React Hook useMemo has a missing dependency: 'props'. Either include it or remove the dependency array
);
};
Loading
Loading