From 6b3854058672b00456232c0c2c077362a10eb85a Mon Sep 17 00:00:00 2001 From: Paul Bienkowski Date: Sat, 4 Dec 2021 13:28:35 +0100 Subject: [PATCH] Make road colors and untagged roads display configurable --- frontend/src/mapstyles/index.js | 45 ------------- frontend/src/pages/MapPage/LayerSidebar.tsx | 35 ++++++++-- frontend/src/pages/MapPage/index.tsx | 73 +++++++++++++++++++-- frontend/src/reducers/mapConfig.ts | 12 ++-- 4 files changed, 102 insertions(+), 63 deletions(-) diff --git a/frontend/src/mapstyles/index.js b/frontend/src/mapstyles/index.js index e40e5a3..7c468e2 100644 --- a/frontend/src/mapstyles/index.js +++ b/frontend/src/mapstyles/index.js @@ -27,51 +27,6 @@ export function colorByDistance(attribute = 'distance_overtaker_mean', fallback ] } -export const roadsLayer = { - id: 'obs', - type: 'line', - source: 'obs', - 'source-layer': 'obs_roads', - layout: { - 'line-cap': 'round', - 'line-join': 'round', - }, - paint: { - 'line-width': [ - 'interpolate', - ['exponential', 1.5], - ['zoom'], - 12, - 2, - 17, - ['case', ['!', ['to-boolean', ['get', 'distance_overtaker_mean']]], 2, 6], - ], - 'line-color': colorByDistance(), - 'line-opacity': [ - 'interpolate', - ['linear'], - ['zoom'], - 12, - 0, - 13, - ['case', ['!', ['to-boolean', ['get', 'distance_overtaker_mean']]], 0, 1], - 14, - ['case', ['!', ['to-boolean', ['get', 'distance_overtaker_mean']]], 0, 1], - 15, - 1, - ], - 'line-offset': [ - 'interpolate', - ['exponential', 1.5], - ['zoom'], - 12, - ['get', 'offset_direction'], - 19, - ['*', ['get', 'offset_direction'], 8], - ], - }, - minzoom: 12, -} export const trackLayer = { type: 'line', diff --git a/frontend/src/pages/MapPage/LayerSidebar.tsx b/frontend/src/pages/MapPage/LayerSidebar.tsx index 56d601a..c8aa5ff 100644 --- a/frontend/src/pages/MapPage/LayerSidebar.tsx +++ b/frontend/src/pages/MapPage/LayerSidebar.tsx @@ -1,15 +1,25 @@ import React from 'react' import {connect} from 'react-redux' -import {List, Select} from 'semantic-ui-react' +import {List, Select, Header, Checkbox} 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'}, + {value: 'positron', key: 'positron', text: 'Positron'}, + {value: 'bright', key: 'bright', text: 'OSM Bright'}, ] -function LayerSidebar({mapConfig, setBasemapStyle}) { +const ROAD_ATTRIBUTE_OPTIONS = [ + {value: 'distance_overtaker_mean', key: 'distance_overtaker_mean', text: 'Overtaker distance mean'}, + {value: 'distance_overtaker_min', key: 'distance_overtaker_min', text: 'Overtaker distance minimum'}, + {value: 'distance_overtaker_max', key: 'distance_overtaker_max', text: 'Overtaker distance maximum'}, + {value: 'distance_overtaker_median', key: 'distance_overtaker_median', text: 'Overtaker distance median'}, + {value: 'overtaking_event_count', key: 'overtaking_event_count', text: 'Event count'}, +] + +function LayerSidebar({mapConfig, setMapConfigFlag}) { + const showUntagged = mapConfig?.obsRoads?.showUntagged ?? true + return (
@@ -18,7 +28,22 @@ function LayerSidebar({mapConfig, setBasemapStyle}) { setMapConfigFlag('obsRoads.attribute', value)} /> diff --git a/frontend/src/pages/MapPage/index.tsx b/frontend/src/pages/MapPage/index.tsx index c08358e..9b9eae1 100644 --- a/frontend/src/pages/MapPage/index.tsx +++ b/frontend/src/pages/MapPage/index.tsx @@ -1,18 +1,72 @@ -import React, {useState, useCallback} from 'react' +import React, {useState, useCallback, useMemo} from 'react' import _ from 'lodash' -import {Sidebar, Button} from 'semantic-ui-react' +import {Button} from 'semantic-ui-react' import {Layer, Source} from 'react-map-gl' +import produce from 'immer' +import {connect} from 'react-redux' import {Page, Map} from 'components' import {useConfig} from 'config' - -import {roadsLayer} from '../../mapstyles' +import {colorByDistance} from 'mapstyles' import RoadInfo from './RoadInfo' import LayerSidebar from './LayerSidebar' import styles from './styles.module.less' -export default function MapPage() { + +const untaggedRoadsLayer = { + id: 'obs_roads_untagged', + type: 'line', + source: 'obs', + 'source-layer': 'obs_roads', + filter: ['!', ['to-boolean', ['get', 'distance_overtaker_mean']]], + layout: { + 'line-cap': 'round', + 'line-join': 'round', + }, + paint: { + 'line-width': [ + 'interpolate', + ['exponential', 1.5], + ['zoom'], + 12, + 2, + 17, + 2, + ], + 'line-color': "#ABC", + 'line-opacity': [ + 'interpolate', + ['linear'], + ['zoom'], + 14, + 0, + 15, + 1, + ], + 'line-offset': [ + 'interpolate', + ['exponential', 1.5], + ['zoom'], + 12, + ['get', 'offset_direction'], + 19, + ['*', ['get', 'offset_direction'], 8], + ], + }, + minzoom: 12, +} + +const getRoadsLayer = attribute => produce(untaggedRoadsLayer, draft => { + draft.id = 'obs_roads_normal' + draft.filter = draft.filter[1] // remove '!' + draft.paint['line-width'][6] = 6 + draft.paint['line-color'] = colorByDistance(attribute) + draft.paint['line-opacity'][3] = 12 + draft.paint['line-opacity'][5] = 13 +}) + +function MapPage({mapConfig}) { const {obsMapSource} = useConfig() || {} const [clickLocation, setClickLocation] = useState<{longitude: number; latitude: number} | null>(null) @@ -33,6 +87,10 @@ export default function MapPage() { const [layerSidebar, setLayerSidebar] = useState(true) + const showUntagged = mapConfig?.obsRoads?.showUntagged ?? true + const roadsLayerColorAttribute = mapConfig?.obsRoads?.attribute ?? 'distance_overtaker_mean' + const roadsLayer = useMemo(() => getRoadsLayer(roadsLayerColorAttribute ), [roadsLayerColorAttribute ]) + if (!obsMapSource) { return null } @@ -55,7 +113,8 @@ export default function MapPage() { onClick={() => setLayerSidebar(layerSidebar ? false : true)} /> - + {showUntagged && } + @@ -65,3 +124,5 @@ export default function MapPage() { ) } + +export default connect((state) => ({mapConfig: state.mapConfig}))(MapPage) diff --git a/frontend/src/reducers/mapConfig.ts b/frontend/src/reducers/mapConfig.ts index a8e0b23..2c468b4 100644 --- a/frontend/src/reducers/mapConfig.ts +++ b/frontend/src/reducers/mapConfig.ts @@ -1,4 +1,5 @@ import produce from 'immer' +import _ from 'lodash' type BaseMapStyle = 'positron' | 'bright' type MapConfigState = { @@ -13,18 +14,15 @@ const initialState: MapConfigState = { }, } -export function setBasemapStyle(style: BaseMapStyle) { - return {type: 'MAPCONFIG.SET_BASEMAP_STYLE', payload: {style}} +export function setMapConfigFlag(flag: string, value: unknown) { + return {type: 'MAPCONFIG.SET_FLAG', payload: {flag, value}} } export default function mapConfigReducer(state = initialState, action) { switch (action.type) { - case 'MAPCONFIG.SET_BASEMAP_STYLE': + case 'MAPCONFIG.SET_FLAG': return produce(state, draft => { - if (!draft.baseMap) { - draft.baseMap = {} - } - draft.baseMap.style = action.payload.style + _.set(draft, action.payload.flag, action.payload.value) }) default: