From 4f6f4da6d963134c2b772edb080975d37ca3c6b8 Mon Sep 17 00:00:00 2001 From: Evan Siroky Date: Sun, 1 Mar 2020 15:57:21 -0800 Subject: [PATCH 1/5] refactor(location): use otp-ui location-search component --- lib/actions/map.js | 13 + .../form/connected-location-field.js | 76 +++ lib/components/form/default-search-form.js | 10 +- lib/components/form/location-field.js | 605 ------------------ lib/components/mobile/location-search.js | 10 +- lib/components/mobile/search-screen.js | 10 +- lib/components/mobile/welcome-screen.js | 8 +- lib/index.js | 2 +- package.json | 8 +- yarn.lock | 574 ++++++++++++++++- 10 files changed, 682 insertions(+), 634 deletions(-) create mode 100644 lib/components/form/connected-location-field.js delete mode 100644 lib/components/form/location-field.js diff --git a/lib/actions/map.js b/lib/actions/map.js index b1b0ece2e..afd409141 100644 --- a/lib/actions/map.js +++ b/lib/actions/map.js @@ -35,6 +35,19 @@ export function clearLocation (payload) { } } +/** + * Handler for @opentripplanner/location-field onLocationSelected + */ +export function onLocationSelected ({ locationType, location, resultType }) { + return function (dispatch, getState) { + if (resultType === 'CURRENT_LOCATION') { + dispatch(setLocationToCurrent({ type: locationType })) + } else { + dispatch(setLocation({ location, type: locationType })) + } + } +} + export function setLocation (payload) { return function (dispatch, getState) { const otpState = getState().otp diff --git a/lib/components/form/connected-location-field.js b/lib/components/form/connected-location-field.js new file mode 100644 index 000000000..ef9dfba6f --- /dev/null +++ b/lib/components/form/connected-location-field.js @@ -0,0 +1,76 @@ +import LocationField from '@opentripplanner/location-field' +import { + DropdownContainer, + FormGroup, + Input, + InputGroup, + InputGroupAddon +} from '@opentripplanner/location-field/lib/styled' +import { connect } from 'react-redux' +import styled from 'styled-components' + +import { clearLocation, onLocationSelected } from '../../actions/map' +import { addLocationSearch, getCurrentPosition } from '../../actions/location' +import { findNearbyStops } from '../../actions/api' +import { getActiveSearch, getShowUserSettings } from '../../util/state' + +const StyledLocationField = styled(LocationField)` + width: 100%; + + ${DropdownContainer} { + display: table-cell; + vertical-align: middle; + width: 1%; + } + + ${FormGroup} { + display: table; + padding: 6px 12px; + width: 100%; + } + + ${Input} { + display: table-cell; + padding: 6px 12px; + width: 100%; + } + + ${InputGroup} { + width: 100%; + } + + ${InputGroupAddon} { + display: table-cell; + vertical-align: middle; + width: 1%; + } +` + +// connect to redux store + +const mapStateToProps = (state, ownProps) => { + const { config, currentQuery, location, transitIndex, user } = state.otp + const { currentPosition, nearbyStops, sessionSearches } = location + const activeSearch = getActiveSearch(state.otp) + const query = activeSearch ? activeSearch.query : currentQuery + return { + currentPosition, + geocoderConfig: config.geocoder, + location: query[ownProps.locationType], + nearbyStops, + sessionSearches, + showUserSettings: getShowUserSettings(state.otp), + stopsIndex: transitIndex.stops, + userLocationsAndRecentPlaces: [...user.locations, ...user.recentPlaces] + } +} + +const mapDispatchToProps = { + addLocationSearch, + findNearbyStops, + getCurrentPosition, + onLocationSelected, + clearLocation +} + +export default connect(mapStateToProps, mapDispatchToProps)(StyledLocationField) diff --git a/lib/components/form/default-search-form.js b/lib/components/form/default-search-form.js index b6c72cd52..1f2578231 100644 --- a/lib/components/form/default-search-form.js +++ b/lib/components/form/default-search-form.js @@ -1,7 +1,7 @@ import React, { Component } from 'react' import PropTypes from 'prop-types' -import LocationField from './location-field' +import LocationField from './connected-location-field' import SwitchButton from './switch-button' import TabbedFormPanel from './tabbed-form-panel' import defaultIcons from '../icons' @@ -34,14 +34,14 @@ export default class DefaultSearchForm extends Component {
diff --git a/lib/components/form/location-field.js b/lib/components/form/location-field.js deleted file mode 100644 index 7c52c6e6b..000000000 --- a/lib/components/form/location-field.js +++ /dev/null @@ -1,605 +0,0 @@ -import React, { Component } from 'react' -import PropTypes from 'prop-types' -import ReactDOM from 'react-dom' -import { - Button, - FormGroup, - FormControl, - InputGroup, - DropdownButton, - MenuItem -} from 'react-bootstrap' -import { connect } from 'react-redux' -import { throttle } from 'throttle-debounce' - -import LocationIcon from '../icons/location-icon' -import { setLocation, setLocationToCurrent, clearLocation } from '../../actions/map' -import { addLocationSearch, getCurrentPosition } from '../../actions/location' -import { findNearbyStops } from '../../actions/api' -import { distanceStringImperial } from '../../util/distance' -import getGeocoder from '../../util/geocoder' -import { formatStoredPlaceName } from '../../util/map' -import { getActiveSearch, getShowUserSettings } from '../../util/state' -import { isIE } from '../../util/ui' - -class LocationField extends Component { - static propTypes = { - config: PropTypes.object, - currentPosition: PropTypes.object, - hideExistingValue: PropTypes.bool, - location: PropTypes.object, - label: PropTypes.string, - nearbyStops: PropTypes.array, - sessionSearches: PropTypes.array, - showClearButton: PropTypes.bool, - static: PropTypes.bool, // show autocomplete options as fixed/inline element rather than dropdown - stopsIndex: PropTypes.object, - type: PropTypes.string, // replace with locationType? - - // callbacks - onClick: PropTypes.func, - onLocationSelected: PropTypes.func, - - // dispatch - addLocationSearch: PropTypes.func, - clearLocation: PropTypes.func, - setLocation: PropTypes.func, - setLocationToCurrent: PropTypes.func - } - - static defaultProps = { - showClearButton: true - } - - constructor (props) { - super(props) - this.state = { - value: props.location && !props.hideExistingValue - ? props.location.name - : '', - menuVisible: false, - geocodedFeatures: [], - activeIndex: null - } - } - - componentDidUpdate (prevProps) { - // If location is updated externally, replace value and geocoded features - // in internal state. - // TODO: This might be considered an anti-pattern. There may be a more - // effective way to handle this. - const { location } = this.props - if (location !== prevProps.location) { - this.setState({ - value: location !== null ? location.name : '', - geocodedFeatures: [] - }) - } - } - - _geocodeAutocomplete = throttle(1000, (text) => { - if (!text) { - console.warn('No text entry provided for geocode autocomplete search.') - return - } - getGeocoder(this.props.config.geocoder) - .autocomplete({ text }) - .then((result) => { - this.setState({ geocodedFeatures: result.features }) - }).catch((err) => { - console.error(err) - }) - }) - - _geocodeSearch (text) { - if (!text) { - console.warn('No text entry provided for geocode search.') - return - } - getGeocoder(this.props.config.geocoder) - .search({ text }) - .then((result) => { - if (result.features && result.features.length > 0) { - // Only replace geocode items if results were found - this.setState({ geocodedFeatures: result.features }) - } else { - console.warn('No results found for geocode search. Not replacing results.') - } - }).catch((err) => { - console.error(err) - }) - } - - _getFormControlClassname () { - return this.props.type + '-form-control' - } - - _onClearButtonClick = () => { - const { type } = this.props - this.props.clearLocation({ type }) - this.setState({ - value: '', - geocodedFeatures: [] - }) - ReactDOM.findDOMNode(this.formControl).focus() - this._onTextInputClick() - } - - _onDropdownToggle = (v, e) => { - // if clicked on input form control, keep dropdown open; otherwise, toggle - const targetIsInput = - e.target.className.indexOf(this._getFormControlClassname()) !== -1 - const menuVisible = targetIsInput ? true : !this.state.menuVisible - this.setState({ menuVisible }) - } - /** - * Only hide menu if the target clicked is not a menu item in the dropdown. - * Otherwise, the click will not "finish" and the menu will hide without the - * user having made a selection. - */ - _onBlurFormGroup = (e) => { - // IE does not use relatedTarget, so this check handles cross-browser support. - // see https://stackoverflow.com/a/49325196/915811 - const target = e.relatedTarget !== null ? e.relatedTarget : document.activeElement - if (!this.props.location && (!target || target.getAttribute('role') !== 'menuitem')) { - this.setState({ menuVisible: false, value: '', geocodedFeatures: [] }) - } - } - - _onTextInputChange = (evt) => { - this.setState({ value: evt.target.value, menuVisible: true }) - this._geocodeAutocomplete(evt.target.value) - } - - _onTextInputClick = () => { - const { config, currentPosition, nearbyStops, onClick } = this.props - if (typeof onClick === 'function') onClick() - this.setState({ menuVisible: true }) - if (nearbyStops.length === 0 && currentPosition && currentPosition.coords) { - this.props.findNearbyStops({ - lat: currentPosition.coords.latitude, - lon: currentPosition.coords.longitude, - max: config.geocoder.maxNearbyStops || 4 - }) - } - } - - _onKeyDown = (evt) => { - const { activeIndex, menuVisible } = this.state - switch (evt.key) { - // 'Down' arrow key pressed: move selected menu item down by one position - case 'ArrowDown': - // Suppress default 'ArrowDown' behavior which moves cursor to end - evt.preventDefault() - if (!menuVisible) { - // If the menu is not visible, simulate a text input click to show it. - return this._onTextInputClick() - } - if (activeIndex === this.menuItemCount - 1) { - return this.setState({ activeIndex: null }) - } - return this.setState({ - activeIndex: activeIndex === null - ? 0 - : activeIndex + 1 - }) - - // 'Up' arrow key pressed: move selection up by one position - case 'ArrowUp': - // Suppress default 'ArrowUp' behavior which moves cursor to beginning - evt.preventDefault() - if (activeIndex === 0) { - return this.setState({ activeIndex: null }) - } - return this.setState({ - activeIndex: activeIndex === null - ? this.menuItemCount - 1 - : activeIndex - 1 - }) - - // 'Enter' keypress serves two purposes: - // - If pressed when typing in search string, switch from 'autocomplete' - // to 'search' geocoding - // - If pressed when dropdown results menu is active, apply the location - // associated with current selected menu item - case 'Enter': - if (typeof activeIndex === 'number') { // Menu is active - // Retrieve location selection handler from lookup object and invoke - const locationSelected = this.locationSelectedLookup[activeIndex] - if (locationSelected) locationSelected() - - // Clear selection & hide the menu - this.setState({ - menuVisible: false, - activeIndex: null - }) - } else { // Menu not active; get geocode 'search' results - this._geocodeSearch(evt.target.value) - // Ensure menu is visible. - this.setState({ menuVisible: true }) - } - - // Suppress default 'Enter' behavior which causes page to reload - evt.preventDefault() - break - case 'Escape': - // Clear selection & hide the menu - return this.setState({ - menuVisible: false, - activeIndex: null - }) - // Any other key pressed: clear active selection - default: - return this.setState({ activeIndex: null }) - } - } - - _setLocation (location) { - const { onLocationSelected, setLocation, type } = this.props - onLocationSelected && onLocationSelected() - setLocation({ type, location }) - } - - _useCurrentLocation = () => { - const { - currentPosition, - getCurrentPosition, - onLocationSelected, - setLocationToCurrent, - type - } = this.props - if (currentPosition.coords) { - // We already have geolocation coordinates - setLocationToCurrent({ type }) - onLocationSelected && onLocationSelected() - } else { - // Call geolocation.getCurrentPosition and set as from/to type - this.setState({ fetchingLocation: true }) - getCurrentPosition(type, onLocationSelected) - } - } - - /** - * Provide alert to user with reason for geolocation error - */ - _geolocationAlert = () => { - window.alert( - `Geolocation either has been disabled for ${window.location.host} or is not available in your browser.\n\nReason: ${this.props.currentPosition.error.message || 'Unknown reason'}` - ) - } - - render () { - const { - currentPosition, - label, - location, - user, - showClearButton, - showUserSettings, - static: isStatic, - suppressNearby, - type, - nearbyStops - } = this.props - const locations = [...user.locations, ...user.recentPlaces] - const { activeIndex } = this.state - let geocodedFeatures = this.state.geocodedFeatures - if (geocodedFeatures.length > 5) geocodedFeatures = geocodedFeatures.slice(0, 5) - - let sessionSearches = this.props.sessionSearches - if (sessionSearches.length > 5) sessionSearches = sessionSearches.slice(0, 5) - - // Assemble menu contents, to be displayed either as dropdown or static panel. - // Menu items are created in four phases: (1) the current location, (2) any - // geocoder search results; (3) nearby transit stops; and (4) saved searches - - let menuItems = [] // array of menu items for display (may include non-selectable items e.g. dividers/headings) - let itemIndex = 0 // the index of the current location-associated menu item (excluding non-selectable items) - this.locationSelectedLookup = {} // maps itemIndex to a location selection handler (for use by the _onKeyDown method) - - /* 1) Process geocode search result option(s) */ - if (geocodedFeatures.length > 0) { - // Add the menu sub-heading (not a selectable item) - // menuItems.push(Search Results) - - // Iterate through the geocoder results - menuItems = menuItems.concat(geocodedFeatures.map((feature, i) => { - // Create the selection handler - const locationSelected = () => { - getGeocoder(this.props.config.geocoder) - .getLocationFromGeocodedFeature(feature) - .then(location => { - // Set the current location - this._setLocation(location) - // Add to the location search history - this.props.addLocationSearch({ location }) - }) - } - - // Add to the selection handler lookup (for use in _onKeyDown) - this.locationSelectedLookup[itemIndex] = locationSelected - - // Create and return the option menu item - const option = createOption('map-pin', feature.properties.label, locationSelected, itemIndex === activeIndex, i === geocodedFeatures.length - 1) - itemIndex++ - return option - })) - } - - /* 2) Process nearby transit stop options */ - if (nearbyStops.length > 0 && !suppressNearby) { - // Add the menu sub-heading (not a selectable item) - menuItems.push(Nearby Stops) - - // Iterate through the found nearby stops - menuItems = menuItems.concat(nearbyStops.map((stopId, i) => { - // Constuct the location - const stop = this.props.stopsIndex[stopId] - const location = { - name: stop.name, - lat: stop.lat, - lon: stop.lon - } - - // Create the location selected handler - const locationSelected = () => { this._setLocation(location) } - - // Add to the selection handler lookup (for use in _onKeyDown) - this.locationSelectedLookup[itemIndex] = locationSelected - - // Create and return the option menu item - const option = createTransitStopOption(stop, locationSelected, itemIndex === activeIndex, i === nearbyStops.length - 1) - itemIndex++ - return option - })) - } - - /* 3) Process recent search history options */ - if (sessionSearches.length > 0) { - // Add the menu sub-heading (not a selectable item) - menuItems.push(Recently Searched) - - // Iterate through any saved locations - menuItems = menuItems.concat(sessionSearches.map((location, i) => { - // Create the location-selected handler - const locationSelected = () => { this._setLocation(location) } - - // Add to the selection handler lookup (for use in _onKeyDown) - this.locationSelectedLookup[itemIndex] = locationSelected - - // Create and return the option menu item - const option = createOption('search', location.name, locationSelected, itemIndex === activeIndex, i === sessionSearches.length - 1) - itemIndex++ - return option - })) - } - - /* 3b) Process stored user locations */ - if (locations.length > 0 && showUserSettings) { - // Add the menu sub-heading (not a selectable item) - menuItems.push(My Places) - - // Iterate through any saved locations - menuItems = menuItems.concat(locations.map((location, i) => { - // Create the location-selected handler - const locationSelected = () => { this._setLocation(location) } - - // Add to the selection handler lookup (for use in _onKeyDown) - this.locationSelectedLookup[itemIndex] = locationSelected - - // Create and return the option menu item - const option = createOption( - location.icon, - formatStoredPlaceName(location), - locationSelected, - itemIndex === activeIndex, - i === locations.length - 1 - ) - itemIndex++ - return option - })) - } - - /* 4) Process the current location */ - let locationSelected, optionIcon, optionTitle - - if (!currentPosition.error) { // current position detected successfully - locationSelected = this._useCurrentLocation - optionIcon = 'location-arrow' - optionTitle = 'Use Current Location' - } else { // error detecting current position - locationSelected = this._geolocationAlert - optionIcon = 'ban' - optionTitle = 'Current location not available' - } - - // Add to the selection handler lookup (for use in _onKeyDown) - this.locationSelectedLookup[itemIndex] = locationSelected - - if (!suppressNearby) { - // Create and add the option item to the menu items array - const currentLocationOption = createOption( - optionIcon, - optionTitle, - locationSelected, - itemIndex === activeIndex - ) - menuItems.push(currentLocationOption) - itemIndex++ - } - - // Store the number of location-associated items for reference in the _onKeyDown method - this.menuItemCount = itemIndex - - /** the text input element **/ - const placeholder = currentPosition.fetching === type - ? 'Fetching location...' - : label || type - const textControl = { this.formControl = ctl }} - className={this._getFormControlClassname()} - type='text' - value={this.state.value} - placeholder={placeholder} - onChange={this._onTextInputChange} - onClick={this._onTextInputClick} - onKeyDown={this._onKeyDown} - /> - - // Only include the clear ('X') button add-on if a location is selected - // or if the input field has text. - const clearButton = showClearButton && location - ? - - - : null - if (isStatic) { - // 'static' mode (menu is displayed alongside input, e.g., for mobile view) - return ( -
-
- - - - - - {textControl} - {clearButton} - - -
-
    - {menuItems.length > 0 // Show typing prompt to avoid empty screen - ? menuItems - : - Begin typing to search for locations - - } -
-
- ) - } else { - // default display mode with dropdown menu - return ( -
- - - {/* location field icon -- also serves as dropdown anchor */} - } - noCaret - > - {menuItems} - - {textControl} - {clearButton} - - -
- ) - } - } -} - -// helper functions for dropdown options - -let itemKey = 0 - -function createOption (icon, title, onSelect, isActive, isLast) { - return - {isIE() - // In internet explorer 11, some really weird stuff is happening where it - // is not possible to click the text of the title, but if you click just - // above it, then it works. So, if using IE 11, just return the title text - // and avoid all the extra fancy stuff. - // See https://github.com/ibi-group/trimet-mod-otp/issues/237 - ? title - : ( -
-
-
- {title} -
-
- ) - } -
-} - -function createTransitStopOption (stop, onSelect, isActive) { - return -
-
- -
{distanceStringImperial(stop.dist, true)}
-
-
-
{stop.name} ({stop.code})
-
- {(stop.routes || []).map((route, i) => { - const name = route.shortName || route.longName - return ( - - {name} - - ) - })} -
-
-
-
- -} - -// connect to redux store - -const mapStateToProps = (state, ownProps) => { - const activeSearch = getActiveSearch(state.otp) - const query = activeSearch ? activeSearch.query : state.otp.currentQuery - const location = query[ownProps.type] - const showUserSettings = getShowUserSettings(state.otp) - return { - config: state.otp.config, - location, - user: state.otp.user, - currentPosition: state.otp.location.currentPosition, - sessionSearches: state.otp.location.sessionSearches, - nearbyStops: state.otp.location.nearbyStops, - showUserSettings, - stopsIndex: state.otp.transitIndex.stops - } -} - -const mapDispatchToProps = { - addLocationSearch, - findNearbyStops, - getCurrentPosition, - setLocation, - setLocationToCurrent, - clearLocation -} - -export default connect(mapStateToProps, mapDispatchToProps)(LocationField) diff --git a/lib/components/mobile/location-search.js b/lib/components/mobile/location-search.js index 5c7404947..11a7e02d6 100644 --- a/lib/components/mobile/location-search.js +++ b/lib/components/mobile/location-search.js @@ -4,7 +4,7 @@ import { connect } from 'react-redux' import MobileContainer from './container' import MobileNavigationBar from './navigation-bar' -import LocationField from '../form/location-field' +import LocationField from '../form/connected-location-field' import { MobileScreens, setMobileScreen } from '../../actions/ui' @@ -36,12 +36,12 @@ class MobileLocationSearch extends Component { />
diff --git a/lib/components/mobile/search-screen.js b/lib/components/mobile/search-screen.js index 364b3d17f..bfa2952cf 100644 --- a/lib/components/mobile/search-screen.js +++ b/lib/components/mobile/search-screen.js @@ -5,7 +5,7 @@ import { Row, Col } from 'react-bootstrap' import DateTimePreview from '../form/date-time-preview' import DefaultMap from '../map/default-map' -import LocationField from '../form/location-field' +import LocationField from '../form/connected-location-field' import PlanTripButton from '../form/plan-trip-button' import SettingsPreview from '../form/settings-preview' import SwitchButton from '../form/switch-button' @@ -51,13 +51,13 @@ class MobileSearchScreen extends Component {
diff --git a/lib/components/mobile/welcome-screen.js b/lib/components/mobile/welcome-screen.js index d162605a3..47d6ab4f0 100644 --- a/lib/components/mobile/welcome-screen.js +++ b/lib/components/mobile/welcome-screen.js @@ -3,8 +3,8 @@ import PropTypes from 'prop-types' import { connect } from 'react-redux' import MobileContainer from './container' -import LocationField from '../form/location-field' import UserSettings from '../form/user-settings' +import LocationField from '../form/connected-location-field' import DefaultMap from '../map/default-map' import MobileNavigationBar from './navigation-bar' @@ -44,9 +44,9 @@ class MobileWelcomeScreen extends Component {
diff --git a/lib/index.js b/lib/index.js index bd8f7a849..c671bff9c 100644 --- a/lib/index.js +++ b/lib/index.js @@ -4,7 +4,7 @@ import DateTimeSelector from './components/form/date-time-selector' import DefaultSearchForm from './components/form/default-search-form' import ErrorMessage from './components/form/error-message' import GeneralSettingsPanel from './components/form/general-settings-panel' -import LocationField from './components/form/location-field' +import LocationField from './components/form/connected-location-field' import ModeSelector from './components/form/mode-selector' import ModesPanel from './components/form/modes-panel' import PlanTripButton from './components/form/plan-trip-button' diff --git a/package.json b/package.json index 2662e82ef..00b272720 100644 --- a/package.json +++ b/package.json @@ -31,6 +31,7 @@ "@conveyal/lonlat": "^1.1.0", "@mapbox/polyline": "^0.2.0", "@opentripplanner/from-to-location-picker": "^0.0.14", + "@opentripplanner/location-field": "^0.0.16", "bootstrap": "^3.3.7", "bowser": "^1.9.3", "clone": "^2.1.0", @@ -72,7 +73,6 @@ "redux-actions": "^1.2.1", "redux-logger": "^2.7.4", "redux-thunk": "^2.3.0", - "styled-components": "^5.0.1", "throttle-debounce": "^2.0.1", "transitive-js": "^0.13.0", "turf-along": "^3.0.12", @@ -90,11 +90,13 @@ "react": "^16.9.0", "react-dom": "^16.9.0", "redux-mock-store": "^1.5.3", - "semantic-release": "^15.13.12" + "semantic-release": "^15.13.12", + "styled-components": "^5.0.1" }, "peerDependencies": { "react": ">=15.0.0", - "react-dom": ">=15.0.0" + "react-dom": ">=15.0.0", + "styled-components": "^5.0.1" }, "jest": { "globalSetup": "/__tests__/test-utils/global-setup.js", diff --git a/yarn.lock b/yarn.lock index d6a58d096..bb5084d0a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9,6 +9,13 @@ dependencies: "@babel/highlight" "^7.0.0" +"@babel/code-frame@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.8.3.tgz#33e25903d7481181534e12ec0a25f16b6fcf419e" + integrity sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g== + dependencies: + "@babel/highlight" "^7.8.3" + "@babel/core@^7.1.0", "@babel/core@^7.1.2", "@babel/core@^7.3.4": version "7.5.5" resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.5.5.tgz#17b2686ef0d6bc58f963dddd68ab669755582c30" @@ -40,6 +47,16 @@ source-map "^0.5.0" trim-right "^1.0.1" +"@babel/generator@^7.8.6": + version "7.8.6" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.8.6.tgz#57adf96d370c9a63c241cd719f9111468578537a" + integrity sha512-4bpOR5ZBz+wWcMeVtcf7FbjcFzCp+817z2/gHNncIRcM9MmKzUhtWCYAq27RAfUrAFwb+OCG1s9WEaVxfi6cjg== + dependencies: + "@babel/types" "^7.8.6" + jsesc "^2.5.1" + lodash "^4.17.13" + source-map "^0.5.0" + "@babel/helper-annotate-as-pure@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.0.0.tgz#323d39dd0b50e10c7c06ca7d7638e6864d8c5c32" @@ -110,6 +127,15 @@ "@babel/template" "^7.1.0" "@babel/types" "^7.0.0" +"@babel/helper-function-name@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.8.3.tgz#eeeb665a01b1f11068e9fb86ad56a1cb1a824cca" + integrity sha512-BCxgX1BC2hD/oBlIFUgOCQDOPV8nSINxCwM3o93xP4P9Fq6aV5sgv2cOOITDMtCfQ+3PvHp3l689XZvAM9QyOA== + dependencies: + "@babel/helper-get-function-arity" "^7.8.3" + "@babel/template" "^7.8.3" + "@babel/types" "^7.8.3" + "@babel/helper-get-function-arity@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz#83572d4320e2a4657263734113c42868b64e49c3" @@ -117,6 +143,13 @@ dependencies: "@babel/types" "^7.0.0" +"@babel/helper-get-function-arity@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.8.3.tgz#b894b947bd004381ce63ea1db9f08547e920abd5" + integrity sha512-FVDR+Gd9iLjUMY1fzE2SR0IuaJToR4RkCDARVfsBBPSP53GEqSFjD8gNyxg246VUyc/ALRxFaAK8rVG7UT7xRA== + dependencies: + "@babel/types" "^7.8.3" + "@babel/helper-hoist-variables@^7.4.4": version "7.4.4" resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.4.4.tgz#0298b5f25c8c09c53102d52ac4a98f773eb2850a" @@ -205,6 +238,13 @@ dependencies: "@babel/types" "^7.4.4" +"@babel/helper-split-export-declaration@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.8.3.tgz#31a9f30070f91368a7182cf05f831781065fc7a9" + integrity sha512-3x3yOeyBhW851hroze7ElzdkeRXQYQbFIb7gLK1WQYsw2GWDay5gAJNw1sWJ0VFP6z5J1whqeXH/WCdCjZv6dA== + dependencies: + "@babel/types" "^7.8.3" + "@babel/helper-wrap-function@^7.1.0", "@babel/helper-wrap-function@^7.2.0": version "7.2.0" resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.2.0.tgz#c4e0012445769e2815b55296ead43a958549f6fa" @@ -233,6 +273,15 @@ esutils "^2.0.2" js-tokens "^4.0.0" +"@babel/highlight@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.8.3.tgz#28f173d04223eaaa59bc1d439a3836e6d1265797" + integrity sha512-PX4y5xQUvy0fnEVHrYOarRPXVWafSjTW9T0Hab8gVIawpl2Sj0ORyrygANq+KjcNlSSTw0YCLSNA8OyZ1I4yEg== + dependencies: + chalk "^2.0.0" + esutils "^2.0.2" + js-tokens "^4.0.0" + "@babel/parser@7.1.3": version "7.1.3" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.1.3.tgz#2c92469bac2b7fbff810b67fca07bd138b48af77" @@ -243,6 +292,11 @@ resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.5.5.tgz#02f077ac8817d3df4a832ef59de67565e71cca4b" integrity sha512-E5BN68cqR7dhKan1SfqgPGhQ178bkVKpXTPEXnFJBrEt8/DKRZlybmy+IgYLTeN7tp1R5Ccmbm2rBk17sHYU3g== +"@babel/parser@^7.8.6": + version "7.8.6" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.8.6.tgz#ba5c9910cddb77685a008e3c587af8d27b67962c" + integrity sha512-trGNYSfwq5s0SgM1BMEB8hX3NDmO7EP2wsDGDexiaKMB92BaRpS+qZfpkMqUBhcsOTBwNy9B/jieo4ad/t/z2g== + "@babel/plugin-proposal-async-generator-functions@^7.2.0": version "7.2.0" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.2.0.tgz#b289b306669dce4ad20b0252889a15768c9d417e" @@ -936,6 +990,15 @@ "@babel/parser" "^7.4.4" "@babel/types" "^7.4.4" +"@babel/template@^7.8.3": + version "7.8.6" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.8.6.tgz#86b22af15f828dfb086474f964dcc3e39c43ce2b" + integrity sha512-zbMsPMy/v0PWFZEhQJ66bqjhH+z0JgMoBWuikXybgG3Gkd/3t5oQ1Rw2WQhnSrsOmsKXnZOx15tkC4qON/+JPg== + dependencies: + "@babel/code-frame" "^7.8.3" + "@babel/parser" "^7.8.6" + "@babel/types" "^7.8.6" + "@babel/traverse@^7.0.0", "@babel/traverse@^7.1.0", "@babel/traverse@^7.1.4", "@babel/traverse@^7.4.3", "@babel/traverse@^7.4.4", "@babel/traverse@^7.5.5": version "7.5.5" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.5.5.tgz#f664f8f368ed32988cd648da9f72d5ca70f165bb" @@ -951,6 +1014,21 @@ globals "^11.1.0" lodash "^4.17.13" +"@babel/traverse@^7.4.5": + version "7.8.6" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.8.6.tgz#acfe0c64e1cd991b3e32eae813a6eb564954b5ff" + integrity sha512-2B8l0db/DPi8iinITKuo7cbPznLCEk0kCxDoB9/N6gGNg/gxOXiR/IcymAFPiBwk5w6TtQ27w4wpElgp9btR9A== + dependencies: + "@babel/code-frame" "^7.8.3" + "@babel/generator" "^7.8.6" + "@babel/helper-function-name" "^7.8.3" + "@babel/helper-split-export-declaration" "^7.8.3" + "@babel/parser" "^7.8.6" + "@babel/types" "^7.8.6" + debug "^4.1.0" + globals "^11.1.0" + lodash "^4.17.13" + "@babel/types@^7.0.0", "@babel/types@^7.0.0-beta.49", "@babel/types@^7.1.3", "@babel/types@^7.2.0", "@babel/types@^7.3.0", "@babel/types@^7.4.0", "@babel/types@^7.4.4", "@babel/types@^7.5.5": version "7.5.5" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.5.5.tgz#97b9f728e182785909aa4ab56264f090a028d18a" @@ -960,6 +1038,15 @@ lodash "^4.17.13" to-fast-properties "^2.0.0" +"@babel/types@^7.8.3", "@babel/types@^7.8.6": + version "7.8.6" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.8.6.tgz#629ecc33c2557fcde7126e58053127afdb3e6d01" + integrity sha512-wqz7pgWMIrht3gquyEFPVXeXCti72Rm8ep9b5tQKz9Yg9LzJA3HxosF1SB3Kc81KD1A3XBkkVYtJvCKS2Z/QrA== + dependencies: + esutils "^2.0.2" + lodash "^4.17.13" + to-fast-properties "^2.0.0" + "@cnakazawa/watch@^1.0.3": version "1.0.3" resolved "https://registry.yarnpkg.com/@cnakazawa/watch/-/watch-1.0.3.tgz#099139eaec7ebf07a27c1786a3ff64f39464d2ef" @@ -976,7 +1063,7 @@ "@conveyal/lonlat" "^1.3.0" geocoder-arcgis "^2.0.4" -"@conveyal/lonlat@^1.1.0", "@conveyal/lonlat@^1.1.2", "@conveyal/lonlat@^1.3.0": +"@conveyal/lonlat@^1.1.0", "@conveyal/lonlat@^1.1.2", "@conveyal/lonlat@^1.3.0", "@conveyal/lonlat@^1.4.0": version "1.4.0" resolved "https://registry.yarnpkg.com/@conveyal/lonlat/-/lonlat-1.4.0.tgz#18a5c1349078a779e710d24af11bc02b24127ba0" integrity sha512-ag1FcRuwRGAZgeZ4e3sUq+gblf1Pgma2c9SaIVXluIrgsZ9Lrq7xhCbV0ErN8chyg/OCOoG8m/l3mgzbycQCnQ== @@ -986,6 +1073,28 @@ resolved "https://registry.yarnpkg.com/@csstools/convert-colors/-/convert-colors-1.4.0.tgz#ad495dc41b12e75d588c6db8b9834f08fa131eb7" integrity sha512-5a6wqoJV/xEdbRNKVo6I4hO3VjyDq//8q2f9I6PBAvMesJHFauXDorcNCsr9RzvsZnaWi5NYCcfyqP1QeFHFbw== +"@emotion/is-prop-valid@^0.8.3", "@emotion/is-prop-valid@^0.8.6": + version "0.8.7" + resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-0.8.7.tgz#803449993f436f9a6c67752251ea3fc492a1044c" + integrity sha512-OPkKzUeiid0vEKjZqnGcy2mzxjIlCffin+L2C02pdz/bVlt5zZZE2VzO0D3XOPnH0NEeF21QNKSXiZphjr4xiQ== + dependencies: + "@emotion/memoize" "0.7.4" + +"@emotion/memoize@0.7.4": + version "0.7.4" + resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.7.4.tgz#19bf0f5af19149111c40d98bb0cf82119f5d9eeb" + integrity sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw== + +"@emotion/stylis@^0.8.4": + version "0.8.5" + resolved "https://registry.yarnpkg.com/@emotion/stylis/-/stylis-0.8.5.tgz#deacb389bd6ee77d1e7fcaccce9e16c5c7e78e04" + integrity sha512-h6KtPihKFn3T9fuIrwvXXUOwlx3rfUvfZIcP5a6rh8Y7zjE3O06hT5Ss4S/YI1AYhuZ1kjaE/5EaOOI2NqSylQ== + +"@emotion/unitless@^0.7.4": + version "0.7.5" + resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.7.5.tgz#77211291c1900a700b8a78cfafda3160d76949ed" + integrity sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg== + "@jest/console@^24.7.1": version "24.7.1" resolved "https://registry.yarnpkg.com/@jest/console/-/console-24.7.1.tgz#32a9e42535a97aedfe037e725bd67e954b459545" @@ -1137,6 +1246,13 @@ resolved "https://registry.yarnpkg.com/@mapbox/polyline/-/polyline-0.2.0.tgz#6e25980744aa22331f94b645a542c02d3fcfee97" integrity sha1-biWYB0SqIjMflLZFpULALT/P7pc= +"@mapbox/polyline@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@mapbox/polyline/-/polyline-1.1.0.tgz#7bdd1da3a25c1d059af3897e0ee581b7c7b80243" + integrity sha512-NwiMS+AA/ZLIgd69YYXtQ0jtIBu8nQuVaRr4NxBoRjEd9ddKDoe4q8a51Ukk7Vj+jwQtbupqmvoLni1QhnJ4Pg== + dependencies: + meow "^5.0.0" + "@nodelib/fs.scandir@2.1.1": version "2.1.1" resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.1.tgz#7fa8fed654939e1a39753d286b48b4836d00e0eb" @@ -1208,6 +1324,85 @@ universal-user-agent "^3.0.0" url-template "^2.0.8" +"@opentripplanner/core-utils@^0.0.14": + version "0.0.14" + resolved "https://registry.yarnpkg.com/@opentripplanner/core-utils/-/core-utils-0.0.14.tgz#9e58e78227759ab5c13e1dad22467c474bd102b7" + integrity sha512-JMtOermSYrpPN649DEexd/EKdMPisBrooHiUAeCSdapXgxN7y1h+fUZj+OglLgUoo48wPRv7ru/n5doqVrGSaQ== + dependencies: + "@mapbox/polyline" "^1.1.0" + "@turf/along" "^6.0.1" + bowser "^2.7.0" + lodash.isequal "^4.5.0" + moment "^2.24.0" + moment-timezone "^0.5.27" + prop-types "^15.7.2" + qs "^6.9.1" + +"@opentripplanner/core-utils@^0.0.16": + version "0.0.16" + resolved "https://registry.yarnpkg.com/@opentripplanner/core-utils/-/core-utils-0.0.16.tgz#72b85f9e36fb5dc00d442d9c2e6d883efdc3fa8d" + integrity sha512-ekPxWC0woOJDbfj0Lxk+NX2fLpIGpbDRQbEsO/rF+UCCvg4sCcmobjHaMwtW6rAXtVzNMmFDYXctPW/49Qdq8A== + dependencies: + "@mapbox/polyline" "^1.1.0" + "@turf/along" "^6.0.1" + bowser "^2.7.0" + lodash.isequal "^4.5.0" + moment "^2.24.0" + moment-timezone "^0.5.27" + prop-types "^15.7.2" + qs "^6.9.1" + +"@opentripplanner/from-to-location-picker@^0.0.14": + version "0.0.14" + resolved "https://registry.yarnpkg.com/@opentripplanner/from-to-location-picker/-/from-to-location-picker-0.0.14.tgz#efe2a3452d58d769bc0d5904753df8516279f6c7" + integrity sha512-w2jf+wErtH34CdxQkAyHf446JeCsVxOYej6JRK15jc3+LCWi4bct2A0tf1wp9uNdMvAnL06AZL6hwsED6WqrVA== + dependencies: + "@opentripplanner/core-utils" "^0.0.14" + "@opentripplanner/location-icon" "^0.0.13" + prop-types "^15.7.2" + +"@opentripplanner/geocoder@^0.0.16": + version "0.0.16" + resolved "https://registry.yarnpkg.com/@opentripplanner/geocoder/-/geocoder-0.0.16.tgz#55bdff8be36b2b68b83d62008c0fd45e03dd2a11" + integrity sha512-wpIyKThP4FhNiXDLHGHyux+g7+BAWN43ZZzdOgSBhSHoKRYXee+Ga7ht3zsNtJroZhkDQkEISXiNejK16SCWvQ== + dependencies: + "@conveyal/geocoder-arcgis-geojson" "^0.0.2" + "@conveyal/lonlat" "^1.4.0" + isomorphic-mapzen-search "^1.4.1" + lodash.memoize "^4.1.2" + +"@opentripplanner/humanize-distance@^0.0.16": + version "0.0.16" + resolved "https://registry.yarnpkg.com/@opentripplanner/humanize-distance/-/humanize-distance-0.0.16.tgz#e8197671b45719ce5c728d34c60e80b6d816d287" + integrity sha512-qec9FZGhITC1u+YIBn0+6drxvbJr4N7FX0+VdpXl4+op6xVPlH+LPRittQhdOXdwEjUwHA9qvmksIYE70mg9lw== + +"@opentripplanner/location-field@^0.0.16": + version "0.0.16" + resolved "https://registry.yarnpkg.com/@opentripplanner/location-field/-/location-field-0.0.16.tgz#1d23792965e9bfcd1044521b9bef261fbba090a7" + integrity sha512-nnEspCddomJGJgWuGh8S2npUogKKa6oPCopCl0sdgU7UyI/xUpgwHwTHaxJyJNWQmd4RT+GgKv9jlzKRVtxFXA== + dependencies: + "@opentripplanner/core-utils" "^0.0.16" + "@opentripplanner/geocoder" "^0.0.16" + "@opentripplanner/humanize-distance" "^0.0.16" + "@opentripplanner/location-icon" "^0.0.16" + prop-types "^15.7.2" + styled-icons "^9.1.0" + throttle-debounce "^2.1.0" + +"@opentripplanner/location-icon@^0.0.13": + version "0.0.13" + resolved "https://registry.yarnpkg.com/@opentripplanner/location-icon/-/location-icon-0.0.13.tgz#18e53e2dcd916814675340c9a69d2bc7797bb177" + integrity sha512-KeGm9xQLA2qdQHuPod706OUuoUk25cDjJrFA+waWaN9qQqcqSxOBavcLg5FH9yRQR8uuSTgi1yooIlccOUYnxQ== + dependencies: + styled-icons "^9.1.0" + +"@opentripplanner/location-icon@^0.0.16": + version "0.0.16" + resolved "https://registry.yarnpkg.com/@opentripplanner/location-icon/-/location-icon-0.0.16.tgz#16824fb8dd522f59be39b28a2a31617b27532bcd" + integrity sha512-QcbmO7aOcbECpKfZc2VNGxYq/HY7JZP+7FW6W1PBG98ThIbdg4cSwWWf7kf8fl3LpJAhqMdV14AE1O/P/Sq8rw== + dependencies: + styled-icons "^9.1.0" + "@semantic-release/commit-analyzer@^6.1.0": version "6.2.0" resolved "https://registry.yarnpkg.com/@semantic-release/commit-analyzer/-/commit-analyzer-6.2.0.tgz#5cd25ce67ba9ba5b46e47457505e63629e186695" @@ -1281,6 +1476,237 @@ lodash "^4.17.4" read-pkg-up "^6.0.0" +"@styled-icons/boxicons-logos@^9.4.1": + version "9.4.1" + resolved "https://registry.yarnpkg.com/@styled-icons/boxicons-logos/-/boxicons-logos-9.4.1.tgz#774e7f73839e834445dcc0ae4c0c356221767664" + integrity sha512-DN6Za9paJeWkoIXI1newSSfDALIR8ecaAsgzP3ZD+NRJHy6idW+1ouC5p3DlRM29+Cp4yJ/z3bH9whBDbd7YXQ== + dependencies: + "@styled-icons/styled-icon" "^9.4.1" + tslib "^1.9.3" + +"@styled-icons/boxicons-regular@^9.4.1": + version "9.4.1" + resolved "https://registry.yarnpkg.com/@styled-icons/boxicons-regular/-/boxicons-regular-9.4.1.tgz#742a1d0b5798c54f189b9278810d8110df8f9754" + integrity sha512-910zIWCB0JkEgk9I7zIIEdPc8xibg3xrT4Wo7gIu4lGEr4u9OOQT3c0ajJD7F+JlhWcWBVumzjfjOT8A5UjPJw== + dependencies: + "@styled-icons/styled-icon" "^9.4.1" + tslib "^1.9.3" + +"@styled-icons/boxicons-solid@^9.4.1": + version "9.4.1" + resolved "https://registry.yarnpkg.com/@styled-icons/boxicons-solid/-/boxicons-solid-9.4.1.tgz#5219a0c900f2ccc5dc9056c4ee2d1c180d9dbdf1" + integrity sha512-7FvU6KSnxBprsidta3/0grTkimYWDUnSZCyLscT1OwjmfyFPpnLNmJASQDrEtORF2GPw5Y2gc/q6h2RI4OnYcA== + dependencies: + "@styled-icons/styled-icon" "^9.4.1" + tslib "^1.9.3" + +"@styled-icons/crypto@^9.4.1": + version "9.4.1" + resolved "https://registry.yarnpkg.com/@styled-icons/crypto/-/crypto-9.4.1.tgz#9abe2a3165f78a1592ea1d910aa1e1210b990fef" + integrity sha512-qIjzvaw0kFykDN7PTGD8d3HvFVoX7kW7nwlvvzW/pGhVzpUHE7Mh2Syc04HpoknCgO0fCjAzXaxi9Igu3nS9NA== + dependencies: + "@styled-icons/styled-icon" "^9.4.1" + tslib "^1.9.3" + +"@styled-icons/entypo-social@^9.5.0": + version "9.5.0" + resolved "https://registry.yarnpkg.com/@styled-icons/entypo-social/-/entypo-social-9.5.0.tgz#d5c69c928dbcb83c39d8359e50c148bd497bcaff" + integrity sha512-yEpaJtTUriZSZPT/iqxgNONgxDYr0MHXANvoUW2CB0Ey4zTZst+2x7EJ9KgL2CjdBgA0bs8hnx5etGHUi8BtuA== + dependencies: + "@styled-icons/styled-icon" "^9.4.1" + tslib "^1.9.3" + +"@styled-icons/entypo@^9.5.0": + version "9.5.0" + resolved "https://registry.yarnpkg.com/@styled-icons/entypo/-/entypo-9.5.0.tgz#170c484e53820ec683d338353e44bae71d773611" + integrity sha512-gy/CXs45g1o5c61BnSnpd/cb84sXIARPByOa354FkN0aUHqepbF2qtBjZ3Udho6zWpm1nGOOUiawQb53PnG9vg== + dependencies: + "@styled-icons/styled-icon" "^9.4.1" + tslib "^1.9.3" + +"@styled-icons/evil@^9.4.1": + version "9.4.1" + resolved "https://registry.yarnpkg.com/@styled-icons/evil/-/evil-9.4.1.tgz#159d5c026e7d0689b453684b719ecb13e4ea0fe5" + integrity sha512-ejCBH+aXrjtBM+iMJomYlZ/xiJ+NGHVlIfQmkgD6roxtJzMzAmhwXgC5S3p0no2n1EXluUdJiufrI/QtP7iNbA== + dependencies: + "@styled-icons/styled-icon" "^9.4.1" + tslib "^1.9.3" + +"@styled-icons/fa-brands@^9.4.1": + version "9.4.1" + resolved "https://registry.yarnpkg.com/@styled-icons/fa-brands/-/fa-brands-9.4.1.tgz#ad329324875bb7db00ff5fb68ce98203fbe03b7a" + integrity sha512-zqlS/Y3mQLdBgRhZo1op5+twKYYwfS7OjqL90N+etokIWPqv1b7nwPWzwKoRpqDfCt/gyqmgxXqWufFd0CAx7Q== + dependencies: + "@styled-icons/styled-icon" "^9.4.1" + tslib "^1.9.3" + +"@styled-icons/fa-regular@^9.4.1": + version "9.4.1" + resolved "https://registry.yarnpkg.com/@styled-icons/fa-regular/-/fa-regular-9.4.1.tgz#556b1840e97db031b5c07a7175b57103e3fd988b" + integrity sha512-tpgLOUPECtWNwVs7G82IaDkb1T13yNyDNZBB85sEO02ldHAZe6tt0Yi5gGCBExtU/p+4/jLTcU+pcoh/mySlVg== + dependencies: + "@styled-icons/styled-icon" "^9.4.1" + tslib "^1.9.3" + +"@styled-icons/fa-solid@^9.4.1": + version "9.4.1" + resolved "https://registry.yarnpkg.com/@styled-icons/fa-solid/-/fa-solid-9.4.1.tgz#d30de755f8fee6e932032e97fa592cb1eaa21d8e" + integrity sha512-ZyPxbCFmuuy3XotCI0SgHyUn3gTvQXm+iVnh+8r0gR8Kd88iTTubTqxgtdS0lrefaB4ayl6vEg20Dv9e9PvYVg== + dependencies: + "@styled-icons/styled-icon" "^9.4.1" + tslib "^1.9.3" + +"@styled-icons/feather@^9.4.1": + version "9.4.1" + resolved "https://registry.yarnpkg.com/@styled-icons/feather/-/feather-9.4.1.tgz#5e8a4193e70d477e9ad249f921c6d637f9fc631c" + integrity sha512-ucMOPhvaCp6N4lxL+z/66Kech20jAdMfewER732jhjV8P3FknoAY2+0CXXE+tBvJoJ/SOJZDOsW58Gr7yAWXOQ== + dependencies: + "@styled-icons/styled-icon" "^9.4.1" + tslib "^1.9.3" + +"@styled-icons/foundation@^9.5.0": + version "9.5.0" + resolved "https://registry.yarnpkg.com/@styled-icons/foundation/-/foundation-9.5.0.tgz#011ac022ffcb20868385b97bf4fb173cceaf634d" + integrity sha512-O4Y62bfZfZjhZDXYtJYd/RsID1vpmMtgLSP54b0KbvY70hjdlFQZ0ZVR2fAzA0YSK90VjbYBbQDCCyqim4v3qA== + dependencies: + "@styled-icons/styled-icon" "^9.4.1" + tslib "^1.9.3" + +"@styled-icons/heroicons-outline@^9.5.0": + version "9.5.0" + resolved "https://registry.yarnpkg.com/@styled-icons/heroicons-outline/-/heroicons-outline-9.5.0.tgz#235046e3310e10165b9587a122a60e83e94e51de" + integrity sha512-MMY5NjVVimhTHhk+ADR4/a2KpjIjbmzW+SNPRCKMWgGyqXx1NjBrD72bnvrzApLdMnDvEsM/DYK6DVUW7UZhKw== + dependencies: + "@styled-icons/styled-icon" "^9.4.1" + tslib "^1.9.3" + +"@styled-icons/heroicons-solid@^9.5.0": + version "9.5.0" + resolved "https://registry.yarnpkg.com/@styled-icons/heroicons-solid/-/heroicons-solid-9.5.0.tgz#2ed99d05a9a82c742eb7667c75b0d9c319fdee10" + integrity sha512-dYQYdxZ0BkGpl3nGQmkvONF1+Yq+E6I9S7snba1mirCDWQpIdgylGm+Z9CM/OvdIlhr5da00D4oZu+2CiGdCFQ== + dependencies: + "@styled-icons/styled-icon" "^9.4.1" + tslib "^1.9.3" + +"@styled-icons/icomoon@^9.4.1": + version "9.4.1" + resolved "https://registry.yarnpkg.com/@styled-icons/icomoon/-/icomoon-9.4.1.tgz#b75118a6d10cb8f5e7e15ae7a323009dd2f98e7e" + integrity sha512-oEw84P55EahJFdhQPBnUbvQqB08LuJKq75AkwaCSqk6w1DIEDbjY72lb6mbAwZB/AwNYeRVJJhTHaF1MNY103A== + dependencies: + "@styled-icons/styled-icon" "^9.4.1" + tslib "^1.9.3" + +"@styled-icons/material@^9.4.1": + version "9.4.1" + resolved "https://registry.yarnpkg.com/@styled-icons/material/-/material-9.4.1.tgz#26169db802a10e333a5608aec2611878dd45f6fe" + integrity sha512-7Ucsm7RxCrnznZb+WDptBrGE45ZVBODm6J0e+fy0hvO9sjWAcuoKffYTcQEhDS2pqC1Rcc/nSZHDbqwZrpGJVw== + dependencies: + "@styled-icons/styled-icon" "^9.4.1" + tslib "^1.9.3" + +"@styled-icons/octicons@^9.4.1": + version "9.4.1" + resolved "https://registry.yarnpkg.com/@styled-icons/octicons/-/octicons-9.4.1.tgz#9670b6a3fc70eb80961fa0771464d8dbde18a6ea" + integrity sha512-MHiMMah2agDpmk8JcNLgeZab74TO3elM8CIYIQahrucyVbHfCY7mX1z8OOyXZwrf/hgrBKK4nUM4jf0wxk70+Q== + dependencies: + "@styled-icons/styled-icon" "^9.4.1" + tslib "^1.9.3" + +"@styled-icons/open-iconic@^9.5.0": + version "9.5.0" + resolved "https://registry.yarnpkg.com/@styled-icons/open-iconic/-/open-iconic-9.5.0.tgz#03c70256244ee4a1ed422563f3ce3d0270a6beb8" + integrity sha512-mSDnCPDKYXhXY+oNfgNKMj2+ltl63k8QIC6bCDsX18bYXDqkeEwKthfNw0minabyP4Tq+yJe/B03RH+EdQWmDg== + dependencies: + "@styled-icons/styled-icon" "^9.4.1" + tslib "^1.9.3" + +"@styled-icons/remix-fill@^9.4.1": + version "9.4.1" + resolved "https://registry.yarnpkg.com/@styled-icons/remix-fill/-/remix-fill-9.4.1.tgz#afc7141d0c5c0606ef190b0cebe4793a4449b389" + integrity sha512-OlxQudeM/u+IAHacSVwwiuSYBDSsQNKA4gr8WSFHpy1CEciLc/hE/aNJP+SLcBETdg/C/kJIj8JNme5B8aYIeg== + dependencies: + "@styled-icons/styled-icon" "^9.4.1" + tslib "^1.9.3" + +"@styled-icons/remix-line@^9.4.1": + version "9.4.1" + resolved "https://registry.yarnpkg.com/@styled-icons/remix-line/-/remix-line-9.4.1.tgz#1d4fdaef53f3c366a746f054d70dcd138a4e567e" + integrity sha512-NAdR8LD7ugeUhmd6W3v+GA5/6OBexe15fjQTt1kFHYclS+2nrLQ7MA4kF5SkwsRQNGPy+3CMN5cQoMy5R8NAtQ== + dependencies: + "@styled-icons/styled-icon" "^9.4.1" + tslib "^1.9.3" + +"@styled-icons/styled-icon@^9.4.1": + version "9.4.1" + resolved "https://registry.yarnpkg.com/@styled-icons/styled-icon/-/styled-icon-9.4.1.tgz#9dc236c85afd89edc2bc7265ec7858cbc35d4234" + integrity sha512-qF0E2QOcyR1e6rh1QkKGsFt9vuayhZBJEKRa8erbHpOYLRNiEmoF1dLEVVMUKjnj5jAzzk0fNd8jSz0su3kpKg== + dependencies: + "@emotion/is-prop-valid" "^0.8.6" + tslib "^1.9.3" + +"@styled-icons/typicons@^9.4.1": + version "9.4.1" + resolved "https://registry.yarnpkg.com/@styled-icons/typicons/-/typicons-9.4.1.tgz#b201080bc3985cab1f0ff0e8827350aea14cb309" + integrity sha512-gV3W836B7k7FuNjZJt2H7WYcV+wPf7L5RYJQUL99lPdvADeOUhG2hIVIKvmS4F2Tc3XbyYbRmSBPTHtu4Fcftg== + dependencies: + "@styled-icons/styled-icon" "^9.4.1" + tslib "^1.9.3" + +"@styled-icons/zondicons@^9.5.0": + version "9.5.0" + resolved "https://registry.yarnpkg.com/@styled-icons/zondicons/-/zondicons-9.5.0.tgz#27f184764f586f31aa9256905ab3db1cd833bfa8" + integrity sha512-26PYTzSr85tf1+P/N1zaqbLuJLG1YP9rp3QN1TsCcM19gT0Y3WzVUmiNHdv15jGO9bH/jpV9b7TjuT+1gkMPCw== + dependencies: + "@styled-icons/styled-icon" "^9.4.1" + tslib "^1.9.3" + +"@turf/along@^6.0.1": + version "6.0.1" + resolved "https://registry.yarnpkg.com/@turf/along/-/along-6.0.1.tgz#595cecdc48fc7fcfa83c940a8e3eb24d4c2e04d4" + integrity sha512-6PptAcrsFR3o0Flpktk8Vo68W2txEVTh14zjoTVu+H5docd2+pv5/upA77bg3YFBoJgAxmUFt1leDdjReJ44BQ== + dependencies: + "@turf/bearing" "6.x" + "@turf/destination" "6.x" + "@turf/distance" "6.x" + "@turf/helpers" "6.x" + "@turf/invariant" "6.x" + +"@turf/bearing@6.x": + version "6.0.1" + resolved "https://registry.yarnpkg.com/@turf/bearing/-/bearing-6.0.1.tgz#8da5d17092e571f170cde7bfb2e5b0d74923c92d" + integrity sha512-mXY1NozqV9EFfBTbUItujwfqfQF0G/Xe2fzvnZle90ekPEUfhi4Dgf5JswJTd96J9LiT8kcd6Jonp5khnx0wIg== + dependencies: + "@turf/helpers" "6.x" + "@turf/invariant" "6.x" + +"@turf/destination@6.x": + version "6.0.1" + resolved "https://registry.yarnpkg.com/@turf/destination/-/destination-6.0.1.tgz#5275887fa96ec463f44864a2c17f0b712361794a" + integrity sha512-MroK4nRdp7as174miCAugp8Uvorhe6rZ7MJiC9Hb4+hZR7gNFJyVKmkdDDXIoCYs6MJQsx0buI+gsCpKwgww0Q== + dependencies: + "@turf/helpers" "6.x" + "@turf/invariant" "6.x" + +"@turf/distance@6.x": + version "6.0.1" + resolved "https://registry.yarnpkg.com/@turf/distance/-/distance-6.0.1.tgz#0761f28784286e7865a427c4e7e3593569c2dea8" + integrity sha512-q7t7rWIWfkg7MP1Vt4uLjSEhe5rPfCO2JjpKmk7JC+QZKEQkuvHEqy3ejW1iC7Kw5ZcZNR3qdMGGz+6HnVwqvg== + dependencies: + "@turf/helpers" "6.x" + "@turf/invariant" "6.x" + +"@turf/helpers@6.x": + version "6.1.4" + resolved "https://registry.yarnpkg.com/@turf/helpers/-/helpers-6.1.4.tgz#d6fd7ebe6782dd9c87dca5559bda5c48ae4c3836" + integrity sha512-vJvrdOZy1ngC7r3MDA7zIGSoIgyrkWcGnNIEaqn/APmw+bVLF2gAW7HIsdTxd12s5wQMqEpqIQrmrbRRZ0xC7g== + +"@turf/invariant@6.x": + version "6.1.2" + resolved "https://registry.yarnpkg.com/@turf/invariant/-/invariant-6.1.2.tgz#6013ed6219f9ac2edada9b31e1dfa5918eb0a2f7" + integrity sha512-WU08Ph8j0J2jVGlQCKChXoCtI50BB3yEH21V++V0T4cR1T27HKCxkehV2sYMwTierfMBgjwSwDIsxnR4/2mWXg== + dependencies: + "@turf/helpers" "6.x" + "@types/babel__core@^7.1.0": version "7.1.2" resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.2.tgz#608c74f55928033fce18b99b213c16be4b3d114f" @@ -2312,6 +2738,16 @@ babel-plugin-react-require@^3.1.1: resolved "https://registry.yarnpkg.com/babel-plugin-react-require/-/babel-plugin-react-require-3.1.1.tgz#5c3d2564fa16b1e45212ed52519db147b1596106" integrity sha512-XFz+B0dWx41fnGnugzCWn5rOgrDHb150N5gFhUfO3BgYDCT25o4sofRtd9uUfqUHoRu+t4/r5Cr2RMPIKuCt2g== +"babel-plugin-styled-components@>= 1": + version "1.10.7" + resolved "https://registry.yarnpkg.com/babel-plugin-styled-components/-/babel-plugin-styled-components-1.10.7.tgz#3494e77914e9989b33cc2d7b3b29527a949d635c" + integrity sha512-MBMHGcIA22996n9hZRf/UJLVVgkEOITuR2SvjHLb5dSTUyR4ZRGn+ngITapes36FI3WLxZHfRhkA1ffHxihOrg== + dependencies: + "@babel/helper-annotate-as-pure" "^7.0.0" + "@babel/helper-module-imports" "^7.0.0" + babel-plugin-syntax-jsx "^6.18.0" + lodash "^4.17.11" + babel-plugin-syntax-async-functions@^6.8.0: version "6.13.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz#cad9cad1191b5ad634bf30ae0872391e0647be95" @@ -2347,7 +2783,7 @@ babel-plugin-syntax-flow@^6.18.0: resolved "https://registry.yarnpkg.com/babel-plugin-syntax-flow/-/babel-plugin-syntax-flow-6.18.0.tgz#4c3ab20a2af26aa20cd25995c398c4eb70310c8d" integrity sha1-TDqyCiryaqIM0lmVw5jE63AxDI0= -babel-plugin-syntax-jsx@^6.3.13, babel-plugin-syntax-jsx@^6.8.0: +babel-plugin-syntax-jsx@^6.18.0, babel-plugin-syntax-jsx@^6.3.13, babel-plugin-syntax-jsx@^6.8.0: version "6.18.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz#0af32a9a6e13ca7a3fd5069e62d7b0f58d0d8946" integrity sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY= @@ -2966,6 +3402,11 @@ bowser@^1.9.3: resolved "https://registry.yarnpkg.com/bowser/-/bowser-1.9.4.tgz#890c58a2813a9d3243704334fa81b96a5c150c9a" integrity sha512-9IdMmj2KjigRq6oWhmwv1W36pDuA4STQZ8q6YO9um+x07xgYNCD3Oou+WP/3L1HNz7iqythGet3/p4wvc8AAwQ== +bowser@^2.7.0: + version "2.9.0" + resolved "https://registry.yarnpkg.com/bowser/-/bowser-2.9.0.tgz#3bed854233b419b9a7422d9ee3e85504373821c9" + integrity sha512-2ld76tuLBNFekRgmJfT2+3j5MIrP6bFict8WAIT3beq+srz1gcKNAdNKMqHqauQt63NmAa88HfP1/Ypa9Er3HA== + boxen@^1.2.1: version "1.3.0" resolved "https://registry.yarnpkg.com/boxen/-/boxen-1.3.0.tgz#55c6c39a8ba58d9c61ad22cd877532deb665a20b" @@ -3412,6 +3853,11 @@ camelcase@^5.0.0, camelcase@^5.3.1: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== +camelize@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/camelize/-/camelize-1.0.0.tgz#164a5483e630fa4321e5af07020e531831b2609b" + integrity sha1-FkpUg+Yw+kMh5a8HAg5TGDGyYJs= + caniuse-api@^1.5.2: version "1.6.1" resolved "https://registry.yarnpkg.com/caniuse-api/-/caniuse-api-1.6.1.tgz#b534e7c734c4f81ec5fbe8aca2ad24354b962c6c" @@ -4321,6 +4767,11 @@ css-blank-pseudo@^0.1.4: dependencies: postcss "^7.0.5" +css-color-keywords@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/css-color-keywords/-/css-color-keywords-1.0.0.tgz#fea2616dc676b2962686b3af8dbdbe180b244e05" + integrity sha1-/qJhbcZ2spYmhrOvjb2+GAskTgU= + css-color-names@0.0.4, css-color-names@^0.0.4: version "0.0.4" resolved "https://registry.yarnpkg.com/css-color-names/-/css-color-names-0.0.4.tgz#808adc2e79cf84738069b646cb20ec27beb629e0" @@ -4408,6 +4859,15 @@ css-selector-tokenizer@^0.7.0: fastparse "^1.1.1" regexpu-core "^1.0.0" +css-to-react-native@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/css-to-react-native/-/css-to-react-native-3.0.0.tgz#62dbe678072a824a689bcfee011fc96e02a7d756" + integrity sha512-Ro1yETZA813eoyUp2GDBhG2j+YggidUmzO1/v9eYBKR2EHVEniE2MI/NqpTQ954BMpTPZFsGNPm46qFB9dpaPQ== + dependencies: + camelize "^1.0.0" + css-color-keywords "^1.0.0" + postcss-value-parser "^4.0.2" + css-tree@1.0.0-alpha.29: version "1.0.0-alpha.29" resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.0.0-alpha.29.tgz#3fa9d4ef3142cbd1c301e7664c1f352bd82f5a39" @@ -6893,6 +7353,13 @@ hmac-drbg@^1.0.0: minimalistic-assert "^1.0.0" minimalistic-crypto-utils "^1.0.1" +hoist-non-react-statics@^3.0.0: + version "3.3.2" + resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45" + integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw== + dependencies: + react-is "^16.7.0" + hoist-non-react-statics@^3.1.0, hoist-non-react-statics@^3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.0.tgz#b09178f0122184fb95acf525daaecb4d8f45958b" @@ -7842,7 +8309,7 @@ isomorphic-fetch@^2.1.1, isomorphic-fetch@^2.2.1: node-fetch "^1.0.1" whatwg-fetch ">=0.10.0" -isomorphic-mapzen-search@^1.5.1: +isomorphic-mapzen-search@^1.4.1, isomorphic-mapzen-search@^1.5.1: version "1.5.1" resolved "https://registry.yarnpkg.com/isomorphic-mapzen-search/-/isomorphic-mapzen-search-1.5.1.tgz#5ac0214cec436fb550e8ef362cf8d11b17de8e9c" integrity sha512-38GcjidOqjVQkUzDovx+ceUXHwOliIoFq+qJ/zUzaZwn2h8qEANLMTjaZkFvYN2XdSGB65zBOH5n/iP/Vs1ejA== @@ -9462,6 +9929,21 @@ meow@^4.0.0: redent "^2.0.0" trim-newlines "^2.0.0" +meow@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/meow/-/meow-5.0.0.tgz#dfc73d63a9afc714a5e371760eb5c88b91078aa4" + integrity sha512-CbTqYU17ABaLefO8vCU153ZZlprKYWDljcndKKDCFcYQITzWCXZAVk4QMFZPgvzrnUQ3uItnIE/LoUOwrT15Ig== + dependencies: + camelcase-keys "^4.0.0" + decamelize-keys "^1.0.0" + loud-rejection "^1.0.0" + minimist-options "^3.0.1" + normalize-package-data "^2.3.4" + read-pkg-up "^3.0.0" + redent "^2.0.0" + trim-newlines "^2.0.0" + yargs-parser "^10.0.0" + merge-stream@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-1.0.1.tgz#4041202d508a342ba00174008df0c251b8c135e1" @@ -9757,7 +10239,14 @@ moment-timezone@^0.5.23: dependencies: moment ">= 2.9.0" -"moment@>= 2.9.0", moment@>=1.6.0, moment@^2.17.1: +moment-timezone@^0.5.27: + version "0.5.28" + resolved "https://registry.yarnpkg.com/moment-timezone/-/moment-timezone-0.5.28.tgz#f093d789d091ed7b055d82aa81a82467f72e4338" + integrity sha512-TDJkZvAyKIVWg5EtVqRzU97w0Rb0YVbfpqyjgu6GwXCAohVRqwZjf4fOzDE6p1Ch98Sro/8hQQi65WDXW5STPw== + dependencies: + moment ">= 2.9.0" + +"moment@>= 2.9.0", moment@>=1.6.0, moment@^2.17.1, moment@^2.24.0: version "2.24.0" resolved "https://registry.yarnpkg.com/moment/-/moment-2.24.0.tgz#0d055d53f5052aa653c9f6eb68bb5d12bf5c2b5b" integrity sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg== @@ -11949,6 +12438,11 @@ postcss-value-parser@^4.0.0: resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.0.0.tgz#99a983d365f7b2ad8d0f9b8c3094926eab4b936d" integrity sha512-ESPktioptiSUchCKgggAkzdmkgzKfmp0EU8jXH+5kbIUB+unr0Y4CY9SRMvibuvYUBjNh1ACLbxqYNpdTQOteQ== +postcss-value-parser@^4.0.2: + version "4.0.3" + resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.0.3.tgz#651ff4593aa9eda8d5d0d66593a2417aeaeb325d" + integrity sha512-N7h4pG+Nnu5BEIzyeaaIYWs0LI5XC40OrRh5L60z0QjFsqGWcHcbkBvpe1WYpcIS9yQ8sOi/vIPt1ejQCrMVrg== + postcss-values-parser@^2.0.0, postcss-values-parser@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/postcss-values-parser/-/postcss-values-parser-2.0.1.tgz#da8b472d901da1e205b47bdc98637b9e9e550e5f" @@ -12296,6 +12790,11 @@ qs@^6.3.0, qs@^6.4.0, qs@^6.5.1: resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc" integrity sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ== +qs@^6.9.1: + version "6.9.1" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.9.1.tgz#20082c65cb78223635ab1a9eaca8875a29bf8ec9" + integrity sha512-Cxm7/SS/y/Z3MHWSxXb8lIFqgqBowP5JMlTUFyJN88y0SGQhVmZnqFK/PeuMX9LzUyWsqqhNxIyg0jlzq946yA== + qs@~6.5.2: version "6.5.2" resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" @@ -13722,6 +14221,11 @@ sha@^3.0.0: dependencies: graceful-fs "^4.1.2" +shallowequal@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/shallowequal/-/shallowequal-1.1.0.tgz#188d521de95b9087404fd4dcb68b13df0ae4e7f8" + integrity sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ== + shasum@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/shasum/-/shasum-1.0.2.tgz#e7012310d8f417f4deb5712150e5678b87ae565f" @@ -14369,6 +14873,52 @@ style-loader@^0.13.0: dependencies: loader-utils "^1.0.2" +styled-components@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/styled-components/-/styled-components-5.0.1.tgz#57782a6471031abefb2db5820a1876ae853bc619" + integrity sha512-E0xKTRIjTs4DyvC1MHu/EcCXIj6+ENCP8hP01koyoADF++WdBUOrSGwU1scJRw7/YaYOhDvvoad6VlMG+0j53A== + dependencies: + "@babel/helper-module-imports" "^7.0.0" + "@babel/traverse" "^7.4.5" + "@emotion/is-prop-valid" "^0.8.3" + "@emotion/stylis" "^0.8.4" + "@emotion/unitless" "^0.7.4" + babel-plugin-styled-components ">= 1" + css-to-react-native "^3.0.0" + hoist-non-react-statics "^3.0.0" + shallowequal "^1.1.0" + supports-color "^5.5.0" + +styled-icons@^9.1.0: + version "9.5.0" + resolved "https://registry.yarnpkg.com/styled-icons/-/styled-icons-9.5.0.tgz#d1f6c8dcc3ea81c3d30fe20dfda5d39a8afc593c" + integrity sha512-nby51U6+SRY5010P15XogBZubrqblqXTV50+lA/xBkC1QrTap1BIgCvoJwH9FF5kYI+LKFl/xeco/drwqIR2Pw== + dependencies: + "@styled-icons/boxicons-logos" "^9.4.1" + "@styled-icons/boxicons-regular" "^9.4.1" + "@styled-icons/boxicons-solid" "^9.4.1" + "@styled-icons/crypto" "^9.4.1" + "@styled-icons/entypo" "^9.5.0" + "@styled-icons/entypo-social" "^9.5.0" + "@styled-icons/evil" "^9.4.1" + "@styled-icons/fa-brands" "^9.4.1" + "@styled-icons/fa-regular" "^9.4.1" + "@styled-icons/fa-solid" "^9.4.1" + "@styled-icons/feather" "^9.4.1" + "@styled-icons/foundation" "^9.5.0" + "@styled-icons/heroicons-outline" "^9.5.0" + "@styled-icons/heroicons-solid" "^9.5.0" + "@styled-icons/icomoon" "^9.4.1" + "@styled-icons/material" "^9.4.1" + "@styled-icons/octicons" "^9.4.1" + "@styled-icons/open-iconic" "^9.5.0" + "@styled-icons/remix-fill" "^9.4.1" + "@styled-icons/remix-line" "^9.4.1" + "@styled-icons/styled-icon" "^9.4.1" + "@styled-icons/typicons" "^9.4.1" + "@styled-icons/zondicons" "^9.5.0" + tslib "^1.9.3" + stylehacks@^4.0.0: version "4.0.3" resolved "https://registry.yarnpkg.com/stylehacks/-/stylehacks-4.0.3.tgz#6718fcaf4d1e07d8a1318690881e8d96726a71d5" @@ -14407,7 +14957,7 @@ supports-color@^3.1.0, supports-color@^3.2.3: dependencies: has-flag "^1.0.0" -supports-color@^5.0.0, supports-color@^5.3.0, supports-color@^5.4.0: +supports-color@^5.0.0, supports-color@^5.3.0, supports-color@^5.4.0, supports-color@^5.5.0: version "5.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== @@ -14565,7 +15115,7 @@ throat@^4.0.0: resolved "https://registry.yarnpkg.com/throat/-/throat-4.1.0.tgz#89037cbc92c56ab18926e6ba4cbb200e15672a6a" integrity sha1-iQN8vJLFarGJJua6TLsgDhVnKmo= -throttle-debounce@^2.0.1: +throttle-debounce@^2.0.1, throttle-debounce@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/throttle-debounce/-/throttle-debounce-2.1.0.tgz#257e648f0a56bd9e54fe0f132c4ab8611df4e1d5" integrity sha512-AOvyNahXQuU7NN+VVvOOX+uW6FPaWdAOdRP5HfwYxAfCzXTFKRMoIMk+n+po318+ktcChx+F1Dd91G3YHeMKyg== @@ -14846,6 +15396,11 @@ tslib@^1.9.0: resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a" integrity sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ== +tslib@^1.9.3: + version "1.11.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.11.1.tgz#eb15d128827fbee2841549e171f45ed338ac7e35" + integrity sha512-aZW88SY8kQbU7gpV19lN24LtXh/yD4ZZg6qieAJDDg+YBsJcSmLGK9QpnUjAKVG/xefmvJGd1WUmfpT/g6AJGA== + tty-browserify@0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6" @@ -15946,6 +16501,13 @@ yamljs@^0.3.0: argparse "^1.0.7" glob "^7.0.5" +yargs-parser@^10.0.0: + version "10.1.0" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-10.1.0.tgz#7202265b89f7e9e9f2e5765e0fe735a905edbaa8" + integrity sha512-VCIyR1wJoEBZUqk5PA+oOBF6ypbwh5aNB3I50guxAL/quggdfs4TtNHQrSazFA3fYZ+tEqfs0zIGlv0c/rgjbQ== + dependencies: + camelcase "^4.1.0" + yargs-parser@^11.1.1: version "11.1.1" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-11.1.1.tgz#879a0865973bca9f6bab5cbdf3b1c67ec7d3bcf4" From 7457a62d4305ebe3b2645cc457e56806073280b9 Mon Sep 17 00:00:00 2001 From: Evan Siroky Date: Sun, 1 Mar 2020 15:57:57 -0800 Subject: [PATCH 2/5] fix(mobile): disable usersettings overlay on welcome screen - this only shows up when user data is stored and shown --- lib/components/mobile/welcome-screen.js | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/lib/components/mobile/welcome-screen.js b/lib/components/mobile/welcome-screen.js index 47d6ab4f0..0d2414ea5 100644 --- a/lib/components/mobile/welcome-screen.js +++ b/lib/components/mobile/welcome-screen.js @@ -3,14 +3,12 @@ import PropTypes from 'prop-types' import { connect } from 'react-redux' import MobileContainer from './container' -import UserSettings from '../form/user-settings' import LocationField from '../form/connected-location-field' import DefaultMap from '../map/default-map' import MobileNavigationBar from './navigation-bar' import { MobileScreens, setMobileScreen } from '../../actions/ui' import { setLocationToCurrent } from '../../actions/map' -import { getShowUserSettings } from '../../util/state' class MobileWelcomeScreen extends Component { static propTypes = { @@ -38,7 +36,7 @@ class MobileWelcomeScreen extends Component { } render () { - const { showUserSettings, title } = this.props + const { title } = this.props return ( @@ -52,7 +50,6 @@ class MobileWelcomeScreen extends Component {
- {showUserSettings ? : null}
) @@ -62,8 +59,7 @@ class MobileWelcomeScreen extends Component { // connect to the redux store const mapStateToProps = (state, ownProps) => { - const showUserSettings = getShowUserSettings(state.otp) - return { showUserSettings } + return {} } const mapDispatchToProps = { From 7a1a489735abdf15bc37eb74417153a301e72103 Mon Sep 17 00:00:00 2001 From: Evan Siroky Date: Sun, 1 Mar 2020 16:16:27 -0800 Subject: [PATCH 3/5] refactor(geocoder): depend on otp-ui geocoder --- .../findAddressCandidates-response.json | 154 -------- .../arcgis/reverseGeocode-response.json | 32 -- .../geocoding/arcgis/suggest-response.json | 14 - .../pelias/autocomplete-response.json | 77 ---- .../geocoding/pelias/reverse-response.json | 121 ------ .../geocoding/pelias/search-response.json | 117 ------ __tests__/util/__snapshots__/geocoder.js.snap | 350 ------------------ __tests__/util/geocoder.js | 188 ---------- lib/actions/map.js | 2 +- lib/util/geocoder.js | 318 ---------------- lib/util/index.js | 2 - package.json | 3 +- yarn.lock | 4 +- 13 files changed, 4 insertions(+), 1378 deletions(-) delete mode 100644 __tests__/test-utils/fixtures/geocoding/arcgis/findAddressCandidates-response.json delete mode 100644 __tests__/test-utils/fixtures/geocoding/arcgis/reverseGeocode-response.json delete mode 100644 __tests__/test-utils/fixtures/geocoding/arcgis/suggest-response.json delete mode 100644 __tests__/test-utils/fixtures/geocoding/pelias/autocomplete-response.json delete mode 100644 __tests__/test-utils/fixtures/geocoding/pelias/reverse-response.json delete mode 100644 __tests__/test-utils/fixtures/geocoding/pelias/search-response.json delete mode 100644 __tests__/util/__snapshots__/geocoder.js.snap delete mode 100644 __tests__/util/geocoder.js delete mode 100644 lib/util/geocoder.js diff --git a/__tests__/test-utils/fixtures/geocoding/arcgis/findAddressCandidates-response.json b/__tests__/test-utils/fixtures/geocoding/arcgis/findAddressCandidates-response.json deleted file mode 100644 index 9c63ea07f..000000000 --- a/__tests__/test-utils/fixtures/geocoding/arcgis/findAddressCandidates-response.json +++ /dev/null @@ -1,154 +0,0 @@ -{ - "spatialReference": { - "wkid": 4326, - "latestWkid": 4326 - }, - "candidates": [ - { - "address": "Mill End, Clavering, Saffron Walden, Essex, England", - "location": { - "x": 0.12961000000007061, - "y": 51.973520000000065 - }, - "score": 87.5, - "attributes": { - "Loc_name": "World", - "Status": "T", - "Score": 87.5, - "Match_addr": "Mill End, Clavering, Saffron Walden, Essex, England", - "LongLabel": "Mill End, Clavering, Saffron Walden, Essex, England, GBR", - "ShortLabel": "Mill End", - "Addr_type": "Locality", - "Type": "Village", - "PlaceName": "Mill End", - "Place_addr": "Clavering, Saffron Walden, Essex, England", - "Phone": "", - "URL": "", - "Rank": 15, - "AddBldg": "", - "AddNum": "", - "AddNumFrom": "", - "AddNumTo": "", - "AddRange": "", - "Side": "", - "StPreDir": "", - "StPreType": "", - "StName": "", - "StType": "", - "StDir": "", - "BldgType": "", - "BldgName": "", - "LevelType": "", - "LevelName": "", - "UnitType": "", - "UnitName": "", - "SubAddr": "", - "StAddr": "", - "Block": "", - "Sector": "", - "Nbrhd": "Mill End", - "District": "Clavering", - "City": "Saffron Walden", - "MetroArea": "", - "Subregion": "Essex", - "Region": "England", - "RegionAbbr": "ENG", - "Territory": "", - "Zone": "", - "Postal": "", - "PostalExt": "", - "Country": "GBR", - "LangCode": "ENG", - "Distance": 0, - "X": 0.12961000000007061, - "Y": 51.973520000000065, - "DisplayX": 0.12961000000007061, - "DisplayY": 51.973520000000065, - "Xmin": 0.11961000000007062, - "Xmax": 0.13961000000007062, - "Ymin": 51.963520000000067, - "Ymax": 51.983520000000063, - "ExInfo": "" - }, - "extent": { - "xmin": 0.11961000000007062, - "ymin": 51.963520000000067, - "xmax": 0.13961000000007062, - "ymax": 51.983520000000063 - } - }, - { - "address": "Mill End, Hambleden, Henley-on-Thames, Oxfordshire, England", - "location": { - "x": -0.86689999999993006, - "y": 51.558340000000044 - }, - "score": 87.5, - "attributes": { - "Loc_name": "World", - "Status": "T", - "Score": 87.5, - "Match_addr": "Mill End, Hambleden, Henley-on-Thames, Oxfordshire, England", - "LongLabel": "Mill End, Hambleden, Henley-on-Thames, Oxfordshire, England, GBR", - "ShortLabel": "Mill End", - "Addr_type": "Locality", - "Type": "Village", - "PlaceName": "Mill End", - "Place_addr": "Hambleden, Henley-on-Thames, Oxfordshire, England", - "Phone": "", - "URL": "", - "Rank": 15, - "AddBldg": "", - "AddNum": "", - "AddNumFrom": "", - "AddNumTo": "", - "AddRange": "", - "Side": "", - "StPreDir": "", - "StPreType": "", - "StName": "", - "StType": "", - "StDir": "", - "BldgType": "", - "BldgName": "", - "LevelType": "", - "LevelName": "", - "UnitType": "", - "UnitName": "", - "SubAddr": "", - "StAddr": "", - "Block": "", - "Sector": "", - "Nbrhd": "Mill End", - "District": "Hambleden", - "City": "Henley-on-Thames", - "MetroArea": "", - "Subregion": "Oxfordshire", - "Region": "England", - "RegionAbbr": "ENG", - "Territory": "", - "Zone": "", - "Postal": "", - "PostalExt": "", - "Country": "GBR", - "LangCode": "ENG", - "Distance": 0, - "X": -0.86689999999993006, - "Y": 51.558340000000044, - "DisplayX": -0.86689999999993006, - "DisplayY": 51.558340000000044, - "Xmin": -0.87689999999993007, - "Xmax": -0.85689999999993005, - "Ymin": 51.548340000000046, - "Ymax": 51.568340000000042, - "ExInfo": "" - }, - "extent": { - "xmin": -0.87689999999993007, - "ymin": 51.548340000000046, - "xmax": -0.85689999999993005, - "ymax": 51.568340000000042 - } - } - ] -} diff --git a/__tests__/test-utils/fixtures/geocoding/arcgis/reverseGeocode-response.json b/__tests__/test-utils/fixtures/geocoding/arcgis/reverseGeocode-response.json deleted file mode 100644 index 2b73a1e4c..000000000 --- a/__tests__/test-utils/fixtures/geocoding/arcgis/reverseGeocode-response.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "address": { - "Match_addr": "SW Naito Pkwy, Portland, Oregon, 97204", - "LongLabel": "SW Naito Pkwy, Portland, OR, 97204, USA", - "ShortLabel": "SW Naito Pkwy", - "Addr_type": "StreetName", - "Type": "", - "PlaceName": "", - "AddNum": "", - "Address": "SW Naito Pkwy", - "Block": "", - "Sector": "", - "Neighborhood": "Downtown", - "District": "", - "City": "Portland", - "MetroArea": "Portland-Vancouver Metro Area", - "Subregion": "Multnomah County", - "Region": "Oregon", - "Territory": "", - "Postal": "97204", - "PostalExt": "", - "CountryCode": "USA" - }, - "location": { - "x": -122.67320084756255, - "y": 45.516175523600715, - "spatialReference": { - "wkid": 4326, - "latestWkid": 4326 - } - } -} diff --git a/__tests__/test-utils/fixtures/geocoding/arcgis/suggest-response.json b/__tests__/test-utils/fixtures/geocoding/arcgis/suggest-response.json deleted file mode 100644 index 61c72abaf..000000000 --- a/__tests__/test-utils/fixtures/geocoding/arcgis/suggest-response.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "suggestions": [ - { - "text": "Mill Ends City Park, Portland, OR, USA", - "magicKey": "dHA9MCNsb2M9ODU3OTE0NyNsbmc9MzMjcGw9MzI4OTA3MSNsYnM9MTQ6MjAwNTI3NTc=", - "isCollection": false - }, - { - "text": "Mill End Sports & Social, Penn Road, Mill End, Rickmansworth, Hertfordshire, England, WD3 8, GBR", - "magicKey": "dHA9MCNsb2M9OTY5Mzc0MiNsbmc9MzMjcGw9NTA4NTQ2NiNsYnM9MTQ6MjAwNTI3NTI=", - "isCollection": false - } - ] -} diff --git a/__tests__/test-utils/fixtures/geocoding/pelias/autocomplete-response.json b/__tests__/test-utils/fixtures/geocoding/pelias/autocomplete-response.json deleted file mode 100644 index ea9758c84..000000000 --- a/__tests__/test-utils/fixtures/geocoding/pelias/autocomplete-response.json +++ /dev/null @@ -1,77 +0,0 @@ -{ - "geocoding": { - "version": "0.2", - "attribution": "http://lb-st-mapgeo.tri-met.org:4000/attribution", - "query": { - "text": "Mill Ends", - "parser": "addressit", - "parsed_text": {}, - "tokens": [ - "Mill", - "Ends" - ], - "size": 10, - "private": false, - "focus.point.lat": 45.52, - "focus.point.lon": -122.67, - "lang": { - "name": "English", - "iso6391": "en", - "iso6393": "eng", - "defaulted": true - } - }, - "warnings": [ - "Invalid Parameter: api_key" - ], - "engine": { - "name": "Pelias", - "author": "Mapzen", - "version": "1.0" - }, - "timestamp": 1563948844191 - }, - "type": "FeatureCollection", - "features": [{ - "type": "Feature", - "geometry": { - "type": "Point", - "coordinates": [ - -122.673377, - 45.516278 - ] - }, - "properties": { - "id": "node/4243944023", - "gid": "openstreetmap:venue:node/4243944023", - "layer": "venue", - "source": "openstreetmap", - "source_id": "node/4243944023", - "name": "Mill Ends Park", - "distance": 0.491, - "accuracy": "point", - "country": "United States", - "country_gid": "whosonfirst:country:85633793", - "country_a": "USA", - "region": "Oregon", - "region_gid": "whosonfirst:region:85688513", - "region_a": "OR", - "county": "Multnomah County", - "county_gid": "whosonfirst:county:102081631", - "county_a": "MU", - "locality": "Portland", - "locality_gid": "whosonfirst:locality:101715829", - "neighbourhood": "Downtown", - "neighbourhood_gid": "whosonfirst:neighbourhood:85867131", - "continent": "North America", - "continent_gid": "whosonfirst:continent:102191575", - "label": "Mill Ends Park, Portland, OR, USA" - } - }], - "bbox": [ - -122.673377, - 45.516278, - -122.673377, - 45.516278 - ] -} diff --git a/__tests__/test-utils/fixtures/geocoding/pelias/reverse-response.json b/__tests__/test-utils/fixtures/geocoding/pelias/reverse-response.json deleted file mode 100644 index 0516458c4..000000000 --- a/__tests__/test-utils/fixtures/geocoding/pelias/reverse-response.json +++ /dev/null @@ -1,121 +0,0 @@ -{ - "geocoding": { - "version": "0.2", - "attribution": "http://lb-st-mapgeo.tri-met.org:4000/attribution", - "query": { - "size": 10, - "private": false, - "point.lat": 45.516198, - "point.lon": -122.67324, - "boundary.circle.lat": 45.516198, - "boundary.circle.lon": -122.67324, - "lang": { - "name": "English", - "iso6391": "en", - "iso6393": "eng", - "defaulted": true - }, - "querySize": 20 - }, - "warnings": [ - "Invalid Parameter: api_key" - ], - "engine": { - "name": "Pelias", - "author": "Mapzen", - "version": "1.0" - }, - "timestamp": 1563949092620 - }, - "type": "FeatureCollection", - "features": [{ - "type": "Feature", - "geometry": { - "type": "Point", - "coordinates": [ - -122.673245, - 45.516201 - ] - }, - "properties": { - "id": "way/156366633", - "gid": "openstreetmap:venue:way/156366633", - "layer": "venue", - "source": "openstreetmap", - "source_id": "way/156366633", - "name": "Mill Ends Park", - "confidence": 0.9, - "distance": 0.001, - "accuracy": "point", - "country": "United States", - "country_gid": "whosonfirst:country:85633793", - "country_a": "USA", - "region": "Oregon", - "region_gid": "whosonfirst:region:85688513", - "region_a": "OR", - "county": "Multnomah County", - "county_gid": "whosonfirst:county:102081631", - "county_a": "MU", - "locality": "Portland", - "locality_gid": "whosonfirst:locality:101715829", - "neighbourhood": "Downtown", - "neighbourhood_gid": "whosonfirst:neighbourhood:85867131", - "continent": "North America", - "continent_gid": "whosonfirst:continent:102191575", - "label": "Mill Ends Park, Portland, OR, USA" - }, - "bbox": [ - -122.6732557, - 45.5161964, - -122.673234, - 45.5162067 - ] - }, - { - "type": "Feature", - "geometry": { - "type": "Point", - "coordinates": [ - -122.673609, - 45.516337 - ] - }, - "properties": { - "id": "us/or/portland_metro:bd3f9863242e4ec7", - "gid": "openaddresses:address:us/or/portland_metro:bd3f9863242e4ec7", - "layer": "address", - "source": "openaddresses", - "source_id": "us/or/portland_metro:bd3f9863242e4ec7", - "name": "833 SW Naito Pkwy", - "housenumber": "833", - "street": "SW Naito Pkwy", - "postalcode": "97204", - "confidence": 0.8, - "distance": 0.033, - "accuracy": "point", - "country": "United States", - "country_gid": "whosonfirst:country:85633793", - "country_a": "USA", - "region": "Oregon", - "region_gid": "whosonfirst:region:85688513", - "region_a": "OR", - "county": "Multnomah County", - "county_gid": "whosonfirst:county:102081631", - "county_a": "MU", - "locality": "Portland", - "locality_gid": "whosonfirst:locality:101715829", - "neighbourhood": "Downtown", - "neighbourhood_gid": "whosonfirst:neighbourhood:85867131", - "continent": "North America", - "continent_gid": "whosonfirst:continent:102191575", - "label": "833 SW Naito Pkwy, Portland, OR, USA" - } - } - ], - "bbox": [ - -122.673883, - 45.5161964, - -122.673234, - 45.516689 - ] -} diff --git a/__tests__/test-utils/fixtures/geocoding/pelias/search-response.json b/__tests__/test-utils/fixtures/geocoding/pelias/search-response.json deleted file mode 100644 index 61e6407a6..000000000 --- a/__tests__/test-utils/fixtures/geocoding/pelias/search-response.json +++ /dev/null @@ -1,117 +0,0 @@ -{ - "geocoding": { - "version": "0.2", - "attribution": "http://lb-st-mapgeo.tri-met.org:4000/attribution", - "query": { - "text": "Mill Ends", - "size": 10, - "private": false, - "focus.point.lat": 45.52, - "focus.point.lon": -122.67, - "lang": { - "name": "English", - "iso6391": "en", - "iso6393": "eng", - "defaulted": true - }, - "querySize": 20, - "parser": "addressit", - "parsed_text": {} - }, - "warnings": [ - "Invalid Parameter: api_key" - ], - "engine": { - "name": "Pelias", - "author": "Mapzen", - "version": "1.0" - }, - "timestamp": 1563949031708 - }, - "type": "FeatureCollection", - "features": [{ - "type": "Feature", - "geometry": { - "type": "Point", - "coordinates": [ - -122.673377, - 45.516278 - ] - }, - "properties": { - "id": "node/4243944023", - "gid": "openstreetmap:venue:node/4243944023", - "layer": "venue", - "source": "openstreetmap", - "source_id": "node/4243944023", - "name": "Mill Ends Park", - "confidence": 1, - "match_type": "exact", - "distance": 0.491, - "accuracy": "point", - "country": "United States", - "country_gid": "whosonfirst:country:85633793", - "country_a": "USA", - "region": "Oregon", - "region_gid": "whosonfirst:region:85688513", - "region_a": "OR", - "county": "Multnomah County", - "county_gid": "whosonfirst:county:102081631", - "county_a": "MU", - "locality": "Portland", - "locality_gid": "whosonfirst:locality:101715829", - "neighbourhood": "Downtown", - "neighbourhood_gid": "whosonfirst:neighbourhood:85867131", - "continent": "North America", - "continent_gid": "whosonfirst:continent:102191575", - "label": "Mill Ends Park, Portland, OR, USA" - } - }, - { - "type": "Feature", - "geometry": { - "type": "Point", - "coordinates": [ - -122.681441, - 45.511851 - ] - }, - "properties": { - "id": "2584-1136::TRIMET::station", - "gid": "transit:station:2584-1136::TRIMET::station", - "layer": "station", - "source": "transit", - "source_id": "2584-1136::trimet::station", - "name": "PSU Urban Center/SW 5th & Mill MAX Station", - "street": "SW 5th & Mill", - "postalcode": "97201", - "confidence": 1, - "match_type": "exact", - "distance": 1.273, - "accuracy": "centroid", - "country": "United States", - "country_gid": "whosonfirst:country:85633793", - "country_a": "USA", - "region": "Oregon", - "region_gid": "whosonfirst:region:85688513", - "region_a": "OR", - "county": "Multnomah County", - "county_gid": "whosonfirst:county:102081631", - "county_a": "MU", - "locality": "Portland", - "locality_gid": "whosonfirst:locality:101715829", - "neighbourhood": "Downtown", - "neighbourhood_gid": "whosonfirst:neighbourhood:85867131", - "continent": "North America", - "continent_gid": "whosonfirst:continent:102191575", - "label": "PSU Urban Center/SW 5th & Mill MAX Station, Portland, OR, USA" - } - } - ], - "bbox": [ - -122.821522, - 45.495264, - -122.475528, - 45.516278 - ] -} diff --git a/__tests__/util/__snapshots__/geocoder.js.snap b/__tests__/util/__snapshots__/geocoder.js.snap deleted file mode 100644 index 0ec26af09..000000000 --- a/__tests__/util/__snapshots__/geocoder.js.snap +++ /dev/null @@ -1,350 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`geocoder ARCGIS should get location from geocode feature 1`] = ` -Object { - "lat": 51.973520000000065, - "lon": 0.1296100000000706, - "name": "Mill End, Clavering, Saffron Walden, Essex, England, GBR", -} -`; - -exports[`geocoder ARCGIS should make autocomplete query 1`] = ` -Object { - "features": Array [ - Object { - "isCollection": false, - "magicKey": "dHA9MCNsb2M9ODU3OTE0NyNsbmc9MzMjcGw9MzI4OTA3MSNsYnM9MTQ6MjAwNTI3NTc=", - "properties": Object { - "label": "Mill Ends City Park, Portland, OR, USA", - }, - "text": "Mill Ends City Park, Portland, OR, USA", - }, - Object { - "isCollection": false, - "magicKey": "dHA9MCNsb2M9OTY5Mzc0MiNsbmc9MzMjcGw9NTA4NTQ2NiNsYnM9MTQ6MjAwNTI3NTI=", - "properties": Object { - "label": "Mill End Sports & Social, Penn Road, Mill End, Rickmansworth, Hertfordshire, England, WD3 8, GBR", - }, - "text": "Mill End Sports & Social, Penn Road, Mill End, Rickmansworth, Hertfordshire, England, WD3 8, GBR", - }, - ], -} -`; - -exports[`geocoder ARCGIS should make reverse query 1`] = ` -Object { - "lat": 45.516198, - "lon": -122.67324, - "name": "SW Naito Pkwy, Portland, OR, 97204, USA", -} -`; - -exports[`geocoder ARCGIS should make search query 1`] = ` -Object { - "features": Array [ - Object { - "geometry": Object { - "coordinates": Array [ - 0.1296100000000706, - 51.973520000000065, - ], - "type": "point", - }, - "properties": Object { - "confidence": 0.875, - "country": "GBR", - "country_a": "GBR", - "county": "Essex", - "label": "Mill End, Clavering, Saffron Walden, Essex, England, GBR", - "locality": "Saffron Walden", - "name": "Mill End", - "neighbourhood": "Mill End", - "region": "England", - "resultId": undefined, - }, - "type": "feature", - }, - Object { - "geometry": Object { - "coordinates": Array [ - -0.8668999999999301, - 51.558340000000044, - ], - "type": "point", - }, - "properties": Object { - "confidence": 0.875, - "country": "GBR", - "country_a": "GBR", - "county": "Oxfordshire", - "label": "Mill End, Hambleden, Henley-on-Thames, Oxfordshire, England, GBR", - "locality": "Henley-on-Thames", - "name": "Mill End", - "neighbourhood": "Mill End", - "region": "England", - "resultId": undefined, - }, - "type": "feature", - }, - ], - "query": Object { - "text": "Mill Ends", - }, -} -`; - -exports[`geocoder NoApiGeocoder should get location from geocode feature 1`] = ` -Object { - "lat": 45.516198, - "lon": -122.67324, - "name": "45.516198, -122.673240", -} -`; - -exports[`geocoder NoApiGeocoder should make autocomplete query 1`] = ` -Object { - "features": Array [], -} -`; - -exports[`geocoder NoApiGeocoder should make reverse query 1`] = ` -Object { - "lat": 45.5162, - "lon": -122.67324, - "name": "45.5162, -122.67324", -} -`; - -exports[`geocoder NoApiGeocoder should make search query 1`] = ` -Object { - "features": Array [], -} -`; - -exports[`geocoder PELIAS should get location from geocode feature 1`] = ` -Object { - "lat": 45.516198, - "lon": -122.67324, - "name": "Mill Ends Park, Portland, OR, USA", -} -`; - -exports[`geocoder PELIAS should make autocomplete query 1`] = ` -Object { - "bbox": Array [ - -122.673377, - 45.516278, - -122.673377, - 45.516278, - ], - "features": Array [ - Object { - "geometry": Object { - "coordinates": Array [ - -122.673377, - 45.516278, - ], - "type": "Point", - }, - "properties": Object { - "accuracy": "point", - "continent": "North America", - "continent_gid": "whosonfirst:continent:102191575", - "country": "United States", - "country_a": "USA", - "country_gid": "whosonfirst:country:85633793", - "county": "Multnomah County", - "county_a": "MU", - "county_gid": "whosonfirst:county:102081631", - "distance": 0.491, - "gid": "openstreetmap:venue:node/4243944023", - "id": "node/4243944023", - "label": "Mill Ends Park, Portland, OR, USA", - "layer": "venue", - "locality": "Portland", - "locality_gid": "whosonfirst:locality:101715829", - "name": "Mill Ends Park", - "neighbourhood": "Downtown", - "neighbourhood_gid": "whosonfirst:neighbourhood:85867131", - "region": "Oregon", - "region_a": "OR", - "region_gid": "whosonfirst:region:85688513", - "source": "openstreetmap", - "source_id": "node/4243944023", - }, - "type": "Feature", - }, - ], - "geocoding": Object { - "attribution": "http://lb-st-mapgeo.tri-met.org:4000/attribution", - "engine": Object { - "author": "Mapzen", - "name": "Pelias", - "version": "1.0", - }, - "query": Object { - "focus.point.lat": 45.52, - "focus.point.lon": -122.67, - "lang": Object { - "defaulted": true, - "iso6391": "en", - "iso6393": "eng", - "name": "English", - }, - "parsed_text": Object {}, - "parser": "addressit", - "private": false, - "size": 10, - "text": "Mill Ends", - "tokens": Array [ - "Mill", - "Ends", - ], - }, - "timestamp": 1563948844191, - "version": "0.2", - "warnings": Array [ - "Invalid Parameter: api_key", - ], - }, - "isomorphicMapzenSearchQuery": Object { - "api_key": "dummy-mapzen-key", - "text": "Mill Ends", - }, - "type": "FeatureCollection", -} -`; - -exports[`geocoder PELIAS should make reverse query 1`] = ` -Object { - "lat": 45.516198, - "lon": -122.67324, - "name": "Mill Ends Park, Portland, OR, USA", -} -`; - -exports[`geocoder PELIAS should make search query 1`] = ` -Object { - "bbox": Array [ - -122.821522, - 45.495264, - -122.475528, - 45.516278, - ], - "features": Array [ - Object { - "geometry": Object { - "coordinates": Array [ - -122.673377, - 45.516278, - ], - "type": "Point", - }, - "properties": Object { - "accuracy": "point", - "confidence": 1, - "continent": "North America", - "continent_gid": "whosonfirst:continent:102191575", - "country": "United States", - "country_a": "USA", - "country_gid": "whosonfirst:country:85633793", - "county": "Multnomah County", - "county_a": "MU", - "county_gid": "whosonfirst:county:102081631", - "distance": 0.491, - "gid": "openstreetmap:venue:node/4243944023", - "id": "node/4243944023", - "label": "Mill Ends Park, Portland, OR, USA", - "layer": "venue", - "locality": "Portland", - "locality_gid": "whosonfirst:locality:101715829", - "match_type": "exact", - "name": "Mill Ends Park", - "neighbourhood": "Downtown", - "neighbourhood_gid": "whosonfirst:neighbourhood:85867131", - "region": "Oregon", - "region_a": "OR", - "region_gid": "whosonfirst:region:85688513", - "source": "openstreetmap", - "source_id": "node/4243944023", - }, - "type": "Feature", - }, - Object { - "geometry": Object { - "coordinates": Array [ - -122.681441, - 45.511851, - ], - "type": "Point", - }, - "properties": Object { - "accuracy": "centroid", - "confidence": 1, - "continent": "North America", - "continent_gid": "whosonfirst:continent:102191575", - "country": "United States", - "country_a": "USA", - "country_gid": "whosonfirst:country:85633793", - "county": "Multnomah County", - "county_a": "MU", - "county_gid": "whosonfirst:county:102081631", - "distance": 1.273, - "gid": "transit:station:2584-1136::TRIMET::station", - "id": "2584-1136::TRIMET::station", - "label": "PSU Urban Center/SW 5th & Mill MAX Station, Portland, OR, USA", - "layer": "station", - "locality": "Portland", - "locality_gid": "whosonfirst:locality:101715829", - "match_type": "exact", - "name": "PSU Urban Center/SW 5th & Mill MAX Station", - "neighbourhood": "Downtown", - "neighbourhood_gid": "whosonfirst:neighbourhood:85867131", - "postalcode": "97201", - "region": "Oregon", - "region_a": "OR", - "region_gid": "whosonfirst:region:85688513", - "source": "transit", - "source_id": "2584-1136::trimet::station", - "street": "SW 5th & Mill", - }, - "type": "Feature", - }, - ], - "geocoding": Object { - "attribution": "http://lb-st-mapgeo.tri-met.org:4000/attribution", - "engine": Object { - "author": "Mapzen", - "name": "Pelias", - "version": "1.0", - }, - "query": Object { - "focus.point.lat": 45.52, - "focus.point.lon": -122.67, - "lang": Object { - "defaulted": true, - "iso6391": "en", - "iso6393": "eng", - "name": "English", - }, - "parsed_text": Object {}, - "parser": "addressit", - "private": false, - "querySize": 20, - "size": 10, - "text": "Mill Ends", - }, - "timestamp": 1563949031708, - "version": "0.2", - "warnings": Array [ - "Invalid Parameter: api_key", - ], - }, - "isomorphicMapzenSearchQuery": Object { - "api_key": "dummy-mapzen-key", - "size": 10, - "text": "Mill Ends", - }, - "type": "FeatureCollection", -} -`; diff --git a/__tests__/util/geocoder.js b/__tests__/util/geocoder.js deleted file mode 100644 index ada6e8601..000000000 --- a/__tests__/util/geocoder.js +++ /dev/null @@ -1,188 +0,0 @@ -import nock from 'nock' - -import getGeocoder, { PeliasGeocoder } from '../../lib/util/geocoder' - -function mockResponsePath (geocoder, file) { - return `__tests__/test-utils/fixtures/geocoding/${geocoder}/${file}` -} - -describe('geocoder', () => { - const geocoders = [ - { - type: 'ARCGIS' - }, { - apiKey: 'dummy-mapzen-key', - baseUrl: 'https://ws-st.trimet.org/pelias/v1', - type: 'PELIAS' - }, - // this entry represents no geocoder configuration. In this case it is - // expected that the NoApiGeocoder will be used. - undefined - ] - - // nocks for ARCGIS - const baseArcGisPath = '/arcgis/rest/services/World/GeocodeServer/' - nock('https://geocode.arcgis.com') - // autocomplete - .get(`${baseArcGisPath}suggest`) - .query(true) - .replyWithFile(200, mockResponsePath('arcgis', 'suggest-response.json')) - // reverse - .get(`${baseArcGisPath}reverseGeocode`) - .query(true) - .replyWithFile(200, mockResponsePath('arcgis', 'reverseGeocode-response.json')) - // search - .get(`${baseArcGisPath}findAddressCandidates`) - .query(true) - .replyWithFile(200, mockResponsePath('arcgis', 'findAddressCandidates-response.json')) - // a 2nd search for purposes of resolving getLocationFromGeocodedFeature test - .get(`${baseArcGisPath}findAddressCandidates`) - .query(true) - .replyWithFile(200, mockResponsePath('arcgis', 'findAddressCandidates-response.json')) - - // nocks for PELIAS - const basePeliasPath = '/pelias/v1/' - nock('https://ws-st.trimet.org') - // autocomplete - .get(`${basePeliasPath}autocomplete`) - .query(true) - .replyWithFile(200, mockResponsePath('pelias', 'autocomplete-response.json')) - // reverse - .get(`${basePeliasPath}search`) - .query(true) - .replyWithFile(200, mockResponsePath('pelias', 'search-response.json')) - // search - .get(`${basePeliasPath}reverse`) - .query(true) - .replyWithFile(200, mockResponsePath('pelias', 'reverse-response.json')) - - geocoders.forEach(geocoder => { - const geocoderType = geocoder - ? geocoder.type - : 'NoApiGeocoder' - // the describe is in quotes to bypass a lint rule - describe(`${geocoderType}`, () => { - it('should make autocomplete query', async () => { - const result = await getGeocoder(geocoder).autocomplete({ text: 'Mill Ends' }) - expect(result).toMatchSnapshot() - }) - - it('should make search query', async () => { - const result = await getGeocoder(geocoder).search({ text: 'Mill Ends' }) - expect(result).toMatchSnapshot() - }) - - it('should make reverse query', async () => { - const result = await getGeocoder(geocoder) - .reverse({ point: { lat: 45.516198, lon: -122.673240 } }) - expect(result).toMatchSnapshot() - }) - - it('should get location from geocode feature', async () => { - let mockFeature - switch (geocoderType) { - case 'ARCGIS': - mockFeature = { - magicKey: 'abcd', - properties: { - label: 'Mill Ends City Park, Portland, OR, USA' - }, - text: 'Mill Ends City Park, Portland, OR, USA' - } - break - case 'PELIAS': - mockFeature = { - geometry: { - coordinates: [-122.673240, 45.516198], - type: 'Point' - }, - properties: { - label: 'Mill Ends Park, Portland, OR, USA' - } - } - break - case 'NoApiGeocoder': - mockFeature = { - geometry: { - coordinates: [-122.673240, 45.516198], - type: 'Point' - }, - properties: { - label: '45.516198, -122.673240' - } - } - break - default: - throw new Error(`no mock feature defined for geocoder type: ${geocoder.type}`) - } - const result = await getGeocoder(geocoder).getLocationFromGeocodedFeature(mockFeature) - expect(result).toMatchSnapshot() - }) - - // geocoder-specific tests - if (geocoderType === 'PELIAS') { - const mockSources = 'gn,oa,osm,wof' - - // sources should not be sent unless they are explicitly defined in the - // query. See https://github.com/ibi-group/trimet-mod-otp/issues/239 - it('should not send sources in autocomplete by default', () => { - // create mock API to check query - const mockPeliasAPI = { - autocomplete: query => { - expect(query.sources).not.toBe(expect.anything()) - return Promise.resolve() - } - } - const pelias = new PeliasGeocoder(mockPeliasAPI, geocoder) - pelias.autocomplete({ text: 'Mill Ends' }) - }) - - // should send sources if they're defined in the config - it('should send sources in autocomplete if defined in config', () => { - // create mock API to check query - const mockPeliasAPI = { - autocomplete: query => { - expect(query.sources).toBe(mockSources) - return Promise.resolve() - } - } - const pelias = new PeliasGeocoder( - mockPeliasAPI, - { ...geocoder, sources: mockSources } - ) - pelias.autocomplete({ text: 'Mill Ends' }) - }) - - // sources should not be sent unless they are explicitly defined in the - // query. See https://github.com/ibi-group/trimet-mod-otp/issues/239 - it('should not send sources in search by default', () => { - // create mock API to check query - const mockPeliasAPI = { - search: query => { - expect(query.sources).not.toBe(expect.anything()) - return Promise.resolve() - } - } - const pelias = new PeliasGeocoder(mockPeliasAPI, geocoder) - pelias.search({ text: 'Mill Ends' }) - }) - - // should send sources if they're defined in the config - it('should send sources in search if defined in config', () => { - // create mock API to check query - const mockPeliasAPI = { - search: query => { - expect(query.sources).toBe(mockSources) - return Promise.resolve() - } - } - const pelias = new PeliasGeocoder( - mockPeliasAPI, - { ...geocoder, sources: mockSources } - ) - pelias.search({ text: 'Mill Ends' }) - }) - } - }) - }) -}) diff --git a/lib/actions/map.js b/lib/actions/map.js index afd409141..0de7887b0 100644 --- a/lib/actions/map.js +++ b/lib/actions/map.js @@ -1,8 +1,8 @@ +import getGeocoder from '@opentripplanner/geocoder' import { createAction } from 'redux-actions' import { routingQuery } from './api' import { clearActiveSearch } from './form' -import getGeocoder from '../util/geocoder' /* SET_LOCATION action creator. Updates a from or to location in the store * diff --git a/lib/util/geocoder.js b/lib/util/geocoder.js deleted file mode 100644 index c6ac8d6cf..000000000 --- a/lib/util/geocoder.js +++ /dev/null @@ -1,318 +0,0 @@ -import * as arcgis from '@conveyal/geocoder-arcgis-geojson' -import lonlat from '@conveyal/lonlat' -import * as pelias from 'isomorphic-mapzen-search' -import memoize from 'lodash.memoize' - -/** - * Create customized geocoder functions given a certain geocoding API, the - * config for the geocoder and response rewrite functions specific to this - * application. Any geocoder api that is added is expected to have an API that - * behaves very closely to https://github.com/conveyal/isomorphic-mapzen-search - */ -class Geocoder { - constructor (geocoderApi, geocoderConfig) { - this.api = geocoderApi - this.geocoderConfig = geocoderConfig - } - - /** - * Perform an autocomplete query. Eg, using partial text of a possible - * address or POI, attempt to find possible matches. - */ - autocomplete (query) { - return this.api.autocomplete(this.getAutocompleteQuery(query)) - .then(this.rewriteAutocompleteResponse) - } - - /** - * Get an application-specific data structure from a given feature. The - * feature is either the result of an autocomplete or a search query. This - * function returns a Promise because sometimes an asynchronous action - * needs to be taken to translate a feature into a location. For example, - * the ArcGIS autocomplete service returns results that lack full address - * data and GPS and it is expected that an extra call to the `search` API is - * done to obtain that detailed data. - */ - getLocationFromGeocodedFeature (feature) { - const location = lonlat.fromCoordinates(feature.geometry.coordinates) - location.name = feature.properties.label - return Promise.resolve(location) - } - - /** - * Do a reverse-geocode. ie get address information and attributes given a - * GPS coordiante. - */ - reverse (query) { - return this.api.reverse(this.getReverseQuery(query)) - .then(this.rewriteReverseResponse) - } - - /** - * Perform a search query. A search query is different from autocomplete in - * that it is assumed that the text provided is more or less a complete - * well-fromatted address. - */ - search (query) { - return this.api.search(this.getSearchQuery(query)) - .then(this.rewriteSearchResponse) - } - - /** - * Default autocomplete query generator - */ - getAutocompleteQuery (query) { - const {apiKey, baseUrl, boundary, options, focusPoint} = this.geocoderConfig - return { - apiKey, - boundary, - focusPoint, - options, - url: baseUrl ? `${baseUrl}/autocomplete` : undefined, - ...query - } - } - - /** - * Default reverse query generator - */ - getReverseQuery (query) { - const {apiKey, baseUrl, options} = this.geocoderConfig - return { - apiKey, - format: true, - options, - url: baseUrl ? `${baseUrl}/reverse` : undefined, - ...query - } - } - - /** - * Default search query generator. - */ - getSearchQuery (query) { - const {apiKey, baseUrl, boundary, focusPoint, options} = this.geocoderConfig - return { - apiKey, - boundary, - focusPoint, - options, - url: baseUrl ? `${baseUrl}/search` : undefined, - format: false, // keep as returned GeoJSON, - ...query - } - } - - /** - * Default rewriter for autocomplete responses - */ - rewriteAutocompleteResponse (response) { return response } - - /** - * Default rewriter for reverse responses - */ - rewriteReverseResponse (response) { return response } - - /** - * Default rewriter for search responses - */ - rewriteSearchResponse (response) { return response } -} - -/** - * Geocoder implementation for the ArcGIS geocoder. - * See https://developers.arcgis.com/rest/geocode/api-reference/overview-world-geocoding-service.htm - * - * @extends Geocoder - */ -class ArcGISGeocoder extends Geocoder { - /** - * Using the given magicKey and text, perform a search query to get detailed - * address and GPS data. Return data in an application-specific location - * format. - */ - getLocationFromGeocodedFeature (feature) { - return this.api.search({ magicKey: feature.magicKey, text: feature.text }) - .then(response => { - const feature = response.features[0] - const location = lonlat.fromCoordinates(feature.geometry.coordinates) - location.name = feature.properties.label - return location - }) - } - - /** - * Rewrite an autocomplete response into an application specific data format. - * Also, filter out any results that are collections. - */ - rewriteAutocompleteResponse (response) { - return { - // remove any autocomplete results that are collections - // (eg multiple Starbucks) - features: response.features.filter(feature => !feature.isCollection) - // add label property so location-field can handle things ok - .map(feature => ({ - ...feature, - properties: { - label: feature.text - } - })) - } - } - - /** - * Rewrite the response into an application-specific data format using the - * first feature returned from the geocoder. - */ - rewriteReverseResponse (response) { - const { features, query } = response - const { lat, lon } = query - return { - lat, - lon, - name: features[0].properties.label - } - } -} - -/** - * An implementation that doesn't use an API for geocoding. Merely allows - * clicking on the map and finding GPS coordinates by typing them in. - * - * @extends Geocoder - */ -class NoApiGeocoder extends Geocoder { - /** - * Use coordinate string parser. - */ - autocomplete (query) { - return this.parseCoordinateString(query.text) - } - - /** - * Always return the lat/lon. - */ - reverse (query) { - let { lat, lon } = query.point - lat = this.roundGPSDecimal(lat) - lon = this.roundGPSDecimal(lon) - return Promise.resolve({ lat, lon, name: `${lat}, ${lon}` }) - } - - /** - * Use coordinate string parser. - */ - search (query) { - return this.parseCoordinateString(query.text) - } - - /** - * Attempt to parse the input as a GPS coordinate. If parseable, return a - * feature. - */ - parseCoordinateString (string) { - let feature - try { - feature = { - geometry: { - coordinates: lonlat.toCoordinates(lonlat.fromLatFirstString(string)), - type: 'Point' - }, - properties: { - label: string - } - } - } catch (e) { - return Promise.resolve({ features: [] }) - } - return Promise.resolve({ features: [feature] }) - } - - roundGPSDecimal (number) { - const roundFactor = 100000 - return Math.round(number * roundFactor) / roundFactor - } -} - -/** - * Geocoder implementation for the Pelias geocoder. - * See https://pelias.io - * - * This is exported for testing purposes only. - * - * @extends Geocoder - */ -export class PeliasGeocoder extends Geocoder { - /** - * Generate an autocomplete query specifically for the Pelias API. The - * `sources` parameter is a Pelias-specific option. - */ - getAutocompleteQuery (query) { - const {apiKey, baseUrl, boundary, focusPoint, options, sources} = this.geocoderConfig - return { - apiKey, - boundary, - focusPoint, - options, - // explicitly send over null for sources if provided sources is not truthy - // in order to avoid default isomorphic-mapzen-search sources form being - // applied - sources: sources || null, - url: baseUrl ? `${baseUrl}/autocomplete` : undefined, - ...query - } - } - - /** - * Generate a search query specifically for the Pelias API. The - * `sources` parameter is a Pelias-specific option. - */ - getSearchQuery (query) { - const {apiKey, baseUrl, boundary, focusPoint, options, sources} = this.geocoderConfig - return { - apiKey, - boundary, - focusPoint, - // explicitly send over null for sources if provided sources is not truthy - // in order to avoid default isomorphic-mapzen-search sources form being - // applied - options, - sources: sources || null, - url: baseUrl ? `${baseUrl}/search` : undefined, - format: false, // keep as returned GeoJSON, - ...query - } - } - - /** - * Rewrite the response into an application-specific data format using the - * first feature returned from the geocoder. - */ - rewriteReverseResponse (response) { - const { 'point.lat': lat, 'point.lon': lon } = response.isomorphicMapzenSearchQuery - return { - lat, - lon, - name: response[0].address - } - } -} - -// Create a memoized getter to avoid recreating new geocoders each time. -const getGeocoder = memoize(geocoderConfig => { - if (!geocoderConfig || !geocoderConfig.type) { - return new NoApiGeocoder() - } - const {type} = geocoderConfig - switch (type) { - case 'ARCGIS': - return new ArcGISGeocoder(arcgis, geocoderConfig) - case 'PELIAS': - return new PeliasGeocoder(pelias, geocoderConfig) - default: - console.error(`Unkown geocoder type: "${type}". Using NoApiGeocoder.`) - return new NoApiGeocoder() - } -}) - -export default getGeocoder diff --git a/lib/util/index.js b/lib/util/index.js index b04bbc761..8d225a961 100644 --- a/lib/util/index.js +++ b/lib/util/index.js @@ -1,5 +1,4 @@ import * as distance from './distance' -import getGeocoder from './geocoder' import * as itinerary from './itinerary' import * as map from './map' import * as profile from './profile' @@ -11,7 +10,6 @@ import * as ui from './ui' const OtpUtils = { distance, - getGeocoder, itinerary, map, profile, diff --git a/package.json b/package.json index 00b272720..c8c983978 100644 --- a/package.json +++ b/package.json @@ -27,10 +27,10 @@ }, "homepage": "https://github.com/opentripplanner/otp-react-redux#readme", "dependencies": { - "@conveyal/geocoder-arcgis-geojson": "^0.0.2", "@conveyal/lonlat": "^1.1.0", "@mapbox/polyline": "^0.2.0", "@opentripplanner/from-to-location-picker": "^0.0.14", + "@opentripplanner/geocoder": "^0.0.16", "@opentripplanner/location-field": "^0.0.16", "bootstrap": "^3.3.7", "bowser": "^1.9.3", @@ -46,7 +46,6 @@ "history": "^4.7.2", "immutability-helper": "^2.1.1", "isomorphic-fetch": "^2.2.1", - "isomorphic-mapzen-search": "^1.5.1", "leaflet": "^1.5.1", "leaflet.polylinemeasure": "github:ppete2/Leaflet.PolylineMeasure", "lodash.debounce": "^4.0.8", diff --git a/yarn.lock b/yarn.lock index bb5084d0a..fe44815a4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8309,7 +8309,7 @@ isomorphic-fetch@^2.1.1, isomorphic-fetch@^2.2.1: node-fetch "^1.0.1" whatwg-fetch ">=0.10.0" -isomorphic-mapzen-search@^1.4.1, isomorphic-mapzen-search@^1.5.1: +isomorphic-mapzen-search@^1.4.1: version "1.5.1" resolved "https://registry.yarnpkg.com/isomorphic-mapzen-search/-/isomorphic-mapzen-search-1.5.1.tgz#5ac0214cec436fb550e8ef362cf8d11b17de8e9c" integrity sha512-38GcjidOqjVQkUzDovx+ceUXHwOliIoFq+qJ/zUzaZwn2h8qEANLMTjaZkFvYN2XdSGB65zBOH5n/iP/Vs1ejA== @@ -15115,7 +15115,7 @@ throat@^4.0.0: resolved "https://registry.yarnpkg.com/throat/-/throat-4.1.0.tgz#89037cbc92c56ab18926e6ba4cbb200e15672a6a" integrity sha1-iQN8vJLFarGJJua6TLsgDhVnKmo= -throttle-debounce@^2.0.1, throttle-debounce@^2.1.0: +throttle-debounce@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/throttle-debounce/-/throttle-debounce-2.1.0.tgz#257e648f0a56bd9e54fe0f132c4ab8611df4e1d5" integrity sha512-AOvyNahXQuU7NN+VVvOOX+uW6FPaWdAOdRP5HfwYxAfCzXTFKRMoIMk+n+po318+ktcChx+F1Dd91G3YHeMKyg== From 984e0c8a666ed039b1cc595ccc463fd7fbda9644 Mon Sep 17 00:00:00 2001 From: Evan Siroky Date: Sun, 1 Mar 2020 16:19:51 -0800 Subject: [PATCH 4/5] refactor(location): remove some stuff no longer needed after - @opentripplanner/location-field now provides this functionality --- lib/util/ui.js | 9 --------- package.json | 2 -- yarn.lock | 5 ----- 3 files changed, 16 deletions(-) diff --git a/lib/util/ui.js b/lib/util/ui.js index c430cc04e..bf5be4753 100644 --- a/lib/util/ui.js +++ b/lib/util/ui.js @@ -1,5 +1,3 @@ -import bowser from 'bowser' - import { MainPanelContent } from '../actions/ui' import { summarizeQuery } from './query' import { getActiveSearch } from './state' @@ -12,13 +10,6 @@ export function isMobile () { return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) } -/** - * Returns true if the user is using a [redacted] browser - */ -export function isIE () { - return bowser.name === 'Internet Explorer' -} - /** * Enables scrolling for a specified selector, while disabling scrolling for all * other targets. This is adapted from https://stackoverflow.com/a/41601290/915811 diff --git a/package.json b/package.json index c8c983978..75f922e0a 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,6 @@ "@opentripplanner/geocoder": "^0.0.16", "@opentripplanner/location-field": "^0.0.16", "bootstrap": "^3.3.7", - "bowser": "^1.9.3", "clone": "^2.1.0", "connected-react-router": "^6.5.2", "copy-to-clipboard": "^3.0.8", @@ -72,7 +71,6 @@ "redux-actions": "^1.2.1", "redux-logger": "^2.7.4", "redux-thunk": "^2.3.0", - "throttle-debounce": "^2.0.1", "transitive-js": "^0.13.0", "turf-along": "^3.0.12", "velocity-react": "^1.3.3" diff --git a/yarn.lock b/yarn.lock index fe44815a4..48d3fff61 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3397,11 +3397,6 @@ bottleneck@^2.18.1: resolved "https://registry.yarnpkg.com/bottleneck/-/bottleneck-2.19.4.tgz#63c505687a0ddaf89a6f515225c75e05833bb079" integrity sha512-2poBdvpAGG+dkMVKZqtDhyuMN6JviD81h89W4bfmt3UO7O60F+qf/84V0alNqL8PM1RByl4SZ1fVMu/ZvxkmcA== -bowser@^1.9.3: - version "1.9.4" - resolved "https://registry.yarnpkg.com/bowser/-/bowser-1.9.4.tgz#890c58a2813a9d3243704334fa81b96a5c150c9a" - integrity sha512-9IdMmj2KjigRq6oWhmwv1W36pDuA4STQZ8q6YO9um+x07xgYNCD3Oou+WP/3L1HNz7iqythGet3/p4wvc8AAwQ== - bowser@^2.7.0: version "2.9.0" resolved "https://registry.yarnpkg.com/bowser/-/bowser-2.9.0.tgz#3bed854233b419b9a7422d9ee3e85504373821c9" From 357db32641246d4474808af22817a5cc8adb65ab Mon Sep 17 00:00:00 2001 From: Evan Siroky Date: Wed, 18 Mar 2020 17:07:43 -0700 Subject: [PATCH 5/5] refactor(location-field): don't underline or change color options on hover --- lib/components/form/connected-location-field.js | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/lib/components/form/connected-location-field.js b/lib/components/form/connected-location-field.js index ef9dfba6f..1f497f84f 100644 --- a/lib/components/form/connected-location-field.js +++ b/lib/components/form/connected-location-field.js @@ -4,7 +4,8 @@ import { FormGroup, Input, InputGroup, - InputGroupAddon + InputGroupAddon, + MenuItemA } from '@opentripplanner/location-field/lib/styled' import { connect } from 'react-redux' import styled from 'styled-components' @@ -44,6 +45,14 @@ const StyledLocationField = styled(LocationField)` vertical-align: middle; width: 1%; } + + ${MenuItemA} { + text-decoration: none; + } + + ${MenuItemA}:hover { + color: #333; + } ` // connect to redux store