diff --git a/example-config.yml b/example-config.yml index 123383bcd..ec5f97ae0 100644 --- a/example-config.yml +++ b/example-config.yml @@ -409,3 +409,8 @@ dateTime: # # Whether to render routes within flex zones of a route's patterns. If set to true, # # routes will not be rendered within flex zones. # hideRouteShapesWithinFlexZones: true + +# API key to make Mapillary API calls. These are used to show street imagery. +# Mapillary calls these "Client Tokens". They can be created at https://www.mapillary.com/dashboard/developers +# mapillary: +# key: diff --git a/lib/actions/map.js b/lib/actions/map.js index 5db88e68f..310d66233 100644 --- a/lib/actions/map.js +++ b/lib/actions/map.js @@ -131,6 +131,7 @@ export function switchLocations() { } export const setLegDiagram = createAction('SET_LEG_DIAGRAM') +export const setMapillaryId = createAction('SET_MAPILLARY_ID') export const setElevationPoint = createAction('SET_ELEVATION_POINT') diff --git a/lib/components/map/map.css b/lib/components/map/map.css index 77652d126..2cb3349b7 100644 --- a/lib/components/map/map.css +++ b/lib/components/map/map.css @@ -15,7 +15,7 @@ } .otp .link-button:focus { - outline:0; + outline: 0; } /* leg diagram */ @@ -29,8 +29,8 @@ z-index: 1000; background-color: white; background-clip: padding-box; - border: 2px solid rgba(127, 127, 127, .5); - border-Radius: 4px; + border: 2px solid rgba(127, 127, 127, 0.5); + border-radius: 4px; cursor: crosshair; } @@ -64,6 +64,22 @@ background: none; } +.otp .leg-diagram .mapillary-close-button { + background: rgba(255, 255, 255, 0.85); + border-radius: 0 0 1em; + display: block; + left: 0; + max-width: 40px; + padding: 0.5em; + position: absolute; + top: 0; + z-index: 10000; +} +.otp .leg-diagram .mapillary-close-button:hover { + background: rgba(200, 200, 200, 0.85); + color: #333; +} + /*** Car Rental Map Icons ***/ .otp .car-rental-icon { diff --git a/lib/components/map/map.js b/lib/components/map/map.js index 12e01609e..4b8ca41e2 100644 --- a/lib/components/map/map.js +++ b/lib/components/map/map.js @@ -1,43 +1,56 @@ -import React, { Component } from 'react' +/* eslint-disable react/prop-types */ +// TODO: Typescript (config object) +import { Button, ButtonGroup } from 'react-bootstrap' import { connect } from 'react-redux' -import { ButtonGroup, Button } from 'react-bootstrap' +import React, { Component } from 'react' + +import { setMapillaryId } from '../../actions/map' import DefaultMap from './default-map' import LegDiagram from './leg-diagram' +import MapillaryFrame from './mapillary-frame' import StylizedMap from './stylized-map' class Map extends Component { - constructor () { + constructor() { super() this.state = { activeViewIndex: 0 } } - getComponentForView (view) { + getComponentForView(view) { // TODO: allow a 'CUSTOM' type switch (view.type) { - case 'DEFAULT': return - case 'STYLIZED': return + case 'DEFAULT': + return + case 'STYLIZED': + return } } - render () { - const { diagramLeg, mapConfig } = this.props + render() { + const { activeMapillaryImage, diagramLeg, mapConfig, setMapillaryId } = + this.props const showDiagram = diagramLeg + const showMapillary = activeMapillaryImage // Use the views defined in the config; if none defined, just show the default map const views = mapConfig.views || [{ type: 'DEFAULT' }] return ( -
+
{/* The map views -- only one is visible at a time */} {views.map((view, i) => { return ( -
{this.getComponentForView(view)}
@@ -46,15 +59,26 @@ class Map extends Component { {/* The toggle buttons -- only show if multiple views */} {views.length > 1 && ( -
+
{views.map((view, i) => { return (
) } @@ -76,9 +106,14 @@ class Map extends Component { const mapStateToProps = (state, ownProps) => { return { + activeMapillaryImage: state.otp.ui.mapillaryId, diagramLeg: state.otp.ui.diagramLeg, mapConfig: state.otp.config.map } } -export default connect(mapStateToProps)(Map) +const mapDispatchToProps = { + setMapillaryId +} + +export default connect(mapStateToProps, mapDispatchToProps)(Map) diff --git a/lib/components/map/mapillary-frame.tsx b/lib/components/map/mapillary-frame.tsx new file mode 100644 index 000000000..795f8d48a --- /dev/null +++ b/lib/components/map/mapillary-frame.tsx @@ -0,0 +1,55 @@ +import { Button } from 'react-bootstrap' +import React, { useEffect, useState } from 'react' + +// eslint-disable-next-line sort-imports-es6-autofix/sort-imports-es6 +import Icon from '../util/icon' + +const MapillaryFrame = ({ + id, + onClose +}: { + id: string + onClose?: () => void +}): React.ReactElement => { + const [fakeLoad, setFakeLoad] = useState(false) + useEffect(() => { + // If the ID changed, show a "fake" loading screen to indicate to the user + // something is happening + setFakeLoad(true) + setTimeout(() => setFakeLoad(false), 750) + }, [id]) + + return ( +
+
+ +
+