mirror of
https://github.com/DOI-DO/j40-cejst-2.git
synced 2025-07-28 11:51:16 -07:00
adds map side panel (#406)
* initial map side panel * componentize MapSidePanel * remove selection from J40Map * adds isFeatureSelected to toggle component * filters data from server for client UI * styling and refactor * added TODO * adds styling to intro and pairing feedback * add mobile styling * adds popup back to fs feature flag * adds tests and aria roles * makes mobile content same as desktop * prettier update * initial e2e mapSidePanel test * adds cypress tests on desktop and mobile * adds sass util and updates cypress tests * cleans up tests * reverts tsconfig file * fixes map alignment * renaming and using constants * renaming sidePanel to infoPanel * intl messaging * adds snapshot testing and utility sass file * PR feedback - adds intl messages - adds data-cy attr to cy tests - snapshot testing for unit tests - fixes bug where side panel extends past the map - moves all wrapper content in MapWrapper * logs isMobile to troubleshoot deployed PR * adds react-device-detect for isMobile detection * adds new instance of map for mobile * adds instance * adds isMobile to state * tests the fix for mobile map view on PR * PR review feedback - localize MapIntroduction - update snapshot tests - QA feedback - constants.isMobile points to react-device-detect
This commit is contained in:
parent
a787bd71ab
commit
36f43b2d44
25 changed files with 1430 additions and 27185 deletions
|
@ -1,4 +1,5 @@
|
|||
/* eslint-disable no-unused-vars */
|
||||
// External Libs:
|
||||
import React, {MouseEvent, useRef, useState} from 'react';
|
||||
import {Map, MapboxGeoJSONFeature, LngLatBoundsLike} from 'maplibre-gl';
|
||||
import ReactMapGL, {
|
||||
|
@ -11,13 +12,20 @@ import ReactMapGL, {
|
|||
FlyToInterpolator,
|
||||
FullscreenControl,
|
||||
MapRef} from 'react-map-gl';
|
||||
import {makeMapStyle} from '../data/mapStyle';
|
||||
import AreaDetail from './areaDetail';
|
||||
import bbox from '@turf/bbox';
|
||||
import * as d3 from 'd3-ease';
|
||||
import {useFlags} from '../contexts/FlagContext';
|
||||
import TerritoryFocusControl from './territoryFocusControl';
|
||||
import {isMobile} from 'react-device-detect';
|
||||
|
||||
// Contexts:
|
||||
import {useFlags} from '../contexts/FlagContext';
|
||||
|
||||
// Components:
|
||||
import TerritoryFocusControl from './territoryFocusControl';
|
||||
import MapInfoPanel from './mapInfoPanel';
|
||||
import AreaDetail from './areaDetail';
|
||||
|
||||
// Styles and constants
|
||||
import {makeMapStyle} from '../data/mapStyle';
|
||||
import 'maplibre-gl/dist/maplibre-gl.css';
|
||||
import * as constants from '../data/constants';
|
||||
import * as styles from './J40Map.module.scss';
|
||||
|
@ -31,13 +39,14 @@ declare global {
|
|||
}
|
||||
|
||||
|
||||
interface IDetailViewInterface {
|
||||
export interface IDetailViewInterface {
|
||||
latitude: number
|
||||
longitude: number
|
||||
zoom: number
|
||||
properties: constants.J40Properties,
|
||||
};
|
||||
|
||||
|
||||
const J40Map = () => {
|
||||
const [viewport, setViewport] = useState<ViewportProps>({
|
||||
latitude: constants.DEFAULT_CENTER[0],
|
||||
|
@ -49,6 +58,8 @@ const J40Map = () => {
|
|||
const [detailViewData, setDetailViewData] = useState<IDetailViewInterface>();
|
||||
const [transitionInProgress, setTransitionInProgress] = useState<boolean>(false);
|
||||
const [geolocationInProgress, setGeolocationInProgress] = useState<boolean>(false);
|
||||
const [isMobileMapState, setIsMobileMapState] = useState<boolean>(false);
|
||||
|
||||
const mapRef = useRef<MapRef>(null);
|
||||
const flags = useFlags();
|
||||
|
||||
|
@ -66,6 +77,7 @@ const J40Map = () => {
|
|||
padding: 40,
|
||||
},
|
||||
);
|
||||
|
||||
// If we've selected a new feature, set 'selected' to false
|
||||
if (selectedFeature && feature.id !== selectedFeature.id) {
|
||||
setMapSelected(selectedFeature, false);
|
||||
|
@ -90,6 +102,8 @@ const J40Map = () => {
|
|||
if (typeof window !== 'undefined' && window.Cypress && mapRef.current) {
|
||||
window.underlyingMap = mapRef.current.getMap();
|
||||
}
|
||||
|
||||
if (isMobile) setIsMobileMapState(true);
|
||||
};
|
||||
|
||||
|
||||
|
@ -110,6 +124,7 @@ const J40Map = () => {
|
|||
});
|
||||
};
|
||||
|
||||
|
||||
const setMapSelected = (feature:MapboxGeoJSONFeature, isSelected:boolean) : void => {
|
||||
// The below can be confirmed during debug with:
|
||||
// mapRef.current.getFeatureState({"id":feature.id, "source":feature.source, "sourceLayer":feature.sourceLayer})
|
||||
|
@ -125,6 +140,7 @@ const J40Map = () => {
|
|||
}
|
||||
};
|
||||
|
||||
|
||||
const onClickTerritoryFocusButton = (event: MouseEvent<HTMLButtonElement>) => {
|
||||
const buttonID = event.target && (event.target as HTMLElement).id;
|
||||
|
||||
|
@ -164,16 +180,15 @@ const J40Map = () => {
|
|||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className={styles.mapAndInfoPanelContainer}>
|
||||
<ReactMapGL
|
||||
{...viewport}
|
||||
className={styles.mapContainer}
|
||||
mapStyle={makeMapStyle(flags)}
|
||||
minZoom={constants.GLOBAL_MIN_ZOOM}
|
||||
maxZoom={constants.GLOBAL_MAX_ZOOM}
|
||||
mapOptions={{hash: true}}
|
||||
width="100%"
|
||||
height="52vw"
|
||||
height={isMobileMapState ? '44vh' : '100%'}
|
||||
dragRotate={false}
|
||||
touchRotate={false}
|
||||
interactiveLayerIds={[constants.HIGH_SCORE_LAYER_NAME]}
|
||||
|
@ -183,8 +198,9 @@ const J40Map = () => {
|
|||
onTransitionStart={onTransitionStart}
|
||||
onTransitionEnd={onTransitionEnd}
|
||||
ref={mapRef}
|
||||
data-cy={'reactMapGL'}
|
||||
>
|
||||
{(detailViewData && !transitionInProgress) && (
|
||||
{('fs' in flags && detailViewData && !transitionInProgress) && (
|
||||
<Popup
|
||||
className={styles.j40Popup}
|
||||
tipSize={5}
|
||||
|
@ -198,7 +214,6 @@ const J40Map = () => {
|
|||
<AreaDetail properties={detailViewData.properties} />
|
||||
</Popup>
|
||||
)}
|
||||
|
||||
<NavigationControl
|
||||
showCompass={false}
|
||||
className={styles.navigationControl}
|
||||
|
@ -214,7 +229,12 @@ const J40Map = () => {
|
|||
<TerritoryFocusControl onClickTerritoryFocusButton={onClickTerritoryFocusButton}/>
|
||||
{'fs' in flags ? <FullscreenControl className={styles.fullscreenControl}/> :'' }
|
||||
</ReactMapGL>
|
||||
</>
|
||||
<MapInfoPanel
|
||||
className={styles.mapInfoPanel}
|
||||
featureProperties={detailViewData?.properties}
|
||||
selectedFeatureId={selectedFeature?.id}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue