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

Release 3.24.0 #1289

Open
wants to merge 11 commits into
base: main
Choose a base branch
from
11 changes: 11 additions & 0 deletions docs/changelog.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
# Changelog

## 3.24.0 (2024-11-13)

**✨ Improvements**

- Keep user search results (scroll position and map fitbounds) when returning from a detail page (#1282)

**🔧 Maintenance**

- Bump next from 13.2.4 to 14.2.15 (#1284)

## 3.23.2 (2024-11-12)

**📝 Documentation**
Expand All @@ -25,6 +35,7 @@
**🔧 Maintenance**

- Remove typesafe-actions package (#1278)
- Bump @next/bundle-analyzer from 12.2.5 to 14.2.14 in /frontend (#1273)

**🐛 Fixes**

Expand Down
1 change: 1 addition & 0 deletions frontend/next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ const nextConfig = {
},
experimental: {
instrumentationHook: true,
scrollRestoration: true,
},
};

Expand Down
4 changes: 2 additions & 2 deletions frontend/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "geotrek-rando-frontend",
"version": "3.23.2",
"version": "3.24.0",
"private": true,
"scripts": {
"debug": "NODE_OPTIONS='--inspect' next ./src",
Expand Down Expand Up @@ -59,7 +59,7 @@
"leaflet-rastercoords": "^1.0.5",
"leaflet.locatecontrol": "^0.81.1",
"leaflet.offline": "^3.1.0",
"next": "13.2.4",
"next": "^14.2.15",
"next-compose-plugins": "^2.2.1",
"next-leaflet-cluster": "^1.0.0",
"next-pwa": "^5.6.0",
Expand Down
17 changes: 2 additions & 15 deletions frontend/src/components/Header/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import { routes } from 'services/routes';

import { Link } from 'components/Link';
import { Display } from 'hooks/useHideOnScrollDown';

import InlineMenu from 'components/InlineMenu';
import { GoToSearchButton } from 'components/GoToSearchButton';
Expand All @@ -15,11 +14,6 @@
export const Header: React.FC = () => {
const menuNode = useRef<HTMLDivElement | null>(null);
const { config, menuItems, isDesktopMenu, intl } = useHeader(menuNode);
/**
* Disabled for now to handle the map on the search page
*/
// const headerState = useHideOnScrollDown(sizes.desktopHeader);
const headerState: Display = 'DISPLAYED';

const headerTop = config.headerTopHtml[intl.locale] ?? config.headerTopHtml.default;
const headerBottom = config.headerBottomHtml[intl.locale] ?? config.headerBottomHtml.default;
Expand All @@ -31,18 +25,11 @@
<HtmlParser template={headerTop} />
</div>
)}
<header
className={cn(
'sticky z-header bg-primary1',
headerState === 'DISPLAYED' ? 'top-0' : '-top-desktopHeader',
)}
role="banner"
id="header"
>
<header className="sticky z-header bg-primary1 top-0" role="banner" id="header">
<div className="h-11 desktop:h-desktopHeader flex justify-between items-center sticky z-header px-3 shadow-sm shrink-0 transition-all duration-300 delay-100">
<Link href={routes.HOME} className="flex items-center">
<div className="shrink-0" id="header_logo">
<img

Check warning on line 32 in frontend/src/components/Header/Header.tsx

View workflow job for this annotation

GitHub Actions / install-and-test

Using `<img>` could result in slower LCP and higher bandwidth. Consider using `<Image />` from `next/image` to automatically optimize images. This may incur additional usage or cost from your provider. See: https://nextjs.org/docs/messages/no-img-element

Check warning on line 32 in frontend/src/components/Header/Header.tsx

View workflow job for this annotation

GitHub Actions / install-and-test

Using `<img>` could result in slower LCP and higher bandwidth. Consider using `<Image />` from `next/image` to automatically optimize images. This may incur additional usage or cost from your provider. See: https://nextjs.org/docs/messages/no-img-element
id="header_logoImg"
className="h-9 w-auto desktop:h-18 mr-3"
alt=""
Expand Down Expand Up @@ -75,7 +62,7 @@
<BurgerMenu
className={cn(isDesktopMenu && 'hidden')}
config={config.menu}
displayState={headerState}
displayState="DISPLAYED"
menuItems={menuItems}
/>
</header>
Expand Down
21 changes: 21 additions & 0 deletions frontend/src/components/Map/SearchMap/BoundsHandler.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { LatLngBounds } from 'leaflet';
import { useEffect } from 'react';
import { useMap } from 'react-leaflet';

interface Props {
bounds: LatLngBounds | null;
}

const BoundsHandler: React.FC<Props> = ({ bounds }) => {
const map = useMap();

useEffect(() => {
if (bounds) {
map.fitBounds(bounds);
}
}, [bounds, map]);

return null;
};

export default BoundsHandler;
3 changes: 1 addition & 2 deletions frontend/src/components/Map/SearchMap/MapContainer.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { getMapConfig } from 'components/Map/config';
import { MapContainer as LeafMapContainer } from 'react-leaflet';
import React, { memo } from 'react';
import { Map } from 'leaflet';

interface Props {
Expand Down Expand Up @@ -28,4 +27,4 @@ const MapContainer: React.FC<Props> = ({ children, whenCreated, hasZoomControl =
);
};

export default memo(MapContainer, () => true);
export default MapContainer;
5 changes: 5 additions & 0 deletions frontend/src/components/Map/SearchMap/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ 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';
import { useListAndMapContext } from 'modules/map/ListAndMapContext';
import BoundsHandler from './BoundsHandler';

export type PropsType = {
segments?: { x: number; y: number }[];
Expand All @@ -35,6 +37,7 @@ const SearchMap: React.FC<PropsType> = props => {
};

const { setMapInstance } = useTileLayer();
const { searchBbox, isNavigatedByBrowser } = useListAndMapContext();

return (
<MapContainer whenCreated={setMapInstance} hasZoomControl={props.hasZoomControl}>
Expand All @@ -44,6 +47,8 @@ const SearchMap: React.FC<PropsType> = props => {
<FilterButton openFilterMenu={props.openFilterMenu} />
{props.hasZoomControl === true && <FullscreenControl />}
<ResetView />
{/* Must be below ResetView */}
{isNavigatedByBrowser && <BoundsHandler bounds={searchBbox} />}
<ScaleControl />
<LocateControl />
<SearchMapChildrens {...props} />
Expand Down
40 changes: 26 additions & 14 deletions frontend/src/components/pages/search/Search.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export const SearchUI: React.FC<Props> = ({ language }) => {
const { subMenuState, selectFilter, hideSubMenu, currentFilterId } = useFilterSubMenu();
const { menuState, displayMenu, hideMenu, filtersList } = useFilterMenu(selectFilter);

const { bboxState, handleMoveMap } = useBbox();
const { bounds, handleMoveMap } = useBbox();

const isMobile = useMediaPredicate('(max-width: 1024px)');

Expand All @@ -62,6 +62,9 @@ export const SearchUI: React.FC<Props> = ({ language }) => {
} = useTextFilter();

const { dateFilter, setDateFilter } = useDateFilter();
const { searchBbox, setPoints, setSearchBbox, isNavigatedByBrowser } = useListAndMapContext();

const bboxState = bounds ?? (isNavigatedByBrowser ? searchBbox : null);

const {
searchResults,
Expand All @@ -76,7 +79,16 @@ export const SearchUI: React.FC<Props> = ({ language }) => {
mobileMapState,
displayMobileMap,
hideMobileMap,
} = useTrekResults({ filtersState, textFilterState, bboxState, dateFilter, page }, language);
} = useTrekResults(
{
filtersState,
textFilterState,
bboxState: bboxState?.toBBoxString() ?? null,
dateFilter,
page,
},
language,
);

const { pageTitle, resultsTitle } = useTitle(filtersState, searchResults?.resultsNumber);

Expand All @@ -85,12 +97,18 @@ export const SearchUI: React.FC<Props> = ({ language }) => {
language,
);

const { setPoints } = useListAndMapContext();

useEffect(() => {
if (mapResults) setPoints(mapResults);
if (mapResults) {
setPoints(mapResults);
}
}, [mapResults, setPoints]);

useEffect(() => {
if (bounds && !isNavigatedByBrowser) {
setSearchBbox(bounds);
}
}, [bounds, isNavigatedByBrowser, setSearchBbox]);

const intl = useIntl();

const onRemoveAllFiltersClick = () => {
Expand Down Expand Up @@ -152,10 +170,7 @@ export const SearchUI: React.FC<Props> = ({ language }) => {
/>
)}

<div
className="flex flex-col h-[calc(100vh-theme(height.desktopHeader))]"
id="search_container"
>
<div className="flex flex-col" id="search_container">
{!isMobile && (
<FilterBarNew
dateFilter={dateFilter}
Expand All @@ -167,11 +182,8 @@ export const SearchUI: React.FC<Props> = ({ language }) => {
language={language}
/>
)}
<div className="flex flex-row flex-1 overflow-y-hidden">
<div
id="search_resultCardList"
className="flex flex-col w-full desktop:w-1/2 overflow-y-scroll"
>
<div className="flex flex-row flex-1">
<div id="search_resultCardList" className="flex flex-col w-full desktop:w-1/2">
<div className="p-4 flex-1">
<Loader loaded={!isLoading}>
<div className="flex flex-col desktop:flex-row desktop:justify-between">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ const FilterField: React.FC<Props> = ({
/>
<div
className={cn(
'fixed left-0 right-0 bg-white p-8 shadow-inner z-[101]',
'fixed left-0 right-0 top-headerAndFilterBar bg-white p-8 shadow-inner z-[101]',
expanded ? 'block' : 'hidden',
)}
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ const FilterBar: React.FC<Props> = ({
const { FILTERS_CATEGORIES } = useFilterBar();

return (
<div className="flex items-center shadow-lg bg-white z-20 border-l border-gresySoft">
<div className="sticky top-desktopHeader flex items-center shadow-lg bg-white z-20 border-l border-gresySoft">
<div className="inline-block ml-4 mr-4 flex items-center">
<Filter size={24} className="text-primary1" aria-hidden />
<span className="uppercase text-primary1 ml-2">
Expand Down
10 changes: 5 additions & 5 deletions frontend/src/components/pages/search/components/useBbox.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,19 @@ import { getGlobalConfig } from 'modules/utils/api.config';
import { useState } from 'react';

interface ReturnType {
bboxState: string | null;
bounds: LatLngBounds | null;
handleMoveMap: (bounds: LatLngBounds) => void;
}

const useBbox = (): ReturnType => {
const [bboxState, setBboxState] = useState<string | null>(null);
const [bounds, setBboxState] = useState<LatLngBounds | null>(null);

const handleMoveMap = (bounds: LatLngBounds) => {
if (getGlobalConfig().enableSearchByMap) setBboxState(bounds.toBBoxString());
const handleMoveMap = (nextBounds: LatLngBounds) => {
if (getGlobalConfig().enableSearchByMap) setBboxState(nextBounds);
};

return {
bboxState,
bounds,
handleMoveMap,
};
};
Expand Down
38 changes: 38 additions & 0 deletions frontend/src/hooks/useBrowserNavigationDetection.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { useRouter } from 'next/router';
import { useEffect, useRef, useState } from 'react';

// Returns “true” if the page is displayed using the browser's "back" or "forward" buttons
const useBrowserNavigationDetection = () => {
const router = useRouter();
const isNavigatedByBrowserRef = useRef(false);
const [isNavigatedByBrowser, setNavigatedByBrowser] = useState(false);

useEffect(() => {
router.beforePopState(() => {
isNavigatedByBrowserRef.current = true;
return true;
});

const handleRouteChangeStart = () => {
// the router.beforePopState() method is always triggered first
// so we have to play with ref to wait for “routeChangeStart” to be triggered
if (isNavigatedByBrowserRef.current) {
setNavigatedByBrowser(true);
isNavigatedByBrowserRef.current = false;
} else {
setNavigatedByBrowser(false);
}
};

router.events.on('routeChangeStart', handleRouteChangeStart);

return () => {
router.beforePopState(() => true);
router.events.off('routeChangeStart', handleRouteChangeStart);
};
}, [router]);

return isNavigatedByBrowser;
};

export default useBrowserNavigationDetection;
23 changes: 22 additions & 1 deletion frontend/src/modules/map/ListAndMapContext.tsx
Original file line number Diff line number Diff line change
@@ -1,28 +1,49 @@
import { createContext, useContext, useState } from 'react';
import { LatLngBounds } from 'leaflet';
import useBrowserNavigationDetection from 'hooks/useBrowserNavigationDetection';
import { MapResults } from '../mapResults/interface';

export interface ListAndMapContext {
hoveredCardId: string | null;
points: MapResults;
searchBbox: LatLngBounds | null;
setPoints: (value: MapResults) => void;
setHoveredCardId: (hoveredCardId: string | null) => void;
setSearchBbox: (bbox: LatLngBounds | null) => void;
isNavigatedByBrowser: boolean;
}

const listAndMapContext = createContext<ListAndMapContext>({
hoveredCardId: null,
points: [],
searchBbox: null,
setPoints: (value: MapResults) => value,
setHoveredCardId: (_: string | null) => _,
setSearchBbox: (_: LatLngBounds | null) => _,
isNavigatedByBrowser: false,
});

export const useListAndMapContext = () => useContext(listAndMapContext);

export const ListAndMapProvider: React.FC<React.PropsWithChildren> = ({ children }) => {
const [hoveredCardId, setHoveredCardId] = useState<string | null>(null);
const [points, setPoints] = useState<MapResults>([]);
const [searchBbox, setSearchBbox] = useState<LatLngBounds | null>(null);

const isNavigatedByBrowser = useBrowserNavigationDetection();

return (
<listAndMapContext.Provider value={{ hoveredCardId, setHoveredCardId, points, setPoints }}>
<listAndMapContext.Provider
value={{
hoveredCardId,
setHoveredCardId,
points,
setPoints,
searchBbox,
setSearchBbox,
isNavigatedByBrowser,
}}
>
{children}
</listAndMapContext.Provider>
);
Expand Down
Loading
Loading