diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 6e2f75e..fe039ad 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -13,6 +13,7 @@ "classnames": "^2.3.1", "downloadjs": "^1.4.7", "fomantic-ui-less": "^2.8.8", + "immer": "^9.0.7", "luxon": "^1.28.0", "maplibre-gl": "^1.15.2", "mini-css-extract-plugin": "^2.4.5", @@ -4873,6 +4874,15 @@ "node": ">=0.10.0" } }, + "node_modules/immer": { + "version": "9.0.7", + "resolved": "https://registry.npmjs.org/immer/-/immer-9.0.7.tgz", + "integrity": "sha512-KGllzpbamZDvOIxnmJ0jI840g7Oikx58lBPWV0hUh7dtAyZpFqqrBZdKka5GlTwMTZ1Tjc/bKKW4VSFAt6BqMA==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/immer" + } + }, "node_modules/import-fresh": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", @@ -12790,6 +12800,11 @@ "optional": true, "peer": true }, + "immer": { + "version": "9.0.7", + "resolved": "https://registry.npmjs.org/immer/-/immer-9.0.7.tgz", + "integrity": "sha512-KGllzpbamZDvOIxnmJ0jI840g7Oikx58lBPWV0hUh7dtAyZpFqqrBZdKka5GlTwMTZ1Tjc/bKKW4VSFAt6BqMA==" + }, "import-fresh": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", diff --git a/frontend/package.json b/frontend/package.json index 58f3bc0..172cfc5 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -12,6 +12,7 @@ "classnames": "^2.3.1", "downloadjs": "^1.4.7", "fomantic-ui-less": "^2.8.8", + "immer": "^9.0.7", "luxon": "^1.28.0", "maplibre-gl": "^1.15.2", "mini-css-extract-plugin": "^2.4.5", diff --git a/frontend/src/components/Map/index.tsx b/frontend/src/components/Map/index.tsx index 7d9f25c..120325e 100644 --- a/frontend/src/components/Map/index.tsx +++ b/frontend/src/components/Map/index.tsx @@ -1,4 +1,5 @@ import React, {useState, useCallback, useMemo, useEffect} from 'react' +import {connect} from 'react-redux' import _ from 'lodash' import ReactMapGl, {WebMercatorViewport, AttributionControl, NavigationControl} from 'react-map-gl' import turfBbox from '@turf/bbox' @@ -6,10 +7,13 @@ import {useHistory, useLocation} from 'react-router-dom' import {useConfig} from 'config' -import {basemap} from '../../mapstyles' +import {baseMapStyles} from '../../mapstyles' + const EMPTY_VIEWPORT = {longitude: 0, latitude: 0, zoom: 0} +export const withBaseMapStyle = connect((state) => ({baseMapStyle: state.mapConfig?.baseMap?.style ?? 'positron'})) + function parseHash(v) { if (!v) return null const m = v.match(/^#([0-9\.]+)\/([0-9\.]+)\/([0-9\.]+)$/) @@ -41,15 +45,17 @@ function useViewportFromUrl() { } -export default function Map({ +function Map({ viewportFromUrl, children, boundsFromJson, + baseMapStyle, ...props }: { viewportFromUrl?: boolean - children: React.ReactNode - boundsFromJson: GeoJSON.Geometry + children: React.ReactNode + boundsFromJson: GeoJSON.Geometry + baseMapStyle: string }) { const [viewportState, setViewportState] = useState(EMPTY_VIEWPORT) const [viewportUrl, setViewportUrl] = useViewportFromUrl() @@ -81,7 +87,7 @@ export default function Map({ }, [boundsFromJson]) return ( - + ) } + +export default withBaseMapStyle(Map) diff --git a/frontend/src/mapstyles/index.js b/frontend/src/mapstyles/index.js index 28e3a62..e40e5a3 100644 --- a/frontend/src/mapstyles/index.js +++ b/frontend/src/mapstyles/index.js @@ -4,6 +4,7 @@ import bright from './bright.json' import positron from './positron.json' export {bright, positron} +export const baseMapStyles = {bright, positron} export function colorByDistance(attribute = 'distance_overtaker_mean', fallback = '#ABC') { return [ diff --git a/frontend/src/pages/MapPage/LayerSidebar.tsx b/frontend/src/pages/MapPage/LayerSidebar.tsx new file mode 100644 index 0000000..56d601a --- /dev/null +++ b/frontend/src/pages/MapPage/LayerSidebar.tsx @@ -0,0 +1,29 @@ +import React from 'react' +import {connect} from 'react-redux' +import {List, Select} from 'semantic-ui-react' + +import * as mapConfigActions from 'reducers/mapConfig' + +const BASEMAP_STYLE_OPTIONS = [ + {key: 'positron', value: 'positron', text: 'Positron'}, + {key: 'bright', value: 'bright', text: 'OSM Bright'}, +] + +function LayerSidebar({mapConfig, setBasemapStyle}) { + return ( +
+ + + Basemap Style +