From 379f113d370876a9b2ba273092c6b44d4ae474cf Mon Sep 17 00:00:00 2001 From: Mateusz Banaszak Date: Wed, 8 Jan 2025 08:08:47 +0100 Subject: [PATCH 01/23] update: npm i --- package-lock.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index b323c5f0..042cf6bd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22622,7 +22622,7 @@ }, "packages/components": { "name": "@mapsindoors/components", - "version": "13.23.0", + "version": "13.24.1", "license": "MIT", "dependencies": { "@11ty/eleventy": "^2.0.1", @@ -22662,7 +22662,7 @@ }, "packages/map-template": { "name": "@mapsindoors/map-template", - "version": "1.61.0", + "version": "1.64.0", "devDependencies": { "@googlemaps/js-api-loader": "^1.15.1", "@mapsindoors/components": "*", From 2e2a7ec9616709dbca767fd9e1d4194d6ea2eb54 Mon Sep 17 00:00:00 2001 From: Mateusz Banaszak Date: Wed, 8 Jan 2025 08:09:00 +0100 Subject: [PATCH 02/23] chore: add center to webcomponent.js --- packages/map-template/releaseTools/webcomponent.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/map-template/releaseTools/webcomponent.js b/packages/map-template/releaseTools/webcomponent.js index d467a79f..a01fa9b4 100644 --- a/packages/map-template/releaseTools/webcomponent.js +++ b/packages/map-template/releaseTools/webcomponent.js @@ -35,7 +35,8 @@ const WebMapsIndoorsMap = r2wc(MapsIndoorsMap, { hideNonMatches: "boolean", showExternalIDs: "boolean", showRoadNames: "boolean", - searchExternalLocations: "boolean" + searchExternalLocations: "boolean", + center: "string" } }) From fa47955d076eac32554dd9aeb9da11f3e9e1bde0 Mon Sep 17 00:00:00 2001 From: Mateusz Banaszak Date: Wed, 8 Jan 2025 08:09:11 +0100 Subject: [PATCH 03/23] add: define center atom --- packages/map-template/src/atoms/centerState.js | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 packages/map-template/src/atoms/centerState.js diff --git a/packages/map-template/src/atoms/centerState.js b/packages/map-template/src/atoms/centerState.js new file mode 100644 index 00000000..caeb7a16 --- /dev/null +++ b/packages/map-template/src/atoms/centerState.js @@ -0,0 +1,8 @@ +import { atom } from 'recoil'; + +const centerState = atom({ + key: 'center', + default: null +}); + +export default centerState; \ No newline at end of file From 087d8d3f9bd48fa53f088a1808698a9d566cdad9 Mon Sep 17 00:00:00 2001 From: Mateusz Banaszak Date: Wed, 8 Jan 2025 08:09:53 +0100 Subject: [PATCH 04/23] chore: create a setter inside MapTemplate.jsx --- .../src/components/MapTemplate/MapTemplate.jsx | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/packages/map-template/src/components/MapTemplate/MapTemplate.jsx b/packages/map-template/src/components/MapTemplate/MapTemplate.jsx index 24c374b4..c113c29b 100644 --- a/packages/map-template/src/components/MapTemplate/MapTemplate.jsx +++ b/packages/map-template/src/components/MapTemplate/MapTemplate.jsx @@ -57,6 +57,7 @@ import showExternalIDsState from '../../atoms/showExternalIDsState.js' import showRoadNamesState from '../../atoms/showRoadNamesState.js'; import searchExternalLocationsState from '../../atoms/searchExternalLocationsState.js'; import isNullOrUndefined from '../../helpers/isNullOrUndefined.js'; +import centerState from '../../atoms/centerState.js'; // Define the Custom Elements from our components package. defineCustomElements(); @@ -92,8 +93,9 @@ defineCustomElements(); * @param {boolean} [props.showRoadNames] - A boolean parameter that dictates whether Mapbox road names should be shown. By default, Mapbox road names are hidden when MapsIndoors data is shown. It is dictated by `mi-transition-level` which default value is 17. * @param {boolean} [props.showExternalIDs] - Determine whether the location details on the map should have an external ID visible. The default value is set to false. * @param {boolean} [props.searchExternalLocations] - If you want to perform search for external locations in the Wayfinding mode. If set to true, Mapbox/Google places will be displayed depending on the Map Provider you are using. If set to false, the results returned will only be MapsIndoors results. The default is true. + * @param {string} [props.center] - TODO */ -function MapTemplate({ apiKey, gmApiKey, mapboxAccessToken, venue, locationId, primaryColor, logo, appUserRoles, directionsFrom, directionsTo, externalIDs, tileStyle, startZoomLevel, bearing, pitch, gmMapId, useMapProviderModule, kioskOriginLocationId, language, supportsUrlParameters, useKeyboard, timeout, miTransitionLevel, category, searchAllVenues, hideNonMatches, showRoadNames, showExternalIDs, searchExternalLocations }) { +function MapTemplate({ apiKey, gmApiKey, mapboxAccessToken, venue, locationId, primaryColor, logo, appUserRoles, directionsFrom, directionsTo, externalIDs, tileStyle, startZoomLevel, bearing, pitch, gmMapId, useMapProviderModule, kioskOriginLocationId, language, supportsUrlParameters, useKeyboard, timeout, miTransitionLevel, category, searchAllVenues, hideNonMatches, showRoadNames, showExternalIDs, searchExternalLocations, center }) { const [, setApiKey] = useRecoilState(apiKeyState); const [, setGmApiKey] = useRecoilState(gmApiKeyState); @@ -122,6 +124,7 @@ function MapTemplate({ apiKey, gmApiKey, mapboxAccessToken, venue, locationId, p const [, setshowExternalIDs] = useRecoilState(showExternalIDsState); const [, setShowRoadNames] = useRecoilState(showRoadNamesState); const [, setSearchExternalLocations] = useRecoilState(searchExternalLocationsState); + const [, setCenter] = useRecoilState(centerState); const [viewModeSwitchVisible, setViewModeSwitchVisible] = useState(); const [showVenueSelector, setShowVenueSelector] = useState(true); @@ -553,6 +556,13 @@ function MapTemplate({ apiKey, gmApiKey, mapboxAccessToken, venue, locationId, p setSearchExternalLocations(searchExternalLocations); }, [searchExternalLocations]); + /* + * TODO + */ + useEffect(() => { + setCenter(center); + }, [center]); + /** * When map position is known while initializing the data, * set map to be ready. From 2f21963d067f246045b9b07403df06277054094c Mon Sep 17 00:00:00 2001 From: Mateusz Banaszak Date: Wed, 8 Jan 2025 08:11:10 +0100 Subject: [PATCH 05/23] add: center to MapsIndoorsMap --- .../src/components/MapsIndoorsMap/MapsIndoorsMap.jsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/map-template/src/components/MapsIndoorsMap/MapsIndoorsMap.jsx b/packages/map-template/src/components/MapsIndoorsMap/MapsIndoorsMap.jsx index 34ba972b..594f4f97 100644 --- a/packages/map-template/src/components/MapsIndoorsMap/MapsIndoorsMap.jsx +++ b/packages/map-template/src/components/MapsIndoorsMap/MapsIndoorsMap.jsx @@ -36,6 +36,7 @@ import getBooleanValue from "../../helpers/GetBooleanValue.js"; * @param {boolean} [props.showExternalIDs] - Determine whether the location details on the map should have an external ID visible. The default value is set to false. * @param {boolean} [props.showRoadNames] - A boolean parameter that dictates whether Mapbox road names should be shown. By default, Mapbox road names are hidden when MapsIndoors data is shown. It is dictated by `mi-transition-level` which default value is 17. * @param {boolean} [props.searchExternalLocations] - If you want to perform search for external results in the Wayfinding mode. If set to true, Mapbox/Google places will be displayed depending on the Map Provider you are using. If set to false, the results returned will only be MapsIndoors results. The default is true. + * @param {string} [props.center] - TODO */ function MapsIndoorsMap(props) { @@ -92,9 +93,10 @@ function MapsIndoorsMap(props) { const showExternalIDsQueryParameter = queryStringParams.get('showExternalIDs'); const showRoadNamesQueryParameter = queryStringParams.get('showRoadNames'); const searchExternalLocationsQueryParameter = queryStringParams.get('searchExternalLocations'); + const centerQueryParameter = queryStringParams.get('center'); // Set the initial props on the Map Template component. - + // For the apiKey and venue, set the venue to "AUSTINOFFICE" if the apiKey is "mapspeople3d" and no venue is provided. We want this as the default venue for the "mapspeople3d" apiKey. const apiKey = props.supportsUrlParameters && apiKeyQueryParameter ? apiKeyQueryParameter : (props.apiKey || defaultProps.apiKey); let venue = props.supportsUrlParameters && venueQueryParameter ? venueQueryParameter : (props.venue || defaultProps.venue); @@ -133,7 +135,9 @@ function MapsIndoorsMap(props) { showExternalIDs: getBooleanValue(props.supportsUrlParameters, defaultProps.showExternalIDs, props.showExternalIDs, showExternalIDsQueryParameter), searchExternalLocations: getBooleanValue(props.supportsUrlParameters, defaultProps.searchExternalLocations, props.searchExternalLocations, searchExternalLocationsQueryParameter), supportsUrlParameters: props.supportsUrlParameters, + center: props.supportsUrlParameters && centerQueryParameter ? centerQueryParameter : props.center }); + }, [props]); return ( From 2d254d26134b663bc0b5e9debf3162ff1eb26b0d Mon Sep 17 00:00:00 2001 From: Mateusz Banaszak Date: Thu, 9 Jan 2025 11:10:10 +0100 Subject: [PATCH 06/23] chore: improve determineMapBounds function so it respects center prop --- .../src/hooks/useMapBoundsDeterminer.js | 170 ++++++++++++++---- 1 file changed, 132 insertions(+), 38 deletions(-) diff --git a/packages/map-template/src/hooks/useMapBoundsDeterminer.js b/packages/map-template/src/hooks/useMapBoundsDeterminer.js index d0aa8939..83f218c7 100644 --- a/packages/map-template/src/hooks/useMapBoundsDeterminer.js +++ b/packages/map-template/src/hooks/useMapBoundsDeterminer.js @@ -1,5 +1,5 @@ import { useEffect, useState } from 'react'; -import { useRecoilValue } from 'recoil'; +import { useRecoilValue, useRecoilState } from 'recoil'; import getDesktopPaddingBottom from '../helpers/GetDesktopPaddingBottom'; // Recoil atoms @@ -13,6 +13,7 @@ import startZoomLevelState from '../atoms/startZoomLevelState'; import currentVenueNameState from '../atoms/currentVenueNameState'; import venuesInSolutionState from '../atoms/venuesInSolutionState'; import venueWasSelectedState from '../atoms/venueWasSelectedState'; +import isMapReadyState from '../atoms/isMapReadyState.js'; // Hooks import getMobilePaddingBottom from '../helpers/GetMobilePaddingBottom'; @@ -22,6 +23,11 @@ import { useIsDesktop } from './useIsDesktop'; // Selectors import currentPitchSelector from '../selectors/currentPitch'; +import centerState from '../atoms/centerState'; +import isNullOrUndefined from '../helpers/isNullOrUndefined'; + +// Turf +import booleanIntersects from '@turf/turf'; /** * Determine where in the world to pan the map, based on the combination of venueName, locationId and kioskOriginLocationId. @@ -44,11 +50,13 @@ const useMapBoundsDeterminer = () => { const mapsIndoorsInstance = useRecoilValue(mapsIndoorsInstanceState); const pitch = useRecoilValue(pitchState); const startZoomLevel = useRecoilValue(startZoomLevelState); - const currentVenueName = useRecoilValue(currentVenueNameState); const venuesInSolution = useRecoilValue(venuesInSolutionState); const currentPitch = useRecoilValue(currentPitchSelector); const venueWasSelected = useRecoilValue(venueWasSelectedState); const [kioskLocationDisplayRuleWasChanged, setKioskLocationDisplayRuleWasChanged] = useState(false); + let centerValue = useRecoilValue(centerState); + const [currentVenueName, setCurrentVenueName] = useRecoilState(currentVenueNameState); + const isMapReady = useRecoilState(isMapReadyState); /** * If the app is inactive, run code to reset to initial map position. @@ -62,7 +70,7 @@ const useMapBoundsDeterminer = () => { /* * When relevant state changes, run code to go to a location in the world. */ - useEffect(() => { + useEffect(() => { determineMapBounds(); }, [mapsIndoorsInstance, currentVenueName, locationId, kioskOriginLocationId, pitch, bearing, startZoomLevel, categories]); @@ -72,51 +80,137 @@ const useMapBoundsDeterminer = () => { */ function determineMapBounds() { const currentVenue = venuesInSolution.find(venue => venue.name.toLowerCase() === currentVenueName.toLowerCase()); + let desktopPadBottom = null; + let desktopPadLeft = null; + let mobilePadBottom = null; + if (mapsIndoorsInstance && currentVenue) { setMapPositionInvestigating(true); + // Parse center prop into coordinates. If it is not included in the URL, latLng are undefined. + const [latitude, longitude] = centerValue + ? centerValue.split(",").map(Number) + : [undefined, undefined]; + + // Create centerPoint object. + const centerPoint = { geometry: { type: 'Point', coordinates: [latitude, longitude] } }; + + // Returns Venue that intersects with center prop. + const intersectingVenueWithCenterPoint = venuesInSolution.find(venue => { + return booleanIntersects(venue.geometry, centerPoint.geometry); + }) + + // If startZoomLevel is not defined, fallback to 16 default value. + const zoomLevel = startZoomLevel ?? 16; + + getDesktopPaddingBottom().then(desktopPaddingBottom => { + desktopPadBottom = desktopPaddingBottom; + }); + + getMobilePaddingBottom().then(mobilePaddingBottom => { + mobilePadBottom = mobilePaddingBottom + }); + + getDesktopPaddingLeft().then(desktopPaddingLeft => { + desktopPadLeft = desktopPaddingLeft; + }); + if (kioskOriginLocationId && isDesktop) { - // When in Kiosk mode (which can only happen on desktop), the map is fitted to the bounds of the given Location with some bottom padding to accommodate - // for the bottom-centered modal. - window.mapsindoors.services.LocationsService.getLocation(kioskOriginLocationId).then(kioskLocation => { - if (kioskLocation) { - // Set the floor to the one that the Location belongs to. - const locationFloor = kioskLocation.properties.floor; - mapsIndoorsInstance.setFloor(locationFloor); - setKioskDisplayRule(kioskLocation); - - getDesktopPaddingBottom().then(desktopPaddingBottom => { + if (!isNullOrUndefined(centerValue)) { + // When in Kiosk mode and center prop is defined, set centerPoint to be center prop. + setMapPositionKnown(centerPoint.geometry); + goTo(centerPoint.geometry, mapsIndoorsInstance, desktopPadBottom, 0, zoomLevel, currentPitch, bearing); + } else { + // When in Kiosk mode (which can only happen on desktop), the map is fitted to the bounds of the given Location with some bottom padding to accommodate + // for the bottom-centered modal. + window.mapsindoors.services.LocationsService.getLocation(kioskOriginLocationId).then(kioskLocation => { + if (kioskLocation) { + // Set the floor to the one that the Location belongs to. + const locationFloor = kioskLocation.properties.floor; + mapsIndoorsInstance.setFloor(locationFloor); + setKioskDisplayRule(kioskLocation); + setMapPositionKnown(kioskLocation.geometry); - goTo(kioskLocation.geometry, mapsIndoorsInstance, desktopPaddingBottom, 0, startZoomLevel, currentPitch, bearing); - }); - } - }); + goTo(kioskLocation.geometry, mapsIndoorsInstance, desktopPadBottom, 0, zoomLevel, currentPitch, bearing); + } + }); + } } else if (locationId && !venueWasSelected) { - // When a LocationID is set, the map is centered fitted to the bounds of the given Location with some padding, - // either bottom (on mobile to accommodate for the bottom sheet) or to the left (on desktop to accommodate for the modal). - window.mapsindoors.services.LocationsService.getLocation(locationId).then(location => { - if (location) { - // Set the floor to the one that the Location belongs to. - const locationFloor = location.properties.floor; - mapsIndoorsInstance.setFloor(locationFloor); + if (!isNullOrUndefined(centerValue)) { + // When locationId is defined and center prop is defined, set centerPoint to be center prop. + if (isDesktop) { + setMapPositionKnown(centerPoint.geometry); + goTo(centerPoint.geometry, mapsIndoorsInstance, 0, desktopPadLeft, zoomLevel, currentPitch, bearing); + } else { + setMapPositionKnown(centerPoint.geometry); + goTo(centerPoint.geometry, mapsIndoorsInstance, mobilePadBottom, 0, zoomLevel, currentPitch, bearing); + } + } else { + // When a LocationID is set, the map is centered fitted to the bounds of the given Location with some padding, + // either bottom (on mobile to accommodate for the bottom sheet) or to the left (on desktop to accommodate for the modal). + window.mapsindoors.services.LocationsService.getLocation(locationId).then(location => { + if (location) { + // Set the floor to the one that the Location belongs to. + const locationFloor = location.properties.floor; + mapsIndoorsInstance.setFloor(locationFloor); - if (isDesktop) { - getDesktopPaddingLeft().then(desktopPaddingLeft => { + if (isDesktop) { setMapPositionKnown(location.geometry); - goTo(location.geometry, mapsIndoorsInstance, 0, desktopPaddingLeft, startZoomLevel, currentPitch, bearing); - }); - } else { - getMobilePaddingBottom().then(mobilePaddingBottom => { + goTo(location.geometry, mapsIndoorsInstance, 0, desktopPadLeft, zoomLevel, currentPitch, bearing); + } else { setMapPositionKnown(location.geometry); - goTo(location.geometry, mapsIndoorsInstance, mobilePaddingBottom, 0, startZoomLevel, currentPitch, bearing); - }); + goTo(location.geometry, mapsIndoorsInstance, mobilePadBottom, 0, zoomLevel, currentPitch, bearing); + } } - } - }); + }); + } } else if (currentVenue) { - // When showing a venue, the map is fitted to the bounds of the Venue with no padding. - setMapPositionKnown(currentVenue.geometry); - goTo(currentVenue.geometry, mapsIndoorsInstance, 0, 0, startZoomLevel, currentPitch, bearing); + if (venueWasSelected) { + // If switching Venues, while having center prop defined, set center prop to undefined. + // It is required to be able to switch between Venues inside Venue Selector. + centerValue = undefined; + if (isDesktop) { + setMapPositionKnown(currentVenue.geometry); + goTo(currentVenue.geometry, mapsIndoorsInstance, 0, desktopPadLeft, zoomLevel, currentPitch, bearing); + } else { + setMapPositionKnown(currentVenue.geometry); + goTo(currentVenue.geometry, mapsIndoorsInstance, mobilePadBottom, 0, zoomLevel, currentPitch, bearing); + } + } else { + if (isNullOrUndefined(centerValue)) { + // If center prop is not defined, pan to currentVenue. + if (isDesktop) { + setMapPositionKnown(currentVenue.geometry); + goTo(currentVenue.geometry, mapsIndoorsInstance, 0, desktopPadLeft, zoomLevel, currentPitch, bearing); + } else { + setMapPositionKnown(currentVenue.geometry); + goTo(currentVenue.geometry, mapsIndoorsInstance, mobilePadBottom, 0, zoomLevel, currentPitch, bearing); + } + } else if (isNullOrUndefined(intersectingVenueWithCenterPoint)) { + // If center prop is defined, but it does not intersects with any Venue, pan to value that is defined by center prop. + if (isDesktop) { + setMapPositionKnown(centerPoint.geometry); + goTo(centerPoint.geometry, mapsIndoorsInstance, 0, desktopPadLeft, zoomLevel, currentPitch, bearing); + } else { + setMapPositionKnown(centerPoint.geometry); + goTo(centerPoint.geometry, mapsIndoorsInstance, mobilePadBottom, 0, zoomLevel, currentPitch, bearing); + } + } else { + // If center prop is defined and it does intersects with a Venue, pan to value that is defined by center prop and + // when map is ready, setCurrentVenueName to the Venue that center prop is intersecting with. + if (isDesktop) { + setMapPositionKnown(centerPoint.geometry); + goTo(centerPoint.geometry, mapsIndoorsInstance, 0, desktopPadLeft, zoomLevel, currentPitch, bearing); + } else { + setMapPositionKnown(centerPoint.geometry); + goTo(centerPoint.geometry, mapsIndoorsInstance, mobilePadBottom, 0, zoomLevel, currentPitch, bearing); + } + + if (isMapReady) { + setCurrentVenueName(intersectingVenueWithCenterPoint.name); + } + } + } } } } @@ -161,7 +255,7 @@ export default useMapBoundsDeterminer; function goTo(geometry, mapsIndoorsInstance, paddingBottom, paddingLeft, zoomLevel, pitch, bearing) { mapsIndoorsInstance.getMapView().tilt(pitch || 0); mapsIndoorsInstance.getMapView().rotate(bearing || 0); - mapsIndoorsInstance.goTo({ type: 'Feature', geometry, properties: {}}, { + mapsIndoorsInstance.goTo({ type: 'Feature', geometry, properties: {} }, { maxZoom: zoomLevel ?? 22, padding: { top: 0, right: 0, bottom: paddingBottom, left: paddingLeft }, }).then(() => { From 95e57bb2bec4d46e93a1337a3ac56b13e3600a91 Mon Sep 17 00:00:00 2001 From: Mateusz Banaszak Date: Thu, 9 Jan 2025 14:45:22 +0100 Subject: [PATCH 07/23] fix: lerna error --- packages/map-template/src/hooks/useMapBoundsDeterminer.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/map-template/src/hooks/useMapBoundsDeterminer.js b/packages/map-template/src/hooks/useMapBoundsDeterminer.js index 83f218c7..97de2de0 100644 --- a/packages/map-template/src/hooks/useMapBoundsDeterminer.js +++ b/packages/map-template/src/hooks/useMapBoundsDeterminer.js @@ -27,7 +27,7 @@ import centerState from '../atoms/centerState'; import isNullOrUndefined from '../helpers/isNullOrUndefined'; // Turf -import booleanIntersects from '@turf/turf'; +import * as turf from '@turf/turf'; /** * Determine where in the world to pan the map, based on the combination of venueName, locationId and kioskOriginLocationId. @@ -97,7 +97,7 @@ const useMapBoundsDeterminer = () => { // Returns Venue that intersects with center prop. const intersectingVenueWithCenterPoint = venuesInSolution.find(venue => { - return booleanIntersects(venue.geometry, centerPoint.geometry); + return turf.booleanIntersects(venue.geometry, centerPoint.geometry); }) // If startZoomLevel is not defined, fallback to 16 default value. From 4324c6ffec122dc7176ad4d9c0cbd2c426b60518 Mon Sep 17 00:00:00 2001 From: Mateusz Banaszak Date: Thu, 9 Jan 2025 14:53:10 +0100 Subject: [PATCH 08/23] fix: jsdocs --- .../map-template/src/components/MapTemplate/MapTemplate.jsx | 4 ++-- .../src/components/MapsIndoorsMap/MapsIndoorsMap.jsx | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/map-template/src/components/MapTemplate/MapTemplate.jsx b/packages/map-template/src/components/MapTemplate/MapTemplate.jsx index c113c29b..1b91d5d7 100644 --- a/packages/map-template/src/components/MapTemplate/MapTemplate.jsx +++ b/packages/map-template/src/components/MapTemplate/MapTemplate.jsx @@ -93,7 +93,7 @@ defineCustomElements(); * @param {boolean} [props.showRoadNames] - A boolean parameter that dictates whether Mapbox road names should be shown. By default, Mapbox road names are hidden when MapsIndoors data is shown. It is dictated by `mi-transition-level` which default value is 17. * @param {boolean} [props.showExternalIDs] - Determine whether the location details on the map should have an external ID visible. The default value is set to false. * @param {boolean} [props.searchExternalLocations] - If you want to perform search for external locations in the Wayfinding mode. If set to true, Mapbox/Google places will be displayed depending on the Map Provider you are using. If set to false, the results returned will only be MapsIndoors results. The default is true. - * @param {string} [props.center] - TODO + * @param {string} [props.center] - Specifies the coordinates where the map should load, represented as latitude and longitude values separated by a comma. If the specified coordinates intersect with a Venue, that Venue will be selected in the Venue Selector. */ function MapTemplate({ apiKey, gmApiKey, mapboxAccessToken, venue, locationId, primaryColor, logo, appUserRoles, directionsFrom, directionsTo, externalIDs, tileStyle, startZoomLevel, bearing, pitch, gmMapId, useMapProviderModule, kioskOriginLocationId, language, supportsUrlParameters, useKeyboard, timeout, miTransitionLevel, category, searchAllVenues, hideNonMatches, showRoadNames, showExternalIDs, searchExternalLocations, center }) { @@ -557,7 +557,7 @@ function MapTemplate({ apiKey, gmApiKey, mapboxAccessToken, venue, locationId, p }, [searchExternalLocations]); /* - * TODO + * React on changes to the center prop. */ useEffect(() => { setCenter(center); diff --git a/packages/map-template/src/components/MapsIndoorsMap/MapsIndoorsMap.jsx b/packages/map-template/src/components/MapsIndoorsMap/MapsIndoorsMap.jsx index 594f4f97..e3efa8e4 100644 --- a/packages/map-template/src/components/MapsIndoorsMap/MapsIndoorsMap.jsx +++ b/packages/map-template/src/components/MapsIndoorsMap/MapsIndoorsMap.jsx @@ -36,7 +36,7 @@ import getBooleanValue from "../../helpers/GetBooleanValue.js"; * @param {boolean} [props.showExternalIDs] - Determine whether the location details on the map should have an external ID visible. The default value is set to false. * @param {boolean} [props.showRoadNames] - A boolean parameter that dictates whether Mapbox road names should be shown. By default, Mapbox road names are hidden when MapsIndoors data is shown. It is dictated by `mi-transition-level` which default value is 17. * @param {boolean} [props.searchExternalLocations] - If you want to perform search for external results in the Wayfinding mode. If set to true, Mapbox/Google places will be displayed depending on the Map Provider you are using. If set to false, the results returned will only be MapsIndoors results. The default is true. - * @param {string} [props.center] - TODO + * @param {string} [props.center] - Specifies the coordinates where the map should load, represented as latitude and longitude values separated by a comma. If the specified coordinates intersect with a Venue, that Venue will be selected in the Venue Selector. */ function MapsIndoorsMap(props) { From 3dc341bd947542bc4bd6ce0eef99f772c0feba75 Mon Sep 17 00:00:00 2001 From: Mateusz Banaszak Date: Thu, 9 Jan 2025 14:53:23 +0100 Subject: [PATCH 09/23] fix: use promise and fix naming --- .../src/hooks/useMapBoundsDeterminer.js | 23 ++++++++----------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/packages/map-template/src/hooks/useMapBoundsDeterminer.js b/packages/map-template/src/hooks/useMapBoundsDeterminer.js index 97de2de0..7cf64cb2 100644 --- a/packages/map-template/src/hooks/useMapBoundsDeterminer.js +++ b/packages/map-template/src/hooks/useMapBoundsDeterminer.js @@ -54,9 +54,9 @@ const useMapBoundsDeterminer = () => { const currentPitch = useRecoilValue(currentPitchSelector); const venueWasSelected = useRecoilValue(venueWasSelectedState); const [kioskLocationDisplayRuleWasChanged, setKioskLocationDisplayRuleWasChanged] = useState(false); - let centerValue = useRecoilValue(centerState); const [currentVenueName, setCurrentVenueName] = useRecoilState(currentVenueNameState); const isMapReady = useRecoilState(isMapReadyState); + let center = useRecoilValue(centerState); /** * If the app is inactive, run code to reset to initial map position. @@ -88,8 +88,8 @@ const useMapBoundsDeterminer = () => { setMapPositionInvestigating(true); // Parse center prop into coordinates. If it is not included in the URL, latLng are undefined. - const [latitude, longitude] = centerValue - ? centerValue.split(",").map(Number) + const [latitude, longitude] = center + ? center.split(",").map(Number) : [undefined, undefined]; // Create centerPoint object. @@ -103,20 +103,15 @@ const useMapBoundsDeterminer = () => { // If startZoomLevel is not defined, fallback to 16 default value. const zoomLevel = startZoomLevel ?? 16; - getDesktopPaddingBottom().then(desktopPaddingBottom => { - desktopPadBottom = desktopPaddingBottom; - }); - getMobilePaddingBottom().then(mobilePaddingBottom => { + Promise.all([getDesktopPaddingBottom(), getDesktopPaddingLeft(), getMobilePaddingBottom()]).then(([desktopPaddingBottom, desktopPaddingLeft, mobilePaddingBottom]) => { + desktopPadBottom = desktopPaddingBottom; mobilePadBottom = mobilePaddingBottom - }); - - getDesktopPaddingLeft().then(desktopPaddingLeft => { desktopPadLeft = desktopPaddingLeft; }); if (kioskOriginLocationId && isDesktop) { - if (!isNullOrUndefined(centerValue)) { + if (!isNullOrUndefined(center)) { // When in Kiosk mode and center prop is defined, set centerPoint to be center prop. setMapPositionKnown(centerPoint.geometry); goTo(centerPoint.geometry, mapsIndoorsInstance, desktopPadBottom, 0, zoomLevel, currentPitch, bearing); @@ -136,7 +131,7 @@ const useMapBoundsDeterminer = () => { }); } } else if (locationId && !venueWasSelected) { - if (!isNullOrUndefined(centerValue)) { + if (!isNullOrUndefined(center)) { // When locationId is defined and center prop is defined, set centerPoint to be center prop. if (isDesktop) { setMapPositionKnown(centerPoint.geometry); @@ -168,7 +163,7 @@ const useMapBoundsDeterminer = () => { if (venueWasSelected) { // If switching Venues, while having center prop defined, set center prop to undefined. // It is required to be able to switch between Venues inside Venue Selector. - centerValue = undefined; + center = undefined; if (isDesktop) { setMapPositionKnown(currentVenue.geometry); goTo(currentVenue.geometry, mapsIndoorsInstance, 0, desktopPadLeft, zoomLevel, currentPitch, bearing); @@ -177,7 +172,7 @@ const useMapBoundsDeterminer = () => { goTo(currentVenue.geometry, mapsIndoorsInstance, mobilePadBottom, 0, zoomLevel, currentPitch, bearing); } } else { - if (isNullOrUndefined(centerValue)) { + if (isNullOrUndefined(center)) { // If center prop is not defined, pan to currentVenue. if (isDesktop) { setMapPositionKnown(currentVenue.geometry); From ef705ffd60e0429071f0f663d4f0270267a8eff6 Mon Sep 17 00:00:00 2001 From: Mateusz Banaszak <56337591+matbmapspeople@users.noreply.github.com> Date: Fri, 10 Jan 2025 07:54:12 +0100 Subject: [PATCH 10/23] Update packages/map-template/src/components/MapTemplate/MapTemplate.jsx Co-authored-by: Anders Mogensen --- .../map-template/src/components/MapTemplate/MapTemplate.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/map-template/src/components/MapTemplate/MapTemplate.jsx b/packages/map-template/src/components/MapTemplate/MapTemplate.jsx index 1b91d5d7..f18df7de 100644 --- a/packages/map-template/src/components/MapTemplate/MapTemplate.jsx +++ b/packages/map-template/src/components/MapTemplate/MapTemplate.jsx @@ -93,7 +93,7 @@ defineCustomElements(); * @param {boolean} [props.showRoadNames] - A boolean parameter that dictates whether Mapbox road names should be shown. By default, Mapbox road names are hidden when MapsIndoors data is shown. It is dictated by `mi-transition-level` which default value is 17. * @param {boolean} [props.showExternalIDs] - Determine whether the location details on the map should have an external ID visible. The default value is set to false. * @param {boolean} [props.searchExternalLocations] - If you want to perform search for external locations in the Wayfinding mode. If set to true, Mapbox/Google places will be displayed depending on the Map Provider you are using. If set to false, the results returned will only be MapsIndoors results. The default is true. - * @param {string} [props.center] - Specifies the coordinates where the map should load, represented as latitude and longitude values separated by a comma. If the specified coordinates intersect with a Venue, that Venue will be selected in the Venue Selector. + * @param {string} [props.center] - Specifies the coordinates where the map should load, represented as latitude and longitude values separated by a comma. If the specified coordinates intersect with a Venue, that Venue will be set as the current Venue. */ function MapTemplate({ apiKey, gmApiKey, mapboxAccessToken, venue, locationId, primaryColor, logo, appUserRoles, directionsFrom, directionsTo, externalIDs, tileStyle, startZoomLevel, bearing, pitch, gmMapId, useMapProviderModule, kioskOriginLocationId, language, supportsUrlParameters, useKeyboard, timeout, miTransitionLevel, category, searchAllVenues, hideNonMatches, showRoadNames, showExternalIDs, searchExternalLocations, center }) { From cd15493eeb6e0d1185c5aa50be32381d302e44f5 Mon Sep 17 00:00:00 2001 From: Mateusz Banaszak Date: Fri, 10 Jan 2025 12:10:05 +0100 Subject: [PATCH 11/23] fix: runtime changes and zoom level --- .../src/components/MapsIndoorsMap/MapsIndoorsMap.jsx | 2 +- packages/map-template/src/hooks/useMapBoundsDeterminer.js | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/packages/map-template/src/components/MapsIndoorsMap/MapsIndoorsMap.jsx b/packages/map-template/src/components/MapsIndoorsMap/MapsIndoorsMap.jsx index e3efa8e4..987c7c06 100644 --- a/packages/map-template/src/components/MapsIndoorsMap/MapsIndoorsMap.jsx +++ b/packages/map-template/src/components/MapsIndoorsMap/MapsIndoorsMap.jsx @@ -126,6 +126,7 @@ function MapsIndoorsMap(props) { language: props.supportsUrlParameters && languageQueryParameter ? languageQueryParameter : props.language, miTransitionLevel: props.supportsUrlParameters && miTransitionLevelQueryParameter ? miTransitionLevelQueryParameter : props.miTransitionLevel, category: props.supportsUrlParameters && categoryQueryParameter ? categoryQueryParameter : props.category, + center: props.supportsUrlParameters && centerQueryParameter ? centerQueryParameter : props.center, // Handle boolean values useKeyboard: getBooleanValue(props.supportsUrlParameters, defaultProps.useKeyboard, props.useKeyboard, useKeyboardQueryParameter), useMapProviderModule: getBooleanValue(props.supportsUrlParameters, defaultProps.useMapProviderModule, props.useMapProviderModule, useMapProviderModuleQueryParameter), @@ -135,7 +136,6 @@ function MapsIndoorsMap(props) { showExternalIDs: getBooleanValue(props.supportsUrlParameters, defaultProps.showExternalIDs, props.showExternalIDs, showExternalIDsQueryParameter), searchExternalLocations: getBooleanValue(props.supportsUrlParameters, defaultProps.searchExternalLocations, props.searchExternalLocations, searchExternalLocationsQueryParameter), supportsUrlParameters: props.supportsUrlParameters, - center: props.supportsUrlParameters && centerQueryParameter ? centerQueryParameter : props.center }); }, [props]); diff --git a/packages/map-template/src/hooks/useMapBoundsDeterminer.js b/packages/map-template/src/hooks/useMapBoundsDeterminer.js index 7cf64cb2..0273b67f 100644 --- a/packages/map-template/src/hooks/useMapBoundsDeterminer.js +++ b/packages/map-template/src/hooks/useMapBoundsDeterminer.js @@ -72,7 +72,7 @@ const useMapBoundsDeterminer = () => { */ useEffect(() => { determineMapBounds(); - }, [mapsIndoorsInstance, currentVenueName, locationId, kioskOriginLocationId, pitch, bearing, startZoomLevel, categories]); + }, [mapsIndoorsInstance, currentVenueName, locationId, kioskOriginLocationId, pitch, bearing, startZoomLevel, categories, center]); /** * Based on the combination of the states for venueName, locationId & kioskOriginLocationId, @@ -101,8 +101,7 @@ const useMapBoundsDeterminer = () => { }) // If startZoomLevel is not defined, fallback to 16 default value. - const zoomLevel = startZoomLevel ?? 16; - + const zoomLevel = startZoomLevel ?? 18; Promise.all([getDesktopPaddingBottom(), getDesktopPaddingLeft(), getMobilePaddingBottom()]).then(([desktopPaddingBottom, desktopPaddingLeft, mobilePaddingBottom]) => { desktopPadBottom = desktopPaddingBottom; From 76ca32c92a2b370d5de58e32624cef540f431845 Mon Sep 17 00:00:00 2001 From: Mateusz Banaszak Date: Fri, 10 Jan 2025 12:18:44 +0100 Subject: [PATCH 12/23] fix: null padding values --- .../src/hooks/useMapBoundsDeterminer.js | 93 +++++++++++-------- 1 file changed, 56 insertions(+), 37 deletions(-) diff --git a/packages/map-template/src/hooks/useMapBoundsDeterminer.js b/packages/map-template/src/hooks/useMapBoundsDeterminer.js index 0273b67f..a703ed89 100644 --- a/packages/map-template/src/hooks/useMapBoundsDeterminer.js +++ b/packages/map-template/src/hooks/useMapBoundsDeterminer.js @@ -80,9 +80,6 @@ const useMapBoundsDeterminer = () => { */ function determineMapBounds() { const currentVenue = venuesInSolution.find(venue => venue.name.toLowerCase() === currentVenueName.toLowerCase()); - let desktopPadBottom = null; - let desktopPadLeft = null; - let mobilePadBottom = null; if (mapsIndoorsInstance && currentVenue) { setMapPositionInvestigating(true); @@ -103,17 +100,13 @@ const useMapBoundsDeterminer = () => { // If startZoomLevel is not defined, fallback to 16 default value. const zoomLevel = startZoomLevel ?? 18; - Promise.all([getDesktopPaddingBottom(), getDesktopPaddingLeft(), getMobilePaddingBottom()]).then(([desktopPaddingBottom, desktopPaddingLeft, mobilePaddingBottom]) => { - desktopPadBottom = desktopPaddingBottom; - mobilePadBottom = mobilePaddingBottom - desktopPadLeft = desktopPaddingLeft; - }); - if (kioskOriginLocationId && isDesktop) { if (!isNullOrUndefined(center)) { // When in Kiosk mode and center prop is defined, set centerPoint to be center prop. - setMapPositionKnown(centerPoint.geometry); - goTo(centerPoint.geometry, mapsIndoorsInstance, desktopPadBottom, 0, zoomLevel, currentPitch, bearing); + getDesktopPaddingBottom().then(desktopPaddingBottom => { + setMapPositionKnown(centerPoint.geometry); + goTo(centerPoint.geometry, mapsIndoorsInstance, desktopPaddingBottom, 0, zoomLevel, currentPitch, bearing); + }); } else { // When in Kiosk mode (which can only happen on desktop), the map is fitted to the bounds of the given Location with some bottom padding to accommodate // for the bottom-centered modal. @@ -124,8 +117,10 @@ const useMapBoundsDeterminer = () => { mapsIndoorsInstance.setFloor(locationFloor); setKioskDisplayRule(kioskLocation); - setMapPositionKnown(kioskLocation.geometry); - goTo(kioskLocation.geometry, mapsIndoorsInstance, desktopPadBottom, 0, zoomLevel, currentPitch, bearing); + getDesktopPaddingBottom().then(desktopPaddingBottom => { + setMapPositionKnown(kioskLocation.geometry); + goTo(kioskLocation.geometry, mapsIndoorsInstance, desktopPaddingBottom, 0, zoomLevel, currentPitch, bearing); + }); } }); } @@ -133,11 +128,15 @@ const useMapBoundsDeterminer = () => { if (!isNullOrUndefined(center)) { // When locationId is defined and center prop is defined, set centerPoint to be center prop. if (isDesktop) { - setMapPositionKnown(centerPoint.geometry); - goTo(centerPoint.geometry, mapsIndoorsInstance, 0, desktopPadLeft, zoomLevel, currentPitch, bearing); + getDesktopPaddingLeft().then(desktopPaddingLeft => { + setMapPositionKnown(centerPoint.geometry); + goTo(centerPoint.geometry, mapsIndoorsInstance, 0, desktopPaddingLeft, zoomLevel, currentPitch, bearing); + }); } else { - setMapPositionKnown(centerPoint.geometry); - goTo(centerPoint.geometry, mapsIndoorsInstance, mobilePadBottom, 0, zoomLevel, currentPitch, bearing); + getMobilePaddingBottom().then(mobilePaddingBottom => { + setMapPositionKnown(centerPoint.geometry); + goTo(centerPoint.geometry, mapsIndoorsInstance, mobilePaddingBottom, 0, zoomLevel, currentPitch, bearing); + }); } } else { // When a LocationID is set, the map is centered fitted to the bounds of the given Location with some padding, @@ -149,11 +148,15 @@ const useMapBoundsDeterminer = () => { mapsIndoorsInstance.setFloor(locationFloor); if (isDesktop) { - setMapPositionKnown(location.geometry); - goTo(location.geometry, mapsIndoorsInstance, 0, desktopPadLeft, zoomLevel, currentPitch, bearing); + getDesktopPaddingLeft().then(desktopPaddingLeft => { + setMapPositionKnown(location.geometry); + goTo(location.geometry, mapsIndoorsInstance, 0, desktopPaddingLeft, zoomLevel, currentPitch, bearing); + }); } else { - setMapPositionKnown(location.geometry); - goTo(location.geometry, mapsIndoorsInstance, mobilePadBottom, 0, zoomLevel, currentPitch, bearing); + getMobilePaddingBottom().then(mobilePaddingBottom => { + setMapPositionKnown(location.geometry); + goTo(location.geometry, mapsIndoorsInstance, mobilePaddingBottom, 0, zoomLevel, currentPitch, bearing); + }); } } }); @@ -164,40 +167,56 @@ const useMapBoundsDeterminer = () => { // It is required to be able to switch between Venues inside Venue Selector. center = undefined; if (isDesktop) { - setMapPositionKnown(currentVenue.geometry); - goTo(currentVenue.geometry, mapsIndoorsInstance, 0, desktopPadLeft, zoomLevel, currentPitch, bearing); + getDesktopPaddingLeft().then(desktopPaddingLeft => { + setMapPositionKnown(currentVenue.geometry); + goTo(currentVenue.geometry, mapsIndoorsInstance, 0, desktopPaddingLeft, zoomLevel, currentPitch, bearing); + }); } else { - setMapPositionKnown(currentVenue.geometry); - goTo(currentVenue.geometry, mapsIndoorsInstance, mobilePadBottom, 0, zoomLevel, currentPitch, bearing); + getMobilePaddingBottom().then(mobilePaddingBottom => { + setMapPositionKnown(currentVenue.geometry); + goTo(currentVenue.geometry, mapsIndoorsInstance, mobilePaddingBottom, 0, zoomLevel, currentPitch, bearing); + }); } } else { if (isNullOrUndefined(center)) { // If center prop is not defined, pan to currentVenue. if (isDesktop) { - setMapPositionKnown(currentVenue.geometry); - goTo(currentVenue.geometry, mapsIndoorsInstance, 0, desktopPadLeft, zoomLevel, currentPitch, bearing); + getDesktopPaddingLeft().then(desktopPaddingLeft => { + setMapPositionKnown(currentVenue.geometry); + goTo(currentVenue.geometry, mapsIndoorsInstance, 0, desktopPaddingLeft, zoomLevel, currentPitch, bearing); + }); } else { - setMapPositionKnown(currentVenue.geometry); - goTo(currentVenue.geometry, mapsIndoorsInstance, mobilePadBottom, 0, zoomLevel, currentPitch, bearing); + getMobilePaddingBottom().then(mobilePaddingBottom => { + setMapPositionKnown(currentVenue.geometry); + goTo(currentVenue.geometry, mapsIndoorsInstance, mobilePaddingBottom, 0, zoomLevel, currentPitch, bearing); + }); } } else if (isNullOrUndefined(intersectingVenueWithCenterPoint)) { // If center prop is defined, but it does not intersects with any Venue, pan to value that is defined by center prop. if (isDesktop) { - setMapPositionKnown(centerPoint.geometry); - goTo(centerPoint.geometry, mapsIndoorsInstance, 0, desktopPadLeft, zoomLevel, currentPitch, bearing); + getDesktopPaddingLeft().then(desktopPaddingLeft => { + setMapPositionKnown(centerPoint.geometry); + goTo(centerPoint.geometry, mapsIndoorsInstance, 0, desktopPaddingLeft, zoomLevel, currentPitch, bearing); + }); } else { - setMapPositionKnown(centerPoint.geometry); - goTo(centerPoint.geometry, mapsIndoorsInstance, mobilePadBottom, 0, zoomLevel, currentPitch, bearing); + getMobilePaddingBottom().then(mobilePaddingBottom => { + setMapPositionKnown(centerPoint.geometry); + goTo(centerPoint.geometry, mapsIndoorsInstance, mobilePaddingBottom, 0, zoomLevel, currentPitch, bearing); + }); } } else { // If center prop is defined and it does intersects with a Venue, pan to value that is defined by center prop and // when map is ready, setCurrentVenueName to the Venue that center prop is intersecting with. if (isDesktop) { - setMapPositionKnown(centerPoint.geometry); - goTo(centerPoint.geometry, mapsIndoorsInstance, 0, desktopPadLeft, zoomLevel, currentPitch, bearing); + getDesktopPaddingLeft().then(desktopPaddingLeft => { + setMapPositionKnown(centerPoint.geometry); + goTo(centerPoint.geometry, mapsIndoorsInstance, 0, desktopPaddingLeft, zoomLevel, currentPitch, bearing); + }); } else { - setMapPositionKnown(centerPoint.geometry); - goTo(centerPoint.geometry, mapsIndoorsInstance, mobilePadBottom, 0, zoomLevel, currentPitch, bearing); + getMobilePaddingBottom().then(mobilePaddingBottom => { + setMapPositionKnown(centerPoint.geometry); + goTo(centerPoint.geometry, mapsIndoorsInstance, mobilePaddingBottom, 0, zoomLevel, currentPitch, bearing); + }); } if (isMapReady) { From c75eb4953a22914764d52e3e2e48f2a495af2d78 Mon Sep 17 00:00:00 2001 From: Mateusz Banaszak Date: Tue, 14 Jan 2025 12:16:58 +0100 Subject: [PATCH 13/23] chore: improve JSDocs --- .../src/components/MapsIndoorsMap/MapsIndoorsMap.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/map-template/src/components/MapsIndoorsMap/MapsIndoorsMap.jsx b/packages/map-template/src/components/MapsIndoorsMap/MapsIndoorsMap.jsx index 987c7c06..96843625 100644 --- a/packages/map-template/src/components/MapsIndoorsMap/MapsIndoorsMap.jsx +++ b/packages/map-template/src/components/MapsIndoorsMap/MapsIndoorsMap.jsx @@ -36,7 +36,7 @@ import getBooleanValue from "../../helpers/GetBooleanValue.js"; * @param {boolean} [props.showExternalIDs] - Determine whether the location details on the map should have an external ID visible. The default value is set to false. * @param {boolean} [props.showRoadNames] - A boolean parameter that dictates whether Mapbox road names should be shown. By default, Mapbox road names are hidden when MapsIndoors data is shown. It is dictated by `mi-transition-level` which default value is 17. * @param {boolean} [props.searchExternalLocations] - If you want to perform search for external results in the Wayfinding mode. If set to true, Mapbox/Google places will be displayed depending on the Map Provider you are using. If set to false, the results returned will only be MapsIndoors results. The default is true. - * @param {string} [props.center] - Specifies the coordinates where the map should load, represented as latitude and longitude values separated by a comma. If the specified coordinates intersect with a Venue, that Venue will be selected in the Venue Selector. + * @param {string} [props.center] - If you want the map to show a specific coordinates, provide the center value, f.ex.: center=9.9,57.05. If the specified coordinates intersect with a Venue, that Venue will be selected in the Venue Selector. */ function MapsIndoorsMap(props) { From 1858817c60a82f9181b6a0792c5472e09349ceea Mon Sep 17 00:00:00 2001 From: Mateusz Banaszak Date: Tue, 14 Jan 2025 12:19:16 +0100 Subject: [PATCH 14/23] chore: use recoilstate and move intersecting point later in the code --- .../src/hooks/useMapBoundsDeterminer.js | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/packages/map-template/src/hooks/useMapBoundsDeterminer.js b/packages/map-template/src/hooks/useMapBoundsDeterminer.js index a703ed89..43f17359 100644 --- a/packages/map-template/src/hooks/useMapBoundsDeterminer.js +++ b/packages/map-template/src/hooks/useMapBoundsDeterminer.js @@ -56,7 +56,7 @@ const useMapBoundsDeterminer = () => { const [kioskLocationDisplayRuleWasChanged, setKioskLocationDisplayRuleWasChanged] = useState(false); const [currentVenueName, setCurrentVenueName] = useRecoilState(currentVenueNameState); const isMapReady = useRecoilState(isMapReadyState); - let center = useRecoilValue(centerState); + const [center, setCenter] = useRecoilState(centerState); /** * If the app is inactive, run code to reset to initial map position. @@ -92,11 +92,6 @@ const useMapBoundsDeterminer = () => { // Create centerPoint object. const centerPoint = { geometry: { type: 'Point', coordinates: [latitude, longitude] } }; - // Returns Venue that intersects with center prop. - const intersectingVenueWithCenterPoint = venuesInSolution.find(venue => { - return turf.booleanIntersects(venue.geometry, centerPoint.geometry); - }) - // If startZoomLevel is not defined, fallback to 16 default value. const zoomLevel = startZoomLevel ?? 18; @@ -163,9 +158,6 @@ const useMapBoundsDeterminer = () => { } } else if (currentVenue) { if (venueWasSelected) { - // If switching Venues, while having center prop defined, set center prop to undefined. - // It is required to be able to switch between Venues inside Venue Selector. - center = undefined; if (isDesktop) { getDesktopPaddingLeft().then(desktopPaddingLeft => { setMapPositionKnown(currentVenue.geometry); @@ -178,6 +170,11 @@ const useMapBoundsDeterminer = () => { }); } } else { + // Returns Venue that intersects with center prop. + const intersectingVenueWithCenterPoint = venuesInSolution.find(venue => { + return turf.booleanIntersects(venue.geometry, centerPoint.geometry); + }); + if (isNullOrUndefined(center)) { // If center prop is not defined, pan to currentVenue. if (isDesktop) { From 53f3d97ae58026e839400d9954534b06eab7382b Mon Sep 17 00:00:00 2001 From: Mateusz Banaszak Date: Fri, 17 Jan 2025 09:06:49 +0100 Subject: [PATCH 15/23] chore: apply suggestions --- .../map-template/src/components/MapTemplate/MapTemplate.jsx | 2 +- .../src/components/MapsIndoorsMap/MapsIndoorsMap.jsx | 2 +- packages/map-template/src/hooks/useMapBoundsDeterminer.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/map-template/src/components/MapTemplate/MapTemplate.jsx b/packages/map-template/src/components/MapTemplate/MapTemplate.jsx index f18df7de..8235a768 100644 --- a/packages/map-template/src/components/MapTemplate/MapTemplate.jsx +++ b/packages/map-template/src/components/MapTemplate/MapTemplate.jsx @@ -93,7 +93,7 @@ defineCustomElements(); * @param {boolean} [props.showRoadNames] - A boolean parameter that dictates whether Mapbox road names should be shown. By default, Mapbox road names are hidden when MapsIndoors data is shown. It is dictated by `mi-transition-level` which default value is 17. * @param {boolean} [props.showExternalIDs] - Determine whether the location details on the map should have an external ID visible. The default value is set to false. * @param {boolean} [props.searchExternalLocations] - If you want to perform search for external locations in the Wayfinding mode. If set to true, Mapbox/Google places will be displayed depending on the Map Provider you are using. If set to false, the results returned will only be MapsIndoors results. The default is true. - * @param {string} [props.center] - Specifies the coordinates where the map should load, represented as latitude and longitude values separated by a comma. If the specified coordinates intersect with a Venue, that Venue will be set as the current Venue. + * @param {string} [props.center] - If you want the map to show a specific coordinates, provide the center value, f.ex.: center=9.9,57.05 (latitude, longitude). If the specified coordinates intersect with a Venue, that Venue will be selected in the Venue Selector. */ function MapTemplate({ apiKey, gmApiKey, mapboxAccessToken, venue, locationId, primaryColor, logo, appUserRoles, directionsFrom, directionsTo, externalIDs, tileStyle, startZoomLevel, bearing, pitch, gmMapId, useMapProviderModule, kioskOriginLocationId, language, supportsUrlParameters, useKeyboard, timeout, miTransitionLevel, category, searchAllVenues, hideNonMatches, showRoadNames, showExternalIDs, searchExternalLocations, center }) { diff --git a/packages/map-template/src/components/MapsIndoorsMap/MapsIndoorsMap.jsx b/packages/map-template/src/components/MapsIndoorsMap/MapsIndoorsMap.jsx index 96843625..ebbaa54d 100644 --- a/packages/map-template/src/components/MapsIndoorsMap/MapsIndoorsMap.jsx +++ b/packages/map-template/src/components/MapsIndoorsMap/MapsIndoorsMap.jsx @@ -36,7 +36,7 @@ import getBooleanValue from "../../helpers/GetBooleanValue.js"; * @param {boolean} [props.showExternalIDs] - Determine whether the location details on the map should have an external ID visible. The default value is set to false. * @param {boolean} [props.showRoadNames] - A boolean parameter that dictates whether Mapbox road names should be shown. By default, Mapbox road names are hidden when MapsIndoors data is shown. It is dictated by `mi-transition-level` which default value is 17. * @param {boolean} [props.searchExternalLocations] - If you want to perform search for external results in the Wayfinding mode. If set to true, Mapbox/Google places will be displayed depending on the Map Provider you are using. If set to false, the results returned will only be MapsIndoors results. The default is true. - * @param {string} [props.center] - If you want the map to show a specific coordinates, provide the center value, f.ex.: center=9.9,57.05. If the specified coordinates intersect with a Venue, that Venue will be selected in the Venue Selector. + * @param {string} [props.center] - If you want the map to show a specific coordinates, provide the center value, f.ex.: center=9.9,57.05 (latitude, longitude). If the specified coordinates intersect with a Venue, that Venue will be selected in the Venue Selector. */ function MapsIndoorsMap(props) { diff --git a/packages/map-template/src/hooks/useMapBoundsDeterminer.js b/packages/map-template/src/hooks/useMapBoundsDeterminer.js index 43f17359..2ab07178 100644 --- a/packages/map-template/src/hooks/useMapBoundsDeterminer.js +++ b/packages/map-template/src/hooks/useMapBoundsDeterminer.js @@ -92,7 +92,7 @@ const useMapBoundsDeterminer = () => { // Create centerPoint object. const centerPoint = { geometry: { type: 'Point', coordinates: [latitude, longitude] } }; - // If startZoomLevel is not defined, fallback to 16 default value. + // If center prop is defined and startZoomLevel is not defined, fallback to 18 default value. const zoomLevel = startZoomLevel ?? 18; if (kioskOriginLocationId && isDesktop) { From a3a1df2972a839ce94dd2f0031b1c4d5ba7aab51 Mon Sep 17 00:00:00 2001 From: Mateusz Banaszak Date: Fri, 17 Jan 2025 12:50:53 +0100 Subject: [PATCH 16/23] chore: create a helper function for getting centerPoint --- package-lock.json | 2 +- .../src/hooks/useMapBoundsDeterminer.js | 58 +++++++++++-------- 2 files changed, 35 insertions(+), 25 deletions(-) diff --git a/package-lock.json b/package-lock.json index 108fb295..c50ca2bb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21465,7 +21465,7 @@ }, "packages/map-template": { "name": "@mapsindoors/map-template", - "version": "1.65.1", + "version": "1.66.1", "devDependencies": { "@googlemaps/js-api-loader": "^1.15.1", "@mapsindoors/components": "*", diff --git a/packages/map-template/src/hooks/useMapBoundsDeterminer.js b/packages/map-template/src/hooks/useMapBoundsDeterminer.js index 2ab07178..09099ccd 100644 --- a/packages/map-template/src/hooks/useMapBoundsDeterminer.js +++ b/packages/map-template/src/hooks/useMapBoundsDeterminer.js @@ -84,14 +84,6 @@ const useMapBoundsDeterminer = () => { if (mapsIndoorsInstance && currentVenue) { setMapPositionInvestigating(true); - // Parse center prop into coordinates. If it is not included in the URL, latLng are undefined. - const [latitude, longitude] = center - ? center.split(",").map(Number) - : [undefined, undefined]; - - // Create centerPoint object. - const centerPoint = { geometry: { type: 'Point', coordinates: [latitude, longitude] } }; - // If center prop is defined and startZoomLevel is not defined, fallback to 18 default value. const zoomLevel = startZoomLevel ?? 18; @@ -99,8 +91,8 @@ const useMapBoundsDeterminer = () => { if (!isNullOrUndefined(center)) { // When in Kiosk mode and center prop is defined, set centerPoint to be center prop. getDesktopPaddingBottom().then(desktopPaddingBottom => { - setMapPositionKnown(centerPoint.geometry); - goTo(centerPoint.geometry, mapsIndoorsInstance, desktopPaddingBottom, 0, zoomLevel, currentPitch, bearing); + setMapPositionKnown(getCenterPoint().geometry); + goTo(getCenterPoint().geometry, mapsIndoorsInstance, desktopPaddingBottom, 0, zoomLevel, currentPitch, bearing); }); } else { // When in Kiosk mode (which can only happen on desktop), the map is fitted to the bounds of the given Location with some bottom padding to accommodate @@ -124,13 +116,13 @@ const useMapBoundsDeterminer = () => { // When locationId is defined and center prop is defined, set centerPoint to be center prop. if (isDesktop) { getDesktopPaddingLeft().then(desktopPaddingLeft => { - setMapPositionKnown(centerPoint.geometry); - goTo(centerPoint.geometry, mapsIndoorsInstance, 0, desktopPaddingLeft, zoomLevel, currentPitch, bearing); + setMapPositionKnown(getCenterPoint().geometry); + goTo(getCenterPoint().geometry, mapsIndoorsInstance, 0, desktopPaddingLeft, zoomLevel, currentPitch, bearing); }); } else { getMobilePaddingBottom().then(mobilePaddingBottom => { - setMapPositionKnown(centerPoint.geometry); - goTo(centerPoint.geometry, mapsIndoorsInstance, mobilePaddingBottom, 0, zoomLevel, currentPitch, bearing); + setMapPositionKnown(getCenterPoint().geometry); + goTo(getCenterPoint().geometry, mapsIndoorsInstance, mobilePaddingBottom, 0, zoomLevel, currentPitch, bearing); }); } } else { @@ -172,7 +164,7 @@ const useMapBoundsDeterminer = () => { } else { // Returns Venue that intersects with center prop. const intersectingVenueWithCenterPoint = venuesInSolution.find(venue => { - return turf.booleanIntersects(venue.geometry, centerPoint.geometry); + return turf.booleanIntersects(venue.geometry, getCenterPoint().geometry); }); if (isNullOrUndefined(center)) { @@ -192,13 +184,13 @@ const useMapBoundsDeterminer = () => { // If center prop is defined, but it does not intersects with any Venue, pan to value that is defined by center prop. if (isDesktop) { getDesktopPaddingLeft().then(desktopPaddingLeft => { - setMapPositionKnown(centerPoint.geometry); - goTo(centerPoint.geometry, mapsIndoorsInstance, 0, desktopPaddingLeft, zoomLevel, currentPitch, bearing); + setMapPositionKnown(getCenterPoint().geometry); + goTo(getCenterPoint().geometry, mapsIndoorsInstance, 0, desktopPaddingLeft, zoomLevel, currentPitch, bearing); }); } else { getMobilePaddingBottom().then(mobilePaddingBottom => { - setMapPositionKnown(centerPoint.geometry); - goTo(centerPoint.geometry, mapsIndoorsInstance, mobilePaddingBottom, 0, zoomLevel, currentPitch, bearing); + setMapPositionKnown(getCenterPoint().geometry); + goTo(getCenterPoint().geometry, mapsIndoorsInstance, mobilePaddingBottom, 0, zoomLevel, currentPitch, bearing); }); } } else { @@ -206,13 +198,13 @@ const useMapBoundsDeterminer = () => { // when map is ready, setCurrentVenueName to the Venue that center prop is intersecting with. if (isDesktop) { getDesktopPaddingLeft().then(desktopPaddingLeft => { - setMapPositionKnown(centerPoint.geometry); - goTo(centerPoint.geometry, mapsIndoorsInstance, 0, desktopPaddingLeft, zoomLevel, currentPitch, bearing); + setMapPositionKnown(getCenterPoint().geometry); + goTo(getCenterPoint(latitude, longitude).geometry, mapsIndoorsInstance, 0, desktopPaddingLeft, zoomLevel, currentPitch, bearing); }); } else { getMobilePaddingBottom().then(mobilePaddingBottom => { - setMapPositionKnown(centerPoint.geometry); - goTo(centerPoint.geometry, mapsIndoorsInstance, mobilePaddingBottom, 0, zoomLevel, currentPitch, bearing); + setMapPositionKnown(getCenterPoint().geometry); + goTo(getCenterPoint().geometry, mapsIndoorsInstance, mobilePaddingBottom, 0, zoomLevel, currentPitch, bearing); }); } @@ -246,6 +238,24 @@ const useMapBoundsDeterminer = () => { setKioskLocationDisplayRuleWasChanged(true); } + /** + * Gets center point GeoJSON object based on latitude and longitude. + * If such a point does not exists, undefined is returned. + * + * @param {number} latitude + * @param {number} longitude + * @returns {GeoJSON.Point} + */ + function getCenterPoint() { + // Parse center prop into coordinates. If it is not included in the URL, latLng are undefined. + const [latitude, longitude] = center + ? center.split(",").map(Number) + : [undefined, undefined]; + + const centerPoint = { geometry: { type: 'Point', coordinates: [latitude, longitude] } }; + return centerPoint; + } + return [mapPositionInvestigating, mapPositionKnown]; }; @@ -273,4 +283,4 @@ function goTo(geometry, mapsIndoorsInstance, paddingBottom, paddingLeft, zoomLev mapsIndoorsInstance.setZoom(zoomLevel); } }); -} +} \ No newline at end of file From dcfa83f7a1d384d0b284b164c7ca8661d2a8dd6b Mon Sep 17 00:00:00 2001 From: Mateusz Banaszak Date: Mon, 20 Jan 2025 08:10:39 +0100 Subject: [PATCH 17/23] chore: improve jsdocs --- .../map-template/src/components/MapTemplate/MapTemplate.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/map-template/src/components/MapTemplate/MapTemplate.jsx b/packages/map-template/src/components/MapTemplate/MapTemplate.jsx index 84d867de..017ba137 100644 --- a/packages/map-template/src/components/MapTemplate/MapTemplate.jsx +++ b/packages/map-template/src/components/MapTemplate/MapTemplate.jsx @@ -93,7 +93,7 @@ defineCustomElements(); * @param {boolean} [props.showRoadNames] - A boolean parameter that dictates whether Mapbox road names should be shown. By default, Mapbox road names are hidden when MapsIndoors data is shown. It is dictated by `mi-transition-level` which default value is 17. * @param {boolean} [props.showExternalIDs] - Determine whether the location details on the map should have an external ID visible. The default value is set to false. * @param {boolean} [props.searchExternalLocations] - If you want to perform search for external locations in the Wayfinding mode. If set to true, Mapbox/Google places will be displayed depending on the Map Provider you are using. If set to false, the results returned will only be MapsIndoors results. The default is true. - * @param {string} [props.center] - If you want the map to show a specific coordinates, provide the center value, f.ex.: center=9.9,57.05 (latitude, longitude). If the specified coordinates intersect with a Venue, that Venue will be selected in the Venue Selector. + * @param {string} [props.center] - Specifies the coordinates (latitude, longitude) for centering the map, e.g., center=9.9,57.05. If the provided coordinates intersect with a Venue, that Venue will automatically be selected in the Venue Selector. This also allows to search for map elements within the selected Venue. */ function MapTemplate({ apiKey, gmApiKey, mapboxAccessToken, venue, locationId, primaryColor, logo, appUserRoles, directionsFrom, directionsTo, externalIDs, tileStyle, startZoomLevel, bearing, pitch, gmMapId, useMapProviderModule, kioskOriginLocationId, language, supportsUrlParameters, useKeyboard, timeout, miTransitionLevel, category, searchAllVenues, hideNonMatches, showRoadNames, showExternalIDs, searchExternalLocations, center }) { From c35b413744dd3cfaa6e6e4eec3156db61283621d Mon Sep 17 00:00:00 2001 From: Mateusz Banaszak Date: Mon, 20 Jan 2025 08:13:04 +0100 Subject: [PATCH 18/23] chore: use better naming for zoomLevel --- .../src/hooks/useMapBoundsDeterminer.js | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/packages/map-template/src/hooks/useMapBoundsDeterminer.js b/packages/map-template/src/hooks/useMapBoundsDeterminer.js index 09099ccd..8fb3c6c1 100644 --- a/packages/map-template/src/hooks/useMapBoundsDeterminer.js +++ b/packages/map-template/src/hooks/useMapBoundsDeterminer.js @@ -85,14 +85,14 @@ const useMapBoundsDeterminer = () => { setMapPositionInvestigating(true); // If center prop is defined and startZoomLevel is not defined, fallback to 18 default value. - const zoomLevel = startZoomLevel ?? 18; + const initialZoomLevel = startZoomLevel ?? 18; if (kioskOriginLocationId && isDesktop) { if (!isNullOrUndefined(center)) { // When in Kiosk mode and center prop is defined, set centerPoint to be center prop. getDesktopPaddingBottom().then(desktopPaddingBottom => { setMapPositionKnown(getCenterPoint().geometry); - goTo(getCenterPoint().geometry, mapsIndoorsInstance, desktopPaddingBottom, 0, zoomLevel, currentPitch, bearing); + goTo(getCenterPoint().geometry, mapsIndoorsInstance, desktopPaddingBottom, 0, initialZoomLevel, currentPitch, bearing); }); } else { // When in Kiosk mode (which can only happen on desktop), the map is fitted to the bounds of the given Location with some bottom padding to accommodate @@ -106,7 +106,7 @@ const useMapBoundsDeterminer = () => { getDesktopPaddingBottom().then(desktopPaddingBottom => { setMapPositionKnown(kioskLocation.geometry); - goTo(kioskLocation.geometry, mapsIndoorsInstance, desktopPaddingBottom, 0, zoomLevel, currentPitch, bearing); + goTo(kioskLocation.geometry, mapsIndoorsInstance, desktopPaddingBottom, 0, initialZoomLevel, currentPitch, bearing); }); } }); @@ -117,12 +117,12 @@ const useMapBoundsDeterminer = () => { if (isDesktop) { getDesktopPaddingLeft().then(desktopPaddingLeft => { setMapPositionKnown(getCenterPoint().geometry); - goTo(getCenterPoint().geometry, mapsIndoorsInstance, 0, desktopPaddingLeft, zoomLevel, currentPitch, bearing); + goTo(getCenterPoint().geometry, mapsIndoorsInstance, 0, desktopPaddingLeft, initialZoomLevel, currentPitch, bearing); }); } else { getMobilePaddingBottom().then(mobilePaddingBottom => { setMapPositionKnown(getCenterPoint().geometry); - goTo(getCenterPoint().geometry, mapsIndoorsInstance, mobilePaddingBottom, 0, zoomLevel, currentPitch, bearing); + goTo(getCenterPoint().geometry, mapsIndoorsInstance, mobilePaddingBottom, 0, initialZoomLevel, currentPitch, bearing); }); } } else { @@ -137,12 +137,12 @@ const useMapBoundsDeterminer = () => { if (isDesktop) { getDesktopPaddingLeft().then(desktopPaddingLeft => { setMapPositionKnown(location.geometry); - goTo(location.geometry, mapsIndoorsInstance, 0, desktopPaddingLeft, zoomLevel, currentPitch, bearing); + goTo(location.geometry, mapsIndoorsInstance, 0, desktopPaddingLeft, initialZoomLevel, currentPitch, bearing); }); } else { getMobilePaddingBottom().then(mobilePaddingBottom => { setMapPositionKnown(location.geometry); - goTo(location.geometry, mapsIndoorsInstance, mobilePaddingBottom, 0, zoomLevel, currentPitch, bearing); + goTo(location.geometry, mapsIndoorsInstance, mobilePaddingBottom, 0, initialZoomLevel, currentPitch, bearing); }); } } @@ -153,12 +153,12 @@ const useMapBoundsDeterminer = () => { if (isDesktop) { getDesktopPaddingLeft().then(desktopPaddingLeft => { setMapPositionKnown(currentVenue.geometry); - goTo(currentVenue.geometry, mapsIndoorsInstance, 0, desktopPaddingLeft, zoomLevel, currentPitch, bearing); + goTo(currentVenue.geometry, mapsIndoorsInstance, 0, desktopPaddingLeft, initialZoomLevel, currentPitch, bearing); }); } else { getMobilePaddingBottom().then(mobilePaddingBottom => { setMapPositionKnown(currentVenue.geometry); - goTo(currentVenue.geometry, mapsIndoorsInstance, mobilePaddingBottom, 0, zoomLevel, currentPitch, bearing); + goTo(currentVenue.geometry, mapsIndoorsInstance, mobilePaddingBottom, 0, initialZoomLevel, currentPitch, bearing); }); } } else { @@ -172,12 +172,12 @@ const useMapBoundsDeterminer = () => { if (isDesktop) { getDesktopPaddingLeft().then(desktopPaddingLeft => { setMapPositionKnown(currentVenue.geometry); - goTo(currentVenue.geometry, mapsIndoorsInstance, 0, desktopPaddingLeft, zoomLevel, currentPitch, bearing); + goTo(currentVenue.geometry, mapsIndoorsInstance, 0, desktopPaddingLeft, initialZoomLevel, currentPitch, bearing); }); } else { getMobilePaddingBottom().then(mobilePaddingBottom => { setMapPositionKnown(currentVenue.geometry); - goTo(currentVenue.geometry, mapsIndoorsInstance, mobilePaddingBottom, 0, zoomLevel, currentPitch, bearing); + goTo(currentVenue.geometry, mapsIndoorsInstance, mobilePaddingBottom, 0, initialZoomLevel, currentPitch, bearing); }); } } else if (isNullOrUndefined(intersectingVenueWithCenterPoint)) { @@ -185,12 +185,12 @@ const useMapBoundsDeterminer = () => { if (isDesktop) { getDesktopPaddingLeft().then(desktopPaddingLeft => { setMapPositionKnown(getCenterPoint().geometry); - goTo(getCenterPoint().geometry, mapsIndoorsInstance, 0, desktopPaddingLeft, zoomLevel, currentPitch, bearing); + goTo(getCenterPoint().geometry, mapsIndoorsInstance, 0, desktopPaddingLeft, initialZoomLevel, currentPitch, bearing); }); } else { getMobilePaddingBottom().then(mobilePaddingBottom => { setMapPositionKnown(getCenterPoint().geometry); - goTo(getCenterPoint().geometry, mapsIndoorsInstance, mobilePaddingBottom, 0, zoomLevel, currentPitch, bearing); + goTo(getCenterPoint().geometry, mapsIndoorsInstance, mobilePaddingBottom, 0, initialZoomLevel, currentPitch, bearing); }); } } else { @@ -199,12 +199,12 @@ const useMapBoundsDeterminer = () => { if (isDesktop) { getDesktopPaddingLeft().then(desktopPaddingLeft => { setMapPositionKnown(getCenterPoint().geometry); - goTo(getCenterPoint(latitude, longitude).geometry, mapsIndoorsInstance, 0, desktopPaddingLeft, zoomLevel, currentPitch, bearing); + goTo(getCenterPoint(latitude, longitude).geometry, mapsIndoorsInstance, 0, desktopPaddingLeft, initialZoomLevel, currentPitch, bearing); }); } else { getMobilePaddingBottom().then(mobilePaddingBottom => { setMapPositionKnown(getCenterPoint().geometry); - goTo(getCenterPoint().geometry, mapsIndoorsInstance, mobilePaddingBottom, 0, zoomLevel, currentPitch, bearing); + goTo(getCenterPoint().geometry, mapsIndoorsInstance, mobilePaddingBottom, 0, initialZoomLevel, currentPitch, bearing); }); } From e92cf4e3a0ef9164848ca72d6a966cb8211a1835 Mon Sep 17 00:00:00 2001 From: Mateusz Banaszak Date: Mon, 20 Jan 2025 12:06:02 +0100 Subject: [PATCH 19/23] chore: improve JSDocs for center prop --- .../map-template/src/components/MapTemplate/MapTemplate.jsx | 2 +- .../src/components/MapsIndoorsMap/MapsIndoorsMap.jsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/map-template/src/components/MapTemplate/MapTemplate.jsx b/packages/map-template/src/components/MapTemplate/MapTemplate.jsx index 017ba137..1f7b1657 100644 --- a/packages/map-template/src/components/MapTemplate/MapTemplate.jsx +++ b/packages/map-template/src/components/MapTemplate/MapTemplate.jsx @@ -93,7 +93,7 @@ defineCustomElements(); * @param {boolean} [props.showRoadNames] - A boolean parameter that dictates whether Mapbox road names should be shown. By default, Mapbox road names are hidden when MapsIndoors data is shown. It is dictated by `mi-transition-level` which default value is 17. * @param {boolean} [props.showExternalIDs] - Determine whether the location details on the map should have an external ID visible. The default value is set to false. * @param {boolean} [props.searchExternalLocations] - If you want to perform search for external locations in the Wayfinding mode. If set to true, Mapbox/Google places will be displayed depending on the Map Provider you are using. If set to false, the results returned will only be MapsIndoors results. The default is true. - * @param {string} [props.center] - Specifies the coordinates (latitude, longitude) for centering the map, e.g., center=9.9,57.05. If the provided coordinates intersect with a Venue, that Venue will automatically be selected in the Venue Selector. This also allows to search for map elements within the selected Venue. + * @param {string} [props.center] - Specifies the coordinates where the map should load, represented as latitude and longitude values separated by a comma. If the specified coordinates intersect with a Venue, that Venue will be set as the current Venue. */ function MapTemplate({ apiKey, gmApiKey, mapboxAccessToken, venue, locationId, primaryColor, logo, appUserRoles, directionsFrom, directionsTo, externalIDs, tileStyle, startZoomLevel, bearing, pitch, gmMapId, useMapProviderModule, kioskOriginLocationId, language, supportsUrlParameters, useKeyboard, timeout, miTransitionLevel, category, searchAllVenues, hideNonMatches, showRoadNames, showExternalIDs, searchExternalLocations, center }) { diff --git a/packages/map-template/src/components/MapsIndoorsMap/MapsIndoorsMap.jsx b/packages/map-template/src/components/MapsIndoorsMap/MapsIndoorsMap.jsx index ebbaa54d..387a0915 100644 --- a/packages/map-template/src/components/MapsIndoorsMap/MapsIndoorsMap.jsx +++ b/packages/map-template/src/components/MapsIndoorsMap/MapsIndoorsMap.jsx @@ -36,7 +36,7 @@ import getBooleanValue from "../../helpers/GetBooleanValue.js"; * @param {boolean} [props.showExternalIDs] - Determine whether the location details on the map should have an external ID visible. The default value is set to false. * @param {boolean} [props.showRoadNames] - A boolean parameter that dictates whether Mapbox road names should be shown. By default, Mapbox road names are hidden when MapsIndoors data is shown. It is dictated by `mi-transition-level` which default value is 17. * @param {boolean} [props.searchExternalLocations] - If you want to perform search for external results in the Wayfinding mode. If set to true, Mapbox/Google places will be displayed depending on the Map Provider you are using. If set to false, the results returned will only be MapsIndoors results. The default is true. - * @param {string} [props.center] - If you want the map to show a specific coordinates, provide the center value, f.ex.: center=9.9,57.05 (latitude, longitude). If the specified coordinates intersect with a Venue, that Venue will be selected in the Venue Selector. + * @param {string} [props.center] - Specifies the coordinates where the map should load, represented as latitude and longitude values separated by a comma. If the specified coordinates intersect with a Venue, that Venue will be set as the current Venue. */ function MapsIndoorsMap(props) { From c2ea6f52a77fd62f449630730d213f766d4b1523 Mon Sep 17 00:00:00 2001 From: Mateusz Banaszak Date: Mon, 20 Jan 2025 17:35:54 +0100 Subject: [PATCH 20/23] add: helper function to get a proper zoom level --- .../src/hooks/useMapBoundsDeterminer.js | 42 +++++++++++-------- 1 file changed, 25 insertions(+), 17 deletions(-) diff --git a/packages/map-template/src/hooks/useMapBoundsDeterminer.js b/packages/map-template/src/hooks/useMapBoundsDeterminer.js index 8fb3c6c1..0ed8465d 100644 --- a/packages/map-template/src/hooks/useMapBoundsDeterminer.js +++ b/packages/map-template/src/hooks/useMapBoundsDeterminer.js @@ -84,15 +84,12 @@ const useMapBoundsDeterminer = () => { if (mapsIndoorsInstance && currentVenue) { setMapPositionInvestigating(true); - // If center prop is defined and startZoomLevel is not defined, fallback to 18 default value. - const initialZoomLevel = startZoomLevel ?? 18; - if (kioskOriginLocationId && isDesktop) { if (!isNullOrUndefined(center)) { // When in Kiosk mode and center prop is defined, set centerPoint to be center prop. getDesktopPaddingBottom().then(desktopPaddingBottom => { setMapPositionKnown(getCenterPoint().geometry); - goTo(getCenterPoint().geometry, mapsIndoorsInstance, desktopPaddingBottom, 0, initialZoomLevel, currentPitch, bearing); + goTo(getCenterPoint().geometry, mapsIndoorsInstance, desktopPaddingBottom, 0, getZoomLevel(startZoomLevel), currentPitch, bearing); }); } else { // When in Kiosk mode (which can only happen on desktop), the map is fitted to the bounds of the given Location with some bottom padding to accommodate @@ -106,7 +103,7 @@ const useMapBoundsDeterminer = () => { getDesktopPaddingBottom().then(desktopPaddingBottom => { setMapPositionKnown(kioskLocation.geometry); - goTo(kioskLocation.geometry, mapsIndoorsInstance, desktopPaddingBottom, 0, initialZoomLevel, currentPitch, bearing); + goTo(kioskLocation.geometry, mapsIndoorsInstance, desktopPaddingBottom, 0, getZoomLevel(startZoomLevel), currentPitch, bearing); }); } }); @@ -117,12 +114,12 @@ const useMapBoundsDeterminer = () => { if (isDesktop) { getDesktopPaddingLeft().then(desktopPaddingLeft => { setMapPositionKnown(getCenterPoint().geometry); - goTo(getCenterPoint().geometry, mapsIndoorsInstance, 0, desktopPaddingLeft, initialZoomLevel, currentPitch, bearing); + goTo(getCenterPoint().geometry, mapsIndoorsInstance, 0, desktopPaddingLeft, getZoomLevel(startZoomLevel), currentPitch, bearing); }); } else { getMobilePaddingBottom().then(mobilePaddingBottom => { setMapPositionKnown(getCenterPoint().geometry); - goTo(getCenterPoint().geometry, mapsIndoorsInstance, mobilePaddingBottom, 0, initialZoomLevel, currentPitch, bearing); + goTo(getCenterPoint().geometry, mapsIndoorsInstance, mobilePaddingBottom, 0, getZoomLevel(startZoomLevel), currentPitch, bearing); }); } } else { @@ -137,12 +134,12 @@ const useMapBoundsDeterminer = () => { if (isDesktop) { getDesktopPaddingLeft().then(desktopPaddingLeft => { setMapPositionKnown(location.geometry); - goTo(location.geometry, mapsIndoorsInstance, 0, desktopPaddingLeft, initialZoomLevel, currentPitch, bearing); + goTo(location.geometry, mapsIndoorsInstance, 0, desktopPaddingLeft, getZoomLevel(startZoomLevel), currentPitch, bearing); }); } else { getMobilePaddingBottom().then(mobilePaddingBottom => { setMapPositionKnown(location.geometry); - goTo(location.geometry, mapsIndoorsInstance, mobilePaddingBottom, 0, initialZoomLevel, currentPitch, bearing); + goTo(location.geometry, mapsIndoorsInstance, mobilePaddingBottom, 0, getZoomLevel(startZoomLevel), currentPitch, bearing); }); } } @@ -153,12 +150,12 @@ const useMapBoundsDeterminer = () => { if (isDesktop) { getDesktopPaddingLeft().then(desktopPaddingLeft => { setMapPositionKnown(currentVenue.geometry); - goTo(currentVenue.geometry, mapsIndoorsInstance, 0, desktopPaddingLeft, initialZoomLevel, currentPitch, bearing); + goTo(currentVenue.geometry, mapsIndoorsInstance, 0, desktopPaddingLeft, getZoomLevel(startZoomLevel), currentPitch, bearing); }); } else { getMobilePaddingBottom().then(mobilePaddingBottom => { setMapPositionKnown(currentVenue.geometry); - goTo(currentVenue.geometry, mapsIndoorsInstance, mobilePaddingBottom, 0, initialZoomLevel, currentPitch, bearing); + goTo(currentVenue.geometry, mapsIndoorsInstance, mobilePaddingBottom, 0, getZoomLevel(startZoomLevel), currentPitch, bearing); }); } } else { @@ -172,12 +169,12 @@ const useMapBoundsDeterminer = () => { if (isDesktop) { getDesktopPaddingLeft().then(desktopPaddingLeft => { setMapPositionKnown(currentVenue.geometry); - goTo(currentVenue.geometry, mapsIndoorsInstance, 0, desktopPaddingLeft, initialZoomLevel, currentPitch, bearing); + goTo(currentVenue.geometry, mapsIndoorsInstance, 0, desktopPaddingLeft, getZoomLevel(startZoomLevel), currentPitch, bearing); }); } else { getMobilePaddingBottom().then(mobilePaddingBottom => { setMapPositionKnown(currentVenue.geometry); - goTo(currentVenue.geometry, mapsIndoorsInstance, mobilePaddingBottom, 0, initialZoomLevel, currentPitch, bearing); + goTo(currentVenue.geometry, mapsIndoorsInstance, mobilePaddingBottom, 0, getZoomLevel(startZoomLevel), currentPitch, bearing); }); } } else if (isNullOrUndefined(intersectingVenueWithCenterPoint)) { @@ -185,12 +182,12 @@ const useMapBoundsDeterminer = () => { if (isDesktop) { getDesktopPaddingLeft().then(desktopPaddingLeft => { setMapPositionKnown(getCenterPoint().geometry); - goTo(getCenterPoint().geometry, mapsIndoorsInstance, 0, desktopPaddingLeft, initialZoomLevel, currentPitch, bearing); + goTo(getCenterPoint().geometry, mapsIndoorsInstance, 0, desktopPaddingLeft, getZoomLevel(startZoomLevel), currentPitch, bearing); }); } else { getMobilePaddingBottom().then(mobilePaddingBottom => { setMapPositionKnown(getCenterPoint().geometry); - goTo(getCenterPoint().geometry, mapsIndoorsInstance, mobilePaddingBottom, 0, initialZoomLevel, currentPitch, bearing); + goTo(getCenterPoint().geometry, mapsIndoorsInstance, mobilePaddingBottom, 0, getZoomLevel(startZoomLevel), currentPitch, bearing); }); } } else { @@ -199,12 +196,12 @@ const useMapBoundsDeterminer = () => { if (isDesktop) { getDesktopPaddingLeft().then(desktopPaddingLeft => { setMapPositionKnown(getCenterPoint().geometry); - goTo(getCenterPoint(latitude, longitude).geometry, mapsIndoorsInstance, 0, desktopPaddingLeft, initialZoomLevel, currentPitch, bearing); + goTo(getCenterPoint(latitude, longitude).geometry, mapsIndoorsInstance, 0, desktopPaddingLeft, getZoomLevel(startZoomLevel), currentPitch, bearing); }); } else { getMobilePaddingBottom().then(mobilePaddingBottom => { setMapPositionKnown(getCenterPoint().geometry); - goTo(getCenterPoint().geometry, mapsIndoorsInstance, mobilePaddingBottom, 0, initialZoomLevel, currentPitch, bearing); + goTo(getCenterPoint().geometry, mapsIndoorsInstance, mobilePaddingBottom, 0, getZoomLevel(startZoomLevel), currentPitch, bearing); }); } @@ -256,6 +253,17 @@ const useMapBoundsDeterminer = () => { return centerPoint; } + /** + * Returns startZoomLevel if it is defined. Otherwise it returns default zoom level + * + * @param {number} startZoomLevel + * @returns {number} + */ + function getZoomLevel(startZoomLevel) { + const defaultZoomLevel = 18; + return isNullOrUndefined(startZoomLevel) ? defaultZoomLevel : startZoomLevel; + } + return [mapPositionInvestigating, mapPositionKnown]; }; From 67d42c640995c631a47dacc86aebd733a6136157 Mon Sep 17 00:00:00 2001 From: Mateusz Banaszak Date: Mon, 20 Jan 2025 17:36:08 +0100 Subject: [PATCH 21/23] check if menuInfo?.mainmenu exists --- packages/map-template/src/hooks/useCurrentVenue.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/map-template/src/hooks/useCurrentVenue.js b/packages/map-template/src/hooks/useCurrentVenue.js index 8139e4f8..d95f99b2 100644 --- a/packages/map-template/src/hooks/useCurrentVenue.js +++ b/packages/map-template/src/hooks/useCurrentVenue.js @@ -92,10 +92,12 @@ export const useCurrentVenue = () => { for (const key of keys) { // Get the categories from the App Config that have a matching key. - const appConfigCategory = appConfig?.menuInfo.mainmenu.find(category => category.categoryKey === key); + if (appConfig?.menuInfo?.mainmenu) { + const appConfigCategory = appConfig.menuInfo.mainmenu.find(category => category.categoryKey === key); - if (appConfigCategory) { - uniqueCategories.set(appConfigCategory.categoryKey, { displayName: location.properties.categories[key], iconUrl: appConfigCategory?.iconUrl }) + if (appConfigCategory) { + uniqueCategories.set(appConfigCategory.categoryKey, { displayName: location.properties.categories[key], iconUrl: appConfigCategory?.iconUrl }) + } } } } From b09d40cf0af8fc30f881f43b339be324af6f7828 Mon Sep 17 00:00:00 2001 From: Mateusz Banaszak Date: Wed, 22 Jan 2025 15:36:07 +0100 Subject: [PATCH 22/23] fix: weird padding when no props are applied --- .../src/hooks/useMapBoundsDeterminer.js | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/packages/map-template/src/hooks/useMapBoundsDeterminer.js b/packages/map-template/src/hooks/useMapBoundsDeterminer.js index 0ed8465d..c7851c98 100644 --- a/packages/map-template/src/hooks/useMapBoundsDeterminer.js +++ b/packages/map-template/src/hooks/useMapBoundsDeterminer.js @@ -166,17 +166,8 @@ const useMapBoundsDeterminer = () => { if (isNullOrUndefined(center)) { // If center prop is not defined, pan to currentVenue. - if (isDesktop) { - getDesktopPaddingLeft().then(desktopPaddingLeft => { - setMapPositionKnown(currentVenue.geometry); - goTo(currentVenue.geometry, mapsIndoorsInstance, 0, desktopPaddingLeft, getZoomLevel(startZoomLevel), currentPitch, bearing); - }); - } else { - getMobilePaddingBottom().then(mobilePaddingBottom => { - setMapPositionKnown(currentVenue.geometry); - goTo(currentVenue.geometry, mapsIndoorsInstance, mobilePaddingBottom, 0, getZoomLevel(startZoomLevel), currentPitch, bearing); - }); - } + setMapPositionKnown(currentVenue.geometry); + goTo(currentVenue.geometry, mapsIndoorsInstance, 0, 0, getZoomLevel(startZoomLevel), currentPitch, bearing); } else if (isNullOrUndefined(intersectingVenueWithCenterPoint)) { // If center prop is defined, but it does not intersects with any Venue, pan to value that is defined by center prop. if (isDesktop) { @@ -246,8 +237,8 @@ const useMapBoundsDeterminer = () => { function getCenterPoint() { // Parse center prop into coordinates. If it is not included in the URL, latLng are undefined. const [latitude, longitude] = center - ? center.split(",").map(Number) - : [undefined, undefined]; + ? center.split(",").map(Number) + : [undefined, undefined]; const centerPoint = { geometry: { type: 'Point', coordinates: [latitude, longitude] } }; return centerPoint; From e114fc35911ff4af2718bee56e29114c08ce4630 Mon Sep 17 00:00:00 2001 From: Mateusz Banaszak Date: Wed, 22 Jan 2025 15:37:46 +0100 Subject: [PATCH 23/23] chore: clean up --- packages/map-template/src/hooks/useMapBoundsDeterminer.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/map-template/src/hooks/useMapBoundsDeterminer.js b/packages/map-template/src/hooks/useMapBoundsDeterminer.js index c7851c98..6b9c34c0 100644 --- a/packages/map-template/src/hooks/useMapBoundsDeterminer.js +++ b/packages/map-template/src/hooks/useMapBoundsDeterminer.js @@ -187,7 +187,7 @@ const useMapBoundsDeterminer = () => { if (isDesktop) { getDesktopPaddingLeft().then(desktopPaddingLeft => { setMapPositionKnown(getCenterPoint().geometry); - goTo(getCenterPoint(latitude, longitude).geometry, mapsIndoorsInstance, 0, desktopPaddingLeft, getZoomLevel(startZoomLevel), currentPitch, bearing); + goTo(getCenterPoint().geometry, mapsIndoorsInstance, 0, desktopPaddingLeft, getZoomLevel(startZoomLevel), currentPitch, bearing); }); } else { getMobilePaddingBottom().then(mobilePaddingBottom => {