From 7b977567329459ade033f01d53e81a74f152d2af Mon Sep 17 00:00:00 2001 From: Florian Sommariva Date: Tue, 5 Sep 2023 16:36:31 +0200 Subject: [PATCH 01/37] Create viewPoint module --- frontend/src/modules/viewPoint/adapter.ts | 26 +++++++++++++++++ frontend/src/modules/viewPoint/api.ts | 11 ++++++++ frontend/src/modules/viewPoint/connector.ts | 10 +++++++ frontend/src/modules/viewPoint/interface.ts | 31 +++++++++++++++++++++ 4 files changed, 78 insertions(+) create mode 100644 frontend/src/modules/viewPoint/adapter.ts create mode 100644 frontend/src/modules/viewPoint/api.ts create mode 100644 frontend/src/modules/viewPoint/connector.ts create mode 100644 frontend/src/modules/viewPoint/interface.ts diff --git a/frontend/src/modules/viewPoint/adapter.ts b/frontend/src/modules/viewPoint/adapter.ts new file mode 100644 index 000000000..8725f35e3 --- /dev/null +++ b/frontend/src/modules/viewPoint/adapter.ts @@ -0,0 +1,26 @@ +import { getViewPointMetadata } from './connector'; +import { RawViewPoint, ViewPoint } from './interface'; + +export const adaptViewPoints = async (rawViewpoints: RawViewPoint[]): Promise => { + if (rawViewpoints.length === 0) { + return []; + } + const viewPoints = await Promise.all( + rawViewpoints.map(async viewpoints => { + const metadata = await getViewPointMetadata(viewpoints.metadata_url); + return { + annotations: viewpoints.annotations, + id: String(viewpoints.id), + author: viewpoints.author, + legend: viewpoints.legend, + license: viewpoints.license, + metadata, + pictureTilesUrl: decodeURI(viewpoints.picture_tiles_url), + title: viewpoints.title, + thumbnailUrl: viewpoints.thumbnail_url, + }; + }), + ); + + return viewPoints.filter(({ metadata, pictureTilesUrl }) => metadata && pictureTilesUrl); +}; diff --git a/frontend/src/modules/viewPoint/api.ts b/frontend/src/modules/viewPoint/api.ts new file mode 100644 index 000000000..136813016 --- /dev/null +++ b/frontend/src/modules/viewPoint/api.ts @@ -0,0 +1,11 @@ +import { GeotrekAPI } from 'services/api/client'; +import { ViewPoint } from './interface'; + +export const fetchViewPointMetadata = (url: string): Promise => { + try { + return GeotrekAPI.get(url).then(r => r.data); + } catch (e) { + console.error('Error in viewpointsMetadata/api/fetch', e); + throw e; + } +}; diff --git a/frontend/src/modules/viewPoint/connector.ts b/frontend/src/modules/viewPoint/connector.ts new file mode 100644 index 000000000..975c73197 --- /dev/null +++ b/frontend/src/modules/viewPoint/connector.ts @@ -0,0 +1,10 @@ +import { fetchViewPointMetadata } from './api'; +import { ViewPoint } from './interface'; + +export const getViewPointMetadata = async (url: string): Promise => { + try { + return await fetchViewPointMetadata(url); + } catch (e) { + return null; + } +}; diff --git a/frontend/src/modules/viewPoint/interface.ts b/frontend/src/modules/viewPoint/interface.ts new file mode 100644 index 000000000..944a34843 --- /dev/null +++ b/frontend/src/modules/viewPoint/interface.ts @@ -0,0 +1,31 @@ +import { FeatureCollection } from 'geojson'; + +export interface RawViewPoint { + annotations: FeatureCollection; + id: number; + author: string | null; + legend: string | null; + license: string | null; + metadata_url: string; + picture_tiles_url: string; + title: string | null; + thumbnail_url: string; +} + +export interface ViewPoint { + annotations: FeatureCollection; + id: string; + author: string | null; + legend: string | null; + license: string | null; + metadata: { + levels: number; + sizeX: number; + sizeY: number; + tileWidth: number; + tileHeight: number; + } | null; + pictureTilesUrl: string; + title: string | null; + thumbnailUrl: string; +} From 4f1b996751076d6daa22b8ad61497928bbcfdd76 Mon Sep 17 00:00:00 2001 From: Florian Sommariva Date: Tue, 5 Sep 2023 16:39:01 +0200 Subject: [PATCH 02/37] Define state to select map ID --- frontend/src/components/pages/details/useDetails.tsx | 4 ++++ frontend/src/components/pages/site/useOutdoorSite.tsx | 5 ++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/frontend/src/components/pages/details/useDetails.tsx b/frontend/src/components/pages/details/useDetails.tsx index 98eaa405d..1f3d2eae0 100644 --- a/frontend/src/components/pages/details/useDetails.tsx +++ b/frontend/src/components/pages/details/useDetails.tsx @@ -91,6 +91,8 @@ export const useDetails = ( const intl = useIntl(); + // "default" is the world; reals "id" are related to HD viewpoints ids + const [mapId, setMapId] = useState('default'); const [mobileMapState, setMobileMapState] = useState<'DISPLAYED' | 'HIDDEN' | null>('HIDDEN'); const displayMobileMap = useCallback(() => setMobileMapState('DISPLAYED'), [setMobileMapState]); const hideMobileMap = useCallback(() => setMobileMapState('HIDDEN'), [setMobileMapState]); @@ -120,5 +122,7 @@ export const useDetails = ( hideMobileMap, path, sectionRef, + mapId, + setMapId, }; }; diff --git a/frontend/src/components/pages/site/useOutdoorSite.tsx b/frontend/src/components/pages/site/useOutdoorSite.tsx index dd42ae771..468a0411a 100644 --- a/frontend/src/components/pages/site/useOutdoorSite.tsx +++ b/frontend/src/components/pages/site/useOutdoorSite.tsx @@ -44,7 +44,8 @@ export const useOutdoorSite = (outdoorSiteUrl: string | string[] | undefined, la (list, item) => ({ ...list, [item.name]: useSectionReferenceCallback(item.name) }), {} as Record void>, ); - + // "default" is the world; reals "id" are related to HD viewpoints ids + const [mapId, setMapId] = useState('default'); const [mobileMapState, setMobileMapState] = useState<'DISPLAYED' | 'HIDDEN'>('HIDDEN'); const displayMobileMap = () => setMobileMapState('DISPLAYED'); const hideMobileMap = () => setMobileMapState('HIDDEN'); @@ -62,5 +63,7 @@ export const useOutdoorSite = (outdoorSiteUrl: string | string[] | undefined, la hideMobileMap, path, sectionRef, + mapId, + setMapId, }; }; From 0e85397e524e89f2d33f417ddb00bee2e3e22a64 Mon Sep 17 00:00:00 2001 From: Florian Sommariva Date: Tue, 5 Sep 2023 16:39:28 +0200 Subject: [PATCH 03/37] Create BackToMapButton component --- .../BackToMapButton/BackToMapButton.tsx | 34 +++++++++++++++++++ .../src/components/BackToMapButton/index.ts | 1 + 2 files changed, 35 insertions(+) create mode 100644 frontend/src/components/BackToMapButton/BackToMapButton.tsx create mode 100644 frontend/src/components/BackToMapButton/index.ts diff --git a/frontend/src/components/BackToMapButton/BackToMapButton.tsx b/frontend/src/components/BackToMapButton/BackToMapButton.tsx new file mode 100644 index 000000000..5e8ed2d18 --- /dev/null +++ b/frontend/src/components/BackToMapButton/BackToMapButton.tsx @@ -0,0 +1,34 @@ +import { useCallback } from 'react'; +import { Map } from 'components/Icons/Map'; +import { FormattedMessage } from 'react-intl'; +import { cn } from 'services/utils/cn'; + +export const BackToMapButton: React.FC< + React.ButtonHTMLAttributes & { + displayMap?: () => void; + setMapId?: (key: string) => void; + } +> = ({ displayMap, setMapId, ...nativeButtonProps }) => { + const handleClick = useCallback(() => { + displayMap?.(); + setMapId?.('default'); + }, [displayMap, setMapId]); + + return ( + + ); +}; diff --git a/frontend/src/components/BackToMapButton/index.ts b/frontend/src/components/BackToMapButton/index.ts new file mode 100644 index 000000000..0449c4f26 --- /dev/null +++ b/frontend/src/components/BackToMapButton/index.ts @@ -0,0 +1 @@ +export { BackToMapButton } from './BackToMapButton'; From 3622e59410fd4bc61ff64575382b05b41ae91c97 Mon Sep 17 00:00:00 2001 From: Florian Sommariva Date: Tue, 5 Sep 2023 16:39:56 +0200 Subject: [PATCH 04/37] Create viewpoints annotations components --- .../components/ViewPointHD/AnnotationItem.tsx | 107 ++++++++++++++++++ .../components/ViewPointHD/AnnotationList.tsx | 23 ++++ 2 files changed, 130 insertions(+) create mode 100644 frontend/src/components/Map/components/ViewPointHD/AnnotationItem.tsx create mode 100644 frontend/src/components/Map/components/ViewPointHD/AnnotationList.tsx diff --git a/frontend/src/components/Map/components/ViewPointHD/AnnotationItem.tsx b/frontend/src/components/Map/components/ViewPointHD/AnnotationItem.tsx new file mode 100644 index 000000000..7951c4d1b --- /dev/null +++ b/frontend/src/components/Map/components/ViewPointHD/AnnotationItem.tsx @@ -0,0 +1,107 @@ +import L from 'leaflet'; +import { GeoJsonProperties, Geometry } from 'geojson'; +import { Circle, CircleMarker, Polygon, Polyline, Tooltip, useMap } from 'react-leaflet'; + +type Props = { + geometry: Geometry; + properties: GeoJsonProperties; + id: string; +}; + +const MetaData = ({ properties }: { properties: GeoJsonProperties }) => { + if (properties === null || !properties.name) { + return null; + } + return {properties.name}; +}; + +export const AnnotationItem = ({ geometry, properties, id }: Props) => { + const map = useMap(); + if (geometry.type === 'GeometryCollection') { + return ( + <> + {geometry.geometries.map((geom, index) => ( + + ))} + + ); + } + + if (geometry.type === 'Point' || geometry.type === 'MultiPoint') { + const coordinatesAsMultiPoint = + geometry.type === 'Point' ? [geometry.coordinates] : geometry.coordinates; + return ( + <> + {coordinatesAsMultiPoint.map((coordinates, index) => { + const [lat, lng] = coordinates; + return ( + + + + ); + })} + + ); + } + + if (geometry.type === 'LineString' || geometry.type === 'MultiLineString') { + const coordinatesAsMultiLineString = + geometry.type === 'LineString' ? [geometry.coordinates] : geometry.coordinates; + + return ( + <> + {coordinatesAsMultiLineString.map((group, index) => { + return ( + [lng, lat])} + > + + + ); + })} + + ); + } + + if (geometry.type === 'Polygon' || geometry.type === 'MultiPolygon') { + const coordinatesAsMultiPolygon = + geometry.type === 'Polygon' ? [geometry.coordinates] : geometry.coordinates; + + // Circle + if (properties?.annotationType === 'circle') { + const LPolygon = L.geoJSON(geometry); + const center = LPolygon.getBounds().getCenter(); + const [lat, lng] = geometry.coordinates[0][0] as [number, number]; + const diagonal = map.distance(center, [lng, lat]); + const radius = Math.sqrt(Math.pow(diagonal, 2) / 2); + + return ( + + + + ); + } + + // Square, Rectangle, Polygon + return ( + <> + {coordinatesAsMultiPolygon.map((group, index) => ( + line.map<[number, number]>(([lat, lng]) => [lng, lat]))} + > + + + ))} + + ); + } + + return null; +}; diff --git a/frontend/src/components/Map/components/ViewPointHD/AnnotationList.tsx b/frontend/src/components/Map/components/ViewPointHD/AnnotationList.tsx new file mode 100644 index 000000000..ebe596c4f --- /dev/null +++ b/frontend/src/components/Map/components/ViewPointHD/AnnotationList.tsx @@ -0,0 +1,23 @@ +import { GeoJsonProperties, Geometry } from 'geojson'; +import { AnnotationItem } from './AnnotationItem'; + +export type PropsType = { + contents?: { + geometry: Geometry; + properties: GeoJsonProperties; + }[]; +}; + +export const AnnotationList = ({ contents, ...props }: PropsType) => { + if (contents === undefined) { + return null; + } + + return ( + <> + {contents.map((contentProps, index) => ( + + ))} + + ); +}; From 3238193a50a58c6b0e2a23fc3e5dd1185b985d7e Mon Sep 17 00:00:00 2001 From: Florian Sommariva Date: Tue, 5 Sep 2023 16:47:33 +0200 Subject: [PATCH 05/37] Display map by default --- .../components/Map/DetailsMap/DetailsMap.tsx | 217 ++++++++++-------- frontend/src/hooks/useTileLayer.ts | 30 +-- 2 files changed, 136 insertions(+), 111 deletions(-) diff --git a/frontend/src/components/Map/DetailsMap/DetailsMap.tsx b/frontend/src/components/Map/DetailsMap/DetailsMap.tsx index 44c6c2607..599ecb3ae 100644 --- a/frontend/src/components/Map/DetailsMap/DetailsMap.tsx +++ b/frontend/src/components/Map/DetailsMap/DetailsMap.tsx @@ -128,7 +128,9 @@ export const DetailsMap: React.FC = props => { [props.bbox.corner2.y, props.bbox.corner2.x], ]; - const { map, setMapInstance } = useTileLayer(props.trekId, bounds); + const mapToDisplay = props.viewPoints?.find(({ id }) => id === props.mapId) ?? 'default'; + + const { map, setMapInstance } = useTileLayer(props.trekId, bounds, mapToDisplay); useEffect(() => { if (map && center) { @@ -138,6 +140,12 @@ export const DetailsMap: React.FC = props => { const { visibleSection } = useContext(VisibleSectionContext); + useEffect(() => { + if (visibleSection === 'report' && reportVisibility) { + props.setMapId?.('default'); + } + }, [visibleSection, props.setMapId]); + const hasTitle = Boolean(props.title); return ( @@ -150,7 +158,11 @@ export const DetailsMap: React.FC = props => { )} > = props => { } onClick={hideMap} /> )} {props.hasZoomControl && } - - - 0 - ? trekChildrenMobileVisibility - : null - } - poiVisibility={props.poiPoints && props.poiPoints.length > 0 ? poiMobileVisibility : null} - referencePointsVisibility={ - props.pointsReference && props.pointsReference.length > 0 - ? referencePointsMobileVisibility - : null - } - touristicContentVisibility={ - props.touristicContentPoints && props.touristicContentPoints.length > 0 - ? touristicContentMobileVisibility - : null - } - informationDeskMobileVisibility={ - props.informationDesks && - props.informationDesks.some(({ longitude, latitude }) => longitude && latitude) - ? informationDeskMobileVisibility - : null - } - coursesVisibility={ - Boolean(props.courses) && props.courses.length > 0 ? coursesVisibility : null - } - experiencesVisibility={ - Boolean(props.experiences) && props.experiences.length > 0 - ? experiencesVisibility - : null - } - signageVisibility={props.signage ? signageVisibility : null} - serviceVisibility={props.service && props.service.length > 0 ? serviceVisibility : null} - infrastructureVisibility={props.infrastructure ? infrastructureVisibility : null} - toggleTrekChildrenVisibility={toggleTrekChildrenVisibility} - togglePoiVisibility={togglePoiVisibility} - toggleReferencePointsVisibility={toggleReferencePointsVisibility} - toggleTouristicContentVisibility={toggleTouristicContentVisibility} - toggleInformationDeskVisibility={toggleInformationDeskVisibility} - toggleCoursesVisibility={toggleCoursesVisibility} - toggleExperiencesVisibility={toggleExperiencesVisibility} - toggleSignageVisibility={toggleSignageVisibility} - toggleServiceVisibility={toggleServiceVisibility} - toggleInfrastructureVisibility={toggleInfrastructureVisibility} - /> - {props.trekGeometry && ( - - )} - {props.outdoorGeometry && } - {props.eventGeometry && ( - - )} - - {props.displayAltimetricProfile === true && props.trekGeoJSON && ( - - )} - {props.title !== undefined && ( -
- + + + + 0 + ? trekChildrenMobileVisibility + : null + } + poiVisibility={ + props.poiPoints && props.poiPoints.length > 0 ? poiMobileVisibility : null + } + referencePointsVisibility={ + props.pointsReference && props.pointsReference.length > 0 + ? referencePointsMobileVisibility + : null + } + touristicContentVisibility={ + props.touristicContentPoints && props.touristicContentPoints.length > 0 + ? touristicContentMobileVisibility + : null + } + informationDeskMobileVisibility={ + props.informationDesks && + props.informationDesks.some(({ longitude, latitude }) => longitude && latitude) + ? informationDeskMobileVisibility + : null + } + coursesVisibility={ + Boolean(props.courses) && props.courses.length > 0 ? coursesVisibility : null + } + experiencesVisibility={ + Boolean(props.experiences) && props.experiences.length > 0 + ? experiencesVisibility + : null + } + signageVisibility={props.signage ? signageVisibility : null} + serviceVisibility={ + props.service && props.service.length > 0 ? serviceVisibility : null + } + infrastructureVisibility={props.infrastructure ? infrastructureVisibility : null} + toggleTrekChildrenVisibility={toggleTrekChildrenVisibility} + togglePoiVisibility={togglePoiVisibility} + toggleReferencePointsVisibility={toggleReferencePointsVisibility} + toggleTouristicContentVisibility={toggleTouristicContentVisibility} + toggleInformationDeskVisibility={toggleInformationDeskVisibility} + toggleCoursesVisibility={toggleCoursesVisibility} + toggleExperiencesVisibility={toggleExperiencesVisibility} + toggleSignageVisibility={toggleSignageVisibility} + toggleServiceVisibility={toggleServiceVisibility} + toggleInfrastructureVisibility={toggleInfrastructureVisibility} + /> + {props.trekGeometry && ( + + )} + {props.outdoorGeometry && } + {props.eventGeometry && ( + + )} + -
+ {props.displayAltimetricProfile === true && props.trekGeoJSON && ( + + )} + {props.title !== undefined && ( +
+ +
+ )} + )}
diff --git a/frontend/src/hooks/useTileLayer.ts b/frontend/src/hooks/useTileLayer.ts index c959c499f..c9475ca7a 100644 --- a/frontend/src/hooks/useTileLayer.ts +++ b/frontend/src/hooks/useTileLayer.ts @@ -6,10 +6,12 @@ import { useIntl } from 'react-intl'; require('leaflet.locatecontrol'); import 'leaflet.locatecontrol/dist/L.Control.Locate.min.css'; import injectOfflineMode from 'services/offline/injectOfflineMode'; +import { ViewPoint } from 'modules/viewPoint/interface'; export const useTileLayer = ( id?: number, center?: LatLngBoundsExpression | null, + mapToDisplay: ViewPoint | 'default' = 'default', ): { map: Map | null; setMapInstance: (newMap: Map) => void; @@ -25,19 +27,21 @@ export const useTileLayer = ( injectOfflineMode(newMap, id, center); } - L.control - // @ts-ignore no type available in this plugin - .locate({ - locateOptions: { - enableHighAccuracy: true, - }, - icon: 'gg-track', - strings: { - title: intl.formatMessage({ id: 'search.map.seeMe' }), - }, - position: 'bottomright', - }) - .addTo(newMap); + if (mapToDisplay === 'default') { + L.control + // @ts-ignore no type available in this plugin + .locate({ + locateOptions: { + enableHighAccuracy: true, + }, + icon: 'gg-track', + strings: { + title: intl.formatMessage({ id: 'search.map.seeMe' }), + }, + position: 'bottomright', + }) + .addTo(newMap); + } }; return { From 78b9ccb797f3b3b0d1c1094e47179cfccd361d82 Mon Sep 17 00:00:00 2001 From: Florian Sommariva Date: Tue, 5 Sep 2023 16:48:12 +0200 Subject: [PATCH 06/37] Install leaflet-rastercoords package --- frontend/package.json | 1 + frontend/yarn.lock | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/frontend/package.json b/frontend/package.json index dc74bb529..689e7f5be 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -54,6 +54,7 @@ "html-react-parser": "^2.0.0", "leaflet": "^1.7.1", "leaflet-boundary-canvas": "^1.0.0", + "leaflet-rastercoords": "^1.0.5", "leaflet.locatecontrol": "0.74.0", "leaflet.offline": "^3.0.1", "next": "^13.1.6", diff --git a/frontend/yarn.lock b/frontend/yarn.lock index 1b4867bfa..6139b6f33 100644 --- a/frontend/yarn.lock +++ b/frontend/yarn.lock @@ -7739,6 +7739,13 @@ leaflet-i18n@^0.3.1: resolved "https://registry.yarnpkg.com/leaflet-i18n/-/leaflet-i18n-0.3.1.tgz#404e75dc6704f4a2399d1cd05f0dd1dd178300b5" integrity sha1-QE513GcE9KI5nRzQXw3R3ReDALU= +leaflet-rastercoords@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/leaflet-rastercoords/-/leaflet-rastercoords-1.0.5.tgz#6a188f8b88d5613333556a01cbd1eef68a60ebca" + integrity sha512-PGrxD6dhbChN45acRedZMfG1OvOKidwzUHU+lfD3Save9fNSHUeuL9c8BKg84t29Xp7mgvjoF0KIHzYoNNN+gQ== + dependencies: + leaflet "^1.7.1" + leaflet-textpath@^1.2.3: version "1.2.3" resolved "https://registry.yarnpkg.com/leaflet-textpath/-/leaflet-textpath-1.2.3.tgz#0adef3a2d438c1c781f4e1154b8fa2f963cfd8a7" From a371e8eda928d8f30499bf15087591882ad9183b Mon Sep 17 00:00:00 2001 From: Florian Sommariva Date: Tue, 5 Sep 2023 16:49:21 +0200 Subject: [PATCH 07/37] Create Viewpoint component --- .../Map/components/ViewPointHD/index.tsx | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 frontend/src/components/Map/components/ViewPointHD/index.tsx diff --git a/frontend/src/components/Map/components/ViewPointHD/index.tsx b/frontend/src/components/Map/components/ViewPointHD/index.tsx new file mode 100644 index 000000000..c65e445a5 --- /dev/null +++ b/frontend/src/components/Map/components/ViewPointHD/index.tsx @@ -0,0 +1,47 @@ +import L from 'leaflet'; +import { ViewPoint } from 'modules/viewPoint/interface'; +import { useEffect, useState } from 'react'; +import { useMap } from 'react-leaflet'; +// @ts-ignore +L.RasterCoords = require('leaflet-rastercoords'); + +const ViewPointHD: React.FC = ({ pictureTilesUrl, metadata }) => { + if (!metadata || !pictureTilesUrl) { + return null; + } + + const { sizeX, sizeY, tileWidth } = metadata; + const map = useMap(); + + // @ts-ignore + const [raster] = useState(new L.RasterCoords(map, [sizeX, sizeY], tileWidth)); + + useEffect(() => { + if (map === undefined) { + return; + } + + const { offsetHeight, offsetWidth } = map.getContainer(); + const southWest = raster.unproject([0, sizeY - (sizeY - offsetHeight) / 2]); + const northEast = raster.unproject([sizeX - (sizeX - offsetWidth) / 2, 0]); + const bounds = new L.LatLngBounds(southWest, northEast); + + map.fitBounds(bounds); + map.setMaxZoom(raster.zoomLevel()); + + const layer = new L.TileLayer(pictureTilesUrl, { + noWrap: false, + bounds: raster.getMaxBounds(), + maxNativeZoom: raster.zoomLevel(), + }); + map.addLayer(layer); + return () => { + if (layer !== null) { + map.removeLayer(layer); + } + }; + }, [map, raster]); + + return null; +}; +export default ViewPointHD; From 4b67fdb8d93ce68b830b672d194596b92d3a715d Mon Sep 17 00:00:00 2001 From: Florian Sommariva Date: Tue, 5 Sep 2023 16:56:29 +0200 Subject: [PATCH 08/37] Get viewpoint from trek page --- .../src/components/pages/details/__tests__/Details.test.tsx | 2 +- frontend/src/modules/details/adapter.ts | 4 ++++ frontend/src/modules/details/api.ts | 2 +- frontend/src/modules/details/connector.ts | 4 ++++ frontend/src/modules/details/interface.ts | 3 +++ frontend/src/modules/details/mocks/mocks.ts | 1 + 6 files changed, 14 insertions(+), 2 deletions(-) diff --git a/frontend/src/components/pages/details/__tests__/Details.test.tsx b/frontend/src/components/pages/details/__tests__/Details.test.tsx index d1306c429..ce197d9ec 100644 --- a/frontend/src/components/pages/details/__tests__/Details.test.tsx +++ b/frontend/src/components/pages/details/__tests__/Details.test.tsx @@ -48,7 +48,7 @@ describe('Details', () => { .query({ language: 'fr', fields: - 'id,name,departure,arrival,cities,attachments,practice,public_transport,access,advised_parking,description_teaser,ambiance,themes,duration,length_2d,ascent,descent,difficulty,route,networks,description,geometry,parking_location,pdf,gpx,kml,departure_city,disabled_infrastructure,accessibilities,source,information_desks,labels,advice,gear,points_reference,children,web_links,elevation_area_url,altimetric_profile,reservation_id,accessibility_signage,accessibility_slope,accessibility_width,accessibility_covering,accessibility_exposure,accessibility_advice,attachments_accessibility,accessibility_level,ratings,ratings_description', + 'id,name,departure,arrival,cities,attachments,practice,public_transport,access,advised_parking,description_teaser,ambiance,themes,duration,length_2d,ascent,descent,difficulty,route,networks,description,geometry,parking_location,pdf,gpx,kml,departure_city,disabled_infrastructure,accessibilities,source,information_desks,labels,advice,gear,points_reference,children,web_links,elevation_area_url,altimetric_profile,reservation_id,accessibility_signage,accessibility_slope,accessibility_width,accessibility_covering,accessibility_exposure,accessibility_advice,attachments_accessibility,accessibility_level,ratings,ratings_description,view_points', format: 'geojson', }) .reply(200, rawDetailsMock); diff --git a/frontend/src/modules/details/adapter.ts b/frontend/src/modules/details/adapter.ts index a29f63a89..74dac4b0a 100644 --- a/frontend/src/modules/details/adapter.ts +++ b/frontend/src/modules/details/adapter.ts @@ -30,6 +30,7 @@ import { getTrekGeometryAsLineStringCoordinates, } from 'modules/utils/geometry'; import { formatHours } from 'modules/utils/time'; +import { ViewPoint } from 'modules/viewPoint/interface'; import { TrekRatingScale } from '../trekRatingScale/interface'; import { TrekRatingChoices } from '../trekRating/interface'; import { Details, RawDetails, Reservation, TrekChildGeometry, TrekFamily } from './interface'; @@ -58,6 +59,7 @@ export const adaptResults = ({ reservation, trekRating, trekRatingScale, + viewPoints, }: { accessbilityLevel: AccessibilityLevel | null; rawDetails: RawDetails; @@ -82,6 +84,7 @@ export const adaptResults = ({ reservation: Reservation | null; trekRating: TrekRatingChoices; trekRatingScale: TrekRatingScale[]; + viewPoints: ViewPoint[]; }): Details => { try { const coordinates = getTrekGeometryAsLineStringCoordinates(geometry); @@ -187,6 +190,7 @@ export const adaptResults = ({ signage, service, infrastructure, + viewPoints, }; } catch (e) { console.error('Error in details/adapter', e); diff --git a/frontend/src/modules/details/api.ts b/frontend/src/modules/details/api.ts index f80e9511c..33618cdfa 100644 --- a/frontend/src/modules/details/api.ts +++ b/frontend/src/modules/details/api.ts @@ -5,7 +5,7 @@ import { RawDetails, RawTrekChildGeometry, RawTrekChildIds, RawTrekName } from ' const fieldsParams = { fields: - 'id,name,departure,arrival,cities,attachments,practice,public_transport,access,advised_parking,description_teaser,ambiance,themes,duration,length_2d,ascent,descent,difficulty,route,networks,description,geometry,parking_location,pdf,gpx,kml,departure_city,disabled_infrastructure,accessibilities,source,information_desks,labels,advice,gear,points_reference,children,web_links,elevation_area_url,altimetric_profile,reservation_id,accessibility_signage,accessibility_slope,accessibility_width,accessibility_covering,accessibility_exposure,accessibility_advice,attachments_accessibility,accessibility_level,ratings,ratings_description', + 'id,name,departure,arrival,cities,attachments,practice,public_transport,access,advised_parking,description_teaser,ambiance,themes,duration,length_2d,ascent,descent,difficulty,route,networks,description,geometry,parking_location,pdf,gpx,kml,departure_city,disabled_infrastructure,accessibilities,source,information_desks,labels,advice,gear,points_reference,children,web_links,elevation_area_url,altimetric_profile,reservation_id,accessibility_signage,accessibility_slope,accessibility_width,accessibility_covering,accessibility_exposure,accessibility_advice,attachments_accessibility,accessibility_level,ratings,ratings_description,view_points', format: 'geojson', }; diff --git a/frontend/src/modules/details/connector.ts b/frontend/src/modules/details/connector.ts index b4dd3f8af..768476cbc 100644 --- a/frontend/src/modules/details/connector.ts +++ b/frontend/src/modules/details/connector.ts @@ -13,6 +13,7 @@ import { getInfrastructure } from 'modules/infrastructure/connector'; import { getGlobalConfig } from 'modules/utils/api.config'; import { getTouristicContentsNearTarget } from 'modules/touristicContent/connector'; import { CommonDictionaries } from 'modules/dictionaries/interface'; +import { adaptViewPoints } from 'modules/viewPoint/adapter'; import { getTrekRating } from '../trekRating/connector'; import { getTrekRatingScale } from '../trekRatingScale/connector'; import { adaptChildren, adaptResults, adaptTrekChildGeometry } from './adapter'; @@ -52,6 +53,8 @@ export const getDetails = async ( getAccessibilities(language), ]); + const viewPoints = await adaptViewPoints(rawDetails.properties.view_points ?? []); + const [ activity, difficulty, @@ -118,6 +121,7 @@ export const getDetails = async ( project: getGlobalConfig().reservationProject, } : null, + viewPoints, }); } catch (e) { console.error('Error in details/connector principal', e); diff --git a/frontend/src/modules/details/interface.ts b/frontend/src/modules/details/interface.ts index 41e1e663e..b8a17f0bb 100644 --- a/frontend/src/modules/details/interface.ts +++ b/frontend/src/modules/details/interface.ts @@ -24,6 +24,7 @@ import { SensitiveArea } from 'modules/sensitiveArea/interface'; import { SignageDictionary } from 'modules/signage/interface'; import { Service } from 'modules/service/interface'; import { InfrastructureDictionary } from 'modules/infrastructure/interface'; +import { RawViewPoint, ViewPoint } from 'modules/viewPoint/interface'; import { TrekRatingWithScale } from '../trekRating/interface'; export interface RawDetails { @@ -93,6 +94,7 @@ export interface RawDetailsProperties { gear: string | null; ratings: number[]; ratings_description: string; + view_points: RawViewPoint[]; } // Fields parsed with react-html-parser in page @@ -190,6 +192,7 @@ export interface Details extends DetailsHtml { signage: SignageDictionary | null; service: Service[] | null; infrastructure: InfrastructureDictionary | null; + viewPoints: ViewPoint[]; } export interface WebLink { diff --git a/frontend/src/modules/details/mocks/mocks.ts b/frontend/src/modules/details/mocks/mocks.ts index b8ed384fa..48c221f07 100644 --- a/frontend/src/modules/details/mocks/mocks.ts +++ b/frontend/src/modules/details/mocks/mocks.ts @@ -136,6 +136,7 @@ export const rawDetailsProperties: RawDetailsProperties = { altimetric_profile: 'https://geotrekdemo.ecrins-parcnational.fr/api/fr/treks/2/profile.json', ratings: [], ratings_description: '', + view_points: [], }; export const rawDetails: RawDetails = { From e594bec2b9a8e94141f1c28c9b4b61efb82ff56d Mon Sep 17 00:00:00 2001 From: Florian Sommariva Date: Tue, 5 Sep 2023 16:57:08 +0200 Subject: [PATCH 09/37] Get viewpoint from outdoorsite page --- frontend/src/modules/outdoorSite/adapter.ts | 4 ++++ frontend/src/modules/outdoorSite/api.ts | 2 +- frontend/src/modules/outdoorSite/connector.ts | 4 ++++ frontend/src/modules/outdoorSite/interface.ts | 3 +++ 4 files changed, 12 insertions(+), 1 deletion(-) diff --git a/frontend/src/modules/outdoorSite/adapter.ts b/frontend/src/modules/outdoorSite/adapter.ts index 5df5c41c8..ca485e767 100644 --- a/frontend/src/modules/outdoorSite/adapter.ts +++ b/frontend/src/modules/outdoorSite/adapter.ts @@ -4,6 +4,7 @@ import { Service } from 'modules/service/interface'; import { InfrastructureDictionary } from 'modules/infrastructure/interface'; import { getAttachments, getThumbnail, getThumbnails } from 'modules/utils/adapter'; import { adaptGeometry } from 'modules/utils/geometry'; +import { ViewPoint } from 'modules/viewPoint/interface'; import { CityDictionnary } from '../city/interface'; import { Choices } from '../filters/interface'; import { InformationDeskDictionnary } from '../informationDesk/interface'; @@ -101,6 +102,7 @@ export const adaptOutdoorSiteDetails = ({ signage, service, infrastructure, + viewPoints, }: { rawOutdoorSiteDetails: RawOutdoorSiteDetails; pois: Poi[]; @@ -122,6 +124,7 @@ export const adaptOutdoorSiteDetails = ({ signage: SignageDictionary | null; service: Service[] | null; infrastructure: InfrastructureDictionary | null; + viewPoints: ViewPoint[]; }): OutdoorSiteDetails => ({ ...adaptOutdoorSites({ rawOutdoorSites: [ @@ -179,6 +182,7 @@ export const adaptOutdoorSiteDetails = ({ signage, service, infrastructure, + viewPoints, }); export const adaptOutdoorSitePopupResults = ({ diff --git a/frontend/src/modules/outdoorSite/api.ts b/frontend/src/modules/outdoorSite/api.ts index 0e9eb4903..31c77fbfc 100644 --- a/frontend/src/modules/outdoorSite/api.ts +++ b/frontend/src/modules/outdoorSite/api.ts @@ -15,7 +15,7 @@ export const fetchOutdoorSites = (query: APIQuery): Promise Date: Tue, 5 Sep 2023 16:49:51 +0200 Subject: [PATCH 10/37] Define the rules of map projection according to viewpoints --- .../Map/components/ViewPointHD/CRSPixel.ts | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 frontend/src/components/Map/components/ViewPointHD/CRSPixel.ts diff --git a/frontend/src/components/Map/components/ViewPointHD/CRSPixel.ts b/frontend/src/components/Map/components/ViewPointHD/CRSPixel.ts new file mode 100644 index 000000000..6530c2a49 --- /dev/null +++ b/frontend/src/components/Map/components/ViewPointHD/CRSPixel.ts @@ -0,0 +1,18 @@ +import L from 'leaflet'; +import { ViewPoint } from 'modules/viewPoint/interface'; + +export const CRSPixel = ({ metadata }: ViewPoint) => { + if (metadata === null) { + return L.CRS.Simple; + } + const { sizeX, sizeY, tileWidth, levels } = metadata; + const step = 2 ** (levels - 1); + return L.Util.extend(L.CRS.Simple, { + transformation: new L.Transformation( + Math.min(step * tileWidth, sizeX) / step / sizeX, + 0, + Math.min(step * tileWidth, sizeY) / step / sizeY, + 0, + ), + }); +}; From 96316b9fd7d26e6e07d4356b3ae0e0935a8abfa3 Mon Sep 17 00:00:00 2001 From: Florian Sommariva Date: Tue, 5 Sep 2023 16:55:22 +0200 Subject: [PATCH 11/37] Display viewpoint photo instead of map --- .../components/Map/DetailsMap/DetailsMap.tsx | 23 ++++++++++++++++--- .../src/components/pages/details/Details.tsx | 5 ++++ .../components/pages/site/OutdoorSiteUI.tsx | 6 ++++- 3 files changed, 30 insertions(+), 4 deletions(-) diff --git a/frontend/src/components/Map/DetailsMap/DetailsMap.tsx b/frontend/src/components/Map/DetailsMap/DetailsMap.tsx index 599ecb3ae..0cf4ca074 100644 --- a/frontend/src/components/Map/DetailsMap/DetailsMap.tsx +++ b/frontend/src/components/Map/DetailsMap/DetailsMap.tsx @@ -1,9 +1,8 @@ import { GeometryList } from 'components/Map/DetailsMap/GeometryList'; import { LatLngBoundsExpression } from 'leaflet'; -import React, { useContext, useEffect } from 'react'; +import { useContext, useEffect } from 'react'; import { MapContainer, ScaleControl } from 'react-leaflet'; import 'leaflet/dist/leaflet.css'; -import styled, { css } from 'styled-components'; import { ArrowLeft } from 'components/Icons/ArrowLeft'; @@ -28,6 +27,8 @@ import { InformationDesk } from 'modules/informationDesk/interface'; import { SignageDictionary } from 'modules/signage/interface'; import { InfrastructureDictionary } from 'modules/infrastructure/interface'; import { cn } from 'services/utils/cn'; +import { ViewPoint } from 'modules/viewPoint/interface'; +import { BackToMapButton } from 'components/BackToMapButton'; import { BackButton } from '../components/BackButton'; import { TrekMarkersAndCourse } from './TrekMarkersAndCourse'; @@ -40,6 +41,9 @@ 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'; export interface GeometryListProps { geometry: @@ -56,6 +60,7 @@ export interface GeometryListProps { } export type PropsType = { + mapId?: string; access?: any; experiences?: any; courses?: any; @@ -86,6 +91,9 @@ export type PropsType = { signage?: SignageDictionary | null; service?: PointWithIcon[]; infrastructure?: InfrastructureDictionary | null; + viewPoints?: ViewPoint[]; + displayMap?: () => void; + setMapId?: (id: string) => void; }; export const DetailsMap: React.FC = props => { const { reportVisibility, setReportVisibility } = useDetailsAndMapContext(); @@ -175,8 +183,8 @@ export const DetailsMap: React.FC = props => { zoomControl={props.hasZoomControl} whenCreated={setMapInstance} bounds={bounds} + {...(mapToDisplay !== 'default' && { crs: CRSPixel(mapToDisplay) })} > - {reportVisibility && coordinatesReportTouched ? ( } onClick={hideMap}> @@ -185,6 +193,15 @@ export const DetailsMap: React.FC = props => { } onClick={hideMap} /> )} {props.hasZoomControl && } + {mapToDisplay !== 'default' && ( + <> + + {'type' in mapToDisplay.annotations && ( + + )} + + + )} {mapToDisplay === 'default' && ( <> diff --git a/frontend/src/components/pages/details/Details.tsx b/frontend/src/components/pages/details/Details.tsx index a06a85666..cff467b22 100644 --- a/frontend/src/components/pages/details/Details.tsx +++ b/frontend/src/components/pages/details/Details.tsx @@ -598,6 +598,7 @@ export const DetailsUIWithoutContext: React.FC = ({ slug, parentId, langu )} > = ({ slug, parentId, langu id: `DETAILS-SERVICE-${service.id}`, }))} infrastructure={details.infrastructure} + viewPoints={details.viewPoints} + displayMap={displayMobileMap} + setMapId={setMapId} /> @@ -679,6 +683,7 @@ export const DetailsUIWithoutContext: React.FC = ({ slug, parentId, langu refetch, sectionsReferences, trekFamily, + mapId, ], ); }; diff --git a/frontend/src/components/pages/site/OutdoorSiteUI.tsx b/frontend/src/components/pages/site/OutdoorSiteUI.tsx index dc4690ff9..976819788 100644 --- a/frontend/src/components/pages/site/OutdoorSiteUI.tsx +++ b/frontend/src/components/pages/site/OutdoorSiteUI.tsx @@ -531,6 +531,7 @@ const OutdoorSiteUIWithoutContext: React.FC = ({ outdoorSiteUrl, language )} > = ({ outdoorSiteUrl, language }))} infrastructure={outdoorSiteContent.infrastructure} hideMap={hideMobileMap} + viewPoints={outdoorSiteContent.viewPoints} + displayMap={displayMobileMap} + setMapId={setMapId} /> @@ -583,7 +587,7 @@ const OutdoorSiteUIWithoutContext: React.FC = ({ outdoorSiteUrl, language )} ), - [outdoorSiteContent, isLoading, mobileMapState, sectionsReferences, hasNavigator], + [outdoorSiteContent, isLoading, mobileMapState, sectionsReferences, hasNavigator, mapId], ); }; From 5ee78857df134ae6654d6d7794c2ce568b1f6cc5 Mon Sep 17 00:00:00 2001 From: Florian Sommariva Date: Tue, 5 Sep 2023 16:58:57 +0200 Subject: [PATCH 12/37] Active report redifine default map --- frontend/src/components/Report/Report.tsx | 4 +++- frontend/src/components/pages/details/Details.tsx | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/frontend/src/components/Report/Report.tsx b/frontend/src/components/Report/Report.tsx index 0dda86954..ac883b5d4 100644 --- a/frontend/src/components/Report/Report.tsx +++ b/frontend/src/components/Report/Report.tsx @@ -19,11 +19,12 @@ import CoordinatesRow from './CoordinatesRow'; interface Props { displayMobileMap?: () => void; + setMapId?: (str: string) => void; trekId: number; startPoint: PointGeometry; } -const Report: React.FC = ({ displayMobileMap, startPoint, trekId }) => { +const Report: React.FC = ({ displayMobileMap, setMapId, startPoint, trekId }) => { const { state, coordinatesReportTouched, @@ -53,6 +54,7 @@ const Report: React.FC = ({ displayMobileMap, startPoint, trekId }) => { const isMobile = useMediaPredicate('(max-width: 1024px)'); const handleReportButtonClick = () => { + setMapId?.('default'); if (isMobile) { displayMobileMap?.(); setReportVisibility(true); diff --git a/frontend/src/components/pages/details/Details.tsx b/frontend/src/components/pages/details/Details.tsx index cff467b22..6b42af804 100644 --- a/frontend/src/components/pages/details/Details.tsx +++ b/frontend/src/components/pages/details/Details.tsx @@ -477,6 +477,7 @@ export const DetailsUIWithoutContext: React.FC = ({ slug, parentId, langu > Date: Tue, 5 Sep 2023 17:00:57 +0200 Subject: [PATCH 13/37] Handle OpenMapbutton component with viewpoint --- .../OpenMapButton/OpenMapButton.tsx | 31 +++++++++++++------ 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/frontend/src/components/OpenMapButton/OpenMapButton.tsx b/frontend/src/components/OpenMapButton/OpenMapButton.tsx index 3c000165c..e325acbca 100644 --- a/frontend/src/components/OpenMapButton/OpenMapButton.tsx +++ b/frontend/src/components/OpenMapButton/OpenMapButton.tsx @@ -1,26 +1,39 @@ +import { useCallback } from 'react'; import { Map } from 'components/Icons/Map'; import { FormattedMessage } from 'react-intl'; import { useHideOnScrollDown } from 'hooks/useHideOnScrollDown'; -import { Button } from 'components/Button'; import { cn } from 'services/utils/cn'; export const OpenMapButton: React.FC< - React.ButtonHTMLAttributes & { displayMap: () => void } -> = ({ displayMap, ...nativeButtonProps }) => { + React.ButtonHTMLAttributes & { + displayMap: () => void; + setMapId?: (key: string) => void; + } +> = ({ displayMap, setMapId, ...nativeButtonProps }) => { const buttonDisplayState = useHideOnScrollDown(); + const handleClick = useCallback(() => { + displayMap(); + setMapId?.('default'); + }, [displayMap, setMapId]); + return ( - + + ); }; From 7149a43e19da3d9e9753b610faf50b800411d319 Mon Sep 17 00:00:00 2001 From: Florian Sommariva Date: Tue, 5 Sep 2023 17:20:14 +0200 Subject: [PATCH 14/37] Create detailsMedias component --- .../DetailsMedias/DetailsMedias.tsx | 83 +++++++++++++++++++ .../details/components/DetailsMedias/index.ts | 1 + frontend/src/translations/ca.json | 6 ++ frontend/src/translations/de.json | 6 ++ frontend/src/translations/en.json | 6 ++ frontend/src/translations/es.json | 6 ++ frontend/src/translations/fr.json | 6 ++ frontend/src/translations/it.json | 6 ++ 8 files changed, 120 insertions(+) create mode 100644 frontend/src/components/pages/details/components/DetailsMedias/DetailsMedias.tsx create mode 100644 frontend/src/components/pages/details/components/DetailsMedias/index.ts diff --git a/frontend/src/components/pages/details/components/DetailsMedias/DetailsMedias.tsx b/frontend/src/components/pages/details/components/DetailsMedias/DetailsMedias.tsx new file mode 100644 index 000000000..f65f0e4ae --- /dev/null +++ b/frontend/src/components/pages/details/components/DetailsMedias/DetailsMedias.tsx @@ -0,0 +1,83 @@ +import ImageWithLegend from 'components/ImageWithLegend'; +import ArrowRight from 'components/Map/components/DetailsMapDrawer/ArrowRight'; +import { ViewPoint } from 'modules/viewPoint/interface'; +import { useCallback } from 'react'; +import { FormattedMessage } from 'react-intl'; +import { cn } from 'services/utils/cn'; + +interface DetailsMediasProps { + viewPoints: ViewPoint[]; + displayMap: () => void; + setMapId: (key: string) => void; +} + +export const DetailsMedias: React.FC = ({ + viewPoints, + displayMap, + setMapId, +}) => { + const handleClick = useCallback( + (id: string) => { + displayMap(); + setMapId(id); + }, + [displayMap, setMapId], + ); + + return ( +
+

+ +

+
    + {viewPoints.map(viewPoint => { + const legend = [viewPoint.legend, viewPoint.author].filter(Boolean).join(' - '); + return ( +
  • +
    + +
    +
    +
    +

    + {viewPoint.title} +

    + {legend.length > 0 && ( +

    + {legend} +

    + )} +
    + +
    +
  • + ); + })} +
+
+ ); +}; diff --git a/frontend/src/components/pages/details/components/DetailsMedias/index.ts b/frontend/src/components/pages/details/components/DetailsMedias/index.ts new file mode 100644 index 000000000..c6fbcc7f1 --- /dev/null +++ b/frontend/src/components/pages/details/components/DetailsMedias/index.ts @@ -0,0 +1 @@ +export { DetailsMedias } from './DetailsMedias'; diff --git a/frontend/src/translations/ca.json b/frontend/src/translations/ca.json index cdcae3af6..83dc48a60 100644 --- a/frontend/src/translations/ca.json +++ b/frontend/src/translations/ca.json @@ -127,6 +127,7 @@ "description": "Descripció", "recommandations": "Recomanacions", "informationDesks": "Llocs d’informació", + "medias": "Mitjans de comunicació", "practicalInformations": "Infos pràctiques", "forecastWidget": "Informe del temps", "accessibility": "Accessibilitat", @@ -240,6 +241,11 @@ "coursesFullTitle": "Les {count} parcours à découvrir", "sitesFullTitle": "Els {count} llocs de pràcticar a descobrir" }, + "viewPoint": { + "title": "Fotos HD", + "credit": "Crèdit fotogràfic :", + "browsePicture": "Navega per la foto" + }, "Wind": { "N": "Nord", "S": "Sud", diff --git a/frontend/src/translations/de.json b/frontend/src/translations/de.json index 46d5b593c..ca748a971 100644 --- a/frontend/src/translations/de.json +++ b/frontend/src/translations/de.json @@ -127,6 +127,7 @@ "description": "Beschreibung", "recommandations": "Empfehlungen", "informationDesks": "Orte der Information", + "medias": "Medien", "practicalInformations": "Praktische Informationen", "forecastWidget": "Wetterbericht", "accessibility": "Zugänglichkeit", @@ -240,6 +241,11 @@ "coursesFullTitle": "Les {count} parcours à découvrir", "sitesFullTitle": "Die {count} Orte der Praxis, die es zu entdecken gilt" }, + "viewPoint": { + "title": "HD-Fotos", + "credit": "Fotogutschrift:", + "browsePicture": "Foto durchsuchen" + }, "Wind": { "N": "Norden", "S": "Süden", diff --git a/frontend/src/translations/en.json b/frontend/src/translations/en.json index 7d2cbafcb..1be0c34d2 100644 --- a/frontend/src/translations/en.json +++ b/frontend/src/translations/en.json @@ -130,6 +130,7 @@ "description": "Description", "recommandations": "Recommandations", "informationDesks": "Information desks", + "medias": "Medias", "practicalInformations": "Practical informations", "forecastWidget": "Forecast", "accessibility": "Accessibility", @@ -247,6 +248,11 @@ "coursesFullTitle": "Les {count} parcours à découvrir", "sitesFullTitle": "The {count} places of practice to discover" }, + "viewPoint": { + "title": "HD photos", + "credit": "Photo credit:", + "browsePicture": "Browse photo" + }, "Wind": { "N": "North", "S": "South", diff --git a/frontend/src/translations/es.json b/frontend/src/translations/es.json index 33bbd62df..47455832d 100644 --- a/frontend/src/translations/es.json +++ b/frontend/src/translations/es.json @@ -127,6 +127,7 @@ "description": "Descripción", "recommandations": "Recomendaciones", "informationDesks": "Lugares de información", + "medias": "Medias", "practicalInformations": "Infos prácticas", "forecastWidget": "Reporte del clima", "accessibility": "Accesibilidad", @@ -240,6 +241,11 @@ "coursesFullTitle": "Les {count} parcours à découvrir", "sitesFullTitle": "Los {count} lugares de práctica para descubrir" }, + "viewPoint": { + "title": "Fotos HD", + "credit": "Crédito de la foto:", + "browsePicture": "Examinar foto" + }, "Wind": { "N": "Norte", "S": "Sur", diff --git a/frontend/src/translations/fr.json b/frontend/src/translations/fr.json index 0aa8ad45a..74747e677 100644 --- a/frontend/src/translations/fr.json +++ b/frontend/src/translations/fr.json @@ -130,6 +130,7 @@ "description": "Description", "recommandations": "Recommandations", "informationDesks": "Lieux de renseignement", + "medias": "Medias", "practicalInformations": "Infos pratiques", "forecastWidget": "Météo", "accessibility": "Accessibilité", @@ -247,6 +248,11 @@ "coursesFullTitle": "Les {count} parcours à découvrir", "sitesFullTitle": "Les {count} lieux de pratique à découvrir" }, + "viewPoint": { + "title": "Photos HD", + "credit": "Crédit photo :", + "browsePicture": "Parcourir la photo" + }, "Wind": { "N": "Nord", "S": "Sud", diff --git a/frontend/src/translations/it.json b/frontend/src/translations/it.json index a27c9f8fd..dacf898cd 100644 --- a/frontend/src/translations/it.json +++ b/frontend/src/translations/it.json @@ -130,6 +130,7 @@ "description": "Descrizione", "recommandations": "Raccomandazioni", "informationDesks": "Luoghi di informazione", + "medias": "Medias", "practicalInformations": "Informazioni pratiche", "forecastWidget": "Bollettino meteorologico", "accessibility": "Accessibilità", @@ -250,6 +251,11 @@ "coursesFullTitle": "Les {count} parcours à découvrir", "sitesFullTitle": "Il {conteggio} dei luoghi di pratica da scoprire" }, + "viewPoint": { + "title": "Foto HD", + "credit": "Credito foto:", + "browsePicture": "Sfoglia foto" + }, "Wind": { "N": "Nord", "S": "Sud", From 5855e2c1755bda0b0c0cc2f7090cc8f83cbdd668 Mon Sep 17 00:00:00 2001 From: Florian Sommariva Date: Tue, 5 Sep 2023 17:22:54 +0200 Subject: [PATCH 15/37] Call detailMedias section in details pages --- frontend/config/details.json | 12 +++++++ .../src/components/pages/details/Details.tsx | 31 +++++++++++++++++-- .../DetailsMedias/DetailsMedias.tsx | 13 +++----- .../src/components/pages/details/interface.ts | 2 ++ .../components/pages/site/OutdoorSiteUI.tsx | 31 +++++++++++++++++-- 5 files changed, 77 insertions(+), 12 deletions(-) diff --git a/frontend/config/details.json b/frontend/config/details.json index 22978b7e9..b143aa80c 100644 --- a/frontend/config/details.json +++ b/frontend/config/details.json @@ -7,6 +7,12 @@ "anchor": true, "order": 10 }, + { + "name": "medias", + "display": true, + "anchor": false, + "order": 15 + }, { "name": "itinerancySteps", "display": true, @@ -170,6 +176,12 @@ "anchor": true, "order": 10 }, + { + "name": "medias", + "display": true, + "anchor": false, + "order": 15 + }, { "name": "poi", "display": true, diff --git a/frontend/src/components/pages/details/Details.tsx b/frontend/src/components/pages/details/Details.tsx index 6b42af804..b5a662ed2 100644 --- a/frontend/src/components/pages/details/Details.tsx +++ b/frontend/src/components/pages/details/Details.tsx @@ -10,7 +10,7 @@ import { OpenMapButton } from 'components/OpenMapButton'; import { useShowOnScrollPosition } from 'hooks/useShowOnScrollPosition'; import { useMediaPredicate } from 'react-media-hook'; import { sizes } from 'stylesheet'; -import React, { useMemo, useRef } from 'react'; +import { useCallback, useMemo, useRef } from 'react'; import { TrekChildGeometry } from 'modules/details/interface'; import { cleanHTMLElementsFromString } from 'modules/utils/string'; import Report from 'components/Report/Report'; @@ -51,6 +51,7 @@ import { DetailsSensitiveArea } from './components/DetailsSensitiveArea'; import { useOnScreenSection } from './hooks/useHighlightedSection'; import { DetailsGear } from './components/DetailsGear'; import { useDetailsSections } from './useDetailsSections'; +import { DetailsMedias } from './components/DetailsMedias'; interface Props { slug: string | string[] | undefined; @@ -72,6 +73,8 @@ export const DetailsUIWithoutContext: React.FC = ({ slug, parentId, langu displayMobileMap, hideMobileMap, sectionRef, + mapId, + setMapId, } = useDetails(slug, parentId, language); const isMobile = useMediaPredicate('(max-width: 1024px)'); @@ -105,6 +108,14 @@ export const DetailsUIWithoutContext: React.FC = ({ slug, parentId, langu (getGlobalConfig().minAltitudeDifferenceToDisplayElevationProfile ?? 0) < higherDifferenceElevation; + const handleViewPointClick = useCallback( + (viewPointId: string) => { + setMapId(viewPointId); + displayMobileMap(); + }, + [displayMobileMap, setMapId], + ); + return useMemo( () => ( <> @@ -135,7 +146,7 @@ export const DetailsUIWithoutContext: React.FC = ({ slug, parentId, langu id="details_informationContainer" className="flex flex-col w-full relative -top-detailsHeaderMobile desktop:top-0 desktop:w-3/5" > - +
{({ isFullscreen, toggleFullscreen }) => ( @@ -197,6 +208,22 @@ export const DetailsUIWithoutContext: React.FC = ({ slug, parentId, langu ); } + if (section.name === 'medias' && details.viewPoints.length > 0) { + return ( +
+ + + +
+ ); + } if (section.name === 'itinerancySteps' && details.children.length > 0) { return (
void; - setMapId: (key: string) => void; + handleViewPointClick: (key: string) => void; } export const DetailsMedias: React.FC = ({ viewPoints, - displayMap, - setMapId, + handleViewPointClick, }) => { const handleClick = useCallback( - (id: string) => { - displayMap(); - setMapId(id); + (viewPointId: string) => { + handleViewPointClick(viewPointId); }, - [displayMap, setMapId], + [handleViewPointClick], ); return ( diff --git a/frontend/src/components/pages/details/interface.ts b/frontend/src/components/pages/details/interface.ts index 001d4ca21..8931fb343 100644 --- a/frontend/src/components/pages/details/interface.ts +++ b/frontend/src/components/pages/details/interface.ts @@ -1,5 +1,6 @@ export type DetailsSectionTrekNames = | 'presentation' + | 'medias' | 'itinerancySteps' | 'poi' | 'description' @@ -32,6 +33,7 @@ export type DetailsSectionTouristicEventNames = export type DetailsSectionOutdoorSiteNames = | 'presentation' + | 'medias' | 'poi' | 'description' | 'subsites' diff --git a/frontend/src/components/pages/site/OutdoorSiteUI.tsx b/frontend/src/components/pages/site/OutdoorSiteUI.tsx index 976819788..057114d2b 100644 --- a/frontend/src/components/pages/site/OutdoorSiteUI.tsx +++ b/frontend/src/components/pages/site/OutdoorSiteUI.tsx @@ -18,7 +18,7 @@ import { } from 'components/pages/details/utils'; import { VisibleSectionProvider } from 'components/pages/details/VisibleSectionContext'; import { DetailsChildrenSection } from 'components/pages/details/components/DetailsChildrenSection'; -import { useMemo, useRef } from 'react'; +import { useCallback, useMemo, useRef } from 'react'; import { FormattedMessage, useIntl } from 'react-intl'; import Loader from 'components/Loader'; import { useMediaPredicate } from 'react-media-hook'; @@ -42,6 +42,7 @@ import { DetailsCoverCarousel } from '../details/components/DetailsCoverCarousel import { DetailsSensitiveArea } from '../details/components/DetailsSensitiveArea'; import { DetailsAndMapProvider } from '../details/DetailsAndMapContext'; import { useDetailsSections } from '../details/useDetailsSections'; +import { DetailsMedias } from '../details/components/DetailsMedias'; interface Props { outdoorSiteUrl: string | string[] | undefined; @@ -60,6 +61,8 @@ const OutdoorSiteUIWithoutContext: React.FC = ({ outdoorSiteUrl, language sectionsReferences, sectionsPositions, sectionRef, + mapId, + setMapId, } = useOutdoorSite(outdoorSiteUrl, language); const intl = useIntl(); @@ -85,6 +88,14 @@ const OutdoorSiteUIWithoutContext: React.FC = ({ outdoorSiteUrl, language sizes.detailsHeaderDesktop, }); + const handleViewPointClick = useCallback( + (viewPointId: string) => { + setMapId(viewPointId); + displayMobileMap(); + }, + [displayMobileMap, setMapId], + ); + return useMemo( () => ( <> @@ -117,7 +128,7 @@ const OutdoorSiteUIWithoutContext: React.FC = ({ outdoorSiteUrl, language id="outdoorSiteContent_informations" className="flex flex-col w-full relative -top-detailsHeaderMobile desktop:top-0 desktop:w-3/5" > - +
{({ isFullscreen, toggleFullscreen }) => ( @@ -188,6 +199,22 @@ const OutdoorSiteUIWithoutContext: React.FC = ({ outdoorSiteUrl, language
); } + if (section.name === 'medias' && outdoorSiteContent.viewPoints.length > 0) { + return ( +
+ + + +
+ ); + } if ( section.name === 'poi' && outdoorSiteContent?.pois?.length && From 4fb0da1bc11bd8609bea9241d18aba76c57e969e Mon Sep 17 00:00:00 2001 From: Florian Sommariva Date: Wed, 6 Sep 2023 17:28:08 +0200 Subject: [PATCH 16/37] Display annotation in control section --- .../src/components/Map/DetailsMap/DetailsMap.tsx | 14 ++++++++++++-- .../components/Map/DetailsMap/useDetailsMap.tsx | 6 ++++++ .../ControlSection/ControlPanel/index.tsx | 10 ++++++++++ .../components/ControlSection/ControlSection.tsx | 2 ++ frontend/src/translations/ca.json | 3 ++- frontend/src/translations/de.json | 3 ++- frontend/src/translations/en.json | 3 ++- frontend/src/translations/es.json | 3 ++- frontend/src/translations/fr.json | 3 ++- frontend/src/translations/it.json | 3 ++- 10 files changed, 42 insertions(+), 8 deletions(-) diff --git a/frontend/src/components/Map/DetailsMap/DetailsMap.tsx b/frontend/src/components/Map/DetailsMap/DetailsMap.tsx index 0cf4ca074..4decfa135 100644 --- a/frontend/src/components/Map/DetailsMap/DetailsMap.tsx +++ b/frontend/src/components/Map/DetailsMap/DetailsMap.tsx @@ -126,6 +126,8 @@ export const DetailsMap: React.FC = props => { toggleServiceVisibility, infrastructureVisibility, toggleInfrastructureVisibility, + annotationViewpointVisibility, + toggleAnnotationViewpointVisibility, } = useDetailsMap(); const mapConfig = getMapConfig(); @@ -196,8 +198,16 @@ export const DetailsMap: React.FC = props => { {mapToDisplay !== 'default' && ( <> - {'type' in mapToDisplay.annotations && ( - + {'type' in mapToDisplay.annotations && annotationViewpointVisibility && ( + <> + + {annotationViewpointVisibility === 'DISPLAYED' && ( + + )} + )} diff --git a/frontend/src/components/Map/DetailsMap/useDetailsMap.tsx b/frontend/src/components/Map/DetailsMap/useDetailsMap.tsx index cfd0cd6f9..c2de58632 100644 --- a/frontend/src/components/Map/DetailsMap/useDetailsMap.tsx +++ b/frontend/src/components/Map/DetailsMap/useDetailsMap.tsx @@ -21,6 +21,8 @@ export const useDetailsMap = () => { const [signageVisibility, setSignageVisibility] = useState('HIDDEN'); const [serviceVisibility, setServiceVisibility] = useState('HIDDEN'); const [infrastructureVisibility, setInfrastructureVisibility] = useState('HIDDEN'); + const [annotationViewpointVisibility, setAnnotationViewpointVisibility] = + useState('DISPLAYED'); const toggleTrekChildrenVisibility = () => setTrekChildrenVisibility(toggleVisibility); @@ -37,6 +39,8 @@ export const useDetailsMap = () => { const toggleSignageVisibility = () => setSignageVisibility(toggleVisibility); const toggleServiceVisibility = () => setServiceVisibility(toggleVisibility); const toggleInfrastructureVisibility = () => setInfrastructureVisibility(toggleVisibility); + const toggleAnnotationViewpointVisibility = () => + setAnnotationViewpointVisibility(toggleVisibility); return { trekChildrenMobileVisibility, @@ -59,5 +63,7 @@ export const useDetailsMap = () => { toggleServiceVisibility, infrastructureVisibility, toggleInfrastructureVisibility, + annotationViewpointVisibility, + toggleAnnotationViewpointVisibility, }; }; diff --git a/frontend/src/components/Map/components/ControlSection/ControlPanel/index.tsx b/frontend/src/components/Map/components/ControlSection/ControlPanel/index.tsx index 9f6e02d28..b5a7316d0 100644 --- a/frontend/src/components/Map/components/ControlSection/ControlPanel/index.tsx +++ b/frontend/src/components/Map/components/ControlSection/ControlPanel/index.tsx @@ -33,6 +33,8 @@ export const ControlPanel: React.FC = ({ toggleServiceVisibility, infrastructureVisibility, toggleInfrastructureVisibility, + annotationViewpointVisibility, + toggleAnnotationViewpointVisibility, }) => { return (
@@ -116,6 +118,14 @@ export const ControlPanel: React.FC = ({ transKey="search.map.panel.service" /> )} + {annotationViewpointVisibility && toggleAnnotationViewpointVisibility && ( + + )}
); }; diff --git a/frontend/src/components/Map/components/ControlSection/ControlSection.tsx b/frontend/src/components/Map/components/ControlSection/ControlSection.tsx index bd5925591..5a815ee5e 100644 --- a/frontend/src/components/Map/components/ControlSection/ControlSection.tsx +++ b/frontend/src/components/Map/components/ControlSection/ControlSection.tsx @@ -30,6 +30,8 @@ export interface ControlSectionProps { toggleServiceVisibility?: () => void; infrastructureVisibility?: Visibility; toggleInfrastructureVisibility?: () => void; + annotationViewpointVisibility?: Visibility; + toggleAnnotationViewpointVisibility?: () => void; className?: string; position?: ControlPosition; } diff --git a/frontend/src/translations/ca.json b/frontend/src/translations/ca.json index 83dc48a60..3425bc2c6 100644 --- a/frontend/src/translations/ca.json +++ b/frontend/src/translations/ca.json @@ -100,7 +100,8 @@ "experiences": "Lieux de pratique", "signage": "Senyalització", "infrastructure": "Infrastructures", - "service": "Others infos" + "service": "Others infos", + "annotations": "Annotations" }, "resetView": "Recenter el mapa" }, diff --git a/frontend/src/translations/de.json b/frontend/src/translations/de.json index ca748a971..37a59fe22 100644 --- a/frontend/src/translations/de.json +++ b/frontend/src/translations/de.json @@ -100,7 +100,8 @@ "experiences": "Lieux de pratique", "signage": "Beschilderung", "infrastructure": "Infrastructures", - "service": "Others infos" + "service": "Others infos", + "annotations": "Annotations" }, "resetView": "Karte zentrieren" }, diff --git a/frontend/src/translations/en.json b/frontend/src/translations/en.json index 1be0c34d2..67f955356 100644 --- a/frontend/src/translations/en.json +++ b/frontend/src/translations/en.json @@ -103,7 +103,8 @@ "experiences": "Lieux de pratique", "signage": "Signage", "infrastructure": "Infrastructures", - "service": "Others infos" + "service": "Others infos", + "annotations": "Annotations" }, "resetView": "Recenter map" }, diff --git a/frontend/src/translations/es.json b/frontend/src/translations/es.json index 47455832d..b43b66247 100644 --- a/frontend/src/translations/es.json +++ b/frontend/src/translations/es.json @@ -100,7 +100,8 @@ "experiences": "Lieux de pratique", "signage": "Señalización", "infrastructure": "Infrastructures", - "service": "Others infos" + "service": "Others infos", + "annotations": "Annotations" }, "resetView": "Centrarse la mapa" }, diff --git a/frontend/src/translations/fr.json b/frontend/src/translations/fr.json index 74747e677..71bb4fda3 100644 --- a/frontend/src/translations/fr.json +++ b/frontend/src/translations/fr.json @@ -103,7 +103,8 @@ "experiences": "Lieux de pratique", "signage": "Signalétiques", "infrastructure": "Aménagements", - "service": "Autres infos" + "service": "Autres infos", + "annotations": "Annotations" }, "resetView": "Recentrer la carte" }, diff --git a/frontend/src/translations/it.json b/frontend/src/translations/it.json index dacf898cd..4f2be9751 100644 --- a/frontend/src/translations/it.json +++ b/frontend/src/translations/it.json @@ -103,7 +103,8 @@ "experiences": "Lieux de pratique", "signage": "Segnaletica", "infrastructure": "Infrastructures", - "service": "Others infos" + "service": "Others infos", + "annotations": "Annotations" }, "resetView": "Rimettere a fuoco la mappa" }, From edfabf922ccbe2e00ea433b2d136f8a6c9d49e44 Mon Sep 17 00:00:00 2001 From: Florian Sommariva Date: Wed, 6 Sep 2023 18:36:58 +0200 Subject: [PATCH 17/37] Remove backToMapButton on fullscreen mode --- frontend/src/styles/global.css | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/frontend/src/styles/global.css b/frontend/src/styles/global.css index 8a7c6e475..9c28b038c 100644 --- a/frontend/src/styles/global.css +++ b/frontend/src/styles/global.css @@ -76,3 +76,7 @@ .leaflet-container .leaflet-control-zoom { @apply order-first; } + +.leaflet-container:fullscreen #backToMapButton { + @apply hidden; +} From 5eafbc2c050ddd7c41a123a40f723eb9facaba5d Mon Sep 17 00:00:00 2001 From: Florian Sommariva Date: Wed, 13 Sep 2023 11:36:16 +0200 Subject: [PATCH 18/37] Get viewpoint for POI module --- frontend/src/modules/poi/adapter.ts | 37 +++++++++++++++---------- frontend/src/modules/poi/api.ts | 2 +- frontend/src/modules/poi/interface.ts | 3 ++ frontend/src/modules/poi/mocks/index.ts | 4 ++- 4 files changed, 30 insertions(+), 16 deletions(-) diff --git a/frontend/src/modules/poi/adapter.ts b/frontend/src/modules/poi/adapter.ts index 299333021..78c520d88 100644 --- a/frontend/src/modules/poi/adapter.ts +++ b/frontend/src/modules/poi/adapter.ts @@ -1,5 +1,6 @@ import { PoiTypeDictionnary } from 'modules/poiType/interface'; import { getAttachments, getThumbnails } from 'modules/utils/adapter'; +import { adaptViewPoints } from 'modules/viewPoint/adapter'; import { Poi, RawPoi } from './interface'; export const adaptPoi = ({ @@ -8,17 +9,25 @@ export const adaptPoi = ({ }: { rawPoisResults: RawPoi[]; poiTypes: PoiTypeDictionnary; -}): Poi[] => - rawPoisResults.map(rawPoi => ({ - id: `${rawPoi.id}`, - name: rawPoi.name, - description: rawPoi.description, - thumbnails: getThumbnails(rawPoi.attachments), - attachments: getAttachments(rawPoi.attachments), - type: poiTypes[rawPoi.type], - geometry: { - x: rawPoi.geometry.coordinates[0], - y: rawPoi.geometry.coordinates[1], - z: rawPoi.geometry.coordinates[2], - }, - })); +}): Promise => + Promise.all( + rawPoisResults.map(async rawPoi => { + const viewPoints = + rawPoi.view_points?.length > 0 ? await adaptViewPoints(rawPoi.view_points) : []; + + return { + id: `${rawPoi.id}`, + name: rawPoi.name, + description: rawPoi.description, + thumbnails: getThumbnails(rawPoi.attachments), + attachments: getAttachments(rawPoi.attachments), + type: poiTypes[rawPoi.type], + geometry: { + x: rawPoi.geometry.coordinates[0], + y: rawPoi.geometry.coordinates[1], + z: rawPoi.geometry.coordinates[2], + }, + viewPoints, + }; + }), + ); diff --git a/frontend/src/modules/poi/api.ts b/frontend/src/modules/poi/api.ts index fc63f2f55..45dd9d014 100644 --- a/frontend/src/modules/poi/api.ts +++ b/frontend/src/modules/poi/api.ts @@ -3,7 +3,7 @@ import { APIQuery, APIResponseForList } from 'services/api/interface'; import { RawPoi } from './interface'; const fieldsParams = { - fields: 'id,name,description,attachments,type,geometry', + fields: 'id,name,description,attachments,type,geometry,view_points', }; export const fetchPois = (query: APIQuery): Promise> => diff --git a/frontend/src/modules/poi/interface.ts b/frontend/src/modules/poi/interface.ts index d70e3080c..ed5be3417 100644 --- a/frontend/src/modules/poi/interface.ts +++ b/frontend/src/modules/poi/interface.ts @@ -1,5 +1,6 @@ import { Attachment, Coordinate3D, RawAttachment, RawPointGeometry3D } from 'modules/interface'; import { PoiType } from 'modules/poiType/interface'; +import { RawViewPoint, ViewPoint } from 'modules/viewPoint/interface'; export interface RawPoi { id: number; @@ -8,6 +9,7 @@ export interface RawPoi { type: number; attachments: RawAttachment[]; geometry: RawPointGeometry3D; + view_points: RawViewPoint[]; } export interface Poi { @@ -18,4 +20,5 @@ export interface Poi { attachments: Attachment[]; type: PoiType; geometry: Coordinate3D; + viewPoints: ViewPoint[]; } diff --git a/frontend/src/modules/poi/mocks/index.ts b/frontend/src/modules/poi/mocks/index.ts index 2e53465f2..918de04c1 100644 --- a/frontend/src/modules/poi/mocks/index.ts +++ b/frontend/src/modules/poi/mocks/index.ts @@ -45,6 +45,7 @@ export const mockPois = (): PoisResponse => ({ type: 'Point', coordinates: [6.2061167, 44.8985958, 1787], }, + view_points: [], }, { description: 'Test refuge', @@ -56,6 +57,7 @@ export const mockPois = (): PoisResponse => ({ type: 'Point', coordinates: [6.1667321, 44.7604322, 2409], }, + view_points: [], }, ], }); @@ -66,7 +68,7 @@ export const mockPoiRoute = (times: number, trekId: number): void => mockData: mockPois(), additionalQueries: { near_trek: trekId, - fields: 'id,name,description,attachments,type,geometry', + fields: 'id,name,description,attachments,type,geometry,view_points', page_size: getGlobalConfig().maxPoiPerPage, }, times, From b185a3e7d4a154e3a07e0e88f5073c5e1605c20d Mon Sep 17 00:00:00 2001 From: Florian Sommariva Date: Wed, 13 Sep 2023 15:39:00 +0200 Subject: [PATCH 19/37] Improve DetailsMedia component to use it as accordion --- .../DetailsMedias/DetailsMedias.tsx | 67 +++++++++++++++++-- frontend/src/translations/ca.json | 4 ++ frontend/src/translations/de.json | 4 ++ frontend/src/translations/en.json | 4 ++ frontend/src/translations/es.json | 4 ++ frontend/src/translations/fr.json | 4 ++ frontend/src/translations/it.json | 4 ++ 7 files changed, 84 insertions(+), 7 deletions(-) diff --git a/frontend/src/components/pages/details/components/DetailsMedias/DetailsMedias.tsx b/frontend/src/components/pages/details/components/DetailsMedias/DetailsMedias.tsx index c6d449cdf..1bd04935d 100644 --- a/frontend/src/components/pages/details/components/DetailsMedias/DetailsMedias.tsx +++ b/frontend/src/components/pages/details/components/DetailsMedias/DetailsMedias.tsx @@ -1,19 +1,29 @@ import ImageWithLegend from 'components/ImageWithLegend'; import ArrowRight from 'components/Map/components/DetailsMapDrawer/ArrowRight'; import { ViewPoint } from 'modules/viewPoint/interface'; -import { useCallback } from 'react'; +import { useCallback, useId, useState } from 'react'; import { FormattedMessage } from 'react-intl'; import { cn } from 'services/utils/cn'; +import { Minus } from 'components/Icons/Minus'; +import { Plus } from 'components/Icons/Plus'; interface DetailsMediasProps { + className?: string; viewPoints: ViewPoint[]; handleViewPointClick: (key: string) => void; + asAccordion?: boolean; + titleTag?: 'h2' | 'h3' | 'h4' | 'h5' | 'h6'; } export const DetailsMedias: React.FC = ({ + className, viewPoints, handleViewPointClick, + asAccordion = false, + titleTag: TitleTag = 'h2', }) => { + const SubTitleTag = TitleTag === 'h2' ? 'h3' : 'h4'; + const handleClick = useCallback( (viewPointId: string) => { handleViewPointClick(viewPointId); @@ -21,12 +31,55 @@ export const DetailsMedias: React.FC = ({ [handleViewPointClick], ); + const id = useId(); + const [isOpen, setOpen] = useState(true); + + if (viewPoints.length === 0) { + return null; + } + return ( -
-

+
+ -

-
    + {asAccordion && ( + + )} + +
      {viewPoints.map(viewPoint => { const legend = [viewPoint.legend, viewPoint.author].filter(Boolean).join(' - '); return ( @@ -45,9 +98,9 @@ export const DetailsMedias: React.FC = ({
-

+ {viewPoint.title} -

+ {legend.length > 0 && (

{legend} diff --git a/frontend/src/translations/ca.json b/frontend/src/translations/ca.json index 3425bc2c6..60fdda097 100644 --- a/frontend/src/translations/ca.json +++ b/frontend/src/translations/ca.json @@ -279,6 +279,10 @@ "courseType": "Tipus de cursa", "network": "Xarxa" }, + "accordion": { + "open": "Open", + "close": "Close" + }, "consents": { "modal": { "purposes": { diff --git a/frontend/src/translations/de.json b/frontend/src/translations/de.json index 37a59fe22..63c7d6694 100644 --- a/frontend/src/translations/de.json +++ b/frontend/src/translations/de.json @@ -279,6 +279,10 @@ "courseType": "Art des Rennens", "network": "Netzwerk" }, + "accordion": { + "open": "Open", + "close": "Close" + }, "consents": { "modal": { "purposes": { diff --git a/frontend/src/translations/en.json b/frontend/src/translations/en.json index 67f955356..0cf3a3fe1 100644 --- a/frontend/src/translations/en.json +++ b/frontend/src/translations/en.json @@ -325,6 +325,10 @@ "courseType": "Course type", "network": "Network" }, + "accordion": { + "open": "Open", + "close": "Close" + }, "consents": { "modal": { "purposes": { diff --git a/frontend/src/translations/es.json b/frontend/src/translations/es.json index b43b66247..a096d7a39 100644 --- a/frontend/src/translations/es.json +++ b/frontend/src/translations/es.json @@ -279,6 +279,10 @@ "courseType": "Tipo de carrera", "network": "La red" }, + "accordion": { + "open": "Open", + "close": "Close" + }, "consents": { "modal": { "purposes": { diff --git a/frontend/src/translations/fr.json b/frontend/src/translations/fr.json index 71bb4fda3..875d57729 100644 --- a/frontend/src/translations/fr.json +++ b/frontend/src/translations/fr.json @@ -325,6 +325,10 @@ "courseType": "Type de parcours", "network": "Réseau" }, + "accordion": { + "open": "Ouvrir", + "close": "Fermer" + }, "consents": { "modal": { "purposes": { diff --git a/frontend/src/translations/it.json b/frontend/src/translations/it.json index 4f2be9751..e65f7f92f 100644 --- a/frontend/src/translations/it.json +++ b/frontend/src/translations/it.json @@ -289,6 +289,10 @@ "courseType": "Tipo de gara", "network": "Rete" }, + "accordion": { + "open": "Open", + "close": "Close" + }, "consents": { "modal": { "purposes": { From ecf9068572cb73078fc60a3c6fd36434964c2b5c Mon Sep 17 00:00:00 2001 From: Florian Sommariva Date: Wed, 13 Sep 2023 15:42:23 +0200 Subject: [PATCH 20/37] Improve DetailsCard to support medias prop --- .../src/components/pages/details/Details.tsx | 11 +- .../components/DetailsCard/DetailsCard.tsx | 182 +-- .../__snapshots__/DetailsCard.test.tsx.snap | 1148 ++++++++--------- .../components/DetailsCard/useDetailsCard.tsx | 47 +- .../DetailsCardSection/DetailsCardSection.tsx | 9 + .../components/pages/site/OutdoorSiteUI.tsx | 15 +- 6 files changed, 715 insertions(+), 697 deletions(-) diff --git a/frontend/src/components/pages/details/Details.tsx b/frontend/src/components/pages/details/Details.tsx index b5a662ed2..6c20f5982 100644 --- a/frontend/src/components/pages/details/Details.tsx +++ b/frontend/src/components/pages/details/Details.tsx @@ -271,6 +271,12 @@ export const DetailsUIWithoutContext: React.FC = ({ slug, parentId, langu iconName: poi.type.label, }))} type="POI" + medias={{ + viewPoints: { + data: details.pois.flatMap(({ viewPoints }) => viewPoints), + handleViewPointClick, + }, + }} /> ); @@ -687,7 +693,10 @@ export const DetailsUIWithoutContext: React.FC = ({ slug, parentId, langu id: `DETAILS-SERVICE-${service.id}`, }))} infrastructure={details.infrastructure} - viewPoints={details.viewPoints} + viewPoints={[ + ...details.viewPoints, + ...details.pois.flatMap(({ viewPoints }) => viewPoints).filter(Boolean), + ]} displayMap={displayMobileMap} setMapId={setMapId} /> diff --git a/frontend/src/components/pages/details/components/DetailsCard/DetailsCard.tsx b/frontend/src/components/pages/details/components/DetailsCard/DetailsCard.tsx index 3744d4942..69857c50a 100644 --- a/frontend/src/components/pages/details/components/DetailsCard/DetailsCard.tsx +++ b/frontend/src/components/pages/details/components/DetailsCard/DetailsCard.tsx @@ -8,12 +8,13 @@ import useHasMounted from 'hooks/useHasMounted'; import parse from 'html-react-parser'; import { useListAndMapContext } from 'modules/map/ListAndMapContext'; import { FormattedMessage } from 'react-intl'; -import styled from 'styled-components'; -import { MAX_WIDTH_MOBILE } from 'stylesheet'; import { cn } from 'services/utils/cn'; import { Arrow } from 'components/Icons/Arrow'; +import { ViewPoint } from 'modules/viewPoint/interface'; import { Attachment } from '../../../../../modules/interface'; import { useDetailsCard } from './useDetailsCard'; +import { DetailsMedias } from '../DetailsMedias'; + export interface DetailsCardProps { id: string; name: string; @@ -26,6 +27,12 @@ export interface DetailsCardProps { className?: string; redirectionUrl?: string; type?: string; + medias?: { + viewPoints: { + data: ViewPoint[]; + handleViewPointClick: (id: string) => void; + }; + }; } export const DetailsCard: React.FC = ({ @@ -40,8 +47,10 @@ export const DetailsCard: React.FC = ({ className = '', redirectionUrl, type, + medias, }) => { - const { truncateState, toggleTruncateState, heightState, detailsCardRef } = useDetailsCard(); + const hasMedia = Boolean(medias?.viewPoints.data.length); + const { truncateState, toggleTruncateState, detailsCardRef } = useDetailsCard(hasMedia); const descriptionStyled = truncateState === 'TRUNCATE' ? ( @@ -54,97 +63,108 @@ export const DetailsCard: React.FC = ({ const { setHoveredCardId } = useListAndMapContext(); const hasNavigator = useHasMounted(typeof navigator !== 'undefined' && navigator.onLine); - return ( - { - setHoveredCardId(id); - }} - onMouseLeave={() => { - setHoveredCardId(null); - }} > -

-
- - {({ isFullscreen, toggleFullscreen }) => ( - <> - {type === 'TOURISTIC_CONTENT' && - redirectionUrl && - attachments.length > 0 && - hasNavigator && ( +
{ + setHoveredCardId(id); + }} + onMouseLeave={() => { + setHoveredCardId(null); + }} + > +
+
+ + {({ isFullscreen, toggleFullscreen }) => ( + <> + {type === 'TOURISTIC_CONTENT' && + redirectionUrl && + attachments.length > 0 && + hasNavigator && ( + + )} + {type !== 'TOURISTIC_CONTENT' && attachments.length > 0 && hasNavigator && ( )} - {type !== 'TOURISTIC_CONTENT' && attachments.length > 0 && hasNavigator && ( - - )} - - )} - - + + )} + + +
-
-
- {place && ( +
+ {place && ( + +

{place}

+
+ )} -

{place}

+

{name}

- )} - -

{name}

-
- {Boolean(description) && ( -
- {descriptionStyled} - {truncateState !== 'NONE' && ( - - )} -
- )} +
+ )} + {truncateState !== 'NONE' && ( + + )} + + )} +
- + ); }; @@ -160,9 +180,3 @@ const OptionalLink: React.FC = ({ redirectionUrl, children }) <>{children} ); }; - -const DetailsCardContainer = styled.li<{ height: number }>` - @media (min-width: ${MAX_WIDTH_MOBILE}px) { - height: ${props => props.height}px; - } -`; diff --git a/frontend/src/components/pages/details/components/DetailsCard/__tests__/__snapshots__/DetailsCard.test.tsx.snap b/frontend/src/components/pages/details/components/DetailsCard/__tests__/__snapshots__/DetailsCard.test.tsx.snap index 2ddf1ad3c..58ec9cfe0 100644 --- a/frontend/src/components/pages/details/components/DetailsCard/__tests__/__snapshots__/DetailsCard.test.tsx.snap +++ b/frontend/src/components/pages/details/components/DetailsCard/__tests__/__snapshots__/DetailsCard.test.tsx.snap @@ -6,97 +6,95 @@ Object { "baseElement":
  • - -
    - Lorem ipsum -
    - +
    + - - Lorem ipsum - Lorem ipsum + + Lorem ipsum - Lorem ipsum + - - -
    -
    -
    + + Voir l'image en plein écran + + + + + +
    -
    -
    - Randonnée pédestre +
    + Randonnée pédestre +
    -
  • -
    -

    - Église St Louis -

    +

    + Église St Louis +

    @@ -110,218 +108,216 @@ Object {
  • - - - + + Voir l'image en plein écran + + + + +
    -
    - - -
  • -
  • - -
  • - + + +
  • + +
  • + +
    -
    -
    - Randonnée pédestre +
    + Randonnée pédestre +
    - -
    -

    - Église St Louis -

    +

    + Église St Louis +

    @@ -336,97 +332,95 @@ Object { , "container":
  • - -
    - Lorem ipsum -
    - +
    + - - Lorem ipsum - Lorem ipsum + + Lorem ipsum - Lorem ipsum + - - -
    -
    -
    + + Voir l'image en plein écran + + + + + +
    -
    -
    - Randonnée pédestre +
    + Randonnée pédestre +
    -
    -
    -
  • -
    -

    - Église St Louis -

    +
    +
    +

    + Église St Louis +

    @@ -498,97 +492,318 @@ Object { "baseElement":
  • - -
    - Lorem ipsum -
    - +
    + - - Lorem ipsum - Lorem ipsum + + Lorem ipsum - Lorem ipsum + - - -
    -
    -
    + + Voir l'image en plein écran + + + + + +
    -
    -
    - Randonnée pédestre +
    + Randonnée pédestre +
    +
    +

    + Église St Louis +

    +
    + + Pour espérer apercevoir cet oiseau, partir la nuit au printemps, parcourir un grand dénivelé afin d'arriver sur son terrain de prédilection à plus de 2000 m voire 3000 m d'altitude avant le lever du jour et là, entendre le chant guttural caractéristique qui trahit sa présence. Mais pour le voir, il faudra bien ouvrir les yeux ou se munir d'une paire de jumelles. Et alors là, quel bonheur ! Le lagopède alpin est l'espèce arctique par excellence, menacée entre autre par le réchauffement climatique. Il fait partie des espèces à protéger dans le cœur du Parc national des Ecrins. + +
    +
  • + +
    +
    +
  • -

    - Église St Louis -

    +
    +
    +
    +
    +
    + + + +
    +
    + + +
  • +
  • + +
  • + +
    +
    +
    +
    + +
    +
    + Randonnée pédestre +
    +
    + +
    +

    + Église St Louis +

    @@ -600,13 +815,16 @@ Object {
    -
    -
  • , + "container":
    +
  • +

    Église St Louis

    -
    -
    - - Pour espérer apercevoir cet oiseau, partir la nuit au printemps, parcourir un grand dénivelé afin d'arriver sur son terrain de prédilection à plus de 2000 m voire 3000 m d'altitude avant le lever du jour et là, entendre le chant guttural caractéristique qui trahit sa présence. Mais pour le voir, il faudra bien ouvrir les yeux ou se munir d'une paire de jumelles. Et alors là, quel bonheur ! Le lagopède alpin est l'espèce arctique par excellence, menacée entre autre par le réchauffement climatique. Il fait partie des espèces à protéger dans le cœur du Parc national des Ecrins. - -
    -
    -
    -
  • -
    - , - "container":
    -
  • -
    -
    -
    -
    -
    -
    - - - -
    -
    - - -
  • -
  • - -
  • - -
    - - - - -
    -
    - Randonnée pédestre -
    -
    - - -
    -

    - Église St Louis -

    -
    diff --git a/frontend/src/components/pages/details/components/DetailsCard/useDetailsCard.tsx b/frontend/src/components/pages/details/components/DetailsCard/useDetailsCard.tsx index 4f209e5e1..542ef04b6 100644 --- a/frontend/src/components/pages/details/components/DetailsCard/useDetailsCard.tsx +++ b/frontend/src/components/pages/details/components/DetailsCard/useDetailsCard.tsx @@ -2,63 +2,48 @@ import debounce from 'debounce'; import useIsomorphicLayoutEffect from 'hooks/useIsomorphicLayoutEffect'; import { useCallback, useEffect, useRef, useState } from 'react'; -const DETAILS_CARD_DEFAULT_HEIGHT = 200; +const DETAILS_CARD_DEFAULT_HEIGHT = 220; -export const useDetailsCard = () => { +export const useDetailsCard = (hasMedia = false) => { const detailsCardRef = useRef(null); - const [heightState, setHeightState] = useState(DETAILS_CARD_DEFAULT_HEIGHT); - const [truncateState, setTruncateState] = useState<'NONE' | 'TRUNCATE' | 'FULL'>( - () => 'TRUNCATE', - ); + const [truncateState, setTruncateState] = useState<'NONE' | 'TRUNCATE' | 'FULL'>('TRUNCATE'); const toggleTruncateState = () => setTruncateState(currentTruncateState => currentTruncateState === 'TRUNCATE' ? 'FULL' : 'TRUNCATE', ); - useEffect(() => { - if (truncateState === 'TRUNCATE') { - setHeightState(DETAILS_CARD_DEFAULT_HEIGHT); - } else { - const newHeight = detailsCardRef.current?.getBoundingClientRect().height; - if (newHeight !== undefined) { - setHeightState(Math.max(DETAILS_CARD_DEFAULT_HEIGHT, newHeight)); - } - } - }, [truncateState, setHeightState]); useEffect(() => { - if ( - detailsCardRef.current && - detailsCardRef.current.querySelector('.line-clamp-2')?.offsetHeight === - detailsCardRef.current.querySelector('.line-clamp-2')?.scrollHeight - ) { + const descriptionNode = detailsCardRef.current?.querySelector('.line-clamp-2'); + if (descriptionNode?.offsetHeight === descriptionNode?.scrollHeight && !hasMedia) { setTruncateState('NONE'); } - }, []); + }, [hasMedia]); const handleResize = useCallback( debounce( () => { setTruncateState(prevState => { - if (detailsCardRef.current === null) { + if (detailsCardRef.current === null || hasMedia) { return prevState; } + const descriptionNode = + detailsCardRef.current.querySelector('.line-clamp-2'); + if ( prevState === 'TRUNCATE' && - detailsCardRef.current.querySelector('.line-clamp-2')?.offsetHeight === - detailsCardRef.current.querySelector('.line-clamp-2')?.scrollHeight + (!descriptionNode || descriptionNode.offsetHeight <= descriptionNode.scrollHeight) ) { return 'NONE'; } else if ( prevState === 'FULL' && - heightState >= detailsCardRef.current?.getBoundingClientRect().height + DETAILS_CARD_DEFAULT_HEIGHT >= detailsCardRef.current.getBoundingClientRect().height ) { return 'NONE'; } else if ( - (prevState === 'NONE' || prevState === 'FULL') && - heightState < detailsCardRef.current?.getBoundingClientRect().height + prevState !== 'TRUNCATE' && + DETAILS_CARD_DEFAULT_HEIGHT < detailsCardRef.current.getBoundingClientRect().height ) { - setHeightState(DETAILS_CARD_DEFAULT_HEIGHT); return 'TRUNCATE'; } return prevState; @@ -67,7 +52,7 @@ export const useDetailsCard = () => { 1000, false, ), - [setTruncateState, setHeightState, detailsCardRef], + [setTruncateState, detailsCardRef], ); useIsomorphicLayoutEffect(() => { @@ -77,5 +62,5 @@ export const useDetailsCard = () => { }; }, []); - return { truncateState, toggleTruncateState, heightState, detailsCardRef }; + return { truncateState, toggleTruncateState, detailsCardRef }; }; diff --git a/frontend/src/components/pages/details/components/DetailsCardSection/DetailsCardSection.tsx b/frontend/src/components/pages/details/components/DetailsCardSection/DetailsCardSection.tsx index 05a817217..8b6e7ac39 100644 --- a/frontend/src/components/pages/details/components/DetailsCardSection/DetailsCardSection.tsx +++ b/frontend/src/components/pages/details/components/DetailsCardSection/DetailsCardSection.tsx @@ -2,6 +2,7 @@ import getActivityColor from 'components/pages/search/components/ResultCard/getA import { Separator } from 'components/Separator'; import styled from 'styled-components'; import { MAX_WIDTH_MOBILE, scrollBar, sizes } from 'stylesheet'; +import { ViewPoint } from 'modules/viewPoint/interface'; import { marginDetailsChild } from '../../Details'; import { DetailsCard, DetailsCardProps } from '../DetailsCard/DetailsCard'; @@ -12,6 +13,12 @@ interface DetailsCardSectionProps { generateUrlFunction?: (id: string | number, title: string) => string; type: 'POI' | 'TOURISTIC_CONTENT'; htmlId?: string; + medias?: { + viewPoints: { + data: ViewPoint[]; + handleViewPointClick: (id: string) => void; + }; + }; } export const DetailsCardSection: React.FC = ({ @@ -21,6 +28,7 @@ export const DetailsCardSection: React.FC = ({ displayBadge = false, generateUrlFunction, type, + medias, }) => { return (
    @@ -58,6 +66,7 @@ export const DetailsCardSection: React.FC = ({ : undefined } type={type} + medias={medias} /> ))} diff --git a/frontend/src/components/pages/site/OutdoorSiteUI.tsx b/frontend/src/components/pages/site/OutdoorSiteUI.tsx index 057114d2b..1a14140aa 100644 --- a/frontend/src/components/pages/site/OutdoorSiteUI.tsx +++ b/frontend/src/components/pages/site/OutdoorSiteUI.tsx @@ -242,6 +242,14 @@ const OutdoorSiteUIWithoutContext: React.FC = ({ outdoorSiteUrl, language iconName: poi.type.label, }))} type="POI" + medias={{ + viewPoints: { + data: outdoorSiteContent.pois.flatMap( + ({ viewPoints }) => viewPoints, + ), + handleViewPointClick, + }, + }} /> ); @@ -604,7 +612,12 @@ const OutdoorSiteUIWithoutContext: React.FC = ({ outdoorSiteUrl, language }))} infrastructure={outdoorSiteContent.infrastructure} hideMap={hideMobileMap} - viewPoints={outdoorSiteContent.viewPoints} + viewPoints={[ + ...outdoorSiteContent.viewPoints, + ...outdoorSiteContent.pois + .flatMap(({ viewPoints }) => viewPoints) + .filter(Boolean), + ]} displayMap={displayMobileMap} setMapId={setMapId} /> From f70fcc692875c45902a741279499f81f74559b37 Mon Sep 17 00:00:00 2001 From: Florian Sommariva Date: Tue, 19 Sep 2023 14:54:47 +0200 Subject: [PATCH 21/37] Add geometry field to viewPoints adapter --- frontend/src/modules/viewPoint/adapter.ts | 21 +++++++++++---------- frontend/src/modules/viewPoint/interface.ts | 3 +++ 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/frontend/src/modules/viewPoint/adapter.ts b/frontend/src/modules/viewPoint/adapter.ts index 8725f35e3..2001ac19f 100644 --- a/frontend/src/modules/viewPoint/adapter.ts +++ b/frontend/src/modules/viewPoint/adapter.ts @@ -6,18 +6,19 @@ export const adaptViewPoints = async (rawViewpoints: RawViewPoint[]): Promise { - const metadata = await getViewPointMetadata(viewpoints.metadata_url); + rawViewpoints.map(async viewpoint => { + const metadata = await getViewPointMetadata(viewpoint.metadata_url); return { - annotations: viewpoints.annotations, - id: String(viewpoints.id), - author: viewpoints.author, - legend: viewpoints.legend, - license: viewpoints.license, + annotations: viewpoint.annotations, + id: String(viewpoint.id), + author: viewpoint.author, + geometry: viewpoint.geometry ?? null, + legend: viewpoint.legend, + license: viewpoint.license, metadata, - pictureTilesUrl: decodeURI(viewpoints.picture_tiles_url), - title: viewpoints.title, - thumbnailUrl: viewpoints.thumbnail_url, + pictureTilesUrl: decodeURI(viewpoint.picture_tiles_url), + title: viewpoint.title, + thumbnailUrl: viewpoint.thumbnail_url, }; }), ); diff --git a/frontend/src/modules/viewPoint/interface.ts b/frontend/src/modules/viewPoint/interface.ts index 944a34843..4a8b70eb0 100644 --- a/frontend/src/modules/viewPoint/interface.ts +++ b/frontend/src/modules/viewPoint/interface.ts @@ -1,4 +1,5 @@ import { FeatureCollection } from 'geojson'; +import { PointGeometry } from 'modules/interface'; export interface RawViewPoint { annotations: FeatureCollection; @@ -10,6 +11,7 @@ export interface RawViewPoint { picture_tiles_url: string; title: string | null; thumbnail_url: string; + geometry?: PointGeometry; } export interface ViewPoint { @@ -28,4 +30,5 @@ export interface ViewPoint { pictureTilesUrl: string; title: string | null; thumbnailUrl: string; + geometry: PointGeometry | null; } From 57063d7893823d8e1f0cb46eb746fd269a0f51dc Mon Sep 17 00:00:00 2001 From: Florian Sommariva Date: Tue, 19 Sep 2023 17:02:39 +0200 Subject: [PATCH 22/37] Fix POI viewPoints display --- .../src/components/pages/details/Details.tsx | 10 +-- .../components/DetailsCard/DetailsCard.tsx | 77 ++++++++++--------- .../__snapshots__/DetailsCard.test.tsx.snap | 36 ++++----- .../DetailsCardSection/DetailsCardSection.tsx | 15 ++-- .../DetailsMedias/DetailsMedias.tsx | 4 +- .../components/pages/site/OutdoorSiteUI.tsx | 12 +-- frontend/src/modules/poi/interface.ts | 2 +- frontend/src/modules/viewPoint/interface.ts | 6 +- frontend/src/translations/ca.json | 4 +- frontend/src/translations/de.json | 4 +- frontend/src/translations/en.json | 4 +- frontend/src/translations/es.json | 4 +- frontend/src/translations/fr.json | 4 +- frontend/src/translations/it.json | 4 +- 14 files changed, 88 insertions(+), 98 deletions(-) diff --git a/frontend/src/components/pages/details/Details.tsx b/frontend/src/components/pages/details/Details.tsx index 6c20f5982..6079dbd0d 100644 --- a/frontend/src/components/pages/details/Details.tsx +++ b/frontend/src/components/pages/details/Details.tsx @@ -269,14 +269,10 @@ export const DetailsUIWithoutContext: React.FC = ({ slug, parentId, langu attachments: poi.attachments, iconUri: poi.type.pictogramUri, iconName: poi.type.label, + viewPoints: poi.viewPoints, }))} type="POI" - medias={{ - viewPoints: { - data: details.pois.flatMap(({ viewPoints }) => viewPoints), - handleViewPointClick, - }, - }} + handleViewPointClick={handleViewPointClick} /> ); @@ -695,7 +691,7 @@ export const DetailsUIWithoutContext: React.FC = ({ slug, parentId, langu infrastructure={details.infrastructure} viewPoints={[ ...details.viewPoints, - ...details.pois.flatMap(({ viewPoints }) => viewPoints).filter(Boolean), + ...details.pois.flatMap(({ viewPoints = [] }) => viewPoints).filter(Boolean), ]} displayMap={displayMobileMap} setMapId={setMapId} diff --git a/frontend/src/components/pages/details/components/DetailsCard/DetailsCard.tsx b/frontend/src/components/pages/details/components/DetailsCard/DetailsCard.tsx index 69857c50a..72a314dc3 100644 --- a/frontend/src/components/pages/details/components/DetailsCard/DetailsCard.tsx +++ b/frontend/src/components/pages/details/components/DetailsCard/DetailsCard.tsx @@ -27,15 +27,14 @@ export interface DetailsCardProps { className?: string; redirectionUrl?: string; type?: string; - medias?: { - viewPoints: { - data: ViewPoint[]; - handleViewPointClick: (id: string) => void; - }; - }; + viewPoints?: ViewPoint[]; } -export const DetailsCard: React.FC = ({ +interface DetailsCardPropsWithHandleViewPointClick extends DetailsCardProps { + handleViewPointClick?: (id: string) => void; +} + +export const DetailsCard: React.FC = ({ id, name, description, @@ -47,9 +46,10 @@ export const DetailsCard: React.FC = ({ className = '', redirectionUrl, type, - medias, + handleViewPointClick, + viewPoints, }) => { - const hasMedia = Boolean(medias?.viewPoints.data.length); + const hasMedia = Boolean(viewPoints?.length); const { truncateState, toggleTruncateState, detailsCardRef } = useDetailsCard(hasMedia); const descriptionStyled = truncateState === 'TRUNCATE' ? ( @@ -66,7 +66,7 @@ export const DetailsCard: React.FC = ({ return (
  • = ({
    { setHoveredCardId(id); @@ -117,7 +116,7 @@ export const DetailsCard: React.FC = ({
  • -
    +
    {place && (

    {place}

    @@ -129,36 +128,42 @@ export const DetailsCard: React.FC = ({ {Boolean(description) && ( <> {descriptionStyled} - {medias && Number(medias.viewPoints.data.length) > 0 && truncateState !== 'TRUNCATE' && ( -
    + {Number(viewPoints?.length) > 0 && truncateState !== 'TRUNCATE' && ( +
    )} {truncateState !== 'NONE' && ( - + +
    )} )} diff --git a/frontend/src/components/pages/details/components/DetailsCard/__tests__/__snapshots__/DetailsCard.test.tsx.snap b/frontend/src/components/pages/details/components/DetailsCard/__tests__/__snapshots__/DetailsCard.test.tsx.snap index 58ec9cfe0..0a9799596 100644 --- a/frontend/src/components/pages/details/components/DetailsCard/__tests__/__snapshots__/DetailsCard.test.tsx.snap +++ b/frontend/src/components/pages/details/components/DetailsCard/__tests__/__snapshots__/DetailsCard.test.tsx.snap @@ -6,10 +6,10 @@ Object { "baseElement":
  • , "container":
  • , "container":
  • string; type: 'POI' | 'TOURISTIC_CONTENT'; htmlId?: string; - medias?: { - viewPoints: { - data: ViewPoint[]; - handleViewPointClick: (id: string) => void; - }; - }; + handleViewPointClick?: (id: string) => void; } export const DetailsCardSection: React.FC = ({ @@ -28,7 +22,7 @@ export const DetailsCardSection: React.FC = ({ displayBadge = false, generateUrlFunction, type, - medias, + handleViewPointClick, }) => { return (
    @@ -41,7 +35,7 @@ export const DetailsCardSection: React.FC = ({

    = ({ : undefined } type={type} - medias={medias} + handleViewPointClick={handleViewPointClick} + viewPoints={card.viewPoints} /> ))} diff --git a/frontend/src/components/pages/details/components/DetailsMedias/DetailsMedias.tsx b/frontend/src/components/pages/details/components/DetailsMedias/DetailsMedias.tsx index 1bd04935d..e74907718 100644 --- a/frontend/src/components/pages/details/components/DetailsMedias/DetailsMedias.tsx +++ b/frontend/src/components/pages/details/components/DetailsMedias/DetailsMedias.tsx @@ -10,7 +10,7 @@ import { Plus } from 'components/Icons/Plus'; interface DetailsMediasProps { className?: string; viewPoints: ViewPoint[]; - handleViewPointClick: (key: string) => void; + handleViewPointClick?: (key: string) => void; asAccordion?: boolean; titleTag?: 'h2' | 'h3' | 'h4' | 'h5' | 'h6'; } @@ -26,7 +26,7 @@ export const DetailsMedias: React.FC = ({ const handleClick = useCallback( (viewPointId: string) => { - handleViewPointClick(viewPointId); + handleViewPointClick?.(viewPointId); }, [handleViewPointClick], ); diff --git a/frontend/src/components/pages/site/OutdoorSiteUI.tsx b/frontend/src/components/pages/site/OutdoorSiteUI.tsx index 1a14140aa..e15ec3fdb 100644 --- a/frontend/src/components/pages/site/OutdoorSiteUI.tsx +++ b/frontend/src/components/pages/site/OutdoorSiteUI.tsx @@ -240,16 +240,10 @@ const OutdoorSiteUIWithoutContext: React.FC = ({ outdoorSiteUrl, language attachments: poi.attachments, iconUri: poi.type.pictogramUri, iconName: poi.type.label, + viewPoints: poi.viewPoints, }))} type="POI" - medias={{ - viewPoints: { - data: outdoorSiteContent.pois.flatMap( - ({ viewPoints }) => viewPoints, - ), - handleViewPointClick, - }, - }} + handleViewPointClick={handleViewPointClick} /> ); @@ -615,7 +609,7 @@ const OutdoorSiteUIWithoutContext: React.FC = ({ outdoorSiteUrl, language viewPoints={[ ...outdoorSiteContent.viewPoints, ...outdoorSiteContent.pois - .flatMap(({ viewPoints }) => viewPoints) + .flatMap(({ viewPoints = [] }) => viewPoints) .filter(Boolean), ]} displayMap={displayMobileMap} diff --git a/frontend/src/modules/poi/interface.ts b/frontend/src/modules/poi/interface.ts index ed5be3417..a38b54271 100644 --- a/frontend/src/modules/poi/interface.ts +++ b/frontend/src/modules/poi/interface.ts @@ -20,5 +20,5 @@ export interface Poi { attachments: Attachment[]; type: PoiType; geometry: Coordinate3D; - viewPoints: ViewPoint[]; + viewPoints?: ViewPoint[]; } diff --git a/frontend/src/modules/viewPoint/interface.ts b/frontend/src/modules/viewPoint/interface.ts index 4a8b70eb0..94aabe23a 100644 --- a/frontend/src/modules/viewPoint/interface.ts +++ b/frontend/src/modules/viewPoint/interface.ts @@ -1,5 +1,5 @@ import { FeatureCollection } from 'geojson'; -import { PointGeometry } from 'modules/interface'; +import { RawPointGeometry2D } from 'modules/interface'; export interface RawViewPoint { annotations: FeatureCollection; @@ -11,7 +11,7 @@ export interface RawViewPoint { picture_tiles_url: string; title: string | null; thumbnail_url: string; - geometry?: PointGeometry; + geometry?: RawPointGeometry2D; } export interface ViewPoint { @@ -30,5 +30,5 @@ export interface ViewPoint { pictureTilesUrl: string; title: string | null; thumbnailUrl: string; - geometry: PointGeometry | null; + geometry: RawPointGeometry2D | null; } diff --git a/frontend/src/translations/ca.json b/frontend/src/translations/ca.json index 60fdda097..374ab5671 100644 --- a/frontend/src/translations/ca.json +++ b/frontend/src/translations/ca.json @@ -121,9 +121,9 @@ "poiFullTitle": "{count, plural, =0 {sense patrimoni} one {# patrimoni a descobrir} other {Els # patrimonis a descobrir}}", "source": "Font", "touristicContent": "Proper", - "readMore": "llegir més", "knowMore": "Més informació", - "readLess": "llegir menys", + "moreInformation": "More information", + "lessInformation": "Less information", "close": "Tancar", "description": "Descripció", "recommandations": "Recomanacions", diff --git a/frontend/src/translations/de.json b/frontend/src/translations/de.json index 63c7d6694..0f06c77b7 100644 --- a/frontend/src/translations/de.json +++ b/frontend/src/translations/de.json @@ -121,9 +121,9 @@ "poiFullTitle": "{count, plural, =0 {Kein Erbe} one {# Erbe zu entdecken} other {Die # Erbgüter, die es zu entdecken gilt}}", "source": "Quelle", "touristicContent": "In der Nähe", - "readMore": "weiterlesen", "knowMore": "Mehr darüber erfahren", - "readLess": "weniger lesen", + "moreInformation": "More information", + "lessInformation": "Less information", "close": "Schließen", "description": "Beschreibung", "recommandations": "Empfehlungen", diff --git a/frontend/src/translations/en.json b/frontend/src/translations/en.json index 0cf3a3fe1..d7a8bd49d 100644 --- a/frontend/src/translations/en.json +++ b/frontend/src/translations/en.json @@ -124,9 +124,9 @@ "poiFullTitle": "{count, plural, =0 {No point of interest} one {# point of interest} other {# points of interest}}", "source": "Source", "touristicContent": "Close by", - "readMore": "read more", "knowMore": "Find out more", - "readLess": "read less", + "moreInformation": "More information", + "lessInformation": "Less information", "close": "Close", "description": "Description", "recommandations": "Recommandations", diff --git a/frontend/src/translations/es.json b/frontend/src/translations/es.json index a096d7a39..47ae25463 100644 --- a/frontend/src/translations/es.json +++ b/frontend/src/translations/es.json @@ -121,9 +121,9 @@ "poiFullTitle": "{count, plural, =0 {sin patrimonio} one {# patrimonio para descubrir} other {Els # patrimonios para descubrir}}", "source": "Fuente", "touristicContent": "Cercano", - "readMore": "lleer más", "knowMore": "Más información", - "readLess": "lleer menos", + "moreInformation": "More information", + "lessInformation": "Less information", "close": "Cerrar", "description": "Descripción", "recommandations": "Recomendaciones", diff --git a/frontend/src/translations/fr.json b/frontend/src/translations/fr.json index 875d57729..e0acf4d53 100644 --- a/frontend/src/translations/fr.json +++ b/frontend/src/translations/fr.json @@ -124,9 +124,9 @@ "poiFullTitle": "{count, plural, =0 {Pas de patrimoine} one {# patrimoine à découvrir} other {Les # patrimoines à découvrir}}", "source": "Source", "touristicContent": "À proximité", - "readMore": "lire la suite", "knowMore": "En savoir plus", - "readLess": "lire moins", + "moreInformation": "Plus d'informations", + "lessInformation": "Moins d'informations", "close": "Fermer", "description": "Description", "recommandations": "Recommandations", diff --git a/frontend/src/translations/it.json b/frontend/src/translations/it.json index e65f7f92f..3ce33bd5c 100644 --- a/frontend/src/translations/it.json +++ b/frontend/src/translations/it.json @@ -124,9 +124,9 @@ "poiFullTitle": "{count, plural, =0 {Nessun patrimonio} one {# Patrimonio da scoprire} other {# I patrimoni da scoprire}}", "source": "Autore", "touristicContent": "Vicino", - "readMore": "Continua a leggere", "knowMore": "Saperne di più", - "readLess": "Leggere meno", + "moreInformation": "More information", + "lessInformation": "Less information", "close": "Chiudere", "description": "Descrizione", "recommandations": "Raccomandazioni", From 7759e61e8545e610c91a6c1ba5d5399f447ab4e0 Mon Sep 17 00:00:00 2001 From: Florian Sommariva Date: Wed, 27 Sep 2023 16:11:29 +0200 Subject: [PATCH 23/37] Review viewPoint HD wording --- .../details/components/DetailsMedias/DetailsMedias.tsx | 2 +- frontend/src/translations/ca.json | 3 ++- frontend/src/translations/de.json | 3 ++- frontend/src/translations/en.json | 7 ++++--- frontend/src/translations/es.json | 3 ++- frontend/src/translations/fr.json | 7 ++++--- frontend/src/translations/it.json | 3 ++- 7 files changed, 17 insertions(+), 11 deletions(-) diff --git a/frontend/src/components/pages/details/components/DetailsMedias/DetailsMedias.tsx b/frontend/src/components/pages/details/components/DetailsMedias/DetailsMedias.tsx index e74907718..8e70acc75 100644 --- a/frontend/src/components/pages/details/components/DetailsMedias/DetailsMedias.tsx +++ b/frontend/src/components/pages/details/components/DetailsMedias/DetailsMedias.tsx @@ -119,7 +119,7 @@ export const DetailsMedias: React.FC = ({ `)} > - + diff --git a/frontend/src/translations/ca.json b/frontend/src/translations/ca.json index 374ab5671..fcaaffe02 100644 --- a/frontend/src/translations/ca.json +++ b/frontend/src/translations/ca.json @@ -244,8 +244,9 @@ }, "viewPoint": { "title": "Fotos HD", + "label": "Foto HD", "credit": "Crèdit fotogràfic :", - "browsePicture": "Navega per la foto" + "examinePicture": "Navega per la foto" }, "Wind": { "N": "Nord", diff --git a/frontend/src/translations/de.json b/frontend/src/translations/de.json index 0f06c77b7..fb00e8e18 100644 --- a/frontend/src/translations/de.json +++ b/frontend/src/translations/de.json @@ -244,8 +244,9 @@ }, "viewPoint": { "title": "HD-Fotos", + "label": "HD-Foto", "credit": "Fotogutschrift:", - "browsePicture": "Foto durchsuchen" + "examinePicture": "Foto durchsuchen" }, "Wind": { "N": "Norden", diff --git a/frontend/src/translations/en.json b/frontend/src/translations/en.json index d7a8bd49d..be0856e88 100644 --- a/frontend/src/translations/en.json +++ b/frontend/src/translations/en.json @@ -250,9 +250,10 @@ "sitesFullTitle": "The {count} places of practice to discover" }, "viewPoint": { - "title": "HD photos", - "credit": "Photo credit:", - "browsePicture": "Browse photo" + "title": "HD pictures", + "label": "HD picture", + "credit": "Picture credit:", + "examinePicture": "Exmamine picture" }, "Wind": { "N": "North", diff --git a/frontend/src/translations/es.json b/frontend/src/translations/es.json index 47ae25463..47f50ba72 100644 --- a/frontend/src/translations/es.json +++ b/frontend/src/translations/es.json @@ -244,8 +244,9 @@ }, "viewPoint": { "title": "Fotos HD", + "label": "Foto HD", "credit": "Crédito de la foto:", - "browsePicture": "Examinar foto" + "examinePicture": "Examinar foto" }, "Wind": { "N": "Norte", diff --git a/frontend/src/translations/fr.json b/frontend/src/translations/fr.json index e0acf4d53..d8a95ec10 100644 --- a/frontend/src/translations/fr.json +++ b/frontend/src/translations/fr.json @@ -250,9 +250,10 @@ "sitesFullTitle": "Les {count} lieux de pratique à découvrir" }, "viewPoint": { - "title": "Photos HD", - "credit": "Crédit photo :", - "browsePicture": "Parcourir la photo" + "title": "Images HD", + "label": "Image HD", + "credit": "Crédit image :", + "examinePicture": "Examiner l'image" }, "Wind": { "N": "Nord", diff --git a/frontend/src/translations/it.json b/frontend/src/translations/it.json index 3ce33bd5c..9e60a2260 100644 --- a/frontend/src/translations/it.json +++ b/frontend/src/translations/it.json @@ -254,8 +254,9 @@ }, "viewPoint": { "title": "Foto HD", + "label": "Foto HD", "credit": "Credito foto:", - "browsePicture": "Sfoglia foto" + "examinePicture": "Sfoglia foto" }, "Wind": { "N": "Nord", From 5acf6c29433cbeb2d831a9c6768d779eb01e4b9f Mon Sep 17 00:00:00 2001 From: Florian Sommariva Date: Wed, 27 Sep 2023 16:17:28 +0200 Subject: [PATCH 24/37] Create ViewPoint icon component --- .../src/components/Icons/ViewPoint/index.tsx | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 frontend/src/components/Icons/ViewPoint/index.tsx diff --git a/frontend/src/components/Icons/ViewPoint/index.tsx b/frontend/src/components/Icons/ViewPoint/index.tsx new file mode 100644 index 000000000..1c70bde15 --- /dev/null +++ b/frontend/src/components/Icons/ViewPoint/index.tsx @@ -0,0 +1,25 @@ +import React from 'react'; +import { GenericIconProps } from '../types'; + +export const ViewPoint: React.FC = ({ + color = 'currentColor', + opacity, + className, + size = 24, +}) => { + return ( + + + + ); +}; From 3f7a143949c883f82390e63b0f23542e51dc41b1 Mon Sep 17 00:00:00 2001 From: Florian Sommariva Date: Wed, 27 Sep 2023 16:16:53 +0200 Subject: [PATCH 25/37] Create ClickableMarker component --- .../ClickableMarker/ClickableMarker.tsx | 36 +++++++++++++++++++ .../Map/components/ClickableMarker/index.tsx | 1 + 2 files changed, 37 insertions(+) create mode 100644 frontend/src/components/Map/components/ClickableMarker/ClickableMarker.tsx create mode 100644 frontend/src/components/Map/components/ClickableMarker/index.tsx diff --git a/frontend/src/components/Map/components/ClickableMarker/ClickableMarker.tsx b/frontend/src/components/Map/components/ClickableMarker/ClickableMarker.tsx new file mode 100644 index 000000000..570582663 --- /dev/null +++ b/frontend/src/components/Map/components/ClickableMarker/ClickableMarker.tsx @@ -0,0 +1,36 @@ +import { HoverableMarker } from 'components/Map/components/HoverableMarker'; +import { Popup } from 'components/Map/components/Popup'; +import { PopupResult } from 'modules/trekResult/interface'; + +interface ClickableMarkerProps { + points: { + location: { x: number; y: number }; + pictogramUri: string; + id: string; + content: PopupResult; + type?: 'TREK' | 'TOURISTIC_CONTENT' | 'OUTDOOR_SITE' | 'TOURISTIC_EVENT' | null; + }[]; +} + +export const ClickableMarker = ({ points, ...props }: ClickableMarkerProps) => { + if (!points?.length) { + return null; + } + + return ( + <> + {points.map(point => ( + + + + ))} + + ); +}; + +export default ClickableMarker; diff --git a/frontend/src/components/Map/components/ClickableMarker/index.tsx b/frontend/src/components/Map/components/ClickableMarker/index.tsx new file mode 100644 index 000000000..68ab31932 --- /dev/null +++ b/frontend/src/components/Map/components/ClickableMarker/index.tsx @@ -0,0 +1 @@ +export { ClickableMarker } from './ClickableMarker'; From 63eae8d78be322d5217834292a69b7e3a04e6d91 Mon Sep 17 00:00:00 2001 From: Florian Sommariva Date: Wed, 27 Sep 2023 16:18:00 +0200 Subject: [PATCH 26/37] Add viewPoint to controlPanel --- .../components/ControlSection/ControlPanel/index.tsx | 11 +++++++++++ .../Map/components/ControlSection/ControlSection.tsx | 2 ++ 2 files changed, 13 insertions(+) diff --git a/frontend/src/components/Map/components/ControlSection/ControlPanel/index.tsx b/frontend/src/components/Map/components/ControlSection/ControlPanel/index.tsx index b5a7316d0..252441707 100644 --- a/frontend/src/components/Map/components/ControlSection/ControlPanel/index.tsx +++ b/frontend/src/components/Map/components/ControlSection/ControlPanel/index.tsx @@ -2,6 +2,7 @@ import { Florist } from 'components/Icons/Florist'; import { Signage } from 'components/Icons/Signage'; import { Infrastructure } from 'components/Icons/Infrastructure'; import { MapPin } from 'components/Icons/MapPin'; +import { ViewPoint } from 'components/Icons/ViewPoint'; import { Line } from './Line'; import IconLocation from './IconLocation'; import IconInfo from './IconInfo'; @@ -35,6 +36,8 @@ export const ControlPanel: React.FC = ({ toggleInfrastructureVisibility, annotationViewpointVisibility, toggleAnnotationViewpointVisibility, + viewPointVisibility, + toggleViewPointVisiblity, }) => { return (
    @@ -118,6 +121,14 @@ export const ControlPanel: React.FC = ({ transKey="search.map.panel.service" /> )} + {viewPointVisibility && toggleViewPointVisiblity && ( + + )} {annotationViewpointVisibility && toggleAnnotationViewpointVisibility && ( void; annotationViewpointVisibility?: Visibility; toggleAnnotationViewpointVisibility?: () => void; + viewPointVisibility?: Visibility; + toggleViewPointVisiblity?: () => void; className?: string; position?: ControlPosition; } From cbe629b3fde7265c6cbf06c85878b060285e01a1 Mon Sep 17 00:00:00 2001 From: Florian Sommariva Date: Wed, 27 Sep 2023 16:25:22 +0200 Subject: [PATCH 27/37] Add ViewPointMarker component --- .../Map/DetailsMap/ViewPointMarkers.tsx | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 frontend/src/components/Map/DetailsMap/ViewPointMarkers.tsx diff --git a/frontend/src/components/Map/DetailsMap/ViewPointMarkers.tsx b/frontend/src/components/Map/DetailsMap/ViewPointMarkers.tsx new file mode 100644 index 000000000..1f49d4733 --- /dev/null +++ b/frontend/src/components/Map/DetailsMap/ViewPointMarkers.tsx @@ -0,0 +1,43 @@ +import { ViewPoint } from 'modules/viewPoint/interface'; +import { renderToStaticMarkup } from 'react-dom/server'; +import { ViewPoint as ViewPointIcon } from 'components/Icons/ViewPoint'; +import { ClickableMarker } from 'components/Map/components/ClickableMarker'; +import { useIntl } from 'react-intl'; + +interface ViewPointMarkersProps { + viewPoints?: ViewPoint[]; + setMapId?: (id: string) => void; +} + +export const ViewPointMarkers = ({ viewPoints, setMapId }: ViewPointMarkersProps) => { + const intl = useIntl(); + + if (!viewPoints?.length) { + return null; + } + + const points = viewPoints + .filter(({ geometry }) => geometry !== null) + .map(({ id, geometry, title, thumbnailUrl }) => ({ + id: `DETAILS-VIEWPOINT-${id}`, + // @ts-ignore geometry cannot be null because it's filtered above + location: { x: geometry.coordinates[0], y: geometry.coordinates[1] }, + name: title, + pictogramUri: renderToStaticMarkup(), + content: { + imgUrl: thumbnailUrl, + place: intl.formatMessage({ id: 'viewPoint.label' }), + title: title ?? '', + button: { + onClick: () => { + setMapId?.(id); + }, + label: 'viewPoint.examinePicture', + }, + }, + })); + + return ; +}; + +export default ViewPointMarkers; From 110f3f71d81ea292c0435aec24ebf058d81af1de Mon Sep 17 00:00:00 2001 From: Florian Sommariva Date: Wed, 27 Sep 2023 16:26:41 +0200 Subject: [PATCH 28/37] Links details Viewpoints and map interaction --- frontend/src/components/Map/DetailsMap/DetailsMap.tsx | 7 +++++++ .../src/components/Map/DetailsMap/MapChildren.tsx | 11 ++++++++++- .../src/components/Map/DetailsMap/useDetailsMap.tsx | 4 ++++ .../components/DetailsMedias/DetailsMedias.tsx | 11 +++++++++++ 4 files changed, 32 insertions(+), 1 deletion(-) diff --git a/frontend/src/components/Map/DetailsMap/DetailsMap.tsx b/frontend/src/components/Map/DetailsMap/DetailsMap.tsx index 4decfa135..34bd4a797 100644 --- a/frontend/src/components/Map/DetailsMap/DetailsMap.tsx +++ b/frontend/src/components/Map/DetailsMap/DetailsMap.tsx @@ -126,6 +126,8 @@ export const DetailsMap: React.FC = props => { toggleServiceVisibility, infrastructureVisibility, toggleInfrastructureVisibility, + viewPointVisibility, + toggleViewPointVisibility, annotationViewpointVisibility, toggleAnnotationViewpointVisibility, } = useDetailsMap(); @@ -255,6 +257,7 @@ export const DetailsMap: React.FC = props => { props.service && props.service.length > 0 ? serviceVisibility : null } infrastructureVisibility={props.infrastructure ? infrastructureVisibility : null} + viewPointVisibility={props.viewPoints ? viewPointVisibility : null} toggleTrekChildrenVisibility={toggleTrekChildrenVisibility} togglePoiVisibility={togglePoiVisibility} toggleReferencePointsVisibility={toggleReferencePointsVisibility} @@ -265,6 +268,7 @@ export const DetailsMap: React.FC = props => { toggleSignageVisibility={toggleSignageVisibility} toggleServiceVisibility={toggleServiceVisibility} toggleInfrastructureVisibility={toggleInfrastructureVisibility} + toggleViewPointVisiblity={toggleViewPointVisibility} /> {props.trekGeometry && ( = props => { signageVisibility={signageVisibility} serviceVisibility={serviceVisibility} infrastructureVisibility={infrastructureVisibility} + viewPoints={props.viewPoints} + viewPointVisibility={viewPointVisibility} + setMapId={props.setMapId} /> {props.displayAltimetricProfile === true && props.trekGeoJSON && ( diff --git a/frontend/src/components/Map/DetailsMap/MapChildren.tsx b/frontend/src/components/Map/DetailsMap/MapChildren.tsx index cb67f46f3..4c5889a2f 100644 --- a/frontend/src/components/Map/DetailsMap/MapChildren.tsx +++ b/frontend/src/components/Map/DetailsMap/MapChildren.tsx @@ -6,9 +6,10 @@ import { OutdoorSite } from 'modules/outdoorSite/interface'; import { SensitiveAreaGeometry } from 'modules/sensitiveArea/interface'; import { SignageDictionary } from 'modules/signage/interface'; import { InfrastructureDictionary } from 'modules/infrastructure/interface'; -import React, { useContext } from 'react'; +import { useContext } from 'react'; import { useMediaPredicate } from 'react-media-hook'; import { Infrastructure } from 'components/Icons/Infrastructure'; +import { ViewPoint } from 'modules/viewPoint/interface'; import { GeometryListProps } from './DetailsMap'; import { MarkersWithIcon } from './MarkersWithIcon'; @@ -20,6 +21,7 @@ import { SensitiveAreas } from './SensitiveAreas'; import { GeometryList } from './GeometryList'; import { TrekChildren } from './TrekChildren'; import { Visibility } from './useDetailsMap'; +import ViewPointMarkers from './ViewPointMarkers'; export interface PointWithIcon { location: { x: number; y: number }; @@ -52,6 +54,9 @@ type Props = { service?: PointWithIcon[]; infrastructureVisibility: Visibility; infrastructure?: InfrastructureDictionary | null; + viewPointVisibility?: Visibility; + viewPoints?: ViewPoint[]; + setMapId?: (id: string) => void; }; export const MapChildren: React.FC = props => { @@ -122,6 +127,10 @@ export const MapChildren: React.FC = props => { {props.serviceVisibility === 'DISPLAYED' && } {(isMobile || visibleSection === 'report') && props.reportVisibility && } + + {(props.viewPointVisibility === 'DISPLAYED' || visibleSection === 'medias') && ( + + )} ); }; diff --git a/frontend/src/components/Map/DetailsMap/useDetailsMap.tsx b/frontend/src/components/Map/DetailsMap/useDetailsMap.tsx index c2de58632..3d26b73ba 100644 --- a/frontend/src/components/Map/DetailsMap/useDetailsMap.tsx +++ b/frontend/src/components/Map/DetailsMap/useDetailsMap.tsx @@ -21,6 +21,7 @@ export const useDetailsMap = () => { const [signageVisibility, setSignageVisibility] = useState('HIDDEN'); const [serviceVisibility, setServiceVisibility] = useState('HIDDEN'); const [infrastructureVisibility, setInfrastructureVisibility] = useState('HIDDEN'); + const [viewPointVisibility, setViewPointVisibility] = useState('HIDDEN'); const [annotationViewpointVisibility, setAnnotationViewpointVisibility] = useState('DISPLAYED'); @@ -39,6 +40,7 @@ export const useDetailsMap = () => { const toggleSignageVisibility = () => setSignageVisibility(toggleVisibility); const toggleServiceVisibility = () => setServiceVisibility(toggleVisibility); const toggleInfrastructureVisibility = () => setInfrastructureVisibility(toggleVisibility); + const toggleViewPointVisibility = () => setViewPointVisibility(toggleVisibility); const toggleAnnotationViewpointVisibility = () => setAnnotationViewpointVisibility(toggleVisibility); @@ -63,6 +65,8 @@ export const useDetailsMap = () => { toggleServiceVisibility, infrastructureVisibility, toggleInfrastructureVisibility, + viewPointVisibility, + toggleViewPointVisibility, annotationViewpointVisibility, toggleAnnotationViewpointVisibility, }; diff --git a/frontend/src/components/pages/details/components/DetailsMedias/DetailsMedias.tsx b/frontend/src/components/pages/details/components/DetailsMedias/DetailsMedias.tsx index 8e70acc75..ef74b29ff 100644 --- a/frontend/src/components/pages/details/components/DetailsMedias/DetailsMedias.tsx +++ b/frontend/src/components/pages/details/components/DetailsMedias/DetailsMedias.tsx @@ -6,6 +6,8 @@ import { FormattedMessage } from 'react-intl'; import { cn } from 'services/utils/cn'; import { Minus } from 'components/Icons/Minus'; import { Plus } from 'components/Icons/Plus'; +import { useListAndMapContext } from 'modules/map/ListAndMapContext'; +import { ViewPoint as ViewPointIcon } from 'components/Icons/ViewPoint'; interface DetailsMediasProps { className?: string; @@ -38,6 +40,8 @@ export const DetailsMedias: React.FC = ({ return null; } + const { setHoveredCardId } = useListAndMapContext(); + return (
    = ({ TitleTag === 'h2' ? 'text-Mobile-H1 desktop:text-H2' : 'text-Mobile-C1 desktop:text-H4', )} > + {asAccordion && ( diff --git a/frontend/src/translations/ca.json b/frontend/src/translations/ca.json index fcaaffe02..c97300dfb 100644 --- a/frontend/src/translations/ca.json +++ b/frontend/src/translations/ca.json @@ -246,7 +246,7 @@ "title": "Fotos HD", "label": "Foto HD", "credit": "Crèdit fotogràfic :", - "examinePicture": "Navega per la foto" + "displayPicture": "Navega per la foto" }, "Wind": { "N": "Nord", diff --git a/frontend/src/translations/de.json b/frontend/src/translations/de.json index fb00e8e18..4352030e3 100644 --- a/frontend/src/translations/de.json +++ b/frontend/src/translations/de.json @@ -246,7 +246,7 @@ "title": "HD-Fotos", "label": "HD-Foto", "credit": "Fotogutschrift:", - "examinePicture": "Foto durchsuchen" + "displayPicture": "Foto durchsuchen" }, "Wind": { "N": "Norden", diff --git a/frontend/src/translations/en.json b/frontend/src/translations/en.json index be0856e88..e582d5381 100644 --- a/frontend/src/translations/en.json +++ b/frontend/src/translations/en.json @@ -253,7 +253,7 @@ "title": "HD pictures", "label": "HD picture", "credit": "Picture credit:", - "examinePicture": "Exmamine picture" + "displayPicture": "Display picture" }, "Wind": { "N": "North", diff --git a/frontend/src/translations/es.json b/frontend/src/translations/es.json index 47f50ba72..07b69aafb 100644 --- a/frontend/src/translations/es.json +++ b/frontend/src/translations/es.json @@ -246,7 +246,7 @@ "title": "Fotos HD", "label": "Foto HD", "credit": "Crédito de la foto:", - "examinePicture": "Examinar foto" + "displayPicture": "Examinar foto" }, "Wind": { "N": "Norte", diff --git a/frontend/src/translations/fr.json b/frontend/src/translations/fr.json index d8a95ec10..6e25aaa68 100644 --- a/frontend/src/translations/fr.json +++ b/frontend/src/translations/fr.json @@ -253,7 +253,7 @@ "title": "Images HD", "label": "Image HD", "credit": "Crédit image :", - "examinePicture": "Examiner l'image" + "displayPicture": "Afficher l'image" }, "Wind": { "N": "Nord", diff --git a/frontend/src/translations/it.json b/frontend/src/translations/it.json index 9e60a2260..3dd126d70 100644 --- a/frontend/src/translations/it.json +++ b/frontend/src/translations/it.json @@ -256,7 +256,7 @@ "title": "Foto HD", "label": "Foto HD", "credit": "Credito foto:", - "examinePicture": "Sfoglia foto" + "displayPicture": "Sfoglia foto" }, "Wind": { "N": "Nord", From 23ccb44b91ea6877ea67bb1f2e500791d7530020 Mon Sep 17 00:00:00 2001 From: Florian Sommariva Date: Tue, 31 Oct 2023 15:48:28 +0100 Subject: [PATCH 30/37] Add classNames to annotations geometry and make tooltip bigger --- .../components/ViewPointHD/AnnotationItem.tsx | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/frontend/src/components/Map/components/ViewPointHD/AnnotationItem.tsx b/frontend/src/components/Map/components/ViewPointHD/AnnotationItem.tsx index 7951c4d1b..d2a794587 100644 --- a/frontend/src/components/Map/components/ViewPointHD/AnnotationItem.tsx +++ b/frontend/src/components/Map/components/ViewPointHD/AnnotationItem.tsx @@ -12,7 +12,11 @@ const MetaData = ({ properties }: { properties: GeoJsonProperties }) => { if (properties === null || !properties.name) { return null; } - return {properties.name}; + return ( + + {properties.name} + + ); }; export const AnnotationItem = ({ geometry, properties, id }: Props) => { @@ -40,7 +44,12 @@ export const AnnotationItem = ({ geometry, properties, id }: Props) => { {coordinatesAsMultiPoint.map((coordinates, index) => { const [lat, lng] = coordinates; return ( - + ); @@ -59,6 +68,7 @@ export const AnnotationItem = ({ geometry, properties, id }: Props) => { return ( [lng, lat])} > @@ -82,7 +92,7 @@ export const AnnotationItem = ({ geometry, properties, id }: Props) => { const radius = Math.sqrt(Math.pow(diagonal, 2) / 2); return ( - + ); @@ -94,6 +104,7 @@ export const AnnotationItem = ({ geometry, properties, id }: Props) => { {coordinatesAsMultiPolygon.map((group, index) => ( line.map<[number, number]>(([lat, lng]) => [lng, lat]))} > From 36a41c1212c29a18fab8daae8544f69d9e515e14 Mon Sep 17 00:00:00 2001 From: Florian Sommariva Date: Tue, 31 Oct 2023 16:30:43 +0100 Subject: [PATCH 31/37] Restyle show more poi card --- .../components/DetailsCard/DetailsCard.tsx | 50 +++++++++---------- .../__snapshots__/DetailsCard.test.tsx.snap | 12 ++--- 2 files changed, 30 insertions(+), 32 deletions(-) diff --git a/frontend/src/components/pages/details/components/DetailsCard/DetailsCard.tsx b/frontend/src/components/pages/details/components/DetailsCard/DetailsCard.tsx index 72a314dc3..9edddb174 100644 --- a/frontend/src/components/pages/details/components/DetailsCard/DetailsCard.tsx +++ b/frontend/src/components/pages/details/components/DetailsCard/DetailsCard.tsx @@ -78,7 +78,7 @@ export const DetailsCard: React.FC = ( overflow-hidden desktop:w-auto h-fit desktop:flex-row transition-all duration-500`, - truncateState !== 'NONE' ? 'desktop:h-auto pb-6' : 'desktop:h-55', + truncateState !== 'NONE' ? 'desktop:h-auto' : 'desktop:h-55', truncateState === 'TRUNCATE' && hasMedia && 'desktop:h-55', )} onMouseEnter={() => { @@ -116,7 +116,7 @@ export const DetailsCard: React.FC = (
    -
    +
    {place && (

    {place}

    @@ -139,31 +139,29 @@ export const DetailsCard: React.FC = (
    )} {truncateState !== 'NONE' && ( -
    - -
    + + + )} )} diff --git a/frontend/src/components/pages/details/components/DetailsCard/__tests__/__snapshots__/DetailsCard.test.tsx.snap b/frontend/src/components/pages/details/components/DetailsCard/__tests__/__snapshots__/DetailsCard.test.tsx.snap index 0a9799596..ba527d415 100644 --- a/frontend/src/components/pages/details/components/DetailsCard/__tests__/__snapshots__/DetailsCard.test.tsx.snap +++ b/frontend/src/components/pages/details/components/DetailsCard/__tests__/__snapshots__/DetailsCard.test.tsx.snap @@ -88,7 +88,7 @@ Object {

    Date: Mon, 15 Jan 2024 12:04:44 +0100 Subject: [PATCH 32/37] Define default fill and stroke for annotations --- frontend/src/styles/global.css | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/frontend/src/styles/global.css b/frontend/src/styles/global.css index 9c28b038c..5af6aceef 100644 --- a/frontend/src/styles/global.css +++ b/frontend/src/styles/global.css @@ -80,3 +80,12 @@ .leaflet-container:fullscreen #backToMapButton { @apply hidden; } + +.leaflet-interactive.annotation { + stroke: red; + fill: green; +} + +.leaflet-interactive.annotation-line { + fill: none; +} From 7238413621439eb2198fb8fc0b4ef308116ccd88 Mon Sep 17 00:00:00 2001 From: Florian Sommariva Date: Wed, 17 Jan 2024 16:13:49 +0100 Subject: [PATCH 33/37] Add baseline to HDViewpoint section --- .../details/components/DetailsMedias/DetailsMedias.tsx | 7 +++++-- frontend/src/translations/ca.json | 1 + frontend/src/translations/de.json | 1 + frontend/src/translations/en.json | 1 + frontend/src/translations/es.json | 1 + frontend/src/translations/fr.json | 1 + frontend/src/translations/it.json | 1 + 7 files changed, 11 insertions(+), 2 deletions(-) diff --git a/frontend/src/components/pages/details/components/DetailsMedias/DetailsMedias.tsx b/frontend/src/components/pages/details/components/DetailsMedias/DetailsMedias.tsx index 3e6d62206..00cc186ee 100644 --- a/frontend/src/components/pages/details/components/DetailsMedias/DetailsMedias.tsx +++ b/frontend/src/components/pages/details/components/DetailsMedias/DetailsMedias.tsx @@ -50,7 +50,7 @@ export const DetailsMedias: React.FC = ({ TitleTag === 'h2' ? 'text-Mobile-H1 desktop:text-H2' : 'text-Mobile-C1 desktop:text-H4', )} > - + {asAccordion && ( )} +

    + +

      diff --git a/frontend/src/translations/ca.json b/frontend/src/translations/ca.json index c97300dfb..b33b87b04 100644 --- a/frontend/src/translations/ca.json +++ b/frontend/src/translations/ca.json @@ -245,6 +245,7 @@ "viewPoint": { "title": "Fotos HD", "label": "Foto HD", + "description": "Navegueu per imatges enriquides i interactives \"ultra alta definició\"", "credit": "Crèdit fotogràfic :", "displayPicture": "Navega per la foto" }, diff --git a/frontend/src/translations/de.json b/frontend/src/translations/de.json index 4352030e3..bddb20cdb 100644 --- a/frontend/src/translations/de.json +++ b/frontend/src/translations/de.json @@ -245,6 +245,7 @@ "viewPoint": { "title": "HD-Fotos", "label": "HD-Foto", + "description": "Navigieren Sie durch angereicherte, interaktive \"ultrahochauflösende\" Bilder", "credit": "Fotogutschrift:", "displayPicture": "Foto durchsuchen" }, diff --git a/frontend/src/translations/en.json b/frontend/src/translations/en.json index e582d5381..5527490aa 100644 --- a/frontend/src/translations/en.json +++ b/frontend/src/translations/en.json @@ -252,6 +252,7 @@ "viewPoint": { "title": "HD pictures", "label": "HD picture", + "description": "Navigate through enriched, interactive \"ultra High Definition\" pictures", "credit": "Picture credit:", "displayPicture": "Display picture" }, diff --git a/frontend/src/translations/es.json b/frontend/src/translations/es.json index 07b69aafb..33b51d617 100644 --- a/frontend/src/translations/es.json +++ b/frontend/src/translations/es.json @@ -244,6 +244,7 @@ }, "viewPoint": { "title": "Fotos HD", + "description": "Navegue por imágenes enriquecidas e interactivas de \"ultra alta definición\"", "label": "Foto HD", "credit": "Crédito de la foto:", "displayPicture": "Examinar foto" diff --git a/frontend/src/translations/fr.json b/frontend/src/translations/fr.json index 6e25aaa68..eb85e1fa4 100644 --- a/frontend/src/translations/fr.json +++ b/frontend/src/translations/fr.json @@ -252,6 +252,7 @@ "viewPoint": { "title": "Images HD", "label": "Image HD", + "description": "Naviguez dans des images \"très haute définition\" enrichies et interactives", "credit": "Crédit image :", "displayPicture": "Afficher l'image" }, diff --git a/frontend/src/translations/it.json b/frontend/src/translations/it.json index 3dd126d70..34689087d 100644 --- a/frontend/src/translations/it.json +++ b/frontend/src/translations/it.json @@ -255,6 +255,7 @@ "viewPoint": { "title": "Foto HD", "label": "Foto HD", + "description": "Navigare attraverso immagini arricchite e interattive ad \"altissima definizione\"", "credit": "Credito foto:", "displayPicture": "Sfoglia foto" }, From 4f4b754f8c46c5396e10d1c8a2ecbebe5557fe5f Mon Sep 17 00:00:00 2001 From: Florian Sommariva Date: Fri, 26 Jan 2024 18:11:43 +0100 Subject: [PATCH 34/37] Add Leaflet-rastercoords typescript definition --- .../components/Map/components/ViewPointHD/index.tsx | 2 -- frontend/src/types/leaflet-rastercoords.d.ts | 13 +++++++++++++ 2 files changed, 13 insertions(+), 2 deletions(-) create mode 100644 frontend/src/types/leaflet-rastercoords.d.ts diff --git a/frontend/src/components/Map/components/ViewPointHD/index.tsx b/frontend/src/components/Map/components/ViewPointHD/index.tsx index c65e445a5..0896548c4 100644 --- a/frontend/src/components/Map/components/ViewPointHD/index.tsx +++ b/frontend/src/components/Map/components/ViewPointHD/index.tsx @@ -2,7 +2,6 @@ import L from 'leaflet'; import { ViewPoint } from 'modules/viewPoint/interface'; import { useEffect, useState } from 'react'; import { useMap } from 'react-leaflet'; -// @ts-ignore L.RasterCoords = require('leaflet-rastercoords'); const ViewPointHD: React.FC = ({ pictureTilesUrl, metadata }) => { @@ -13,7 +12,6 @@ const ViewPointHD: React.FC = ({ pictureTilesUrl, metadata }) => { const { sizeX, sizeY, tileWidth } = metadata; const map = useMap(); - // @ts-ignore const [raster] = useState(new L.RasterCoords(map, [sizeX, sizeY], tileWidth)); useEffect(() => { diff --git a/frontend/src/types/leaflet-rastercoords.d.ts b/frontend/src/types/leaflet-rastercoords.d.ts new file mode 100644 index 000000000..11acedd59 --- /dev/null +++ b/frontend/src/types/leaflet-rastercoords.d.ts @@ -0,0 +1,13 @@ +import { LatLng, LatLngBounds, LatLngExpression, Map, Point, PointExpression } from 'leaflet'; + +declare module 'leaflet' { + class RasterCoords { + constructor(map: Map, imgsize: number[], tilesize?: number, setmaxbounds?: boolean); + + zoomLevel(): number; + unproject(coords: PointExpression): LatLng; + project(coords: LatLngExpression): Point; + getMaxBounds(): LatLngBounds; + setMaxBounds(): void; + } +} From bb41b36372486d0462010cb239774236a2c13dea Mon Sep 17 00:00:00 2001 From: Florian Sommariva Date: Fri, 26 Jan 2024 18:12:27 +0100 Subject: [PATCH 35/37] Avoid breaking the rule of hook for ViewPointHD component --- .../Map/components/ViewPointHD/index.tsx | 20 +++++++++---------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/frontend/src/components/Map/components/ViewPointHD/index.tsx b/frontend/src/components/Map/components/ViewPointHD/index.tsx index 0896548c4..5aab0e82e 100644 --- a/frontend/src/components/Map/components/ViewPointHD/index.tsx +++ b/frontend/src/components/Map/components/ViewPointHD/index.tsx @@ -1,20 +1,18 @@ import L from 'leaflet'; import { ViewPoint } from 'modules/viewPoint/interface'; -import { useEffect, useState } from 'react'; +import { useEffect } from 'react'; import { useMap } from 'react-leaflet'; -L.RasterCoords = require('leaflet-rastercoords'); +import 'leaflet-rastercoords'; const ViewPointHD: React.FC = ({ pictureTilesUrl, metadata }) => { - if (!metadata || !pictureTilesUrl) { - return null; - } - - const { sizeX, sizeY, tileWidth } = metadata; const map = useMap(); - - const [raster] = useState(new L.RasterCoords(map, [sizeX, sizeY], tileWidth)); - useEffect(() => { + if (!metadata || !pictureTilesUrl) { + return; + } + const { sizeX, sizeY, tileWidth } = metadata; + + const raster = new L.RasterCoords(map, [sizeX, sizeY], tileWidth); if (map === undefined) { return; } @@ -38,7 +36,7 @@ const ViewPointHD: React.FC = ({ pictureTilesUrl, metadata }) => { map.removeLayer(layer); } }; - }, [map, raster]); + }, [map, pictureTilesUrl, metadata]); return null; }; From 959a6f48b27812728f462196761222126090d02e Mon Sep 17 00:00:00 2001 From: Florian Sommariva Date: Fri, 26 Jan 2024 18:16:51 +0100 Subject: [PATCH 36/37] Simplify DetailsCardProps interface --- .../pages/details/components/DetailsCard/DetailsCard.tsx | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/frontend/src/components/pages/details/components/DetailsCard/DetailsCard.tsx b/frontend/src/components/pages/details/components/DetailsCard/DetailsCard.tsx index 9edddb174..8022ae3e5 100644 --- a/frontend/src/components/pages/details/components/DetailsCard/DetailsCard.tsx +++ b/frontend/src/components/pages/details/components/DetailsCard/DetailsCard.tsx @@ -28,13 +28,10 @@ export interface DetailsCardProps { redirectionUrl?: string; type?: string; viewPoints?: ViewPoint[]; -} - -interface DetailsCardPropsWithHandleViewPointClick extends DetailsCardProps { handleViewPointClick?: (id: string) => void; } -export const DetailsCard: React.FC = ({ +export const DetailsCard: React.FC = ({ id, name, description, From 0e9fe1fcaefcad38a0b4252faccad749b1815502 Mon Sep 17 00:00:00 2001 From: Florian Sommariva Date: Mon, 29 Jan 2024 17:33:00 +0100 Subject: [PATCH 37/37] Do not save/display HD viewpoint for offline content --- frontend/cache.js | 1 + frontend/src/components/pages/details/Details.tsx | 6 +++++- .../pages/details/components/DetailsCard/DetailsCard.tsx | 2 +- frontend/src/components/pages/site/OutdoorSiteUI.tsx | 6 +++++- 4 files changed, 12 insertions(+), 3 deletions(-) diff --git a/frontend/cache.js b/frontend/cache.js index 67a4685b5..aeeee869a 100644 --- a/frontend/cache.js +++ b/frontend/cache.js @@ -37,6 +37,7 @@ module.exports = [ && !url.host.includes('stamen-tiles') && !url.host.includes('wxs.ign.fr') && !url.host.includes('data.geopf.fr') + && !url.pathname.startsWith('/api/hdviewpoint/drf/hdviewpoints/') && request.destination === 'image' }, handler: 'NetworkFirst', diff --git a/frontend/src/components/pages/details/Details.tsx b/frontend/src/components/pages/details/Details.tsx index 6079dbd0d..9aa47f26b 100644 --- a/frontend/src/components/pages/details/Details.tsx +++ b/frontend/src/components/pages/details/Details.tsx @@ -208,7 +208,11 @@ export const DetailsUIWithoutContext: React.FC = ({ slug, parentId, langu ); } - if (section.name === 'medias' && details.viewPoints.length > 0) { + if ( + hasNavigator && + section.name === 'medias' && + details.viewPoints.length > 0 + ) { return (
      = ({ {Boolean(description) && ( <> {descriptionStyled} - {Number(viewPoints?.length) > 0 && truncateState !== 'TRUNCATE' && ( + {hasNavigator && Number(viewPoints?.length) > 0 && truncateState !== 'TRUNCATE' && (
      = ({ outdoorSiteUrl, language
      ); } - if (section.name === 'medias' && outdoorSiteContent.viewPoints.length > 0) { + if ( + hasNavigator && + section.name === 'medias' && + outdoorSiteContent.viewPoints.length > 0 + ) { return (