diff --git a/lib/components/narrative/narrative-profile-options.js b/lib/components/narrative/narrative-profile-options.js
deleted file mode 100644
index 405d6609a..000000000
--- a/lib/components/narrative/narrative-profile-options.js
+++ /dev/null
@@ -1,86 +0,0 @@
-import React, { Component } from 'react'
-import PropTypes from 'prop-types'
-import { connect } from 'react-redux'
-
-import { setActiveItinerary, setActiveLeg, setActiveStep } from '../../actions/narrative'
-import DefaultItinerary from './default/default-itinerary'
-import NarrativeProfileSummary from './narrative-profile-summary'
-import Loading from './loading'
-import { getActiveSearch } from '../../util/state'
-import { profileOptionsToItineraries } from '../../util/profile'
-
-class NarrativeProfileOptions extends Component {
- static propTypes = {
- options: PropTypes.array,
- query: PropTypes.object,
- itineraryClass: PropTypes.func,
- pending: PropTypes.bool,
- activeOption: PropTypes.number,
- setActiveItinerary: PropTypes.func,
- setActiveLeg: PropTypes.func,
- setActiveStep: PropTypes.func,
- customIcons: PropTypes.object
- }
-
- static defaultProps = {
- itineraryClass: DefaultItinerary
- }
-
- render () {
- const { pending, itineraryClass, query, activeItinerary } = this.props
- if (pending) return
-
- const options = this.props.options
- if (!options) return null
-
- const itineraries = profileOptionsToItineraries(options, query)
-
- return (
-
- )
- }
-}
-
-// connect to the redux store
-const mapStateToProps = (state, ownProps) => {
- const activeSearch = getActiveSearch(state.otp)
- // const { activeItinerary, activeLeg, activeStep } = activeSearch ? activeSearch.activeItinerary : {}
- const pending = activeSearch && activeSearch.pending
- return {
- options:
- activeSearch &&
- activeSearch.response &&
- activeSearch.response.otp
- ? activeSearch.response.otp.profile
- : null,
- pending,
- activeItinerary: activeSearch && activeSearch.activeItinerary,
- activeLeg: activeSearch && activeSearch.activeLeg,
- activeStep: activeSearch && activeSearch.activeStep,
- query: activeSearch && activeSearch.query
- }
-}
-
-const mapDispatchToProps = (dispatch, ownProps) => {
- return {
- setActiveItinerary: (index) => { dispatch(setActiveItinerary({ index })) },
- setActiveLeg: (index, leg) => { dispatch(setActiveLeg({ index, leg })) },
- setActiveStep: (index, step) => { dispatch(setActiveStep({ index, step })) }
- }
-}
-
-export default connect(mapStateToProps, mapDispatchToProps)(NarrativeProfileOptions)
diff --git a/lib/components/narrative/narrative-profile-summary.js b/lib/components/narrative/narrative-profile-summary.js
deleted file mode 100644
index c6a0fcee3..000000000
--- a/lib/components/narrative/narrative-profile-summary.js
+++ /dev/null
@@ -1,82 +0,0 @@
-import React, { Component } from 'react'
-import PropTypes from 'prop-types'
-import { ModeIcon } from '@opentripplanner/trip-form/lib/ModeIcon' // TODO: export this to OTP-ui package root.
-
-
-export default class NarrativeProfileSummary extends Component {
- static propTypes = {
- options: PropTypes.array,
- customIcons: PropTypes.object
- }
-
- render () {
- const { options } = this.props
-
- let bestTransit = 0
- let walk = 0
- let bicycle = 0
- let bicycleRent = 0
-
- options.forEach((option, i) => {
- if (option.transit) {
- if (option.time < bestTransit || bestTransit === 0) {
- bestTransit = option.time
- }
- } else {
- if (option.modes.length === 1 && option.modes[0] === 'bicycle') bicycle = option.time
- else if (option.modes.length === 1 && option.modes[0] === 'walk') walk = option.time
- else if (option.modes.indexOf('bicycle_rent') !== -1) bicycleRent = option.time
- }
- })
-
- const summary = [
- {
- icon: 'BUS',
- title: 'Transit',
- time: bestTransit
- }, {
- icon: 'BICYCLE',
- title: 'Bicycle',
- time: bicycle
- }, {
- icon: 'BICYCLE_RENT',
- title: 'Bikeshare',
- time: bicycleRent
- }, {
- icon: 'WALK',
- title: 'Walk',
- time: walk
- }
- ]
-
- return (
-
- )
- }
-}
diff --git a/lib/components/narrative/narrative-routing-results.js b/lib/components/narrative/narrative-routing-results.js
deleted file mode 100644
index f7f407420..000000000
--- a/lib/components/narrative/narrative-routing-results.js
+++ /dev/null
@@ -1,60 +0,0 @@
-import React, { Component } from 'react'
-import PropTypes from 'prop-types'
-import { connect } from 'react-redux'
-
-import Loading from './loading'
-import NarrativeProfileOptions from './narrative-profile-options'
-import TabbedItineraries from './tabbed-itineraries'
-import ErrorMessage from '../form/error-message'
-
-import { getActiveSearch, getActiveItineraries } from '../../util/state'
-import { setMainPanelContent } from '../../actions/ui'
-
-class NarrativeRoutingResults extends Component {
- static propTypes = {
- customIcons: PropTypes.object,
- itineraryClass: PropTypes.func,
- routingType: PropTypes.string
- }
-
- componentDidUpdate (prevProps) {
- if ((!prevProps.itineraries || prevProps.itineraries.length === 0) &&
- (this.props.itineraries && this.props.itineraries.length > 0)) {
- this.props.setMainPanelContent(null)
- }
- if (!prevProps.error && this.props.error) this.props.setMainPanelContent(null)
- }
-
- render () {
- const { customIcons, error, itineraryClass, itineraryFooter, pending, routingType, itineraries, mainPanelContent } = this.props
- if (pending) return
- if (mainPanelContent) return null
-
- return (
- routingType === 'ITINERARY'
- ?
- )
- }
-}
-
-const mapStateToProps = (state, ownProps) => {
- const activeSearch = getActiveSearch(state.otp)
- return {
- mainPanelContent: state.otp.ui.mainPanelContent,
- error: activeSearch && activeSearch.response && activeSearch.response.error,
- itineraries: getActiveItineraries(state.otp),
- pending: activeSearch && activeSearch.pending,
- routingType: activeSearch && activeSearch.query.routingType
- }
-}
-
-const mapDispatchToProps = {
- setMainPanelContent
-}
-
-export default connect(mapStateToProps, mapDispatchToProps)(NarrativeRoutingResults)
diff --git a/lib/util/itinerary.js b/lib/util/itinerary.js
index 4b468599d..77fb9fe3a 100644
--- a/lib/util/itinerary.js
+++ b/lib/util/itinerary.js
@@ -1,10 +1,7 @@
-import React from 'react'
import { latLngBounds } from 'leaflet'
import polyline from '@mapbox/polyline'
import turfAlong from '@turf/along'
-import ModeIcon from '../components/icons/mode-icon'
-
// All OTP transit modes
export const transitModes = ['TRAM', 'BUS', 'SUBWAY', 'FERRY', 'RAIL', 'GONDOLA']
From d05337fa622c2bc8897de3f27b2673d58f404810 Mon Sep 17 00:00:00 2001
From: binh-dam-ibigroup <56846598+binh-dam-ibigroup@users.noreply.github.com>
Date: Fri, 3 Apr 2020 10:47:33 -0400
Subject: [PATCH 05/31] refactor(icons): Remove lib/components/icons and use
OTP-ui icons package instead.
---
lib/components/form/default-search-form.js | 14 +++-
lib/components/icons/bike-icon.js | 19 -----
lib/components/icons/biketown-icon.js | 18 ----
lib/components/icons/bus-icon.js | 23 ------
lib/components/icons/car2go-icon.js | 16 ----
lib/components/icons/direction-icon.js | 82 -------------------
lib/components/icons/gondola-icon.js | 12 ---
lib/components/icons/index.js | 36 --------
lib/components/icons/lyft-icon.js | 11 ---
lib/components/icons/rail-icon.js | 11 ---
lib/components/icons/reachnow-icon.js | 14 ----
lib/components/icons/streetcar-icon.js | 12 ---
lib/components/icons/tram-icon.js | 12 ---
lib/components/icons/transit-icon.js | 23 ------
lib/components/icons/uber-icon.js | 14 ----
lib/components/icons/walk-icon.js | 14 ----
.../narrative/itinerary-carousel.js | 35 ++------
.../narrative/narrative-routing-results.js | 55 +++++++++++++
lib/index.js | 2 -
19 files changed, 72 insertions(+), 351 deletions(-)
delete mode 100644 lib/components/icons/bike-icon.js
delete mode 100644 lib/components/icons/biketown-icon.js
delete mode 100644 lib/components/icons/bus-icon.js
delete mode 100644 lib/components/icons/car2go-icon.js
delete mode 100644 lib/components/icons/direction-icon.js
delete mode 100644 lib/components/icons/gondola-icon.js
delete mode 100644 lib/components/icons/index.js
delete mode 100644 lib/components/icons/lyft-icon.js
delete mode 100644 lib/components/icons/rail-icon.js
delete mode 100644 lib/components/icons/reachnow-icon.js
delete mode 100644 lib/components/icons/streetcar-icon.js
delete mode 100644 lib/components/icons/tram-icon.js
delete mode 100644 lib/components/icons/transit-icon.js
delete mode 100644 lib/components/icons/uber-icon.js
delete mode 100644 lib/components/icons/walk-icon.js
create mode 100644 lib/components/narrative/narrative-routing-results.js
diff --git a/lib/components/form/default-search-form.js b/lib/components/form/default-search-form.js
index 1f2578231..31df598d8 100644
--- a/lib/components/form/default-search-form.js
+++ b/lib/components/form/default-search-form.js
@@ -1,10 +1,16 @@
-import React, { Component } from 'react'
+import TriMetModeIcon from '@opentripplanner/icons/lib/trimet-mode-icon'
import PropTypes from 'prop-types'
+import React, { Component } from 'react'
import LocationField from './connected-location-field'
-import SwitchButton from './switch-button'
import TabbedFormPanel from './tabbed-form-panel'
-import defaultIcons from '../icons'
+import SwitchButton from './switch-button'
+
+// As of OTP-ui 0.0.18, use the icons props
+// to override icons for certain modes in the mode selector panel.
+const customIcons = {
+ TRANSIT:
+}
export default class DefaultSearchForm extends Component {
static propTypes = {
@@ -13,7 +19,7 @@ export default class DefaultSearchForm extends Component {
}
static defaultProps = {
- icons: defaultIcons,
+ icons: customIcons,
showFrom: true,
showTo: true
}
diff --git a/lib/components/icons/bike-icon.js b/lib/components/icons/bike-icon.js
deleted file mode 100644
index c97d0de98..000000000
--- a/lib/components/icons/bike-icon.js
+++ /dev/null
@@ -1,19 +0,0 @@
-import React, { Component } from 'react'
-
-export default class BikeIcon extends Component {
- render () {
- return (
-
-
- )
- }
-}
diff --git a/lib/components/icons/biketown-icon.js b/lib/components/icons/biketown-icon.js
deleted file mode 100644
index 50fcefac7..000000000
--- a/lib/components/icons/biketown-icon.js
+++ /dev/null
@@ -1,18 +0,0 @@
-import React, { Component } from 'react'
-
-export default class BiketownIcon extends Component {
- render () {
- return (
-
- )
- }
-}
diff --git a/lib/components/icons/bus-icon.js b/lib/components/icons/bus-icon.js
deleted file mode 100644
index 64bbcaf71..000000000
--- a/lib/components/icons/bus-icon.js
+++ /dev/null
@@ -1,23 +0,0 @@
-import React, { Component } from 'react'
-
-export default class BusIcon extends Component {
- render () {
- return (
-
-
- )
- }
-}
diff --git a/lib/components/icons/car2go-icon.js b/lib/components/icons/car2go-icon.js
deleted file mode 100644
index fe4c01f3d..000000000
--- a/lib/components/icons/car2go-icon.js
+++ /dev/null
@@ -1,16 +0,0 @@
-import React, { Component } from 'react'
-
-export default class Car2goIcon extends Component {
- render () {
- return (
-
- )
- }
-}
diff --git a/lib/components/icons/direction-icon.js b/lib/components/icons/direction-icon.js
deleted file mode 100644
index 3203d1e1c..000000000
--- a/lib/components/icons/direction-icon.js
+++ /dev/null
@@ -1,82 +0,0 @@
-import React, { Component } from 'react'
-
-export default class DirectionIcon extends Component {
- render () {
- const { relativeDirection } = this.props
- if (!relativeDirection) return null
- switch (relativeDirection.toUpperCase()) {
- case 'DEPART':
- case 'CONTINUE': return (
-
- )
- }
- return null
- }
-}
diff --git a/lib/components/icons/gondola-icon.js b/lib/components/icons/gondola-icon.js
deleted file mode 100644
index d14bcb744..000000000
--- a/lib/components/icons/gondola-icon.js
+++ /dev/null
@@ -1,12 +0,0 @@
-import React, { Component } from 'react'
-
-export default class GondolaIcon extends Component {
- render () {
- return (
-
-
- )
- }
-}
diff --git a/lib/components/icons/index.js b/lib/components/icons/index.js
deleted file mode 100644
index 8bdf35517..000000000
--- a/lib/components/icons/index.js
+++ /dev/null
@@ -1,36 +0,0 @@
-import React from 'react'
-
-import BikeIcon from './bike-icon'
-import BiketownIcon from './biketown-icon'
-import BusIcon from './bus-icon'
-import Car2goIcon from './car2go-icon'
-import ReachNowIcon from './reachnow-icon'
-import GondolaIcon from './gondola-icon'
-import LyftIcon from './lyft-icon'
-import RailIcon from './rail-icon'
-import StreetcarIcon from './streetcar-icon'
-import TramIcon from './tram-icon'
-import TransitIcon from './transit-icon'
-import UberIcon from './uber-icon'
-import WalkIcon from './walk-icon'
-
-// define Portland-specific mode icons
-export default {
- BICYCLE:
,
- customModeForLeg: (leg) => {
- if (leg.routeLongName && leg.routeLongName.startsWith('Portland Streetcar')) return 'STREETCAR'
- return null
- }
-}
diff --git a/lib/components/icons/lyft-icon.js b/lib/components/icons/lyft-icon.js
deleted file mode 100644
index add6801bf..000000000
--- a/lib/components/icons/lyft-icon.js
+++ /dev/null
@@ -1,11 +0,0 @@
-import React, { Component } from 'react'
-
-export default class LyftIcon extends Component {
- render () {
- return (
-
- )
- }
-}
diff --git a/lib/components/icons/rail-icon.js b/lib/components/icons/rail-icon.js
deleted file mode 100644
index 8f2ab99d6..000000000
--- a/lib/components/icons/rail-icon.js
+++ /dev/null
@@ -1,11 +0,0 @@
-import React, { Component } from 'react'
-
-export default class RailIcon extends Component {
- render () {
- return (
-
- )
- }
-}
diff --git a/lib/components/icons/reachnow-icon.js b/lib/components/icons/reachnow-icon.js
deleted file mode 100644
index bab628729..000000000
--- a/lib/components/icons/reachnow-icon.js
+++ /dev/null
@@ -1,14 +0,0 @@
-import React, { Component } from 'react'
-
-export default class ReachNowIcon extends Component {
- render () {
- return (
-
- )
- }
-}
diff --git a/lib/components/icons/streetcar-icon.js b/lib/components/icons/streetcar-icon.js
deleted file mode 100644
index e53550142..000000000
--- a/lib/components/icons/streetcar-icon.js
+++ /dev/null
@@ -1,12 +0,0 @@
-import React, { Component } from 'react'
-
-export default class StreetcarIcon extends Component {
- render () {
- return (
-
-
- )
- }
-}
diff --git a/lib/components/icons/tram-icon.js b/lib/components/icons/tram-icon.js
deleted file mode 100644
index 10e69e931..000000000
--- a/lib/components/icons/tram-icon.js
+++ /dev/null
@@ -1,12 +0,0 @@
-import React, { Component } from 'react'
-
-export default class TramIcon extends Component {
- render () {
- return (
-
-
- )
- }
-}
diff --git a/lib/components/icons/transit-icon.js b/lib/components/icons/transit-icon.js
deleted file mode 100644
index d2e96487c..000000000
--- a/lib/components/icons/transit-icon.js
+++ /dev/null
@@ -1,23 +0,0 @@
-import React, { Component } from 'react'
-
-export default class TransitIcon extends Component {
- render () {
- // TODO: Find a better general transit icon to use than the bus icon.
- return (
-
- )
- }
-}
diff --git a/lib/components/icons/uber-icon.js b/lib/components/icons/uber-icon.js
deleted file mode 100644
index 77daea91a..000000000
--- a/lib/components/icons/uber-icon.js
+++ /dev/null
@@ -1,14 +0,0 @@
-import React, { Component } from 'react'
-
-export default class UberIcon extends Component {
- render () {
- return (
-
- )
- }
-}
diff --git a/lib/components/icons/walk-icon.js b/lib/components/icons/walk-icon.js
deleted file mode 100644
index a071dcfa4..000000000
--- a/lib/components/icons/walk-icon.js
+++ /dev/null
@@ -1,14 +0,0 @@
-import React, { Component } from 'react'
-
-export default class WalkIcon extends Component {
- render () {
- return (
-
-
- )
- }
-}
diff --git a/lib/components/narrative/itinerary-carousel.js b/lib/components/narrative/itinerary-carousel.js
index ce7a373fa..c560362bd 100644
--- a/lib/components/narrative/itinerary-carousel.js
+++ b/lib/components/narrative/itinerary-carousel.js
@@ -8,9 +8,7 @@ import { setActiveItinerary, setActiveLeg, setActiveStep } from '../../actions/n
import Icon from './icon'
import DefaultItinerary from './default/default-itinerary'
import Loading from './loading'
-import NarrativeProfileSummary from './narrative-profile-summary'
import { getActiveItineraries, getActiveSearch } from '../../util/state'
-import { profileOptionsToItineraries } from '../../util/profile'
import { getTimeFormat } from '../../util/time'
class ItineraryCarousel extends Component {
@@ -26,8 +24,6 @@ class ItineraryCarousel extends Component {
setActiveLeg: PropTypes.func,
setActiveStep: PropTypes.func,
expanded: PropTypes.bool,
- showProfileSummary: PropTypes.bool,
- profileOptions: PropTypes.array,
companies: PropTypes.string
}
@@ -54,18 +50,11 @@ class ItineraryCarousel extends Component {
}
render () {
- const { activeItinerary, itineraries, itineraryClass, hideHeader, pending, showProfileSummary } = this.props
+ const { activeItinerary, itineraries, itineraryClass, hideHeader, pending } = this.props
if (pending) return
if (!itineraries) return null
- let views = []
- if (showProfileSummary) {
- views.push(
)
- }
- views = views.concat(itineraries.map((itinerary, index) => {
+ const views = itineraries.map((itinerary, index) => {
return React.createElement(itineraryClass, {
itinerary,
index,
@@ -74,7 +63,7 @@ class ItineraryCarousel extends Component {
onClick: this._onItineraryClick,
...this.props
})
- }))
+ })
return (
@@ -112,23 +101,13 @@ class ItineraryCarousel extends Component {
const mapStateToProps = (state, ownProps) => {
const activeSearch = getActiveSearch(state.otp)
- let itineraries = null
- let profileOptions = null
- let showProfileSummary = false
- if (activeSearch && activeSearch.response && activeSearch.response.plan) {
- itineraries = getActiveItineraries(state.otp)
- } else if (activeSearch && activeSearch.response && activeSearch.response.otp) {
- profileOptions = activeSearch.response.otp.profile
- itineraries = profileOptionsToItineraries(profileOptions)
- showProfileSummary = true
- }
+ const itineraries = activeSearch && activeSearch.response && activeSearch.response.plan
+ ? getActiveItineraries(state.otp)
+ : null
- const pending = activeSearch && activeSearch.pending
return {
itineraries,
- profileOptions,
- pending,
- showProfileSummary,
+ pending: activeSearch && activeSearch.pending,
activeItinerary: activeSearch && activeSearch.activeItinerary,
activeLeg: activeSearch && activeSearch.activeLeg,
activeStep: activeSearch && activeSearch.activeStep,
diff --git a/lib/components/narrative/narrative-routing-results.js b/lib/components/narrative/narrative-routing-results.js
new file mode 100644
index 000000000..2047d4cfb
--- /dev/null
+++ b/lib/components/narrative/narrative-routing-results.js
@@ -0,0 +1,55 @@
+import React, { Component } from 'react'
+import PropTypes from 'prop-types'
+import { connect } from 'react-redux'
+
+import Loading from './loading'
+import TabbedItineraries from './tabbed-itineraries'
+import ErrorMessage from '../form/error-message'
+
+import { getActiveSearch, getActiveItineraries } from '../../util/state'
+import { setMainPanelContent } from '../../actions/ui'
+
+class NarrativeRoutingResults extends Component {
+ static propTypes = {
+ customIcons: PropTypes.object,
+ itineraryClass: PropTypes.func,
+ routingType: PropTypes.string
+ }
+
+ componentDidUpdate (prevProps) {
+ if ((!prevProps.itineraries || prevProps.itineraries.length === 0) &&
+ (this.props.itineraries && this.props.itineraries.length > 0)) {
+ this.props.setMainPanelContent(null)
+ }
+ if (!prevProps.error && this.props.error) this.props.setMainPanelContent(null)
+ }
+
+ render () {
+ const { customIcons, error, itineraryClass, itineraryFooter, pending, routingType, itineraries, mainPanelContent } = this.props
+ if (pending) return
+ if (error) return
+ if (mainPanelContent) return null
+
+ return (
+ routingType === 'ITINERARY' &&
+
+ )
+ }
+}
+
+const mapStateToProps = (state, ownProps) => {
+ const activeSearch = getActiveSearch(state.otp)
+ return {
+ mainPanelContent: state.otp.ui.mainPanelContent,
+ error: activeSearch && activeSearch.response && activeSearch.response.error,
+ itineraries: getActiveItineraries(state.otp),
+ pending: activeSearch && activeSearch.pending,
+ routingType: activeSearch && activeSearch.query.routingType
+ }
+}
+
+const mapDispatchToProps = {
+ setMainPanelContent
+}
+
+export default connect(mapStateToProps, mapDispatchToProps)(NarrativeRoutingResults)
diff --git a/lib/index.js b/lib/index.js
index 8f8bdd6ae..5fb277044 100644
--- a/lib/index.js
+++ b/lib/index.js
@@ -16,7 +16,6 @@ import TileOverlay from './components/map/tile-overlay'
import ItineraryCarousel from './components/narrative/itinerary-carousel'
import LegDiagramPreview from './components/narrative/leg-diagram-preview'
import NarrativeItineraries from './components/narrative/narrative-itineraries'
-import NarrativeProfileOptions from './components/narrative/narrative-profile-options'
import NarrativeItinerary from './components/narrative/narrative-itinerary'
import NarrativeRoutingResults from './components/narrative/narrative-routing-results'
import RealtimeAnnotation from './components/narrative/realtime-annotation'
@@ -69,7 +68,6 @@ export {
LegDiagramPreview,
NarrativeItineraries,
NarrativeItinerary,
- NarrativeProfileOptions,
NarrativeRoutingResults,
RealtimeAnnotation,
SimpleRealtimeAnnotation,
From 36430381a9cabb26d2d8b3307770e1f61d452391 Mon Sep 17 00:00:00 2001
From: binh-dam-ibigroup <56846598+binh-dam-ibigroup@users.noreply.github.com>
Date: Fri, 3 Apr 2020 10:52:54 -0400
Subject: [PATCH 06/31] docs(default-search-form): Tweak comments.
---
lib/components/form/default-search-form.js | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/lib/components/form/default-search-form.js b/lib/components/form/default-search-form.js
index 31df598d8..299c19ef5 100644
--- a/lib/components/form/default-search-form.js
+++ b/lib/components/form/default-search-form.js
@@ -6,8 +6,8 @@ import LocationField from './connected-location-field'
import TabbedFormPanel from './tabbed-form-panel'
import SwitchButton from './switch-button'
-// As of OTP-ui 0.0.18, use the icons props
-// to override icons for certain modes in the mode selector panel.
+// Use the icons props to override icons for certain modes in the mode selector panel.
+// If no icon is provided for a specific mode, the default OTP-ui icon will be used.
const customIcons = {
TRANSIT:
}
From eeab320b4559230788a24a9939a4f56d6398468a Mon Sep 17 00:00:00 2001
From: binh-dam-ibigroup <56846598+binh-dam-ibigroup@users.noreply.github.com>
Date: Fri, 3 Apr 2020 11:08:14 -0400
Subject: [PATCH 07/31] fix: Fix linting errors and other print-layout merge.
---
lib/components/app/print-layout.js | 13 ++++---------
lib/components/form/default-search-form.js | 2 +-
.../narrative/line-itin/connected-itinerary-body.js | 2 --
3 files changed, 5 insertions(+), 12 deletions(-)
diff --git a/lib/components/app/print-layout.js b/lib/components/app/print-layout.js
index b90771cb1..2fda1815f 100644
--- a/lib/components/app/print-layout.js
+++ b/lib/components/app/print-layout.js
@@ -1,17 +1,15 @@
-import BaseMap from '@opentripplanner/base-map'
-import EndpointsOverlay from '@opentripplanner/endpoints-overlay'
import TriMetLegIcon from '@opentripplanner/icons/lib/trimet-leg-icon'
import PrintableItinerary from '@opentripplanner/printable-itinerary'
-import TransitiveOverlay from '@opentripplanner/transitive-overlay'
import PropTypes from 'prop-types'
import React, { Component } from 'react'
-import { connect } from 'react-redux'
import { Button } from 'react-bootstrap'
+import { connect } from 'react-redux'
import { parseUrlQueryString } from '../../actions/form'
import { routingQuery } from '../../actions/api'
-import { getActiveItinerary } from '../../util/state'
+import DefaultMap from '../map/default-map'
import TripDetails from '../narrative/connected-trip-details'
+import { getActiveItinerary } from '../../util/state'
class PrintLayout extends Component {
static propTypes = {
@@ -91,10 +89,7 @@ class PrintLayout extends Component {
{/* The map, if visible */}
{this.state.mapVisible &&
-
-
-
-
+
}
diff --git a/lib/components/form/default-search-form.js b/lib/components/form/default-search-form.js
index 299c19ef5..d6cf8a03a 100644
--- a/lib/components/form/default-search-form.js
+++ b/lib/components/form/default-search-form.js
@@ -7,7 +7,7 @@ import TabbedFormPanel from './tabbed-form-panel'
import SwitchButton from './switch-button'
// Use the icons props to override icons for certain modes in the mode selector panel.
-// If no icon is provided for a specific mode, the default OTP-ui icon will be used.
+// If no icon is provided for a specific mode, the default OTP-ui icon will be used.
const customIcons = {
TRANSIT:
}
diff --git a/lib/components/narrative/line-itin/connected-itinerary-body.js b/lib/components/narrative/line-itin/connected-itinerary-body.js
index 6ff8994d8..ff174e78f 100644
--- a/lib/components/narrative/line-itin/connected-itinerary-body.js
+++ b/lib/components/narrative/line-itin/connected-itinerary-body.js
@@ -5,7 +5,6 @@ import ItineraryBody from '@opentripplanner/itinerary-body/lib/otp-react-redux/i
import LineColumnContent from '@opentripplanner/itinerary-body/lib/otp-react-redux/line-column-content'
import PlaceName from '@opentripplanner/itinerary-body/lib/otp-react-redux/place-name'
import RouteDescription from '@opentripplanner/itinerary-body/lib/otp-react-redux/route-description'
-import TripDetails from '@opentripplanner/trip-details/lib'
import React, { Component } from 'react'
import { connect } from 'react-redux'
@@ -16,7 +15,6 @@ import TransitLegSubheader from './connected-transit-leg-subheader'
import TripDetails from '../connected-trip-details'
import TripTools from '../trip-tools'
-import TransitLegSubheader from './connected-transit-leg-subheader'
const noop = () => {}
From 0bc4d967742c826770b08a93512afa81bc050b2c Mon Sep 17 00:00:00 2001
From: binh-dam-ibigroup <56846598+binh-dam-ibigroup@users.noreply.github.com>
Date: Fri, 3 Apr 2020 11:09:55 -0400
Subject: [PATCH 08/31] fix: One more lint error fix.
---
lib/components/narrative/line-itin/connected-itinerary-body.js | 1 -
1 file changed, 1 deletion(-)
diff --git a/lib/components/narrative/line-itin/connected-itinerary-body.js b/lib/components/narrative/line-itin/connected-itinerary-body.js
index ff174e78f..9f2d1cf1d 100644
--- a/lib/components/narrative/line-itin/connected-itinerary-body.js
+++ b/lib/components/narrative/line-itin/connected-itinerary-body.js
@@ -15,7 +15,6 @@ import TransitLegSubheader from './connected-transit-leg-subheader'
import TripDetails from '../connected-trip-details'
import TripTools from '../trip-tools'
-
const noop = () => {}
class ConnectedItineraryBody extends Component {
From c781f67a30bcb5ed4bb8c98fbc628d4b2a06d23e Mon Sep 17 00:00:00 2001
From: binh-dam-ibigroup <56846598+binh-dam-ibigroup@users.noreply.github.com>
Date: Fri, 3 Apr 2020 17:54:11 -0400
Subject: [PATCH 09/31] fix(Temp commit with ItinSummary visible in desktop
mode.):
---
lib/components/app/default-main-panel.js | 3 +-
lib/components/icons/bike-icon.js | 19 +++
lib/components/icons/biketown-icon.js | 18 +++
lib/components/icons/bus-icon.js | 23 ++++
lib/components/icons/car2go-icon.js | 16 +++
lib/components/icons/direction-icon.js | 82 ++++++++++++
lib/components/icons/gondola-icon.js | 12 ++
lib/components/icons/index.js | 36 +++++
lib/components/icons/lyft-icon.js | 11 ++
lib/components/icons/rail-icon.js | 11 ++
lib/components/icons/reachnow-icon.js | 14 ++
lib/components/icons/streetcar-icon.js | 12 ++
lib/components/icons/tram-icon.js | 12 ++
lib/components/icons/transit-icon.js | 23 ++++
lib/components/icons/uber-icon.js | 14 ++
lib/components/icons/walk-icon.js | 14 ++
.../narrative/itinerary-carousel.js | 3 +-
.../narrative/line-itin/itin-summary.js | 123 ++++++++++++++++++
.../narrative/line-itin/line-itinerary.js | 77 +++++++++++
.../narrative/narrative-itineraries.js | 3 +-
.../narrative/tabbed-itineraries.js | 3 +-
21 files changed, 525 insertions(+), 4 deletions(-)
create mode 100644 lib/components/icons/bike-icon.js
create mode 100644 lib/components/icons/biketown-icon.js
create mode 100644 lib/components/icons/bus-icon.js
create mode 100644 lib/components/icons/car2go-icon.js
create mode 100644 lib/components/icons/direction-icon.js
create mode 100644 lib/components/icons/gondola-icon.js
create mode 100644 lib/components/icons/index.js
create mode 100644 lib/components/icons/lyft-icon.js
create mode 100644 lib/components/icons/rail-icon.js
create mode 100644 lib/components/icons/reachnow-icon.js
create mode 100644 lib/components/icons/streetcar-icon.js
create mode 100644 lib/components/icons/tram-icon.js
create mode 100644 lib/components/icons/transit-icon.js
create mode 100644 lib/components/icons/uber-icon.js
create mode 100644 lib/components/icons/walk-icon.js
create mode 100644 lib/components/narrative/line-itin/itin-summary.js
create mode 100644 lib/components/narrative/line-itin/line-itinerary.js
diff --git a/lib/components/app/default-main-panel.js b/lib/components/app/default-main-panel.js
index ed3de24b6..9333c9ff1 100644
--- a/lib/components/app/default-main-panel.js
+++ b/lib/components/app/default-main-panel.js
@@ -8,13 +8,14 @@ import PlanTripButton from '../form/plan-trip-button'
import UserSettings from '../form/user-settings'
import NarrativeRoutingResults from '../narrative/narrative-routing-results'
import { getActiveSearch, getShowUserSettings } from '../../util/state'
+import defaultIcons from '../icons'
class DefaultMainPanel extends Component {
render () {
const {
activeSearch,
currentQuery,
- customIcons,
+ customIcons = defaultIcons,
itineraryClass,
itineraryFooter,
mainPanelContent,
diff --git a/lib/components/icons/bike-icon.js b/lib/components/icons/bike-icon.js
new file mode 100644
index 000000000..c97d0de98
--- /dev/null
+++ b/lib/components/icons/bike-icon.js
@@ -0,0 +1,19 @@
+import React, { Component } from 'react'
+
+export default class BikeIcon extends Component {
+ render () {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+ )
+ }
+}
diff --git a/lib/components/icons/biketown-icon.js b/lib/components/icons/biketown-icon.js
new file mode 100644
index 000000000..50fcefac7
--- /dev/null
+++ b/lib/components/icons/biketown-icon.js
@@ -0,0 +1,18 @@
+import React, { Component } from 'react'
+
+export default class BiketownIcon extends Component {
+ render () {
+ return (
+
+
+
+
+
+
+
+
+
+
+ )
+ }
+}
diff --git a/lib/components/icons/bus-icon.js b/lib/components/icons/bus-icon.js
new file mode 100644
index 000000000..64bbcaf71
--- /dev/null
+++ b/lib/components/icons/bus-icon.js
@@ -0,0 +1,23 @@
+import React, { Component } from 'react'
+
+export default class BusIcon extends Component {
+ render () {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ )
+ }
+}
diff --git a/lib/components/icons/car2go-icon.js b/lib/components/icons/car2go-icon.js
new file mode 100644
index 000000000..fe4c01f3d
--- /dev/null
+++ b/lib/components/icons/car2go-icon.js
@@ -0,0 +1,16 @@
+import React, { Component } from 'react'
+
+export default class Car2goIcon extends Component {
+ render () {
+ return (
+
>
+
+
+
+
+
+
+
+ )
+ }
+}
diff --git a/lib/components/icons/direction-icon.js b/lib/components/icons/direction-icon.js
new file mode 100644
index 000000000..3203d1e1c
--- /dev/null
+++ b/lib/components/icons/direction-icon.js
@@ -0,0 +1,82 @@
+import React, { Component } from 'react'
+
+export default class DirectionIcon extends Component {
+ render () {
+ const { relativeDirection } = this.props
+ if (!relativeDirection) return null
+ switch (relativeDirection.toUpperCase()) {
+ case 'DEPART':
+ case 'CONTINUE': return (
+
+
+
+ )
+ case 'LEFT': return (
+
+
+
+ )
+ case 'RIGHT': return (
+
+
+
+ )
+ case 'SLIGHTLY_LEFT': return (
+
+
+
+ )
+ case 'SLIGHTLY_RIGHT': return (
+
+
+
+ )
+ case 'HARD_LEFT': return (
+
+
+
+ )
+ case 'HARD_RIGHT': return (
+
+
+
+ )
+ case 'UTURN_LEFT': return (
+
+
+
+ )
+ case 'UTURN_RIGHT': return (
+
+
+
+ )
+ case 'CIRCLE_CLOCKWISE': return (
+
+
+
+
+
+
+
+
+ )
+ case 'CIRCLE_COUNTERCLOCKWISE': return (
+
+
+
+
+
+
+
+
+ )
+ case 'ELEVATOR': return (
+
+
+
+ )
+ }
+ return null
+ }
+}
diff --git a/lib/components/icons/gondola-icon.js b/lib/components/icons/gondola-icon.js
new file mode 100644
index 000000000..d14bcb744
--- /dev/null
+++ b/lib/components/icons/gondola-icon.js
@@ -0,0 +1,12 @@
+import React, { Component } from 'react'
+
+export default class GondolaIcon extends Component {
+ render () {
+ return (
+
+
+
+
+ )
+ }
+}
diff --git a/lib/components/icons/index.js b/lib/components/icons/index.js
new file mode 100644
index 000000000..8bdf35517
--- /dev/null
+++ b/lib/components/icons/index.js
@@ -0,0 +1,36 @@
+import React from 'react'
+
+import BikeIcon from './bike-icon'
+import BiketownIcon from './biketown-icon'
+import BusIcon from './bus-icon'
+import Car2goIcon from './car2go-icon'
+import ReachNowIcon from './reachnow-icon'
+import GondolaIcon from './gondola-icon'
+import LyftIcon from './lyft-icon'
+import RailIcon from './rail-icon'
+import StreetcarIcon from './streetcar-icon'
+import TramIcon from './tram-icon'
+import TransitIcon from './transit-icon'
+import UberIcon from './uber-icon'
+import WalkIcon from './walk-icon'
+
+// define Portland-specific mode icons
+export default {
+ BICYCLE:
,
+ BICYCLE_RENT:
,
+ BUS:
,
+ CAR_HAIL_LYFT:
,
+ CAR_HAIL_UBER:
,
+ CAR_RENT_CAR2GO:
,
+ CAR_RENT_REACHNOW:
,
+ GONDOLA:
,
+ RAIL:
,
+ STREETCAR:
,
+ TRAM:
,
+ TRANSIT:
,
+ WALK:
,
+ customModeForLeg: (leg) => {
+ if (leg.routeLongName && leg.routeLongName.startsWith('Portland Streetcar')) return 'STREETCAR'
+ return null
+ }
+}
diff --git a/lib/components/icons/lyft-icon.js b/lib/components/icons/lyft-icon.js
new file mode 100644
index 000000000..add6801bf
--- /dev/null
+++ b/lib/components/icons/lyft-icon.js
@@ -0,0 +1,11 @@
+import React, { Component } from 'react'
+
+export default class LyftIcon extends Component {
+ render () {
+ return (
+
+
+
+ )
+ }
+}
diff --git a/lib/components/icons/rail-icon.js b/lib/components/icons/rail-icon.js
new file mode 100644
index 000000000..8f2ab99d6
--- /dev/null
+++ b/lib/components/icons/rail-icon.js
@@ -0,0 +1,11 @@
+import React, { Component } from 'react'
+
+export default class RailIcon extends Component {
+ render () {
+ return (
+
+
+
+ )
+ }
+}
diff --git a/lib/components/icons/reachnow-icon.js b/lib/components/icons/reachnow-icon.js
new file mode 100644
index 000000000..bab628729
--- /dev/null
+++ b/lib/components/icons/reachnow-icon.js
@@ -0,0 +1,14 @@
+import React, { Component } from 'react'
+
+export default class ReachNowIcon extends Component {
+ render () {
+ return (
+
+
+
+
+
+
+ )
+ }
+}
diff --git a/lib/components/icons/streetcar-icon.js b/lib/components/icons/streetcar-icon.js
new file mode 100644
index 000000000..e53550142
--- /dev/null
+++ b/lib/components/icons/streetcar-icon.js
@@ -0,0 +1,12 @@
+import React, { Component } from 'react'
+
+export default class StreetcarIcon extends Component {
+ render () {
+ return (
+
+
+
+
+ )
+ }
+}
diff --git a/lib/components/icons/tram-icon.js b/lib/components/icons/tram-icon.js
new file mode 100644
index 000000000..10e69e931
--- /dev/null
+++ b/lib/components/icons/tram-icon.js
@@ -0,0 +1,12 @@
+import React, { Component } from 'react'
+
+export default class TramIcon extends Component {
+ render () {
+ return (
+
+
+
+
+ )
+ }
+}
diff --git a/lib/components/icons/transit-icon.js b/lib/components/icons/transit-icon.js
new file mode 100644
index 000000000..d2e96487c
--- /dev/null
+++ b/lib/components/icons/transit-icon.js
@@ -0,0 +1,23 @@
+import React, { Component } from 'react'
+
+export default class TransitIcon extends Component {
+ render () {
+ // TODO: Find a better general transit icon to use than the bus icon.
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ )
+ }
+}
diff --git a/lib/components/icons/uber-icon.js b/lib/components/icons/uber-icon.js
new file mode 100644
index 000000000..77daea91a
--- /dev/null
+++ b/lib/components/icons/uber-icon.js
@@ -0,0 +1,14 @@
+import React, { Component } from 'react'
+
+export default class UberIcon extends Component {
+ render () {
+ return (
+
+
+
+
+
+
+ )
+ }
+}
diff --git a/lib/components/icons/walk-icon.js b/lib/components/icons/walk-icon.js
new file mode 100644
index 000000000..a071dcfa4
--- /dev/null
+++ b/lib/components/icons/walk-icon.js
@@ -0,0 +1,14 @@
+import React, { Component } from 'react'
+
+export default class WalkIcon extends Component {
+ render () {
+ return (
+
+
+
+
+
+
+ )
+ }
+}
diff --git a/lib/components/narrative/itinerary-carousel.js b/lib/components/narrative/itinerary-carousel.js
index c560362bd..494d5f2b8 100644
--- a/lib/components/narrative/itinerary-carousel.js
+++ b/lib/components/narrative/itinerary-carousel.js
@@ -7,6 +7,7 @@ import SwipeableViews from 'react-swipeable-views'
import { setActiveItinerary, setActiveLeg, setActiveStep } from '../../actions/narrative'
import Icon from './icon'
import DefaultItinerary from './default/default-itinerary'
+import LineItinerary from './line-itin/line-itinerary'
import Loading from './loading'
import { getActiveItineraries, getActiveSearch } from '../../util/state'
import { getTimeFormat } from '../../util/time'
@@ -28,7 +29,7 @@ class ItineraryCarousel extends Component {
}
static defaultProps = {
- itineraryClass: DefaultItinerary
+ itineraryClass: LineItinerary // DefaultItinerary
}
_onItineraryClick = () => {
diff --git a/lib/components/narrative/line-itin/itin-summary.js b/lib/components/narrative/line-itin/itin-summary.js
new file mode 100644
index 000000000..6d211b258
--- /dev/null
+++ b/lib/components/narrative/line-itin/itin-summary.js
@@ -0,0 +1,123 @@
+import TriMetModeIcon from '@opentripplanner/icons/lib/trimet-mode-icon'
+import React, { Component } from 'react'
+import PropTypes from 'prop-types'
+
+import { calculateFares, calculatePhysicalActivity, isTransit } from '../../../util/itinerary'
+import { formatDuration, formatTime } from '../../../util/time'
+
+// TODO: make this a prop
+const defaultRouteColor = '#008'
+
+export default class ItinerarySummary extends Component {
+ static propTypes = {
+ itinerary: PropTypes.object
+ }
+
+ getIcon = (iconId, customIcons) => {
+ // Check if there is a custom icon
+ if (customIcons && iconId in customIcons) {
+ return customIcons[iconId]
+ }
+
+ // Custom icon not available for the given iconId. Use the ModeIcon component
+ // to show the icon based on the iconId, but always use the default car icon
+ // for any car-based modes that didn't have custom icon
+ if (iconId && iconId.startsWith('CAR')) iconId = 'CAR'
+ return
+ }
+
+ _onSummaryClicked = () => {
+ if (typeof this.props.onClick === 'function') this.props.onClick()
+ }
+
+ render () {
+ const { customIcons, itinerary, timeOptions } = this.props
+ const {
+ centsToString,
+ maxTNCFare,
+ minTNCFare,
+ transitFare
+ } = calculateFares(itinerary)
+ // TODO: support non-USD
+ const minTotalFare = minTNCFare * 100 + transitFare
+ const maxTotalFare = maxTNCFare * 100 + transitFare
+
+ const { caloriesBurned } = calculatePhysicalActivity(itinerary)
+
+ return (
+
+
+ {/* Travel time in hrs/mins */}
+
{formatDuration(itinerary.duration)}
+
+ {/* Duration as time range */}
+
+ {formatTime(itinerary.startTime, timeOptions)} - {formatTime(itinerary.endTime, timeOptions)}
+
+
+ {/* Fare / Calories */}
+
+ {minTotalFare > 0 &&
+ {centsToString(minTotalFare)}
+ {minTotalFare !== maxTotalFare && - {centsToString(maxTotalFare)} }
+ •
+ }
+ {Math.round(caloriesBurned)} Cals
+
+
+ {/* Number of transfers, if applicable */}
+ {itinerary.transfers > 0 && (
+
+ {itinerary.transfers} transfer{itinerary.transfers > 1 ? 's' : ''}
+
+ )}
+
+
+
+ {itinerary.legs.filter(leg => {
+ return !(leg.mode === 'WALK' && itinerary.transitTime > 0)
+ }).map((leg, k) => {
+ return
+
{this.getIcon(leg.mode, customIcons)}
+ {isTransit(leg.mode)
+ ? (
+
+ {getRouteNameForBadge(leg)}
+
+ )
+ : (
)
+ }
+
+ })}
+
+
+ )
+ }
+}
+
+// Helper functions
+
+function getRouteLongName (leg) {
+ return leg.routes && leg.routes.length > 0
+ ? leg.routes[0].longName
+ : leg.routeLongName
+}
+
+function getRouteNameForBadge (leg) {
+ const shortName = leg.routes && leg.routes.length > 0
+ ? leg.routes[0].shortName : leg.routeShortName
+
+ const longName = getRouteLongName(leg)
+
+ // check for max
+ if (longName && longName.toLowerCase().startsWith('max')) return null
+
+ // check for streetcar
+ if (longName && longName.startsWith('Portland Streetcar')) return longName.split('-')[1].trim().split(' ')[0]
+
+ return shortName || longName
+}
+
+function getRouteColorForBadge (leg) {
+ return leg.routeColor ? '#' + leg.routeColor : defaultRouteColor
+}
diff --git a/lib/components/narrative/line-itin/line-itinerary.js b/lib/components/narrative/line-itin/line-itinerary.js
new file mode 100644
index 000000000..2ca69e267
--- /dev/null
+++ b/lib/components/narrative/line-itin/line-itinerary.js
@@ -0,0 +1,77 @@
+import React from 'react'
+
+import NarrativeItinerary from '../narrative-itinerary'
+import SimpleRealtimeAnnotation from '../simple-realtime-annotation'
+import { getLegModeLabel, getTimeZoneOffset, isTransit } from '../../../util/itinerary'
+
+import ItinerarySummary from './itin-summary'
+import ItineraryBody from './connected-itinerary-body'
+
+export default class LineItinerary extends NarrativeItinerary {
+ _headerText () {
+ const { itinerary } = this.props
+ return itinerary.summary || this._getSummary(itinerary)
+ }
+
+ _getSummary (itinerary) {
+ let summary = ''
+ let transitModes = []
+ itinerary.legs.forEach((leg, index) => {
+ if (isTransit(leg.mode)) {
+ const modeStr = getLegModeLabel(leg)
+ if (transitModes.indexOf(modeStr) === -1) transitModes.push(modeStr)
+ }
+ })
+
+ // check for access mode
+ if (!isTransit(itinerary.legs[0].mode)) {
+ summary += getLegModeLabel(itinerary.legs[0])
+ }
+
+ // append transit modes, if applicable
+ if (transitModes.length > 0) {
+ summary += ' to ' + transitModes.join(', ')
+ }
+
+ return summary
+ }
+
+ render () {
+ const {
+ active,
+ companies,
+ customIcons,
+ expanded,
+ itinerary,
+ itineraryFooter,
+ showRealtimeAnnotation,
+ onClick,
+ timeFormat
+ } = this.props
+
+ if (!itinerary) {
+ return
No Itinerary!
+ }
+
+ const timeOptions = {
+ format: timeFormat,
+ offset: getTimeZoneOffset(itinerary)
+ }
+
+ return (
+
+
+ {showRealtimeAnnotation && }
+ {active || expanded
+ ?
+ : null}
+ {itineraryFooter}
+
+ )
+ }
+}
diff --git a/lib/components/narrative/narrative-itineraries.js b/lib/components/narrative/narrative-itineraries.js
index 318c107ee..4c43ef1bf 100644
--- a/lib/components/narrative/narrative-itineraries.js
+++ b/lib/components/narrative/narrative-itineraries.js
@@ -9,6 +9,7 @@ import {
setUseRealtimeResponse
} from '../../actions/narrative'
import DefaultItinerary from './default/default-itinerary'
+import LineItinerary from './line-itin/line-itinerary'
import { getActiveItineraries, getActiveSearch, getRealtimeEffects } from '../../util/state'
import RealtimeAnnotation from './realtime-annotation'
@@ -27,7 +28,7 @@ class NarrativeItineraries extends Component {
}
static defaultProps = {
- itineraryClass: DefaultItinerary
+ itineraryClass: LineItinerary // DefaultItinerary
}
_toggleRealtimeItineraryClick = (e) => {
diff --git a/lib/components/narrative/tabbed-itineraries.js b/lib/components/narrative/tabbed-itineraries.js
index f3c4e2d76..e9d82355c 100644
--- a/lib/components/narrative/tabbed-itineraries.js
+++ b/lib/components/narrative/tabbed-itineraries.js
@@ -5,6 +5,7 @@ import { Button } from 'react-bootstrap'
import { setActiveItinerary, setActiveLeg, setActiveStep, setUseRealtimeResponse } from '../../actions/narrative'
import DefaultItinerary from './default/default-itinerary'
+import LineItinerary from './line-itin/line-itinerary'
import { getActiveSearch, getRealtimeEffects } from '../../util/state'
import { calculateFares, calculatePhysicalActivity, getTimeZoneOffset } from '../../util/itinerary'
import { formatDuration, formatTime, getTimeFormat } from '../../util/time'
@@ -23,7 +24,7 @@ class TabbedItineraries extends Component {
}
static defaultProps = {
- itineraryClass: DefaultItinerary
+ itineraryClass: LineItinerary // DefaultItinerary
}
_toggleRealtimeItineraryClick = (e) => {
From 32cc8ba5c7f8a458644822fbad8bb4fc43d8a6ef Mon Sep 17 00:00:00 2001
From: binh-dam-ibigroup <56846598+binh-dam-ibigroup@users.noreply.github.com>
Date: Mon, 6 Apr 2020 15:22:09 -0400
Subject: [PATCH 10/31] feat(line-itin/itineray.css): Reinstate file.
---
lib/components/app/default-main-panel.js | 4 +-
.../narrative/line-itin/itinerary.css | 375 ++++++++++++++++++
lib/index.css | 1 +
3 files changed, 378 insertions(+), 2 deletions(-)
create mode 100644 lib/components/narrative/line-itin/itinerary.css
diff --git a/lib/components/app/default-main-panel.js b/lib/components/app/default-main-panel.js
index 9333c9ff1..720c132c0 100644
--- a/lib/components/app/default-main-panel.js
+++ b/lib/components/app/default-main-panel.js
@@ -8,14 +8,14 @@ import PlanTripButton from '../form/plan-trip-button'
import UserSettings from '../form/user-settings'
import NarrativeRoutingResults from '../narrative/narrative-routing-results'
import { getActiveSearch, getShowUserSettings } from '../../util/state'
-import defaultIcons from '../icons'
+//import defaultIcons from '../icons'
class DefaultMainPanel extends Component {
render () {
const {
activeSearch,
currentQuery,
- customIcons = defaultIcons,
+ customIcons, // = defaultIcons,
itineraryClass,
itineraryFooter,
mainPanelContent,
diff --git a/lib/components/narrative/line-itin/itinerary.css b/lib/components/narrative/line-itin/itinerary.css
new file mode 100644
index 000000000..89df3acf0
--- /dev/null
+++ b/lib/components/narrative/line-itin/itinerary.css
@@ -0,0 +1,375 @@
+.otp .options.profile .itin-body .place-row {
+ margin-left: 55px;
+}
+
+.otp .line-itin {
+ margin-bottom: 20px;
+}
+
+/* Itinerary summary */
+
+.otp .line-itin .itin-summary {
+ padding-right: 5px;
+ height: 60px;
+ display: table;
+ width: 100%;
+ margin-bottom: 15px;
+}
+
+.otp .desktop-narrative-container .options.itinerary .line-itin .itin-summary {
+ display: none;
+}
+
+.otp .line-itin .itin-summary .details {
+ display: table-cell;
+ vertical-align: top;
+}
+
+.otp .line-itin .itin-summary .header {
+ font-weight: bold;
+ font-size: 18px;
+ margin-top: -3px;
+}
+
+.otp .line-itin .itin-summary .detail {
+ font-size: 13px;
+ color: #999999;
+}
+
+.otp .line-itin .itin-summary .routes {
+ display: table-cell;
+ text-align: right;
+}
+
+.otp .line-itin .itin-summary .routes .route-preview {
+ display: inline-block;
+ margin-left: 8px;
+ vertical-align: top;
+}
+
+.otp .line-itin .itin-summary .routes .route-preview .mode-icon {
+ height: 30px;
+ width: 30px;
+}
+
+.otp .line-itin .itin-summary .routes .route-preview .short-name {
+ color: white;
+ font-weight: 500;
+ text-align: center;
+ margin-top: 6px;
+ font-size: 15px;
+ padding-top: 2px;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ overflow: hidden;
+ width: 30px;
+ height: 30px;
+ border-radius: 15px;
+ border: 2px solid white;
+ box-shadow: 0 0 0.5em #000;
+}
+
+/* Itinerary main body */
+
+.otp .line-itin .itin-body {
+ padding: 20px 0px;
+}
+
+.otp .line-itin .place-row {
+ display: table;
+ width: 100%;
+}
+
+
+/* Departure/arrival time (1st column in table) */
+
+.otp .line-itin .time {
+ display: table-cell;
+ width: 60px;
+ font-size: 14px;
+ color: #999999;
+ text-align: right;
+ padding-right: 4px;
+ padding-top: 1px;
+ vertical-align: top;
+}
+
+/* The place icon and line itself (2nd column in table) */
+.otp .line-itin .line-container {
+ position: relative;
+ display: table-cell;
+ width: 20px;
+ max-width: 20px;
+}
+
+.otp .line-itin .place-icon-group {
+ position: absolute;
+ font-size: 18px;
+ left: -8px;
+ top: -7px;
+ z-index: 20;
+}
+
+.otp .line-itin .leg-line {
+ position: absolute;
+ top: 11px;
+ bottom: -11px;
+ z-index: 10;
+}
+
+// Internet explorer specific media query to apply the below styling to fix
+// rendering issues with table cell display with undefined heights.
+/*@media screen and (-ms-high-contrast: active), (-ms-high-contrast: none) {
+ .otp .line-itin .line-container {
+ overflow: hidden; // hack for IE to render table cell correctly.
+ }
+
+ .otp .line-itin .leg-line {
+ height: 1000px; // hack for IE to render table cell correctly.
+ }
+}*/
+
+.otp .line-itin .leg-line-walk {
+ left: 6px;
+ right: 6px;
+ background: radial-gradient(ellipse at center, #87cefa 40%, transparent 10%);
+ background-size: 12px 12px;
+ background-repeat: repeat-y;
+ background-position: center -5px;
+}
+
+.otp .line-itin .leg-line-bicycle {
+ left: 7.5px;
+ right: 7.5px;
+ background: repeating-linear-gradient(
+ 0deg,
+ red,
+ red 8px,
+ white 8px,
+ white 12.5px
+ );
+}
+
+.otp .line-itin .leg-line-car {
+ left: 7.5px;
+ right: 7.5px;
+ background: repeating-linear-gradient(
+ 0deg,
+ grey,
+ grey 8px,
+ white 8px,
+ white 12.5px
+ );
+}
+
+.otp .line-itin .leg-line-micromobility {
+ left: 7.5px;
+ right: 7.5px;
+ background: repeating-linear-gradient(
+ 0deg,
+ #f5a729,
+ #f5a729 8px,
+ white 8px,
+ white 12.5px
+ );
+}
+
+.otp .line-itin .leg-line-transit {
+ left: 5px;
+ right: 5px;
+ background-color: gray;
+}
+
+/* Place/Leg details (3rd column in table) */
+
+.otp .line-itin .place-details {
+ font-size: 13px;
+ display: table-cell;
+ padding-top: 1px;
+}
+
+.otp .line-itin .place-name {
+ font-size: 18px;
+ line-height: 20px;
+ padding-left: 4px;
+ font-weight: 500;
+ color: black;
+}
+
+.otp .line-itin .place-subheader {
+ font-size: 12px;
+ padding-left: 4px;
+ padding-top: 1px;
+ font-weight: 300;
+ color: gray;
+}
+
+.otp .line-itin .interline-dot {
+ position: relative;
+ float: left;
+ margin-left: -13.5px;
+ z-index: 25;
+ color: #fff;
+}
+
+.otp .line-itin .interline-name {
+ font-size: 14px;
+ font-weight: 400;
+ line-height: 16px;
+}
+
+/* Leg body general */
+
+.otp .line-itin .leg-body {
+ padding: 12px 0px 18px 4px;
+ font-size: 13px;
+ color: #999999;
+}
+
+.otp .line-itin .summary {
+ cursor: pointer;
+}
+
+.otp .line-itin .leg-body .icon {
+ height: 24px;
+ width: 24px;
+ float: left;
+ margin-right: 6px;
+}
+
+.otp .line-itin .leg-body .leg-description {
+ display: table;
+}
+
+.otp .line-itin .leg-body .leg-description > div {
+ display: table-cell;
+ vertical-align: middle;
+}
+
+/* Leg steps (for turn-by-turn) */
+
+.otp .line-itin .leg-body .steps-header {
+ font-size: 13px;
+ margin-top: 10px;
+ color: #999999;
+ font-style: normal;
+ display: inline-block;
+}
+
+.otp .line-itin .leg-body .step-row {
+ font-size: 13px;
+ margin-top: 8px;
+ color: #999999;
+ font-style: normal;
+}
+
+/* Transit leg details */
+
+.otp .line-itin .leg-body .route-name {
+ color: #999999;
+ margin-top: 5px;
+}
+
+.otp .line-itin .leg-body .route-short-name {
+ display: inline-block;
+ background-color: #0f6aac;
+ padding-top: 1px;
+ color: white;
+ font-weight: 500;
+ font-size: 14px;
+ margin-right: 6px;
+ text-align: center;
+ width: 24px;
+ height: 24px;
+ border-radius: 12px;
+ border: 1px solid white;
+ box-shadow: 0 0 0.25em #000;
+ margin-right: 8px;
+}
+
+.otp .line-itin .leg-body .route-long-name {
+ font-size: 13px;
+ line-height: 16px;
+ font-weight: 500;
+}
+
+.otp .line-itin .leg-body .transit-leg-details {
+ margin-top: 5px;
+}
+
+.otp .line-itin .leg-body .agency-info {
+ margin-top: 5px;
+
+}
+
+.otp .line-itin .leg-body .transit-leg-details .header {
+ cursor: pointer;
+ color: #999999;
+ font-size: 13px;
+}
+
+/* Intermediate stops */
+
+.otp .line-itin .leg-body .transit-leg-details .intermediate-stops .stop-row {
+ z-index: 30;
+ position: relative;
+}
+
+.otp .line-itin .leg-body .transit-leg-details .intermediate-stops .stop-marker {
+ float: left;
+ margin-left: -17px;
+ color: white;
+}
+
+.otp .line-itin .leg-body .transit-leg-details .intermediate-stops .stop-name {
+ color: #999999;
+ font-size: 14px;
+ margin-top: 3px;
+}
+
+/* Transit alerts */
+
+.otp .line-itin .leg-body .transit-alerts-toggle {
+ display: inline-block;
+ margin-top: 8px;
+ color: #D14727;
+ font-weight: 400;
+ cursor: pointer;
+}
+
+.otp .line-itin .leg-body .transit-alerts {
+ margin-top: 3px;
+}
+
+.otp .line-itin .leg-body .transit-alerts .transit-alert {
+ margin-top: 5px;
+ background-color: #eee;
+ padding: 8px;
+ color: black;
+ border-radius: 4px;
+}
+
+.otp .line-itin .leg-body .transit-alerts .transit-alert .alert-icon {
+ float: left;
+ font-size: 18px;
+}
+
+.otp .line-itin .leg-body .transit-alerts .transit-alert .alert-header {
+ font-size: 14px;
+ margin-left: 30px;
+ font-weight: 600;
+}
+
+.otp .line-itin .leg-body .transit-alerts .transit-alert .alert-body {
+ font-size: 12px;
+ margin-left: 30px;
+ /* white space pre-wrap is required to render line breaks correctly. */
+ white-space: pre-wrap;
+}
+
+.otp .line-itin .leg-body .transit-alerts .transit-alert .effective-date {
+ margin-top: 5px;
+ margin-left: 30px;
+ font-size: 12px;
+ font-style: italic;
+}
diff --git a/lib/index.css b/lib/index.css
index d768385b0..0fe0005bc 100644
--- a/lib/index.css
+++ b/lib/index.css
@@ -11,6 +11,7 @@
@import url(lib/components/form/form.css);
@import url(lib/components/narrative/narrative.css);
@import url(lib/components/narrative/default/itinerary.css);
+@import url(lib/components/narrative/line-itin/itinerary.css);
@import url(lib/components/mobile/mobile.css);
@import url(lib/components/viewers/viewers.css);
From 48a9544a64e1770bfab44b5fd16c34098e9516fb Mon Sep 17 00:00:00 2001
From: binh-dam-ibigroup <56846598+binh-dam-ibigroup@users.noreply.github.com>
Date: Mon, 6 Apr 2020 15:39:16 -0400
Subject: [PATCH 11/31] refactor(icons): Remove unused old icons.
---
lib/components/app/default-main-panel.js | 3 +-
lib/components/icons/bike-icon.js | 19 ------
lib/components/icons/biketown-icon.js | 18 ------
lib/components/icons/bus-icon.js | 23 -------
lib/components/icons/car2go-icon.js | 16 -----
lib/components/icons/direction-icon.js | 82 ------------------------
lib/components/icons/gondola-icon.js | 12 ----
lib/components/icons/index.js | 36 -----------
lib/components/icons/lyft-icon.js | 11 ----
lib/components/icons/rail-icon.js | 11 ----
lib/components/icons/reachnow-icon.js | 14 ----
lib/components/icons/streetcar-icon.js | 12 ----
lib/components/icons/tram-icon.js | 12 ----
lib/components/icons/transit-icon.js | 23 -------
lib/components/icons/uber-icon.js | 14 ----
lib/components/icons/walk-icon.js | 14 ----
16 files changed, 1 insertion(+), 319 deletions(-)
delete mode 100644 lib/components/icons/bike-icon.js
delete mode 100644 lib/components/icons/biketown-icon.js
delete mode 100644 lib/components/icons/bus-icon.js
delete mode 100644 lib/components/icons/car2go-icon.js
delete mode 100644 lib/components/icons/direction-icon.js
delete mode 100644 lib/components/icons/gondola-icon.js
delete mode 100644 lib/components/icons/index.js
delete mode 100644 lib/components/icons/lyft-icon.js
delete mode 100644 lib/components/icons/rail-icon.js
delete mode 100644 lib/components/icons/reachnow-icon.js
delete mode 100644 lib/components/icons/streetcar-icon.js
delete mode 100644 lib/components/icons/tram-icon.js
delete mode 100644 lib/components/icons/transit-icon.js
delete mode 100644 lib/components/icons/uber-icon.js
delete mode 100644 lib/components/icons/walk-icon.js
diff --git a/lib/components/app/default-main-panel.js b/lib/components/app/default-main-panel.js
index 720c132c0..ed3de24b6 100644
--- a/lib/components/app/default-main-panel.js
+++ b/lib/components/app/default-main-panel.js
@@ -8,14 +8,13 @@ import PlanTripButton from '../form/plan-trip-button'
import UserSettings from '../form/user-settings'
import NarrativeRoutingResults from '../narrative/narrative-routing-results'
import { getActiveSearch, getShowUserSettings } from '../../util/state'
-//import defaultIcons from '../icons'
class DefaultMainPanel extends Component {
render () {
const {
activeSearch,
currentQuery,
- customIcons, // = defaultIcons,
+ customIcons,
itineraryClass,
itineraryFooter,
mainPanelContent,
diff --git a/lib/components/icons/bike-icon.js b/lib/components/icons/bike-icon.js
deleted file mode 100644
index c97d0de98..000000000
--- a/lib/components/icons/bike-icon.js
+++ /dev/null
@@ -1,19 +0,0 @@
-import React, { Component } from 'react'
-
-export default class BikeIcon extends Component {
- render () {
- return (
-
-
-
-
-
-
-
-
-
-
-
- )
- }
-}
diff --git a/lib/components/icons/biketown-icon.js b/lib/components/icons/biketown-icon.js
deleted file mode 100644
index 50fcefac7..000000000
--- a/lib/components/icons/biketown-icon.js
+++ /dev/null
@@ -1,18 +0,0 @@
-import React, { Component } from 'react'
-
-export default class BiketownIcon extends Component {
- render () {
- return (
-
-
-
-
-
-
-
-
-
-
- )
- }
-}
diff --git a/lib/components/icons/bus-icon.js b/lib/components/icons/bus-icon.js
deleted file mode 100644
index 64bbcaf71..000000000
--- a/lib/components/icons/bus-icon.js
+++ /dev/null
@@ -1,23 +0,0 @@
-import React, { Component } from 'react'
-
-export default class BusIcon extends Component {
- render () {
- return (
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- )
- }
-}
diff --git a/lib/components/icons/car2go-icon.js b/lib/components/icons/car2go-icon.js
deleted file mode 100644
index fe4c01f3d..000000000
--- a/lib/components/icons/car2go-icon.js
+++ /dev/null
@@ -1,16 +0,0 @@
-import React, { Component } from 'react'
-
-export default class Car2goIcon extends Component {
- render () {
- return (
-
>
-
-
-
-
-
-
-
- )
- }
-}
diff --git a/lib/components/icons/direction-icon.js b/lib/components/icons/direction-icon.js
deleted file mode 100644
index 3203d1e1c..000000000
--- a/lib/components/icons/direction-icon.js
+++ /dev/null
@@ -1,82 +0,0 @@
-import React, { Component } from 'react'
-
-export default class DirectionIcon extends Component {
- render () {
- const { relativeDirection } = this.props
- if (!relativeDirection) return null
- switch (relativeDirection.toUpperCase()) {
- case 'DEPART':
- case 'CONTINUE': return (
-
-
-
- )
- case 'LEFT': return (
-
-
-
- )
- case 'RIGHT': return (
-
-
-
- )
- case 'SLIGHTLY_LEFT': return (
-
-
-
- )
- case 'SLIGHTLY_RIGHT': return (
-
-
-
- )
- case 'HARD_LEFT': return (
-
-
-
- )
- case 'HARD_RIGHT': return (
-
-
-
- )
- case 'UTURN_LEFT': return (
-
-
-
- )
- case 'UTURN_RIGHT': return (
-
-
-
- )
- case 'CIRCLE_CLOCKWISE': return (
-
-
-
-
-
-
-
-
- )
- case 'CIRCLE_COUNTERCLOCKWISE': return (
-
-
-
-
-
-
-
-
- )
- case 'ELEVATOR': return (
-
-
-
- )
- }
- return null
- }
-}
diff --git a/lib/components/icons/gondola-icon.js b/lib/components/icons/gondola-icon.js
deleted file mode 100644
index d14bcb744..000000000
--- a/lib/components/icons/gondola-icon.js
+++ /dev/null
@@ -1,12 +0,0 @@
-import React, { Component } from 'react'
-
-export default class GondolaIcon extends Component {
- render () {
- return (
-
-
-
-
- )
- }
-}
diff --git a/lib/components/icons/index.js b/lib/components/icons/index.js
deleted file mode 100644
index 8bdf35517..000000000
--- a/lib/components/icons/index.js
+++ /dev/null
@@ -1,36 +0,0 @@
-import React from 'react'
-
-import BikeIcon from './bike-icon'
-import BiketownIcon from './biketown-icon'
-import BusIcon from './bus-icon'
-import Car2goIcon from './car2go-icon'
-import ReachNowIcon from './reachnow-icon'
-import GondolaIcon from './gondola-icon'
-import LyftIcon from './lyft-icon'
-import RailIcon from './rail-icon'
-import StreetcarIcon from './streetcar-icon'
-import TramIcon from './tram-icon'
-import TransitIcon from './transit-icon'
-import UberIcon from './uber-icon'
-import WalkIcon from './walk-icon'
-
-// define Portland-specific mode icons
-export default {
- BICYCLE:
,
- BICYCLE_RENT:
,
- BUS:
,
- CAR_HAIL_LYFT:
,
- CAR_HAIL_UBER:
,
- CAR_RENT_CAR2GO:
,
- CAR_RENT_REACHNOW:
,
- GONDOLA:
,
- RAIL:
,
- STREETCAR:
,
- TRAM:
,
- TRANSIT:
,
- WALK:
,
- customModeForLeg: (leg) => {
- if (leg.routeLongName && leg.routeLongName.startsWith('Portland Streetcar')) return 'STREETCAR'
- return null
- }
-}
diff --git a/lib/components/icons/lyft-icon.js b/lib/components/icons/lyft-icon.js
deleted file mode 100644
index add6801bf..000000000
--- a/lib/components/icons/lyft-icon.js
+++ /dev/null
@@ -1,11 +0,0 @@
-import React, { Component } from 'react'
-
-export default class LyftIcon extends Component {
- render () {
- return (
-
-
-
- )
- }
-}
diff --git a/lib/components/icons/rail-icon.js b/lib/components/icons/rail-icon.js
deleted file mode 100644
index 8f2ab99d6..000000000
--- a/lib/components/icons/rail-icon.js
+++ /dev/null
@@ -1,11 +0,0 @@
-import React, { Component } from 'react'
-
-export default class RailIcon extends Component {
- render () {
- return (
-
-
-
- )
- }
-}
diff --git a/lib/components/icons/reachnow-icon.js b/lib/components/icons/reachnow-icon.js
deleted file mode 100644
index bab628729..000000000
--- a/lib/components/icons/reachnow-icon.js
+++ /dev/null
@@ -1,14 +0,0 @@
-import React, { Component } from 'react'
-
-export default class ReachNowIcon extends Component {
- render () {
- return (
-
-
-
-
-
-
- )
- }
-}
diff --git a/lib/components/icons/streetcar-icon.js b/lib/components/icons/streetcar-icon.js
deleted file mode 100644
index e53550142..000000000
--- a/lib/components/icons/streetcar-icon.js
+++ /dev/null
@@ -1,12 +0,0 @@
-import React, { Component } from 'react'
-
-export default class StreetcarIcon extends Component {
- render () {
- return (
-
-
-
-
- )
- }
-}
diff --git a/lib/components/icons/tram-icon.js b/lib/components/icons/tram-icon.js
deleted file mode 100644
index 10e69e931..000000000
--- a/lib/components/icons/tram-icon.js
+++ /dev/null
@@ -1,12 +0,0 @@
-import React, { Component } from 'react'
-
-export default class TramIcon extends Component {
- render () {
- return (
-
-
-
-
- )
- }
-}
diff --git a/lib/components/icons/transit-icon.js b/lib/components/icons/transit-icon.js
deleted file mode 100644
index d2e96487c..000000000
--- a/lib/components/icons/transit-icon.js
+++ /dev/null
@@ -1,23 +0,0 @@
-import React, { Component } from 'react'
-
-export default class TransitIcon extends Component {
- render () {
- // TODO: Find a better general transit icon to use than the bus icon.
- return (
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- )
- }
-}
diff --git a/lib/components/icons/uber-icon.js b/lib/components/icons/uber-icon.js
deleted file mode 100644
index 77daea91a..000000000
--- a/lib/components/icons/uber-icon.js
+++ /dev/null
@@ -1,14 +0,0 @@
-import React, { Component } from 'react'
-
-export default class UberIcon extends Component {
- render () {
- return (
-
-
-
-
-
-
- )
- }
-}
diff --git a/lib/components/icons/walk-icon.js b/lib/components/icons/walk-icon.js
deleted file mode 100644
index a071dcfa4..000000000
--- a/lib/components/icons/walk-icon.js
+++ /dev/null
@@ -1,14 +0,0 @@
-import React, { Component } from 'react'
-
-export default class WalkIcon extends Component {
- render () {
- return (
-
-
-
-
-
-
- )
- }
-}
From d729c2d7fa8de96e1fdd9999d9a421f5ee58d4af Mon Sep 17 00:00:00 2001
From: binh-dam-ibigroup <56846598+binh-dam-ibigroup@users.noreply.github.com>
Date: Mon, 6 Apr 2020 15:50:58 -0400
Subject: [PATCH 12/31] fix(Fix lint, revert to DefaultItinerary.):
---
lib/components/narrative/itinerary-carousel.js | 3 +--
lib/components/narrative/line-itin/itin-summary.js | 2 +-
lib/components/narrative/narrative-itineraries.js | 3 +--
lib/components/narrative/tabbed-itineraries.js | 5 ++---
4 files changed, 5 insertions(+), 8 deletions(-)
diff --git a/lib/components/narrative/itinerary-carousel.js b/lib/components/narrative/itinerary-carousel.js
index 494d5f2b8..c560362bd 100644
--- a/lib/components/narrative/itinerary-carousel.js
+++ b/lib/components/narrative/itinerary-carousel.js
@@ -7,7 +7,6 @@ import SwipeableViews from 'react-swipeable-views'
import { setActiveItinerary, setActiveLeg, setActiveStep } from '../../actions/narrative'
import Icon from './icon'
import DefaultItinerary from './default/default-itinerary'
-import LineItinerary from './line-itin/line-itinerary'
import Loading from './loading'
import { getActiveItineraries, getActiveSearch } from '../../util/state'
import { getTimeFormat } from '../../util/time'
@@ -29,7 +28,7 @@ class ItineraryCarousel extends Component {
}
static defaultProps = {
- itineraryClass: LineItinerary // DefaultItinerary
+ itineraryClass: DefaultItinerary
}
_onItineraryClick = () => {
diff --git a/lib/components/narrative/line-itin/itin-summary.js b/lib/components/narrative/line-itin/itin-summary.js
index 6d211b258..b7d9d93b2 100644
--- a/lib/components/narrative/line-itin/itin-summary.js
+++ b/lib/components/narrative/line-itin/itin-summary.js
@@ -18,7 +18,7 @@ export default class ItinerarySummary extends Component {
if (customIcons && iconId in customIcons) {
return customIcons[iconId]
}
-
+
// Custom icon not available for the given iconId. Use the ModeIcon component
// to show the icon based on the iconId, but always use the default car icon
// for any car-based modes that didn't have custom icon
diff --git a/lib/components/narrative/narrative-itineraries.js b/lib/components/narrative/narrative-itineraries.js
index 4c43ef1bf..318c107ee 100644
--- a/lib/components/narrative/narrative-itineraries.js
+++ b/lib/components/narrative/narrative-itineraries.js
@@ -9,7 +9,6 @@ import {
setUseRealtimeResponse
} from '../../actions/narrative'
import DefaultItinerary from './default/default-itinerary'
-import LineItinerary from './line-itin/line-itinerary'
import { getActiveItineraries, getActiveSearch, getRealtimeEffects } from '../../util/state'
import RealtimeAnnotation from './realtime-annotation'
@@ -28,7 +27,7 @@ class NarrativeItineraries extends Component {
}
static defaultProps = {
- itineraryClass: LineItinerary // DefaultItinerary
+ itineraryClass: DefaultItinerary
}
_toggleRealtimeItineraryClick = (e) => {
diff --git a/lib/components/narrative/tabbed-itineraries.js b/lib/components/narrative/tabbed-itineraries.js
index e9d82355c..35331bd57 100644
--- a/lib/components/narrative/tabbed-itineraries.js
+++ b/lib/components/narrative/tabbed-itineraries.js
@@ -5,9 +5,8 @@ import { Button } from 'react-bootstrap'
import { setActiveItinerary, setActiveLeg, setActiveStep, setUseRealtimeResponse } from '../../actions/narrative'
import DefaultItinerary from './default/default-itinerary'
-import LineItinerary from './line-itin/line-itinerary'
-import { getActiveSearch, getRealtimeEffects } from '../../util/state'
import { calculateFares, calculatePhysicalActivity, getTimeZoneOffset } from '../../util/itinerary'
+import { getActiveSearch, getRealtimeEffects } from '../../util/state'
import { formatDuration, formatTime, getTimeFormat } from '../../util/time'
class TabbedItineraries extends Component {
@@ -24,7 +23,7 @@ class TabbedItineraries extends Component {
}
static defaultProps = {
- itineraryClass: LineItinerary // DefaultItinerary
+ itineraryClass: DefaultItinerary
}
_toggleRealtimeItineraryClick = (e) => {
From e89098d37fd11180cc030eea6c316c85f32579ea Mon Sep 17 00:00:00 2001
From: binh-dam-ibigroup <56846598+binh-dam-ibigroup@users.noreply.github.com>
Date: Mon, 6 Apr 2020 15:58:01 -0400
Subject: [PATCH 13/31] style: Organize imports per PR comments.
---
lib/components/map/default-map.js | 1 -
lib/components/narrative/line-itin/itin-summary.js | 2 +-
2 files changed, 1 insertion(+), 2 deletions(-)
diff --git a/lib/components/map/default-map.js b/lib/components/map/default-map.js
index 65f103de6..df7b2d28a 100644
--- a/lib/components/map/default-map.js
+++ b/lib/components/map/default-map.js
@@ -13,7 +13,6 @@ import {
setMapPopupLocation,
setMapPopupLocationAndGeocode
} from '../../actions/map'
-
import BoundsUpdatingOverlay from './bounds-updating-overlay'
import EndpointsOverlay from './connected-endpoints-overlay'
import ParkAndRideOverlay from './connected-park-and-ride-overlay'
diff --git a/lib/components/narrative/line-itin/itin-summary.js b/lib/components/narrative/line-itin/itin-summary.js
index b7d9d93b2..146a88b32 100644
--- a/lib/components/narrative/line-itin/itin-summary.js
+++ b/lib/components/narrative/line-itin/itin-summary.js
@@ -1,6 +1,6 @@
import TriMetModeIcon from '@opentripplanner/icons/lib/trimet-mode-icon'
-import React, { Component } from 'react'
import PropTypes from 'prop-types'
+import React, { Component } from 'react'
import { calculateFares, calculatePhysicalActivity, isTransit } from '../../../util/itinerary'
import { formatDuration, formatTime } from '../../../util/time'
From e1a8e1fa0c1efae62e7c556b8f4848059606b0c0 Mon Sep 17 00:00:00 2001
From: binh-dam-ibigroup <56846598+binh-dam-ibigroup@users.noreply.github.com>
Date: Mon, 6 Apr 2020 16:01:21 -0400
Subject: [PATCH 14/31] style(Organize imports per PR comments.):
---
lib/components/narrative/default/itinerary-summary.js | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/lib/components/narrative/default/itinerary-summary.js b/lib/components/narrative/default/itinerary-summary.js
index ed24b33a4..6b4800ba1 100644
--- a/lib/components/narrative/default/itinerary-summary.js
+++ b/lib/components/narrative/default/itinerary-summary.js
@@ -1,7 +1,6 @@
-import React, { Component } from 'react'
-import PropTypes from 'prop-types'
-
import TriMetLegIcon from '@opentripplanner/icons/lib/trimet-leg-icon'
+import PropTypes from 'prop-types'
+import React, { Component } from 'react'
// TODO: add the custom icons hook found in print-layout.
From 1f4a5f986d850404d944b5d0cea2a7faac911be2 Mon Sep 17 00:00:00 2001
From: binh-dam-ibigroup <56846598+binh-dam-ibigroup@users.noreply.github.com>
Date: Tue, 7 Apr 2020 17:08:25 -0400
Subject: [PATCH 15/31] refactor(core-utils/map): Replace util/map with
@opentripplanner/core-utils/map.
---
lib/actions/map.js | 2 +-
lib/components/form/user-settings.js | 6 +-
lib/components/map/stylized-map.js | 9 +-
lib/reducers/create-otp-reducer.js | 2 +-
lib/util/index.js | 4 -
lib/util/map.js | 223 ---------------------------
lib/util/reverse.js | 12 --
7 files changed, 9 insertions(+), 249 deletions(-)
delete mode 100644 lib/util/map.js
delete mode 100644 lib/util/reverse.js
diff --git a/lib/actions/map.js b/lib/actions/map.js
index fce9deb91..6e0e2bdc1 100644
--- a/lib/actions/map.js
+++ b/lib/actions/map.js
@@ -1,9 +1,9 @@
+import { constructLocation } from '@opentripplanner/core-utils/lib/map'
import getGeocoder from '@opentripplanner/geocoder'
import { createAction } from 'redux-actions'
import { routingQuery } from './api'
import { clearActiveSearch } from './form'
-import { constructLocation } from '../util/map'
/* SET_LOCATION action creator. Updates a from or to location in the store
*
diff --git a/lib/components/form/user-settings.js b/lib/components/form/user-settings.js
index fe9e88cb4..159668ce5 100644
--- a/lib/components/form/user-settings.js
+++ b/lib/components/form/user-settings.js
@@ -1,14 +1,14 @@
-import React, { Component } from 'react'
-import { connect } from 'react-redux'
import moment from 'moment'
+import { getDetailText, formatStoredPlaceName, matchLatLon } from '@opentripplanner/core-utils/lib/map'
+import React, { Component } from 'react'
import { Button } from 'react-bootstrap'
+import { connect } from 'react-redux'
import Icon from '../narrative/icon'
import { forgetSearch, toggleTracking } from '../../actions/api'
import { setQueryParam } from '../../actions/form'
import { forgetPlace, forgetStop, setLocation } from '../../actions/map'
import { setViewedStop } from '../../actions/ui'
-import { getDetailText, formatStoredPlaceName, matchLatLon } from '../../util/map'
import { summarizeQuery } from '../../util/query'
const BUTTON_WIDTH = 40
diff --git a/lib/components/map/stylized-map.js b/lib/components/map/stylized-map.js
index cf4a124fa..f3635a5e8 100644
--- a/lib/components/map/stylized-map.js
+++ b/lib/components/map/stylized-map.js
@@ -1,13 +1,12 @@
-import React, { Component } from 'react'
-import PropTypes from 'prop-types'
-import { connect } from 'react-redux'
import { select, event } from 'd3-selection'
import { zoom } from 'd3-zoom'
-
+import { isBikeshareStation, itineraryToTransitive } from '@opentripplanner/core-utils/lib/map'
+import PropTypes from 'prop-types'
+import React, { Component } from 'react'
+import { connect } from 'react-redux'
import Transitive from 'transitive-js'
import { getActiveSearch, getActiveItineraries } from '../../util/state'
-import { isBikeshareStation, itineraryToTransitive } from '../../util/map'
var STYLES = {}
diff --git a/lib/reducers/create-otp-reducer.js b/lib/reducers/create-otp-reducer.js
index 2ea229618..4293dfc62 100644
--- a/lib/reducers/create-otp-reducer.js
+++ b/lib/reducers/create-otp-reducer.js
@@ -2,8 +2,8 @@ import clone from 'clone'
import update from 'immutability-helper'
import isEqual from 'lodash.isequal'
import objectPath from 'object-path'
+import { matchLatLon } from '@opentripplanner/core-utils/lib/map'
-import { matchLatLon } from '../util/map'
import {
ensureSingleAccessMode,
getDefaultQuery,
diff --git a/lib/util/index.js b/lib/util/index.js
index 8d225a961..e95db1bec 100644
--- a/lib/util/index.js
+++ b/lib/util/index.js
@@ -1,9 +1,7 @@
import * as distance from './distance'
import * as itinerary from './itinerary'
-import * as map from './map'
import * as profile from './profile'
import * as query from './query'
-import * as reverse from './reverse'
import * as state from './state'
import * as time from './time'
import * as ui from './ui'
@@ -11,10 +9,8 @@ import * as ui from './ui'
const OtpUtils = {
distance,
itinerary,
- map,
profile,
query,
- reverse,
state,
time,
ui
diff --git a/lib/util/map.js b/lib/util/map.js
deleted file mode 100644
index 8c5d44db7..000000000
--- a/lib/util/map.js
+++ /dev/null
@@ -1,223 +0,0 @@
-import moment from 'moment'
-
-import { isTransit, toSentenceCase } from './itinerary'
-
-export function latlngToString (latlng) {
- return latlng && `${latlng.lat.toFixed(5)}, ${(latlng.lng || latlng.lon).toFixed(5)}`
-}
-
-export function coordsToString (coords) {
- return coords.length && coords.map(c => (+c).toFixed(5)).join(', ')
-}
-
-export function stringToCoords (str) {
- return (str && str.split(',').map(c => +c)) || []
-}
-
-export function constructLocation (latlng) {
- return {
- name: latlngToString(latlng),
- lat: latlng.lat,
- lon: latlng.lng
- }
-}
-
-export function formatStoredPlaceName (location, withDetails = true) {
- let displayName = location.type === 'home' || location.type === 'work'
- ? toSentenceCase(location.type)
- : location.name
- if (withDetails) {
- let detailText = getDetailText(location)
- if (detailText) displayName += ` (${detailText})`
- }
- return displayName
-}
-
-export function getDetailText (location) {
- let detailText
- if (location.type === 'home' || location.type === 'work') {
- detailText = location.name
- }
- if (location.type === 'stop') {
- detailText = location.id
- } else if (location.type === 'recent' && location.timestamp) {
- detailText = moment(location.timestamp).fromNow()
- }
- return detailText
-}
-
-export function matchLatLon (location1, location2) {
- if (!location1 || !location2) return location1 === location2
- return location1.lat === location2.lat && location1.lon === location2.lon
-}
-
-export function itineraryToTransitive (itin, includeGeometry) {
- // console.log('itineraryToTransitive', itin);
- const tdata = {
- journeys: [],
- streetEdges: [],
- places: [],
- patterns: [],
- routes: [],
- stops: []
- }
- const routes = {}
- const stops = {}
- let streetEdgeId = 0
- let patternId = 0
-
- const journey = {
- journey_id: 'itin',
- journey_name: 'Iterarary-derived Journey',
- segments: []
- }
-
- // add 'from' and 'to' places to the tdata places array
- tdata.places.push({
- place_id: 'from',
- place_lat: itin.legs[0].from.lat,
- place_lon: itin.legs[0].from.lon
- })
- tdata.places.push({
- place_id: 'to',
- place_lat: itin.legs[itin.legs.length - 1].to.lat,
- place_lon: itin.legs[itin.legs.length - 1].to.lon
- })
-
- itin.legs.forEach(leg => {
- if (
- leg.mode === 'WALK' ||
- leg.mode === 'BICYCLE' ||
- leg.mode === 'CAR' ||
- leg.mode === 'MICROMOBILITY'
- ) {
- const fromPlaceId = leg.from.bikeShareId
- ? `bicycle_rent_station_${leg.from.bikeShareId}`
- : `itin_street_${streetEdgeId}_from`
- const toPlaceId = leg.to.bikeShareId
- ? `bicycle_rent_station_${leg.to.bikeShareId}`
- : `itin_street_${streetEdgeId}_to`
-
- const segment = {
- type: leg.mode,
- streetEdges: [streetEdgeId],
- from: { type: 'PLACE', place_id: fromPlaceId },
- to: { type: 'PLACE', place_id: toPlaceId }
- }
- // For TNC segments, draw using an arc
- if (leg.mode === 'CAR' && leg.hailedCar) segment.arc = true
- journey.segments.push(segment)
-
- tdata.streetEdges.push({
- edge_id: streetEdgeId,
- geometry: leg.legGeometry
- })
- tdata.places.push({
- place_id: fromPlaceId,
- // Do not label the from place in addition to the to place. Otherwise,
- // in some cases (bike rental station) the label for a single place will
- // appear twice on the rendered transitive view.
- // See https://github.com/conveyal/trimet-mod-otp/issues/152
- // place_name: leg.from.name,
- place_lat: leg.from.lat,
- place_lon: leg.from.lon
- })
- tdata.places.push({
- place_id: toPlaceId,
- place_name: leg.to.name,
- place_lat: leg.to.lat,
- place_lon: leg.to.lon
- })
- streetEdgeId++
- }
- if (isTransit(leg.mode)) {
- // determine if we have valid inter-stop geometry
- const hasInterStopGeometry =
- leg.interStopGeometry &&
- leg.interStopGeometry.length === leg.intermediateStops.length + 1
-
- // create leg-specific pattern
- const ptnId = 'ptn_' + patternId
- const pattern = {
- pattern_id: ptnId,
- pattern_name: 'Pattern ' + patternId,
- route_id: leg.routeId,
- stops: []
- }
-
- // add 'from' stop to stops dictionary and pattern object
- stops[leg.from.stopId] = {
- stop_id: leg.from.stopId,
- stop_name: leg.from.name,
- stop_lat: leg.from.lat,
- stop_lon: leg.from.lon
- }
- pattern.stops.push({ stop_id: leg.from.stopId })
-
- // add intermediate stops to stops dictionary and pattern object
- for (const [i, stop] of leg.intermediateStops.entries()) {
- stops[stop.stopId] = {
- stop_id: stop.stopId,
- stop_name: stop.name,
- stop_lat: stop.lat,
- stop_lon: stop.lon
- }
- pattern.stops.push({
- stop_id: stop.stopId,
- geometry: hasInterStopGeometry && leg.interStopGeometry[i].points
- })
- }
-
- // add 'to' stop to stops dictionary and pattern object
- stops[leg.to.stopId] = {
- stop_id: leg.to.stopId,
- stop_name: leg.to.name,
- stop_lat: leg.to.lat,
- stop_lon: leg.to.lon
- }
- pattern.stops.push({
- stop_id: leg.to.stopId,
- geometry: hasInterStopGeometry && leg.interStopGeometry[leg.interStopGeometry.length - 1].points
- })
-
- // add route to the route dictionary
- routes[leg.routeId] = {
- agency_id: leg.agencyId,
- route_id: leg.routeId,
- route_short_name: leg.routeShortName || '',
- route_long_name: leg.routeLongName || '',
- route_type: leg.routeType,
- route_color: leg.routeColor
- }
-
- // add the pattern to the tdata patterns array
- tdata.patterns.push(pattern)
-
- // add the pattern refrerence to the journey object
- journey.segments.push({
- type: 'TRANSIT',
- patterns: [{
- pattern_id: ptnId,
- from_stop_index: 0,
- to_stop_index: (leg.intermediateStops.length + 2) - 1
- }]
- })
-
- patternId++
- }
- })
-
- // add the routes and stops to the tdata arrays
- for (const k in routes) tdata.routes.push(routes[k])
- for (const k in stops) tdata.stops.push(stops[k])
-
- // add the journey to the tdata journeys array
- tdata.journeys.push(journey)
-
- // console.log('derived tdata', tdata);
- return tdata
-}
-
-export function isBikeshareStation (place) {
- return place.place_id.lastIndexOf('bicycle_rent_station') !== -1
-}
diff --git a/lib/util/reverse.js b/lib/util/reverse.js
deleted file mode 100644
index 8f8f93409..000000000
--- a/lib/util/reverse.js
+++ /dev/null
@@ -1,12 +0,0 @@
-// TODO: add reverse geocode for map click
-// export async function reversePelias (point) {
-// const location = {lon: point.lng, lat: point.lat}
-// const apiKey = getConfigProperty('MAPZEN_TURN_BY_TURN_KEY')
-// const params = {
-// api_key: apiKey,
-// ...location
-// }
-// const url = `https://search.mapzen.com/v1/reverse?${qs.stringify(params)}`
-// const response = await fetch(url)
-// return await response.json()
-// }
From 59c4c004c36790137d109e23b152fa7b5159aede Mon Sep 17 00:00:00 2001
From: binh-dam-ibigroup <56846598+binh-dam-ibigroup@users.noreply.github.com>
Date: Tue, 7 Apr 2020 17:26:50 -0400
Subject: [PATCH 16/31] refactor(util/profile,storage): Replace util/profile,
storage with @opentripplanner/core-utils count
---
lib/actions/api.js | 6 +-
lib/actions/form.js | 4 +-
.../narrative/itinerary-carousel.js | 4 +-
.../narrative/narrative-profile-options.js | 4 +-
lib/reducers/create-otp-reducer.js | 4 +-
lib/util/index.js | 2 -
lib/util/profile.js | 180 ------------------
lib/util/storage.js | 42 ----
8 files changed, 11 insertions(+), 235 deletions(-)
delete mode 100644 lib/util/profile.js
delete mode 100644 lib/util/storage.js
diff --git a/lib/actions/api.js b/lib/actions/api.js
index 705822ecb..17bee06dc 100644
--- a/lib/actions/api.js
+++ b/lib/actions/api.js
@@ -1,17 +1,17 @@
/* globals fetch */
import { push, replace } from 'connected-react-router'
+import haversine from 'haversine'
+import moment from 'moment'
import hash from 'object-hash'
+import { randId } from '@opentripplanner/core-utils/lib/storage'
import { createAction } from 'redux-actions'
import qs from 'qs'
-import moment from 'moment'
-import haversine from 'haversine'
import { rememberPlace } from './map'
import { hasCar } from '../util/itinerary'
import { getTripOptionsFromQuery, getUrlParams } from '../util/query'
import queryParams from '../util/query-params'
import { getStopViewerConfig, queryIsValid } from '../util/state'
-import { randId } from '../util/storage'
import { OTP_API_DATE_FORMAT, OTP_API_TIME_FORMAT } from '../util/time'
if (typeof (fetch) === 'undefined') require('isomorphic-fetch')
diff --git a/lib/actions/form.js b/lib/actions/form.js
index 66860f1a4..a6678f386 100644
--- a/lib/actions/form.js
+++ b/lib/actions/form.js
@@ -1,7 +1,8 @@
import debounce from 'lodash.debounce'
+import isEqual from 'lodash.isequal'
import moment from 'moment'
+import { getItem, randId } from '@opentripplanner/core-utils/lib/storage'
import { createAction } from 'redux-actions'
-import isEqual from 'lodash.isequal'
import {
getDefaultQuery,
@@ -9,7 +10,6 @@ import {
getUrlParams,
planParamsToQuery
} from '../util/query'
-import { getItem, randId } from '../util/storage'
import { queryIsValid } from '../util/state'
import { OTP_API_TIME_FORMAT } from '../util/time'
import { isMobile } from '../util/ui'
diff --git a/lib/components/narrative/itinerary-carousel.js b/lib/components/narrative/itinerary-carousel.js
index ce7a373fa..46bd4cf05 100644
--- a/lib/components/narrative/itinerary-carousel.js
+++ b/lib/components/narrative/itinerary-carousel.js
@@ -1,5 +1,6 @@
-import React, { Component } from 'react'
+import { profileOptionsToItineraries } from '@opentripplanner/core-utils/lib/profile'
import PropTypes from 'prop-types'
+import React, { Component } from 'react'
import { Button } from 'react-bootstrap'
import { connect } from 'react-redux'
import SwipeableViews from 'react-swipeable-views'
@@ -10,7 +11,6 @@ import DefaultItinerary from './default/default-itinerary'
import Loading from './loading'
import NarrativeProfileSummary from './narrative-profile-summary'
import { getActiveItineraries, getActiveSearch } from '../../util/state'
-import { profileOptionsToItineraries } from '../../util/profile'
import { getTimeFormat } from '../../util/time'
class ItineraryCarousel extends Component {
diff --git a/lib/components/narrative/narrative-profile-options.js b/lib/components/narrative/narrative-profile-options.js
index 405d6609a..4b7f1efc5 100644
--- a/lib/components/narrative/narrative-profile-options.js
+++ b/lib/components/narrative/narrative-profile-options.js
@@ -1,5 +1,6 @@
-import React, { Component } from 'react'
+import { profileOptionsToItineraries } from '@opentripplanner/core-utils/lib/profile'
import PropTypes from 'prop-types'
+import React, { Component } from 'react'
import { connect } from 'react-redux'
import { setActiveItinerary, setActiveLeg, setActiveStep } from '../../actions/narrative'
@@ -7,7 +8,6 @@ import DefaultItinerary from './default/default-itinerary'
import NarrativeProfileSummary from './narrative-profile-summary'
import Loading from './loading'
import { getActiveSearch } from '../../util/state'
-import { profileOptionsToItineraries } from '../../util/profile'
class NarrativeProfileOptions extends Component {
static propTypes = {
diff --git a/lib/reducers/create-otp-reducer.js b/lib/reducers/create-otp-reducer.js
index 4293dfc62..8268aa535 100644
--- a/lib/reducers/create-otp-reducer.js
+++ b/lib/reducers/create-otp-reducer.js
@@ -3,6 +3,8 @@ import update from 'immutability-helper'
import isEqual from 'lodash.isequal'
import objectPath from 'object-path'
import { matchLatLon } from '@opentripplanner/core-utils/lib/map'
+import { filterProfileOptions } from '@opentripplanner/core-utils/lib/profile'
+import { getItem, removeItem, storeItem } from '@opentripplanner/core-utils/lib/storage'
import {
ensureSingleAccessMode,
@@ -10,8 +12,6 @@ import {
getTripOptionsFromQuery
} from '../util/query'
import { isTransit, getTransitModes } from '../util/itinerary'
-import { filterProfileOptions } from '../util/profile'
-import { getItem, removeItem, storeItem } from '../util/storage'
import { getUserTimezone } from '../util/time'
import { MainPanelContent, MobileScreens } from '../actions/ui'
diff --git a/lib/util/index.js b/lib/util/index.js
index e95db1bec..291111a9a 100644
--- a/lib/util/index.js
+++ b/lib/util/index.js
@@ -1,6 +1,5 @@
import * as distance from './distance'
import * as itinerary from './itinerary'
-import * as profile from './profile'
import * as query from './query'
import * as state from './state'
import * as time from './time'
@@ -9,7 +8,6 @@ import * as ui from './ui'
const OtpUtils = {
distance,
itinerary,
- profile,
query,
state,
time,
diff --git a/lib/util/profile.js b/lib/util/profile.js
deleted file mode 100644
index ed79ed806..000000000
--- a/lib/util/profile.js
+++ /dev/null
@@ -1,180 +0,0 @@
-export function filterProfileOptions (response) {
- // Filter out similar options. TODO: handle on server?
- const optStrs = []
- const filteredIndices = []
-
- const filteredProfile = response.otp.profile.filter((option, i) => {
- let optStr = option.access.map(a => a.mode).join('/')
- if (option.transit) {
- optStr += ' to ' + option.transit.map(transit => {
- return transit.routes.map(route => route.id).join('/')
- }).join(',')
- }
- if (optStrs.indexOf(optStr) !== -1) return false
- optStrs.push(optStr)
- filteredIndices.push(i)
- return true
- })
-
- const filteredJourneys = response.otp.journeys.filter((journey, i) => filteredIndices.indexOf(i) !== -1)
-
- response.otp.profile = filteredProfile
- response.otp.journeys = filteredJourneys
- return response
-}
-
-/** profileOptionsToItineraries **/
-
-export function profileOptionsToItineraries (options, query) {
- return options.map(option => optionToItinerary(option, query))
-}
-
-// helper functions for profileOptionsToItineraries:
-
-function optionToItinerary (option, query) {
- const itin = {
- duration: option.time,
- legs: [],
- walkTime: 0,
- waitingTime: 0
- }
-
- // access leg
- if (option.access && option.access.length > 0) {
- if (option.access[0].mode === 'BICYCLE_RENT') {
- let status = 'WALK_ON'
- const walkOnEdges = []
- const bikeEdges = []
- const walkOffEdges = []
- let onStationName
- let walkOnTime = 0
- let offStationName
- let walkOffTime = 0
- option.access[0].streetEdges.forEach(edge => {
- // check if we're returning the bike
- if (edge.bikeRentalOffStation) {
- status = 'WALK_OFF'
- offStationName = edge.bikeRentalOffStation.name
- }
-
- if (status === 'WALK_ON') {
- walkOnEdges.push(edge)
- walkOnTime += edge.distance
- } else if (status === 'BIKE') {
- bikeEdges.push(edge)
- } else if (status === 'WALK_OFF') {
- walkOffEdges.push(edge)
- walkOffTime += edge.distance
- }
-
- // check if we're picking up the bike
- if (edge.bikeRentalOnStation) {
- status = 'BIKE'
- onStationName = edge.bikeRentalOnStation.name
- }
- })
-
- itin.walkTime += (walkOnTime + walkOffTime)
-
- // create the 'on' walk leg
- itin.legs.push({
- mode: 'WALK',
- duration: walkOnTime,
- transitLeg: false,
- from: {
- name: locationString(query && query.from.name, 'Destination')
- },
- to: {
- name: onStationName
- }
- })
-
- // create the bike leg
- itin.legs.push({
- mode: 'BICYCLE_RENT',
- duration: option.time - walkOnTime - walkOffTime,
- transitLeg: false,
- from: {
- name: onStationName
- },
- to: {
- name: offStationName
- }
- })
-
- // create the 'off' walk leg
- itin.legs.push({
- mode: 'WALK',
- duration: walkOffTime,
- transitLeg: false,
- from: {
- name: offStationName
- },
- to: {
- name: locationString(query && query.to.name, 'Destination')
- }
- })
- } else {
- itin.legs.push(accessToLeg(option.access[0], query && query.from.name, option.transit ? null : query && query.to.name))
- if (option.access[0].mode === 'WALK') itin.walkTime += option.access[0].time
- }
- }
-
- // transit legs
- if (option.transit) {
- option.transit.forEach(transit => {
- itin.legs.push({
- transitLeg: true,
- mode: transit.mode,
- from: {
- name: transit.fromName
- },
- to: {
- name: transit.toName
- },
- routes: transit.routes,
- duration: transit.rideStats.avg,
- averageWait: transit.waitStats.avg
- })
- itin.waitingTime += transit.waitStats.avg
- })
- }
-
- // egress leg
- if (option.egress && option.egress.length > 0) {
- // find the origin name, for transit trips
- const origin = option.transit ? option.transit[option.transit.length - 1].toName : null
-
- itin.legs.push(accessToLeg(option.egress[0], origin, query && query.to.name))
- if (option.egress[0].mode === 'WALK') itin.walkTime += option.egress[0].time
- }
-
- // construct summary
- if (option.transit) {
- itin.summary = 'Transit'
- } else {
- if (option.modes.length === 1 && option.modes[0] === 'bicycle') itin.summary = 'Bicycle'
- else if (option.modes.length === 1 && option.modes[0] === 'walk') itin.summary = 'Walk'
- else if (option.modes.indexOf('bicycle_rent') !== -1) itin.summary = 'Bikeshare'
- }
-
- return itin
-}
-
-function accessToLeg (access, origin, destination) {
- return {
- mode: access.mode,
- duration: access.time,
- transitLeg: false,
- from: {
- name: locationString(origin, 'Origin')
- },
- to: {
- name: locationString(destination, 'Destination')
- }
- }
-}
-
-function locationString (str, defaultStr) {
- return str ? str.split(',')[0] : defaultStr
-}
diff --git a/lib/util/storage.js b/lib/util/storage.js
deleted file mode 100644
index 4d9b7d88c..000000000
--- a/lib/util/storage.js
+++ /dev/null
@@ -1,42 +0,0 @@
-// Prefix to use with local storage keys.
-const STORAGE_PREFIX = 'otp'
-
-/**
- * Store a javascript object at the specified key.
- */
-export function storeItem (key, object) {
- window.localStorage.setItem(`${STORAGE_PREFIX}.${key}`, JSON.stringify(object))
-}
-
-/**
- * Retrieve a javascript object at the specified key. If not found, defaults to
- * null or, the optionally provided notFoundValue.
- */
-export function getItem (key, notFoundValue = null) {
- let itemAsString
- try {
- itemAsString = window.localStorage.getItem(`${STORAGE_PREFIX}.${key}`)
- const json = JSON.parse(itemAsString)
- if (json) return json
- else return notFoundValue
- } catch (e) {
- // Catch any errors associated with parsing bad JSON.
- console.warn(e, itemAsString)
- return notFoundValue
- }
-}
-
-/**
- * Remove item at specified key.
- */
-export function removeItem (key) {
- window.localStorage.removeItem(`${STORAGE_PREFIX}.${key}`)
-}
-
-/**
- * Generate a random ID. This might not quite be a UUID, but it serves our
- * purposes for now.
- */
-export function randId () {
- return Math.random().toString(36).substr(2, 9)
-}
From 15eb9ede3f5d4d9f6d5cbe8df80239efbfc73b2f Mon Sep 17 00:00:00 2001
From: binh-dam-ibigroup <56846598+binh-dam-ibigroup@users.noreply.github.com>
Date: Tue, 7 Apr 2020 18:33:38 -0400
Subject: [PATCH 17/31] refactor(util/time): Replace util/time with
@opentripplanner/core-utils/time
---
lib/actions/api.js | 2 +-
lib/actions/form.js | 2 +-
lib/components/form/date-time-preview.js | 11 ++-
.../narrative/connected-trip-details.js | 5 +-
.../narrative/default/access-leg.js | 5 +-
.../narrative/default/default-itinerary.js | 2 +-
lib/components/narrative/default/tnc-leg.js | 4 +-
.../narrative/default/transit-leg.js | 7 +-
.../narrative/itinerary-carousel.js | 2 +-
.../narrative/line-itin/itin-summary.js | 4 +-
.../narrative/realtime-annotation.js | 5 +-
.../narrative/tabbed-itineraries.js | 6 +-
lib/components/viewers/stop-viewer.js | 11 ++-
lib/components/viewers/trip-viewer.js | 4 +-
lib/reducers/create-otp-reducer.js | 2 +-
lib/util/index.js | 2 -
lib/util/time.js | 89 -------------------
17 files changed, 33 insertions(+), 130 deletions(-)
delete mode 100644 lib/util/time.js
diff --git a/lib/actions/api.js b/lib/actions/api.js
index 17bee06dc..f717450fd 100644
--- a/lib/actions/api.js
+++ b/lib/actions/api.js
@@ -4,6 +4,7 @@ import haversine from 'haversine'
import moment from 'moment'
import hash from 'object-hash'
import { randId } from '@opentripplanner/core-utils/lib/storage'
+import { OTP_API_DATE_FORMAT, OTP_API_TIME_FORMAT } from '@opentripplanner/core-utils/lib/time'
import { createAction } from 'redux-actions'
import qs from 'qs'
@@ -12,7 +13,6 @@ import { hasCar } from '../util/itinerary'
import { getTripOptionsFromQuery, getUrlParams } from '../util/query'
import queryParams from '../util/query-params'
import { getStopViewerConfig, queryIsValid } from '../util/state'
-import { OTP_API_DATE_FORMAT, OTP_API_TIME_FORMAT } from '../util/time'
if (typeof (fetch) === 'undefined') require('isomorphic-fetch')
// Generic API actions
diff --git a/lib/actions/form.js b/lib/actions/form.js
index a6678f386..5d73405f1 100644
--- a/lib/actions/form.js
+++ b/lib/actions/form.js
@@ -2,6 +2,7 @@ import debounce from 'lodash.debounce'
import isEqual from 'lodash.isequal'
import moment from 'moment'
import { getItem, randId } from '@opentripplanner/core-utils/lib/storage'
+import { OTP_API_TIME_FORMAT } from '@opentripplanner/core-utils/lib/time'
import { createAction } from 'redux-actions'
import {
@@ -11,7 +12,6 @@ import {
planParamsToQuery
} from '../util/query'
import { queryIsValid } from '../util/state'
-import { OTP_API_TIME_FORMAT } from '../util/time'
import { isMobile } from '../util/ui'
import {
MobileScreens,
diff --git a/lib/components/form/date-time-preview.js b/lib/components/form/date-time-preview.js
index 08ce1d25b..44754d044 100644
--- a/lib/components/form/date-time-preview.js
+++ b/lib/components/form/date-time-preview.js
@@ -1,15 +1,14 @@
-import React, { Component } from 'react'
-import PropTypes from 'prop-types'
import moment from 'moment'
-import { connect } from 'react-redux'
-import { Button } from 'react-bootstrap'
-
import {
OTP_API_DATE_FORMAT,
OTP_API_TIME_FORMAT,
getTimeFormat,
getDateFormat
-} from '../../util/time'
+} from '@opentripplanner/core-utils/lib/time'
+import PropTypes from 'prop-types'
+import React, { Component } from 'react'
+import { Button } from 'react-bootstrap'
+import { connect } from 'react-redux'
class DateTimePreview extends Component {
static propTypes = {
diff --git a/lib/components/narrative/connected-trip-details.js b/lib/components/narrative/connected-trip-details.js
index 16183ea1e..daf54e076 100644
--- a/lib/components/narrative/connected-trip-details.js
+++ b/lib/components/narrative/connected-trip-details.js
@@ -1,8 +1,7 @@
+import { getTimeFormat, getLongDateFormat } from '@opentripplanner/core-utils/lib/time'
+import TripDetailsBase from '@opentripplanner/trip-details'
import { connect } from 'react-redux'
import styled from 'styled-components'
-import TripDetailsBase from '@opentripplanner/trip-details'
-
-import { getTimeFormat, getLongDateFormat } from '../../util/time'
const TripDetails = styled(TripDetailsBase)`
border: 2px solid gray;
diff --git a/lib/components/narrative/default/access-leg.js b/lib/components/narrative/default/access-leg.js
index 274282544..1101d3a38 100644
--- a/lib/components/narrative/default/access-leg.js
+++ b/lib/components/narrative/default/access-leg.js
@@ -1,12 +1,11 @@
-import React, {Component} from 'react'
+import { formatDuration } from '@opentripplanner/core-utils/lib/time'
import PropTypes from 'prop-types'
+import React, {Component} from 'react'
import Icon from '../icon'
-
import LegDiagramPreview from '../leg-diagram-preview'
import { distanceString } from '../../../util/distance'
import { getStepInstructions } from '../../../util/itinerary'
-import { formatDuration } from '../../../util/time'
/**
* Default access leg component for narrative itinerary.
diff --git a/lib/components/narrative/default/default-itinerary.js b/lib/components/narrative/default/default-itinerary.js
index 57f2717de..3eae4c049 100644
--- a/lib/components/narrative/default/default-itinerary.js
+++ b/lib/components/narrative/default/default-itinerary.js
@@ -1,3 +1,4 @@
+import { formatDuration, formatTime } from '@opentripplanner/core-utils/lib/time'
import React from 'react'
import NarrativeItinerary from '../narrative-itinerary'
@@ -5,7 +6,6 @@ import ItinerarySummary from './itinerary-summary'
import ItineraryDetails from './itinerary-details'
import TripDetails from '../connected-trip-details'
import TripTools from '../trip-tools'
-import { formatDuration, formatTime } from '../../../util/time'
export default class DefaultItinerary extends NarrativeItinerary {
render () {
diff --git a/lib/components/narrative/default/tnc-leg.js b/lib/components/narrative/default/tnc-leg.js
index 0c8505ff5..afd1ddb22 100644
--- a/lib/components/narrative/default/tnc-leg.js
+++ b/lib/components/narrative/default/tnc-leg.js
@@ -1,6 +1,7 @@
import currencyFormatter from 'currency-formatter'
-import React, { Component } from 'react'
+import { formatDuration } from '@opentripplanner/core-utils/lib/time'
import PropTypes from 'prop-types'
+import React, { Component } from 'react'
import { connect } from 'react-redux'
import {
@@ -8,7 +9,6 @@ import {
getTransportationNetworkCompanyRideEstimate
} from '../../../actions/api'
import { toSentenceCase } from '../../../util/itinerary'
-import { formatDuration } from '../../../util/time'
import { isMobile } from '../../../util/ui'
class TransportationNetworkCompanyLeg extends Component {
diff --git a/lib/components/narrative/default/transit-leg.js b/lib/components/narrative/default/transit-leg.js
index 5809f3f1b..aef7c13eb 100644
--- a/lib/components/narrative/default/transit-leg.js
+++ b/lib/components/narrative/default/transit-leg.js
@@ -1,13 +1,12 @@
-import Icon from '../icon'
-import React, { Component } from 'react'
+import { formatDuration, formatTime } from '@opentripplanner/core-utils/lib/time'
import PropTypes from 'prop-types'
+import React, { Component } from 'react'
+import Icon from '../icon'
import ModeIcon from '../../icons/mode-icon'
import ViewTripButton from '../../viewers/view-trip-button'
import ViewStopButton from '../../viewers/view-stop-button'
-
import { getMapColor } from '../../../util/itinerary'
-import { formatDuration, formatTime } from '../../../util/time'
export default class TransitLeg extends Component {
static propTypes = {
diff --git a/lib/components/narrative/itinerary-carousel.js b/lib/components/narrative/itinerary-carousel.js
index 46bd4cf05..10505ddf6 100644
--- a/lib/components/narrative/itinerary-carousel.js
+++ b/lib/components/narrative/itinerary-carousel.js
@@ -1,4 +1,5 @@
import { profileOptionsToItineraries } from '@opentripplanner/core-utils/lib/profile'
+import { getTimeFormat } from '@opentripplanner/core-utils/lib/time'
import PropTypes from 'prop-types'
import React, { Component } from 'react'
import { Button } from 'react-bootstrap'
@@ -11,7 +12,6 @@ import DefaultItinerary from './default/default-itinerary'
import Loading from './loading'
import NarrativeProfileSummary from './narrative-profile-summary'
import { getActiveItineraries, getActiveSearch } from '../../util/state'
-import { getTimeFormat } from '../../util/time'
class ItineraryCarousel extends Component {
state = {}
diff --git a/lib/components/narrative/line-itin/itin-summary.js b/lib/components/narrative/line-itin/itin-summary.js
index e8965fe35..8766cedeb 100644
--- a/lib/components/narrative/line-itin/itin-summary.js
+++ b/lib/components/narrative/line-itin/itin-summary.js
@@ -1,8 +1,8 @@
-import React, { Component } from 'react'
+import { formatDuration, formatTime } from '@opentripplanner/core-utils/lib/time'
import PropTypes from 'prop-types'
+import React, { Component } from 'react'
import { calculateFares, calculatePhysicalActivity, getLegIcon, isTransit } from '../../../util/itinerary'
-import { formatDuration, formatTime } from '../../../util/time'
// TODO: make this a prop
const defaultRouteColor = '#008'
diff --git a/lib/components/narrative/realtime-annotation.js b/lib/components/narrative/realtime-annotation.js
index 834046d50..d0ecd93d5 100644
--- a/lib/components/narrative/realtime-annotation.js
+++ b/lib/components/narrative/realtime-annotation.js
@@ -1,9 +1,8 @@
-import React, { Component } from 'react'
+import { formatDuration } from '@opentripplanner/core-utils/lib/time'
import PropTypes from 'prop-types'
+import React, { Component } from 'react'
import { Button, OverlayTrigger, Popover } from 'react-bootstrap'
-import { formatDuration } from '../../util/time'
-
export default class RealtimeAnnotation extends Component {
static propTypes = {
realtimeEffects: PropTypes.object,
diff --git a/lib/components/narrative/tabbed-itineraries.js b/lib/components/narrative/tabbed-itineraries.js
index f3c4e2d76..b707b822a 100644
--- a/lib/components/narrative/tabbed-itineraries.js
+++ b/lib/components/narrative/tabbed-itineraries.js
@@ -1,13 +1,13 @@
-import React, { Component } from 'react'
+import { formatDuration, formatTime, getTimeFormat } from '@opentripplanner/core-utils/lib/time'
import PropTypes from 'prop-types'
-import { connect } from 'react-redux'
+import React, { Component } from 'react'
import { Button } from 'react-bootstrap'
+import { connect } from 'react-redux'
import { setActiveItinerary, setActiveLeg, setActiveStep, setUseRealtimeResponse } from '../../actions/narrative'
import DefaultItinerary from './default/default-itinerary'
import { getActiveSearch, getRealtimeEffects } from '../../util/state'
import { calculateFares, calculatePhysicalActivity, getTimeZoneOffset } from '../../util/itinerary'
-import { formatDuration, formatTime, getTimeFormat } from '../../util/time'
class TabbedItineraries extends Component {
static propTypes = {
diff --git a/lib/components/viewers/stop-viewer.js b/lib/components/viewers/stop-viewer.js
index 424d7278b..1c04a1d80 100644
--- a/lib/components/viewers/stop-viewer.js
+++ b/lib/components/viewers/stop-viewer.js
@@ -1,20 +1,19 @@
-import React, { Component } from 'react'
+import moment from 'moment'
+import 'moment-timezone'
+import { formatDuration, formatSecondsAfterMidnight, getTimeFormat, getUserTimezone } from '@opentripplanner/core-utils/lib/time'
+import FromToLocationPicker from '@opentripplanner/from-to-location-picker'
import PropTypes from 'prop-types'
+import React, { Component } from 'react'
import { Button } from 'react-bootstrap'
import { connect } from 'react-redux'
-import moment from 'moment'
-import 'moment-timezone'
import { VelocityTransitionGroup } from 'velocity-react'
-import FromToLocationPicker from '@opentripplanner/from-to-location-picker'
-
import Icon from '../narrative/icon'
import { setMainPanelContent, toggleAutoRefresh } from '../../actions/ui'
import { findStop, findStopTimesForStop } from '../../actions/api'
import { forgetStop, rememberStop, setLocation } from '../../actions/map'
import { routeComparator } from '../../util/itinerary'
import { getShowUserSettings, getStopViewerConfig } from '../../util/state'
-import { formatDuration, formatSecondsAfterMidnight, getTimeFormat, getUserTimezone } from '../../util/time'
class StopViewer extends Component {
state = {}
diff --git a/lib/components/viewers/trip-viewer.js b/lib/components/viewers/trip-viewer.js
index f1d3fe928..821f5d091 100644
--- a/lib/components/viewers/trip-viewer.js
+++ b/lib/components/viewers/trip-viewer.js
@@ -1,5 +1,6 @@
-import React, { Component } from 'react'
+import { formatSecondsAfterMidnight, getTimeFormat } from '@opentripplanner/core-utils/lib/time'
import PropTypes from 'prop-types'
+import React, { Component } from 'react'
import { Button, Label } from 'react-bootstrap'
import { connect } from 'react-redux'
@@ -10,7 +11,6 @@ import { setViewedTrip } from '../../actions/ui'
import { findTrip } from '../../actions/api'
import { setLocation } from '../../actions/map'
-import { formatSecondsAfterMidnight, getTimeFormat } from '../../util/time'
class TripViewer extends Component {
static propTypes = {
diff --git a/lib/reducers/create-otp-reducer.js b/lib/reducers/create-otp-reducer.js
index 8268aa535..84d7358f0 100644
--- a/lib/reducers/create-otp-reducer.js
+++ b/lib/reducers/create-otp-reducer.js
@@ -5,6 +5,7 @@ import objectPath from 'object-path'
import { matchLatLon } from '@opentripplanner/core-utils/lib/map'
import { filterProfileOptions } from '@opentripplanner/core-utils/lib/profile'
import { getItem, removeItem, storeItem } from '@opentripplanner/core-utils/lib/storage'
+import { getUserTimezone } from '@opentripplanner/core-utils/lib/time'
import {
ensureSingleAccessMode,
@@ -12,7 +13,6 @@ import {
getTripOptionsFromQuery
} from '../util/query'
import { isTransit, getTransitModes } from '../util/itinerary'
-import { getUserTimezone } from '../util/time'
import { MainPanelContent, MobileScreens } from '../actions/ui'
const MAX_RECENT_STORAGE = 5
diff --git a/lib/util/index.js b/lib/util/index.js
index 291111a9a..3cb72d8d0 100644
--- a/lib/util/index.js
+++ b/lib/util/index.js
@@ -2,7 +2,6 @@ import * as distance from './distance'
import * as itinerary from './itinerary'
import * as query from './query'
import * as state from './state'
-import * as time from './time'
import * as ui from './ui'
const OtpUtils = {
@@ -10,7 +9,6 @@ const OtpUtils = {
itinerary,
query,
state,
- time,
ui
}
diff --git a/lib/util/time.js b/lib/util/time.js
deleted file mode 100644
index be7e5964c..000000000
--- a/lib/util/time.js
+++ /dev/null
@@ -1,89 +0,0 @@
-import moment from 'moment'
-import 'moment-timezone'
-
-// special constants for making sure the following date format is always sent to
-// OTP regardless of whatever the user has configured as the display format
-export const OTP_API_DATE_FORMAT = 'YYYY-MM-DD'
-export const OTP_API_TIME_FORMAT = 'HH:mm'
-
-/**
- * @param {[type]} config the OTP config object found in store
- * @return {string} the config-defined time formatter or HH:mm (24-hr time)
- */
-export function getTimeFormat (config) {
- return (config.dateTime && config.dateTime.timeFormat)
- ? config.dateTime.timeFormat
- : OTP_API_TIME_FORMAT
-}
-
-export function getDateFormat (config) {
- return (config.dateTime && config.dateTime.dateFormat)
- ? config.dateTime.dateFormat
- : OTP_API_DATE_FORMAT
-}
-
-export function getLongDateFormat (config) {
- return (config.dateTime && config.dateTime.longDateFormat)
- ? config.dateTime.longDateFormat
- : 'D MMMM YYYY'
-}
-
-/**
- * Formats an elapsed time duration for display in narrative
- * TODO: internationalization
- * @param {number} seconds duration in seconds
- * @returns {string} formatted text representation
- */
-export function formatDuration (seconds) {
- const dur = moment.duration(seconds, 'seconds')
- let text = ''
- if (dur.hours() > 0) text += dur.hours() + ' hr, '
- text += dur.minutes() + ' min'
- return text
-}
-
-/**
- * Formats a time value for display in narrative
- * TODO: internationalization/timezone
- * @param {number} ms epoch time value in milliseconds
- * @returns {string} formatted text representation
- */
-export function formatTime (ms, options) {
- return moment(ms + (options && options.offset ? options.offset : 0))
- .format(options && options.format ? options.format : OTP_API_TIME_FORMAT)
-}
-
-/**
- * Formats a seconds after midnight value for display in narrative
- * @param {number} seconds time since midnight in seconds
- * @param {string} timeFormat A valid moment.js time format
- * @return {string} formatted text representation
- */
-export function formatSecondsAfterMidnight (seconds, timeFormat) {
- return moment().startOf('day').seconds(seconds).format(timeFormat)
-}
-
-/**
- * Formats current time for use in OTP query
- * The conversion to the user's timezone is needed for testing purposes.
- */
-export function getCurrentTime () {
- return moment().tz(getUserTimezone()).format(OTP_API_TIME_FORMAT)
-}
-
-/**
- * Formats current date for use in OTP query
- * The conversion to the user's timezone is needed for testing purposes.
- */
-export function getCurrentDate (config) {
- return moment().tz(getUserTimezone()).format(OTP_API_DATE_FORMAT)
-}
-
-/**
- * Get the timezone name that is set for the user that is currently looking at
- * this website. Use a bit of hackery to force a specific timezone if in a
- * test environment.
- */
-export function getUserTimezone () {
- return process.env.NODE_ENV === 'test' ? process.env.TZ : moment.tz.guess()
-}
From 9d5c408ba92fb00ab20aa508a8a9a7fbe12897ce Mon Sep 17 00:00:00 2001
From: binh-dam-ibigroup <56846598+binh-dam-ibigroup@users.noreply.github.com>
Date: Wed, 8 Apr 2020 11:05:56 -0400
Subject: [PATCH 18/31] refactor(util/query-params): Replace query-params with
@opentripplanner/core-utils/query-params.
---
lib/actions/api.js | 2 +-
lib/components/viewers/trip-viewer.js | 1 -
lib/util/query-params.js | 546 --------------------------
lib/util/query.js | 21 +-
4 files changed, 18 insertions(+), 552 deletions(-)
delete mode 100644 lib/util/query-params.js
diff --git a/lib/actions/api.js b/lib/actions/api.js
index f717450fd..b15855e40 100644
--- a/lib/actions/api.js
+++ b/lib/actions/api.js
@@ -3,6 +3,7 @@ import { push, replace } from 'connected-react-router'
import haversine from 'haversine'
import moment from 'moment'
import hash from 'object-hash'
+import queryParams from '@opentripplanner/core-utils/lib/query-params'
import { randId } from '@opentripplanner/core-utils/lib/storage'
import { OTP_API_DATE_FORMAT, OTP_API_TIME_FORMAT } from '@opentripplanner/core-utils/lib/time'
import { createAction } from 'redux-actions'
@@ -11,7 +12,6 @@ import qs from 'qs'
import { rememberPlace } from './map'
import { hasCar } from '../util/itinerary'
import { getTripOptionsFromQuery, getUrlParams } from '../util/query'
-import queryParams from '../util/query-params'
import { getStopViewerConfig, queryIsValid } from '../util/state'
if (typeof (fetch) === 'undefined') require('isomorphic-fetch')
diff --git a/lib/components/viewers/trip-viewer.js b/lib/components/viewers/trip-viewer.js
index 821f5d091..d517938aa 100644
--- a/lib/components/viewers/trip-viewer.js
+++ b/lib/components/viewers/trip-viewer.js
@@ -11,7 +11,6 @@ import { setViewedTrip } from '../../actions/ui'
import { findTrip } from '../../actions/api'
import { setLocation } from '../../actions/map'
-
class TripViewer extends Component {
static propTypes = {
hideBackButton: PropTypes.bool,
diff --git a/lib/util/query-params.js b/lib/util/query-params.js
deleted file mode 100644
index 94ebf17e2..000000000
--- a/lib/util/query-params.js
+++ /dev/null
@@ -1,546 +0,0 @@
-import {
- isTransit,
- isAccessMode,
- isCar,
- hasTransit,
- hasBike,
- hasMicromobility
-} from './itinerary'
-import { getItem } from './storage'
-import { getCurrentDate, getCurrentTime } from './time'
-
-/**
- * name: the default name of the parameter used for internal reference and API calls
- *
- * routingTypes: array of routing type(s) (ITINERARY, PROFILE, or both) this param applies to
- *
- * applicable: an optional function (accepting the current full query as a
- * parameter) indicating whether this query parameter is applicable to the query.
- * (Applicability is assumed if this function is not provided.)
- *
- * default: the default value for this parameter. The default can be also be a
- * function that gets executed when accessing the default value. When the value
- * is a funciton, it will take an argument of the current config of the otp-rr
- * store. This is needed when a brand new time-dependent value is desired to be
- * calculated. It's also helpful for producing tests that have consistent data
- * output.
- *
- * itineraryRewrite: an optional function for translating the key and/or value
- * for ITINERARY mode only (e.g. 'to' is rewritten as 'toPlace'). Accepts the
- * intial internal value as a function parameter.
- *
- * profileRewrite: an optional function for translating the value for PROFILE mode
- *
- * label: a text label for for onscreen display. May either be a text string or a
- * function (accepting the current full query as a parameter) returning a string
- *
- * selector: the default type of UI selector to use in the form. Can be one of:
- * - DROPDOWN: a standard drop-down menu selector
- *
- * options: an array of text/value pairs used with a dropdown selector
- *
- * TODO: validation system for rewrite functions and/or better user documentation
- * TODO: alphabetize below list
- */
-
-// FIXME: Use for parsing URL values?
-// const stringToLocation = string => {
-// const split = string.split(',')
-// return split.length === 2
-// ? {lat: split[0], lon: split[1]}
-// : {lat: null, lon: null}
-// }
-
-const formatPlace = (location, alternateName) => {
- if (!location) return null
- const name = location.name || `${alternateName || 'Place'} (${location.lat},${location.lon})`
- return `${name}::${location.lat},${location.lon}`
-}
-
-// Load stored default query settings from local storage
-let storedSettings = getItem('defaultQuery', {})
-
-const queryParams = [
- { /* from - the trip origin. stored internally as a location (lat/lon/name) object */
- name: 'from',
- routingTypes: [ 'ITINERARY', 'PROFILE' ],
- default: null,
- itineraryRewrite: value => ({ fromPlace: formatPlace(value, 'Origin') }),
- profileRewrite: value => ({ from: { lat: value.lat, lon: value.lon } })
- // FIXME: Use for parsing URL values?
- // fromURL: stringToLocation
- },
-
- { /* to - the trip destination. stored internally as a location (lat/lon/name) object */
- name: 'to',
- routingTypes: [ 'ITINERARY', 'PROFILE' ],
- default: null,
- itineraryRewrite: value => ({ toPlace: formatPlace(value, 'Destination') }),
- profileRewrite: value => ({ to: { lat: value.lat, lon: value.lon } })
- // FIXME: Use for parsing URL values?
- // fromURL: stringToLocation
- },
-
- { /* date - the date of travel, in MM-DD-YYYY format */
- name: 'date',
- routingTypes: [ 'ITINERARY', 'PROFILE' ],
- default: getCurrentDate
- },
-
- { /* time - the arrival/departure time for an itinerary trip, in HH:mm format */
- name: 'time',
- routingTypes: [ 'ITINERARY' ],
- default: getCurrentTime
- },
-
- { /* departArrive - whether this is a depart-at, arrive-by, or leave-now trip */
- name: 'departArrive',
- routingTypes: [ 'ITINERARY' ],
- default: 'NOW',
- itineraryRewrite: value => ({ arriveBy: (value === 'ARRIVE') })
- },
-
- { /* startTime - the start time for a profile trip, in HH:mm format */
- name: 'startTime',
- routingTypes: [ 'PROFILE' ],
- default: '07:00'
- },
-
- { /* endTime - the end time for a profile trip, in HH:mm format */
- name: 'endTime',
- routingTypes: [ 'PROFILE' ],
- default: '09:00'
- },
-
- { /* mode - the allowed modes for a trip, as a comma-separated list */
- name: 'mode',
- routingTypes: [ 'ITINERARY', 'PROFILE' ],
- default: 'WALK,TRANSIT', // TODO: make this dependent on routingType?
- profileRewrite: value => {
- const accessModes = []
- const directModes = []
- const transitModes = []
-
- if (value && value.length > 0) {
- value.split(',').forEach(m => {
- if (isTransit(m)) transitModes.push(m)
- if (isAccessMode(m)) {
- accessModes.push(m)
- // TODO: make configurable whether direct-driving is considered
- if (!isCar(m)) directModes.push(m)
- }
- })
- }
-
- return { accessModes, directModes, transitModes }
- }
- },
-
- { /* showIntermediateStops - whether response should include intermediate stops for transit legs */
- name: 'showIntermediateStops',
- routingTypes: [ 'ITINERARY' ],
- default: true
- },
-
- { /* maxWalkDistance - the maximum distance in meters the user will walk to transit. */
- name: 'maxWalkDistance',
- routingTypes: [ 'ITINERARY' ],
- applicable: query => query.mode && hasTransit(query.mode) && query.mode.indexOf('WALK') !== -1,
- default: 1207, // 3/4 mi.
- selector: 'DROPDOWN',
- label: 'Maximum Walk',
- options: [
- {
- text: '1/10 mile',
- value: 160.9
- }, {
- text: '1/4 mile',
- value: 402.3
- }, {
- text: '1/2 mile',
- value: 804.7
- }, {
- text: '3/4 mile',
- value: 1207
- }, {
- text: '1 mile',
- value: 1609
- }, {
- text: '2 miles',
- value: 3219
- }, {
- text: '5 miles',
- value: 8047
- }
- ]
- },
-
- { /* maxBikeDistance - the maximum distance in meters the user will bike. Not
- * actually an OTP parameter (maxWalkDistance doubles for biking) but we
- * store it separately internally in order to allow different default values,
- * options, etc. Translated to 'maxWalkDistance' via the rewrite function.
- */
- name: 'maxBikeDistance',
- routingTypes: [ 'ITINERARY' ],
- applicable: query => query.mode && hasTransit(query.mode) && query.mode.indexOf('BICYCLE') !== -1,
- default: 4828, // 3 mi.
- selector: 'DROPDOWN',
- label: 'Maximum Bike',
- options: [
- {
- text: '1/4 mile',
- value: 402.3
- }, {
- text: '1/2 mile',
- value: 804.7
- }, {
- text: '3/4 mile',
- value: 1207
- }, {
- text: '1 mile',
- value: 1609
- }, {
- text: '2 miles',
- value: 3219
- }, {
- text: '3 miles',
- value: 4828
- }, {
- text: '5 miles',
- value: 8047
- }, {
- text: '10 miles',
- value: 16093
- }, {
- text: '20 miles',
- value: 32187
- }, {
- text: '30 miles',
- value: 48280
- }
- ],
- itineraryRewrite: value => ({
- maxWalkDistance: value,
- // ensures that the value is repopulated when loaded from URL params
- maxBikeDistance: value
- })
- },
-
- { /* optimize -- how to optimize a trip (non-bike, non-micromobility trips) */
- name: 'optimize',
- applicable: query => hasTransit(query.mode) && !hasBike(query.mode),
- routingTypes: [ 'ITINERARY' ],
- default: 'QUICK',
- selector: 'DROPDOWN',
- label: 'Optimize for',
- options: [
- {
- text: 'Speed',
- value: 'QUICK'
- }, {
- text: 'Fewest Transfers',
- value: 'TRANSFERS'
- }
- ]
- },
-
- { /* optimizeBike -- how to optimize an bike-based trip */
- name: 'optimizeBike',
- applicable: query => hasBike(query.mode),
- routingTypes: [ 'ITINERARY' ],
- default: 'SAFE',
- selector: 'DROPDOWN',
- label: 'Optimize for',
- options: query => {
- const opts = [{
- text: 'Speed',
- value: 'QUICK'
- }, {
- text: 'Bike-Friendly Trip',
- value: 'SAFE'
- }, {
- text: 'Flat Trip',
- value: 'FLAT'
- }]
-
- // Include transit-specific option, if applicable
- if (hasTransit(query.mode)) {
- opts.splice(1, 0, {
- text: 'Fewest Transfers',
- value: 'TRANSFERS'
- })
- }
-
- return opts
- },
- itineraryRewrite: value => ({ optimize: value })
- },
-
- { /* maxWalkTime -- the maximum time the user will spend walking in minutes */
- name: 'maxWalkTime',
- routingTypes: [ 'PROFILE' ],
- default: 15,
- selector: 'DROPDOWN',
- label: 'Max Walk Time',
- applicable: query => query.mode && hasTransit(query.mode) && query.mode.indexOf('WALK') !== -1,
- options: [
- {
- text: '5 minutes',
- value: 5
- }, {
- text: '10 minutes',
- value: 10
- }, {
- text: '15 minutes',
- value: 15
- }, {
- text: '20 minutes',
- value: 20
- }, {
- text: '30 minutes',
- value: 30
- }, {
- text: '45 minutes',
- value: 45
- }, {
- text: '1 hour',
- value: 60
- }
- ]
- },
-
- { /* walkSpeed -- the user's walking speed in m/s */
- name: 'walkSpeed',
- routingTypes: [ 'ITINERARY', 'PROFILE' ],
- default: 1.34,
- selector: 'DROPDOWN',
- label: 'Walk Speed',
- applicable: query => query.mode && query.mode.indexOf('WALK') !== -1,
- options: [
- {
- text: '2 MPH',
- value: 0.89
- }, {
- text: '3 MPH',
- value: 1.34
- }, {
- text: '4 MPH',
- value: 1.79
- }
- ]
- },
-
- { /* maxBikeTime -- the maximum time the user will spend biking in minutes */
- name: 'maxBikeTime',
- routingTypes: [ 'PROFILE' ],
- default: 20,
- selector: 'DROPDOWN',
- label: 'Max Bike Time',
- applicable: query => query.mode && hasTransit(query.mode) && query.mode.indexOf('BICYCLE') !== -1,
- options: [
- {
- text: '5 minutes',
- value: 5
- }, {
- text: '10 minutes',
- value: 10
- }, {
- text: '15 minutes',
- value: 15
- }, {
- text: '20 minutes',
- value: 20
- }, {
- text: '30 minutes',
- value: 30
- }, {
- text: '45 minutes',
- value: 45
- }, {
- text: '1 hour',
- value: 60
- }
- ]
- },
-
- { /* bikeSpeed -- the user's bikeSpeed speed in m/s */
- name: 'bikeSpeed',
- routingTypes: [ 'ITINERARY', 'PROFILE' ],
- default: 3.58,
- selector: 'DROPDOWN',
- label: 'Bicycle Speed',
- applicable: query => query.mode && query.mode.indexOf('BICYCLE') !== -1,
- options: [
- {
- text: '6 MPH',
- value: 2.68
- }, {
- text: '8 MPH',
- value: 3.58
- }, {
- text: '10 MPH',
- value: 4.47
- }, {
- text: '12 MPH',
- value: 5.36
- }
- ]
- },
-
- { /* maxEScooterDistance - the maximum distance in meters the user will ride
- * an E-scooter. Not actually an OTP parameter (maxWalkDistance doubles for
- * any non-transit mode except for car) but we store it separately
- * internally in order to allow different default values, options, etc.
- * Translated to 'maxWalkDistance' via the rewrite function.
- */
- name: 'maxEScooterDistance',
- routingTypes: [ 'ITINERARY' ],
- applicable: query => query.mode && hasTransit(query.mode) && hasMicromobility(query.mode),
- default: 4828, // 3 mi.
- selector: 'DROPDOWN',
- label: 'Maximum E-scooter Distance',
- options: [
- {
- text: '1/4 mile',
- value: 402.3
- }, {
- text: '1/2 mile',
- value: 804.7
- }, {
- text: '3/4 mile',
- value: 1207
- }, {
- text: '1 mile',
- value: 1609
- }, {
- text: '2 miles',
- value: 3219
- }, {
- text: '3 miles',
- value: 4828
- }, {
- text: '5 miles',
- value: 8047
- }, {
- text: '10 miles',
- value: 16093
- }, {
- text: '20 miles',
- value: 32187
- }, {
- text: '30 miles',
- value: 48280
- }
- ],
- itineraryRewrite: value => ({
- maxWalkDistance: value,
- // ensures that the value is repopulated when loaded from URL params
- maxEScooterDistance: value
- })
- },
-
- { /* bikeSpeed -- the user's bikeSpeed speed in m/s */
- name: 'watts',
- routingTypes: [ 'ITINERARY', 'PROFILE' ],
- default: 250,
- selector: 'DROPDOWN',
- label: 'E-scooter Power',
- // this configuration should only be allowed for personal E-scooters as these
- // settings will be defined by the vehicle type of an E-scooter being rented
- applicable: query => (
- query.mode &&
- query.mode.indexOf('MICROMOBILITY') !== -1 &&
- query.mode.indexOf('MICROMOBILITY_RENT') === -1
- ),
- options: [
- {
- text: 'Kid\'s hoverboard (6mph)',
- value: 125
- }, {
- text: 'Entry-level scooter (11mph)',
- value: 250
- }, {
- text: 'Robust E-scooter (18mph)',
- value: 500
- }, {
- text: 'Powerful E-scooter (24mph)',
- value: 1500
- }
- ],
- // rewrite a few other values to add some baseline assumptions about the
- // vehicle
- itineraryRewrite: value => {
- const watts = value
- // the maximum cruising and downhill speed. Units in m/s
- let maximumMicromobilitySpeed
- let weight
- // see https://en.wikipedia.org/wiki/Human_body_weight#Average_weight_around_the_world
- // estimate is for an average North American human with clothes and stuff
- // units are in kg
- const TYPICAL_RIDER_WEIGHT = 90
- switch (watts) {
- case 125:
- // exemplar: Swagtron Turbo 5 hoverboard (https://swagtron.com/product/recertified-swagtron-turbo-five-hoverboard-classic/)
- maximumMicromobilitySpeed = 2.8 // ~= 6mph
- weight = TYPICAL_RIDER_WEIGHT + 9
- break
- case 250:
- // exemplar: Xiaomi M365 (https://www.gearbest.com/skateboard/pp_596618.html)
- maximumMicromobilitySpeed = 5 // ~= 11.5mph
- weight = TYPICAL_RIDER_WEIGHT + 12.5
- break
- case 500:
- // exemplar: Razor EcoSmart Metro (https://www.amazon.com/Razor-EcoSmart-Metro-Electric-Scooter/dp/B002ZDAEIS?SubscriptionId=AKIAJMXJ2YFJTEDLQMUQ&tag=digitren08-20&linkCode=xm2&camp=2025&creative=165953&creativeASIN=B002ZDAEIS&ascsubtag=15599460143449ocb)
- maximumMicromobilitySpeed = 8 // ~= 18mph
- weight = TYPICAL_RIDER_WEIGHT + 30
- break
- case 1000:
- // exemplar: Boosted Rev (https://boostedboards.com/vehicles/scooters/boosted-rev)
- maximumMicromobilitySpeed = 11 // ~= 24mph
- weight = TYPICAL_RIDER_WEIGHT + 21
- break
- }
- return {maximumMicromobilitySpeed, watts, weight}
- }
- },
-
- { /* ignoreRealtimeUpdates -- if true, do not use realtime updates in routing */
- name: 'ignoreRealtimeUpdates',
- routingTypes: [ 'ITINERARY' ],
- default: false
- },
-
- { /* companies -- tnc companies to query */
- name: 'companies',
- routingTypes: [ 'ITINERARY' ],
- default: null
- },
-
- { /* wheelchair -- whether the user requires a wheelchair-accessible trip */
- name: 'wheelchair',
- routingTypes: [ 'ITINERARY' ],
- default: false,
- selector: 'CHECKBOX',
- label: 'Wheelchair Accessible',
- applicable: (query, config) => {
- if (!query.mode || !config.modes) return false
- const configModes = (config.modes.accessModes || []).concat(config.modes.transitModes || [])
- for (const mode of query.mode.split(',')) {
- const configMode = configModes.find(m => m.mode === mode)
- if (!configMode || !configMode.showWheelchairSetting) continue
- if (configMode.company && (!query.companies || !query.companies.split(',').includes(configMode.company))) continue
- return true
- }
- }
- }
-]
-// Iterate over stored settings and update query param defaults.
-// FIXME: this does not get updated if the user defaults are cleared
-queryParams.forEach(param => {
- if (param.name in storedSettings) {
- param.default = storedSettings[param.name]
- param.userDefaultOverride = true
- }
-})
-
-export default queryParams
diff --git a/lib/util/query.js b/lib/util/query.js
index 5779108c7..a667e1172 100644
--- a/lib/util/query.js
+++ b/lib/util/query.js
@@ -1,13 +1,13 @@
+import { coordsToString, matchLatLon, stringToCoords } from '@opentripplanner/core-utils/lib/map'
+import queryParams from '@opentripplanner/core-utils/lib/query-params'
+import { getCurrentTime, getCurrentDate } from '@opentripplanner/core-utils/lib/time'
import qs from 'qs'
import { getTransitModes, hasTransit, isAccessMode, toSentenceCase } from './itinerary'
-import { coordsToString, matchLatLon, stringToCoords } from './map'
-import queryParams from './query-params'
import { getActiveSearch } from './state'
-import { getCurrentTime, getCurrentDate } from './time'
/* The list of default parameters considered in the settings panel */
-
+// Good to go.
export const defaultParams = [
'wheelchair',
'maxWalkDistance',
@@ -22,6 +22,7 @@ export const defaultParams = [
'watts'
]
+// Good to go.
/* A function to retrieve a property value from an entry in the query-params
* table, checking for either a static value or a function */
@@ -31,6 +32,7 @@ export function getQueryParamProperty (paramInfo, property, query) {
: paramInfo[property]
}
+// Good to go.
export function ensureSingleAccessMode (queryModes) {
// Count the number of access modes
const accessCount = queryModes.filter(m => isAccessMode(m)).length
@@ -48,19 +50,23 @@ export function ensureSingleAccessMode (queryModes) {
return queryModes
}
+// Good to go.
export function getUrlParams () {
return qs.parse(window.location.href.split('?')[1])
}
+// Good to go.
export function getOtpUrlParams () {
return Object.keys(getUrlParams()).filter(key => !key.startsWith('ui_'))
}
+// Good to go.
function findLocationType (location, locations = [], types = ['home', 'work', 'suggested']) {
const match = locations.find(l => matchLatLon(l, location))
return match && types.indexOf(match.type) !== -1 ? match.type : null
}
+// Good to go.
export function summarizeQuery (query, locations = []) {
const from = findLocationType(query.from, locations) || query.from.name.split(',')[0]
const to = findLocationType(query.to, locations) || query.to.name.split(',')[0]
@@ -70,6 +76,7 @@ export function summarizeQuery (query, locations = []) {
return `${mode} from ${from} to ${to}`
}
+// CHECK THIS ONE => Used in handleBackButtonPRess
/**
* Assemble any UI-state properties to be tracked via URL into a single object
* TODO: Expand to include additional UI properties
@@ -84,6 +91,7 @@ export function getUiUrlParams (otpState) {
return uiParams
}
+// Good to go.
export function getTripOptionsFromQuery (query, keepPlace = false) {
const options = Object.assign({}, query)
// Delete time/date options and from/to
@@ -97,6 +105,7 @@ export function getTripOptionsFromQuery (query, keepPlace = false) {
return options
}
+// Good to go.
/**
* Gets the default query param by executing the default value function with the
* provided otp config if the default value is a function.
@@ -105,6 +114,7 @@ function getDefaultQueryParamValue (param, config) {
return typeof param.default === 'function' ? param.default(config) : param.default
}
+// Good to go.
/**
* Determines whether the specified query differs from the default query, i.e.,
* whether the user has modified any trip options (including mode) from their
@@ -135,6 +145,7 @@ export function isNotDefaultQuery (query, config) {
return queryIsDifferent
}
+// Good to go.
/**
* Get the default query to OTP based on the given config.
*
@@ -148,6 +159,7 @@ export function getDefaultQuery (config) {
return defaultQuery
}
+// Good to go.
/**
* Create a otp query based on a the url params.
*
@@ -186,6 +198,7 @@ export function planParamsToQuery (params, config) {
return query
}
+// Good to go.
/**
* OTP allows passing a location in the form '123 Main St::lat,lon', so we check
* for the double colon and parse the coordinates accordingly.
From 66ad883afca29891dac97fa071709fc250643cf6 Mon Sep 17 00:00:00 2001
From: binh-dam-ibigroup <56846598+binh-dam-ibigroup@users.noreply.github.com>
Date: Wed, 8 Apr 2020 11:30:58 -0400
Subject: [PATCH 19/31] refactor(util/ui): Replace util/ui with
@opentripplanner/core-utils/ui (except getTitle(state))
---
lib/actions/form.js | 2 +-
lib/components/app/responsive-webapp.js | 15 ++++---
lib/components/form/plan-trip-button.js | 4 +-
lib/components/mobile/results-screen.js | 2 +-
lib/components/narrative/default/tnc-leg.js | 2 +-
lib/util/ui.js | 50 +--------------------
6 files changed, 14 insertions(+), 61 deletions(-)
diff --git a/lib/actions/form.js b/lib/actions/form.js
index 5d73405f1..faf9750fb 100644
--- a/lib/actions/form.js
+++ b/lib/actions/form.js
@@ -3,6 +3,7 @@ import isEqual from 'lodash.isequal'
import moment from 'moment'
import { getItem, randId } from '@opentripplanner/core-utils/lib/storage'
import { OTP_API_TIME_FORMAT } from '@opentripplanner/core-utils/lib/time'
+import { isMobile } from '@opentripplanner/core-utils/lib/ui'
import { createAction } from 'redux-actions'
import {
@@ -12,7 +13,6 @@ import {
planParamsToQuery
} from '../util/query'
import { queryIsValid } from '../util/state'
-import { isMobile } from '../util/ui'
import {
MobileScreens,
setMainPanelContent,
diff --git a/lib/components/app/responsive-webapp.js b/lib/components/app/responsive-webapp.js
index 284200975..7c52b70a3 100644
--- a/lib/components/app/responsive-webapp.js
+++ b/lib/components/app/responsive-webapp.js
@@ -1,19 +1,20 @@
-import React, { Component } from 'react'
+import { ConnectedRouter } from 'connected-react-router'
+import { createHashHistory } from 'history'
+import isEqual from 'lodash.isequal'
+import { isMobile } from '@opentripplanner/core-utils/lib/ui'
import PropTypes from 'prop-types'
+import React, { Component } from 'react'
import { connect } from 'react-redux'
-import isEqual from 'lodash.isequal'
import { Route, Switch, withRouter } from 'react-router'
-import { createHashHistory } from 'history'
-import { ConnectedRouter } from 'connected-react-router'
import PrintLayout from './print-layout'
import { setMapCenter, setMapZoom } from '../../actions/config'
-import { setLocationToCurrent } from '../../actions/map'
-import { getCurrentPosition, receivedPositionResponse } from '../../actions/location'
import { formChanged, parseUrlQueryString } from '../../actions/form'
+import { getCurrentPosition, receivedPositionResponse } from '../../actions/location'
+import { setLocationToCurrent } from '../../actions/map'
import { handleBackButtonPress, matchContentToUrl } from '../../actions/ui'
import { getUrlParams } from '../../util/query'
-import { getTitle, isMobile } from '../../util/ui'
+import { getTitle } from '../../util/ui'
import { getActiveItinerary } from '../../util/state'
class ResponsiveWebapp extends Component {
diff --git a/lib/components/form/plan-trip-button.js b/lib/components/form/plan-trip-button.js
index b619e647b..73d2de18a 100644
--- a/lib/components/form/plan-trip-button.js
+++ b/lib/components/form/plan-trip-button.js
@@ -1,11 +1,11 @@
-import React, { Component } from 'react'
+import { isMobile } from '@opentripplanner/core-utils/lib/ui'
import PropTypes from 'prop-types'
+import React, { Component } from 'react'
import { Button } from 'react-bootstrap'
import { connect } from 'react-redux'
import { routingQuery } from '../../actions/api'
import { setMainPanelContent } from '../../actions/ui'
-import { isMobile } from '../../util/ui'
class PlanTripButton extends Component {
static propTypes = {
diff --git a/lib/components/mobile/results-screen.js b/lib/components/mobile/results-screen.js
index b8c73cc47..fce9656cc 100644
--- a/lib/components/mobile/results-screen.js
+++ b/lib/components/mobile/results-screen.js
@@ -1,3 +1,4 @@
+import { enableScrollForSelector } from '@opentripplanner/core-utils/lib/ui'
import LocationIcon from '@opentripplanner/location-icon'
import PropTypes from 'prop-types'
import React, { Component } from 'react'
@@ -16,7 +17,6 @@ import { MobileScreens, setMobileScreen } from '../../actions/ui'
import { setUseRealtimeResponse } from '../../actions/narrative'
import { clearActiveSearch } from '../../actions/form'
import { getActiveSearch, getRealtimeEffects } from '../../util/state'
-import { enableScrollForSelector } from '../../util/ui'
const LocationContainer = styled.div`
font-weight: 300;
diff --git a/lib/components/narrative/default/tnc-leg.js b/lib/components/narrative/default/tnc-leg.js
index afd1ddb22..905f0da4e 100644
--- a/lib/components/narrative/default/tnc-leg.js
+++ b/lib/components/narrative/default/tnc-leg.js
@@ -1,5 +1,6 @@
import currencyFormatter from 'currency-formatter'
import { formatDuration } from '@opentripplanner/core-utils/lib/time'
+import { isMobile } from '@opentripplanner/core-utils/lib/ui'
import PropTypes from 'prop-types'
import React, { Component } from 'react'
import { connect } from 'react-redux'
@@ -9,7 +10,6 @@ import {
getTransportationNetworkCompanyRideEstimate
} from '../../../actions/api'
import { toSentenceCase } from '../../../util/itinerary'
-import { isMobile } from '../../../util/ui'
class TransportationNetworkCompanyLeg extends Component {
static propTypes = {
diff --git a/lib/util/ui.js b/lib/util/ui.js
index bf5be4753..b577f84fc 100644
--- a/lib/util/ui.js
+++ b/lib/util/ui.js
@@ -5,55 +5,7 @@ import { getActiveSearch } from './state'
// Set default title to the original document title (on load) set in index.html
const DEFAULT_TITLE = document.title
-export function isMobile () {
- // TODO: consider using 3rd-party library?
- return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)
-}
-
-/**
- * Enables scrolling for a specified selector, while disabling scrolling for all
- * other targets. This is adapted from https://stackoverflow.com/a/41601290/915811
- * and intended to fix issues with iOS elastic scrolling, e.g.,
- * https://github.com/conveyal/trimet-mod-otp/issues/92.
- */
-export function enableScrollForSelector (selector) {
- const _overlay = document.querySelector(selector)
- let _clientY = null // remember Y position on touch start
-
- _overlay.addEventListener('touchstart', function (event) {
- if (event.targetTouches.length === 1) {
- // detect single touch
- _clientY = event.targetTouches[0].clientY
- }
- }, false)
-
- _overlay.addEventListener('touchmove', function (event) {
- if (event.targetTouches.length === 1) {
- // detect single touch
- disableRubberBand(event)
- }
- }, false)
-
- function disableRubberBand (event) {
- const clientY = event.targetTouches[0].clientY - _clientY
-
- if (_overlay.scrollTop === 0 && clientY > 0) {
- // element is at the top of its scroll
- event.preventDefault()
- }
-
- if (isOverlayTotallyScrolled() && clientY < 0) {
- // element is at the top of its scroll
- event.preventDefault()
- }
- }
-
- function isOverlayTotallyScrolled () {
- // https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollHeight#Problems_and_solutions
- return _overlay.scrollHeight - _overlay.scrollTop <= _overlay.clientHeight
- }
-}
-
+// This needs to stay.
export function getTitle (state) {
// Override title can optionally be provided in config.yml
const { config, ui, user } = state.otp
From b868238b68028dfc34c97f975debc32475df7140 Mon Sep 17 00:00:00 2001
From: binh-dam-ibigroup <56846598+binh-dam-ibigroup@users.noreply.github.com>
Date: Wed, 8 Apr 2020 11:59:37 -0400
Subject: [PATCH 20/31] refactor(util/query): Replace util/query with
@opentripplanner/core-utils/query (except getUiUrlPara
---
lib/actions/api.js | 2 +-
lib/actions/form.js | 12 +-
lib/actions/narrative.js | 2 +-
lib/actions/ui.js | 5 +-
lib/components/app/responsive-webapp.js | 2 +-
lib/components/form/settings-preview.js | 5 +-
lib/components/form/user-settings.js | 2 +-
lib/components/form/user-trip-settings.js | 2 +-
lib/reducers/create-otp-reducer.js | 8 +-
lib/util/query.js | 206 +---------------------
lib/util/ui.js | 4 +-
11 files changed, 23 insertions(+), 227 deletions(-)
diff --git a/lib/actions/api.js b/lib/actions/api.js
index b15855e40..4731a9353 100644
--- a/lib/actions/api.js
+++ b/lib/actions/api.js
@@ -3,6 +3,7 @@ import { push, replace } from 'connected-react-router'
import haversine from 'haversine'
import moment from 'moment'
import hash from 'object-hash'
+import { getTripOptionsFromQuery, getUrlParams } from '@opentripplanner/core-utils/lib/query'
import queryParams from '@opentripplanner/core-utils/lib/query-params'
import { randId } from '@opentripplanner/core-utils/lib/storage'
import { OTP_API_DATE_FORMAT, OTP_API_TIME_FORMAT } from '@opentripplanner/core-utils/lib/time'
@@ -11,7 +12,6 @@ import qs from 'qs'
import { rememberPlace } from './map'
import { hasCar } from '../util/itinerary'
-import { getTripOptionsFromQuery, getUrlParams } from '../util/query'
import { getStopViewerConfig, queryIsValid } from '../util/state'
if (typeof (fetch) === 'undefined') require('isomorphic-fetch')
diff --git a/lib/actions/form.js b/lib/actions/form.js
index faf9750fb..b1a1011d8 100644
--- a/lib/actions/form.js
+++ b/lib/actions/form.js
@@ -1,17 +1,17 @@
import debounce from 'lodash.debounce'
import isEqual from 'lodash.isequal'
import moment from 'moment'
-import { getItem, randId } from '@opentripplanner/core-utils/lib/storage'
-import { OTP_API_TIME_FORMAT } from '@opentripplanner/core-utils/lib/time'
-import { isMobile } from '@opentripplanner/core-utils/lib/ui'
-import { createAction } from 'redux-actions'
-
import {
getDefaultQuery,
getTripOptionsFromQuery,
getUrlParams,
planParamsToQuery
-} from '../util/query'
+} from '@opentripplanner/core-utils/lib/query'
+import { getItem, randId } from '@opentripplanner/core-utils/lib/storage'
+import { OTP_API_TIME_FORMAT } from '@opentripplanner/core-utils/lib/time'
+import { isMobile } from '@opentripplanner/core-utils/lib/ui'
+import { createAction } from 'redux-actions'
+
import { queryIsValid } from '../util/state'
import {
MobileScreens,
diff --git a/lib/actions/narrative.js b/lib/actions/narrative.js
index 8f016a400..c69c78cc7 100644
--- a/lib/actions/narrative.js
+++ b/lib/actions/narrative.js
@@ -1,7 +1,7 @@
+import { getUrlParams } from '@opentripplanner/core-utils/lib/query'
import { createAction } from 'redux-actions'
import { setUrlSearch } from './api'
-import { getUrlParams } from '../util/query'
export function setActiveItinerary (payload) {
return function (dispatch, getState) {
diff --git a/lib/actions/ui.js b/lib/actions/ui.js
index ad04d2805..02f7374a8 100644
--- a/lib/actions/ui.js
+++ b/lib/actions/ui.js
@@ -1,13 +1,14 @@
+import { push } from 'connected-react-router'
+import { getUrlParams } from '@opentripplanner/core-utils/lib/query'
import { createAction } from 'redux-actions'
import { matchPath } from 'react-router'
-import { push } from 'connected-react-router'
import { findRoute } from './api'
import { setMapCenter, setMapZoom, setRouterId } from './config'
import { clearActiveSearch, parseUrlQueryString, setActiveSearch } from './form'
import { clearLocation } from './map'
import { setActiveItinerary } from './narrative'
-import { getUiUrlParams, getUrlParams } from '../util/query'
+import { getUiUrlParams } from '../util/query'
/**
* Wrapper function for history#push that preserves the current search or, if
diff --git a/lib/components/app/responsive-webapp.js b/lib/components/app/responsive-webapp.js
index 7c52b70a3..233596914 100644
--- a/lib/components/app/responsive-webapp.js
+++ b/lib/components/app/responsive-webapp.js
@@ -1,6 +1,7 @@
import { ConnectedRouter } from 'connected-react-router'
import { createHashHistory } from 'history'
import isEqual from 'lodash.isequal'
+import { getUrlParams } from '@opentripplanner/core-utils/lib/query'
import { isMobile } from '@opentripplanner/core-utils/lib/ui'
import PropTypes from 'prop-types'
import React, { Component } from 'react'
@@ -13,7 +14,6 @@ import { formChanged, parseUrlQueryString } from '../../actions/form'
import { getCurrentPosition, receivedPositionResponse } from '../../actions/location'
import { setLocationToCurrent } from '../../actions/map'
import { handleBackButtonPress, matchContentToUrl } from '../../actions/ui'
-import { getUrlParams } from '../../util/query'
import { getTitle } from '../../util/ui'
import { getActiveItinerary } from '../../util/state'
diff --git a/lib/components/form/settings-preview.js b/lib/components/form/settings-preview.js
index 1cefa4d98..4a3c78575 100644
--- a/lib/components/form/settings-preview.js
+++ b/lib/components/form/settings-preview.js
@@ -1,10 +1,9 @@
-import React, { Component } from 'react'
+import { isNotDefaultQuery } from '@opentripplanner/core-utils/lib/query'
import PropTypes from 'prop-types'
+import React, { Component } from 'react'
import { Button } from 'react-bootstrap'
import { connect } from 'react-redux'
-import { isNotDefaultQuery } from '../../util/query'
-
class SettingsPreview extends Component {
static propTypes = {
// component props
diff --git a/lib/components/form/user-settings.js b/lib/components/form/user-settings.js
index 159668ce5..c7878839b 100644
--- a/lib/components/form/user-settings.js
+++ b/lib/components/form/user-settings.js
@@ -1,5 +1,6 @@
import moment from 'moment'
import { getDetailText, formatStoredPlaceName, matchLatLon } from '@opentripplanner/core-utils/lib/map'
+import { summarizeQuery } from '@opentripplanner/core-utils/lib/query'
import React, { Component } from 'react'
import { Button } from 'react-bootstrap'
import { connect } from 'react-redux'
@@ -9,7 +10,6 @@ import { forgetSearch, toggleTracking } from '../../actions/api'
import { setQueryParam } from '../../actions/form'
import { forgetPlace, forgetStop, setLocation } from '../../actions/map'
import { setViewedStop } from '../../actions/ui'
-import { summarizeQuery } from '../../util/query'
const BUTTON_WIDTH = 40
diff --git a/lib/components/form/user-trip-settings.js b/lib/components/form/user-trip-settings.js
index 6e5ea2383..5d00778f8 100644
--- a/lib/components/form/user-trip-settings.js
+++ b/lib/components/form/user-trip-settings.js
@@ -1,3 +1,4 @@
+import { getTripOptionsFromQuery, isNotDefaultQuery } from '@opentripplanner/core-utils/lib/query'
import React, { Component } from 'react'
import { Button } from 'react-bootstrap'
import { connect } from 'react-redux'
@@ -8,7 +9,6 @@ import {
resetForm,
storeDefaultSettings
} from '../../actions/form'
-import { getTripOptionsFromQuery, isNotDefaultQuery } from '../../util/query'
/**
* This component contains the `Remember/Forget my trip options` and `Restore defaults` commands
diff --git a/lib/reducers/create-otp-reducer.js b/lib/reducers/create-otp-reducer.js
index 84d7358f0..065f90270 100644
--- a/lib/reducers/create-otp-reducer.js
+++ b/lib/reducers/create-otp-reducer.js
@@ -4,14 +4,14 @@ import isEqual from 'lodash.isequal'
import objectPath from 'object-path'
import { matchLatLon } from '@opentripplanner/core-utils/lib/map'
import { filterProfileOptions } from '@opentripplanner/core-utils/lib/profile'
-import { getItem, removeItem, storeItem } from '@opentripplanner/core-utils/lib/storage'
-import { getUserTimezone } from '@opentripplanner/core-utils/lib/time'
-
import {
ensureSingleAccessMode,
getDefaultQuery,
getTripOptionsFromQuery
-} from '../util/query'
+} from '@opentripplanner/core-utils/lib/query'
+import { getItem, removeItem, storeItem } from '@opentripplanner/core-utils/lib/storage'
+import { getUserTimezone } from '@opentripplanner/core-utils/lib/time'
+
import { isTransit, getTransitModes } from '../util/itinerary'
import { MainPanelContent, MobileScreens } from '../actions/ui'
diff --git a/lib/util/query.js b/lib/util/query.js
index a667e1172..c864e91c0 100644
--- a/lib/util/query.js
+++ b/lib/util/query.js
@@ -1,87 +1,10 @@
-import { coordsToString, matchLatLon, stringToCoords } from '@opentripplanner/core-utils/lib/map'
-import queryParams from '@opentripplanner/core-utils/lib/query-params'
-import { getCurrentTime, getCurrentDate } from '@opentripplanner/core-utils/lib/time'
-import qs from 'qs'
-
-import { getTransitModes, hasTransit, isAccessMode, toSentenceCase } from './itinerary'
import { getActiveSearch } from './state'
-/* The list of default parameters considered in the settings panel */
-// Good to go.
-export const defaultParams = [
- 'wheelchair',
- 'maxWalkDistance',
- 'maxWalkTime',
- 'walkSpeed',
- 'maxBikeDistance',
- 'maxBikeTime',
- 'bikeSpeed',
- 'optimize',
- 'optimizeBike',
- 'maxEScooterDistance',
- 'watts'
-]
-
-// Good to go.
-/* A function to retrieve a property value from an entry in the query-params
- * table, checking for either a static value or a function */
-
-export function getQueryParamProperty (paramInfo, property, query) {
- return typeof paramInfo[property] === 'function'
- ? paramInfo[property](query)
- : paramInfo[property]
-}
-
-// Good to go.
-export function ensureSingleAccessMode (queryModes) {
- // Count the number of access modes
- const accessCount = queryModes.filter(m => isAccessMode(m)).length
-
- // If multiple access modes are specified, keep only the first one
- if (accessCount > 1) {
- const firstAccess = queryModes.find(m => isAccessMode(m))
- queryModes = queryModes.filter(m => !isAccessMode(m) || m === firstAccess)
-
- // If no access modes are specified, add 'WALK' as the default
- } else if (accessCount === 0) {
- queryModes.push('WALK')
- }
-
- return queryModes
-}
-
-// Good to go.
-export function getUrlParams () {
- return qs.parse(window.location.href.split('?')[1])
-}
-
-// Good to go.
-export function getOtpUrlParams () {
- return Object.keys(getUrlParams()).filter(key => !key.startsWith('ui_'))
-}
-
-// Good to go.
-function findLocationType (location, locations = [], types = ['home', 'work', 'suggested']) {
- const match = locations.find(l => matchLatLon(l, location))
- return match && types.indexOf(match.type) !== -1 ? match.type : null
-}
-
-// Good to go.
-export function summarizeQuery (query, locations = []) {
- const from = findLocationType(query.from, locations) || query.from.name.split(',')[0]
- const to = findLocationType(query.to, locations) || query.to.name.split(',')[0]
- const mode = hasTransit(query.mode)
- ? 'Transit'
- : toSentenceCase(query.mode)
- return `${mode} from ${from} to ${to}`
-}
-
-// CHECK THIS ONE => Used in handleBackButtonPRess
+// => Used in actions/ui/handleBackButtonPress()
/**
* Assemble any UI-state properties to be tracked via URL into a single object
* TODO: Expand to include additional UI properties
*/
-
export function getUiUrlParams (otpState) {
const activeSearch = getActiveSearch(otpState)
const uiParams = {
@@ -90,130 +13,3 @@ export function getUiUrlParams (otpState) {
}
return uiParams
}
-
-// Good to go.
-export function getTripOptionsFromQuery (query, keepPlace = false) {
- const options = Object.assign({}, query)
- // Delete time/date options and from/to
- delete options.time
- delete options.departArrive
- delete options.date
- if (!keepPlace) {
- delete options.from
- delete options.to
- }
- return options
-}
-
-// Good to go.
-/**
- * Gets the default query param by executing the default value function with the
- * provided otp config if the default value is a function.
- */
-function getDefaultQueryParamValue (param, config) {
- return typeof param.default === 'function' ? param.default(config) : param.default
-}
-
-// Good to go.
-/**
- * Determines whether the specified query differs from the default query, i.e.,
- * whether the user has modified any trip options (including mode) from their
- * default values.
- */
-export function isNotDefaultQuery (query, config) {
- const activeModes = query.mode.split(',')
- const defaultModes = getTransitModes(config).concat(['WALK'])
- let queryIsDifferent = false
- const modesEqual = (activeModes.length === defaultModes.length) &&
- activeModes.sort().every((value, index) => { return value === defaultModes.sort()[index] })
-
- if (!modesEqual) {
- queryIsDifferent = true
- } else {
- defaultParams.forEach(param => {
- const paramInfo = queryParams.find(qp => qp.name === param)
- // Check that the parameter applies to the specified routingType
- if (!paramInfo.routingTypes.includes(query.routingType)) return
- // Check that the applicability test (if provided) is satisfied
- if (typeof paramInfo.applicable === 'function' &&
- !paramInfo.applicable(query, config)) return
- if (query[param] !== getDefaultQueryParamValue(paramInfo, config)) {
- queryIsDifferent = true
- }
- })
- }
- return queryIsDifferent
-}
-
-// Good to go.
-/**
- * Get the default query to OTP based on the given config.
- *
- * @param config the config in the otp-rr store.
- */
-export function getDefaultQuery (config) {
- const defaultQuery = { routingType: 'ITINERARY' }
- queryParams.filter(qp => 'default' in qp).forEach(qp => {
- defaultQuery[qp.name] = getDefaultQueryParamValue(qp, config)
- })
- return defaultQuery
-}
-
-// Good to go.
-/**
- * Create a otp query based on a the url params.
- *
- * @param {Object} params An object representing the parsed querystring of url
- * params.
- * @param config the config in the otp-rr store.
- */
-export function planParamsToQuery (params, config) {
- const query = {}
- for (var key in params) {
- switch (key) {
- case 'fromPlace':
- query.from = parseLocationString(params.fromPlace)
- break
- case 'toPlace':
- query.to = parseLocationString(params.toPlace)
- break
- case 'arriveBy':
- query.departArrive = params.arriveBy === 'true'
- ? 'ARRIVE'
- : params.arriveBy === 'false'
- ? 'DEPART'
- : 'NOW'
- break
- case 'date':
- query.date = params.date || getCurrentDate(config)
- break
- case 'time':
- query.time = params.time || getCurrentTime(config)
- break
- default:
- if (!isNaN(params[key])) query[key] = parseFloat(params[key])
- else query[key] = params[key]
- }
- }
- return query
-}
-
-// Good to go.
-/**
- * OTP allows passing a location in the form '123 Main St::lat,lon', so we check
- * for the double colon and parse the coordinates accordingly.
- */
-function parseLocationString (value) {
- const parts = value.split('::')
- const coordinates = parts[1]
- ? stringToCoords(parts[1])
- : stringToCoords(parts[0])
- const name = parts[1]
- ? parts[0]
- : coordsToString(coordinates)
- return coordinates.length === 2 ? {
- name: name || null,
- lat: coordinates[0] || null,
- lon: coordinates[1] || null
- } : null
-}
diff --git a/lib/util/ui.js b/lib/util/ui.js
index b577f84fc..47e452528 100644
--- a/lib/util/ui.js
+++ b/lib/util/ui.js
@@ -1,11 +1,11 @@
+import { summarizeQuery } from '@opentripplanner/core-utils/lib/query'
+
import { MainPanelContent } from '../actions/ui'
-import { summarizeQuery } from './query'
import { getActiveSearch } from './state'
// Set default title to the original document title (on load) set in index.html
const DEFAULT_TITLE = document.title
-// This needs to stay.
export function getTitle (state) {
// Override title can optionally be provided in config.yml
const { config, ui, user } = state.otp
From 26155143c2330ffcc885dc6f6494e87cab4276dd Mon Sep 17 00:00:00 2001
From: binh-dam-ibigroup <56846598+binh-dam-ibigroup@users.noreply.github.com>
Date: Wed, 8 Apr 2020 14:53:26 -0400
Subject: [PATCH 21/31] refactor(util/itinerary): 1/... Replace util/itinerary
with @opentripplanner/core-utils/itinerary.
---
lib/actions/api.js | 2 +-
lib/components/map/leg-diagram.js | 4 +-
.../narrative/default/access-leg.js | 2 +-
.../narrative/default/itinerary-details.js | 4 +-
lib/components/narrative/default/tnc-leg.js | 2 +-
.../narrative/default/transit-leg.js | 2 +-
.../narrative/leg-diagram-preview.js | 4 +-
.../narrative/line-itin/itin-summary.js | 3 +-
.../narrative/line-itin/line-itinerary.js | 2 +-
.../narrative/tabbed-itineraries.js | 2 +-
lib/reducers/create-otp-reducer.js | 2 +-
lib/util/itinerary.js | 43 +++++++++++++++++--
12 files changed, 54 insertions(+), 18 deletions(-)
diff --git a/lib/actions/api.js b/lib/actions/api.js
index 4731a9353..c13dec433 100644
--- a/lib/actions/api.js
+++ b/lib/actions/api.js
@@ -3,6 +3,7 @@ import { push, replace } from 'connected-react-router'
import haversine from 'haversine'
import moment from 'moment'
import hash from 'object-hash'
+import { hasCar } from '@opentripplanner/core-utils/lib/itinerary'
import { getTripOptionsFromQuery, getUrlParams } from '@opentripplanner/core-utils/lib/query'
import queryParams from '@opentripplanner/core-utils/lib/query-params'
import { randId } from '@opentripplanner/core-utils/lib/storage'
@@ -11,7 +12,6 @@ import { createAction } from 'redux-actions'
import qs from 'qs'
import { rememberPlace } from './map'
-import { hasCar } from '../util/itinerary'
import { getStopViewerConfig, queryIsValid } from '../util/state'
if (typeof (fetch) === 'undefined') require('isomorphic-fetch')
diff --git a/lib/components/map/leg-diagram.js b/lib/components/map/leg-diagram.js
index 901c49608..0f4ae9fd4 100644
--- a/lib/components/map/leg-diagram.js
+++ b/lib/components/map/leg-diagram.js
@@ -1,12 +1,12 @@
import memoize from 'lodash.memoize'
-import React, {Component} from 'react'
+import { getElevationProfile, getTextWidth, legElevationAtDistance } from '@opentripplanner/core-utils/lib/itinerary'
import PropTypes from 'prop-types'
+import React, {Component} from 'react'
import { Button } from 'react-bootstrap'
import { connect } from 'react-redux'
import ReactResizeDetector from 'react-resize-detector'
import { setElevationPoint, showLegDiagram } from '../../actions/map'
-import { getElevationProfile, getTextWidth, legElevationAtDistance } from '../../util/itinerary'
// Fixed dimensions for chart
const height = 160
diff --git a/lib/components/narrative/default/access-leg.js b/lib/components/narrative/default/access-leg.js
index 1101d3a38..e40157677 100644
--- a/lib/components/narrative/default/access-leg.js
+++ b/lib/components/narrative/default/access-leg.js
@@ -1,3 +1,4 @@
+import { getStepInstructions } from '@opentripplanner/core-utils/lib/itinerary'
import { formatDuration } from '@opentripplanner/core-utils/lib/time'
import PropTypes from 'prop-types'
import React, {Component} from 'react'
@@ -5,7 +6,6 @@ import React, {Component} from 'react'
import Icon from '../icon'
import LegDiagramPreview from '../leg-diagram-preview'
import { distanceString } from '../../../util/distance'
-import { getStepInstructions } from '../../../util/itinerary'
/**
* Default access leg component for narrative itinerary.
diff --git a/lib/components/narrative/default/itinerary-details.js b/lib/components/narrative/default/itinerary-details.js
index 2eec48805..b12d214b3 100644
--- a/lib/components/narrative/default/itinerary-details.js
+++ b/lib/components/narrative/default/itinerary-details.js
@@ -1,9 +1,9 @@
-import React, { Component } from 'react'
+import { isTransit } from '@opentripplanner/core-utils/lib/itinerary'
import PropTypes from 'prop-types'
+import React, { Component } from 'react'
import AccessLeg from './access-leg'
import TransitLeg from './transit-leg'
-import { isTransit } from '../../../util/itinerary'
export default class ItineraryDetails extends Component {
static propTypes = {
diff --git a/lib/components/narrative/default/tnc-leg.js b/lib/components/narrative/default/tnc-leg.js
index 905f0da4e..d7d712f51 100644
--- a/lib/components/narrative/default/tnc-leg.js
+++ b/lib/components/narrative/default/tnc-leg.js
@@ -1,4 +1,5 @@
import currencyFormatter from 'currency-formatter'
+import { toSentenceCase } from '@opentripplanner/core-utils/lib/itinerary'
import { formatDuration } from '@opentripplanner/core-utils/lib/time'
import { isMobile } from '@opentripplanner/core-utils/lib/ui'
import PropTypes from 'prop-types'
@@ -9,7 +10,6 @@ import {
getTransportationNetworkCompanyEtaEstimate,
getTransportationNetworkCompanyRideEstimate
} from '../../../actions/api'
-import { toSentenceCase } from '../../../util/itinerary'
class TransportationNetworkCompanyLeg extends Component {
static propTypes = {
diff --git a/lib/components/narrative/default/transit-leg.js b/lib/components/narrative/default/transit-leg.js
index aef7c13eb..b6a6eefe0 100644
--- a/lib/components/narrative/default/transit-leg.js
+++ b/lib/components/narrative/default/transit-leg.js
@@ -1,3 +1,4 @@
+import { getMapColor } from '@opentripplanner/core-utils/lib/itinerary'
import { formatDuration, formatTime } from '@opentripplanner/core-utils/lib/time'
import PropTypes from 'prop-types'
import React, { Component } from 'react'
@@ -6,7 +7,6 @@ import Icon from '../icon'
import ModeIcon from '../../icons/mode-icon'
import ViewTripButton from '../../viewers/view-trip-button'
import ViewStopButton from '../../viewers/view-stop-button'
-import { getMapColor } from '../../../util/itinerary'
export default class TransitLeg extends Component {
static propTypes = {
diff --git a/lib/components/narrative/leg-diagram-preview.js b/lib/components/narrative/leg-diagram-preview.js
index 5a736e5b9..6ce1ed09d 100644
--- a/lib/components/narrative/leg-diagram-preview.js
+++ b/lib/components/narrative/leg-diagram-preview.js
@@ -1,10 +1,10 @@
-import React, {Component} from 'react'
+import { getElevationProfile } from '@opentripplanner/core-utils/lib/itinerary'
import PropTypes from 'prop-types'
+import React, {Component} from 'react'
import { connect } from 'react-redux'
import ReactResizeDetector from 'react-resize-detector'
import { showLegDiagram } from '../../actions/map'
-import { getElevationProfile } from '../../util/itinerary'
const METERS_TO_FEET = 3.28084
diff --git a/lib/components/narrative/line-itin/itin-summary.js b/lib/components/narrative/line-itin/itin-summary.js
index 8766cedeb..20c69ebb7 100644
--- a/lib/components/narrative/line-itin/itin-summary.js
+++ b/lib/components/narrative/line-itin/itin-summary.js
@@ -1,8 +1,9 @@
+import { calculateFares, calculatePhysicalActivity, isTransit } from '@opentripplanner/core-utils/lib/itinerary'
import { formatDuration, formatTime } from '@opentripplanner/core-utils/lib/time'
import PropTypes from 'prop-types'
import React, { Component } from 'react'
-import { calculateFares, calculatePhysicalActivity, getLegIcon, isTransit } from '../../../util/itinerary'
+import { getLegIcon } from '../../../util/itinerary'
// TODO: make this a prop
const defaultRouteColor = '#008'
diff --git a/lib/components/narrative/line-itin/line-itinerary.js b/lib/components/narrative/line-itin/line-itinerary.js
index 2ca69e267..d1257dae9 100644
--- a/lib/components/narrative/line-itin/line-itinerary.js
+++ b/lib/components/narrative/line-itin/line-itinerary.js
@@ -1,8 +1,8 @@
+import { getLegModeLabel, getTimeZoneOffset, isTransit } from '@opentripplanner/core-utils/lib/itinerary'
import React from 'react'
import NarrativeItinerary from '../narrative-itinerary'
import SimpleRealtimeAnnotation from '../simple-realtime-annotation'
-import { getLegModeLabel, getTimeZoneOffset, isTransit } from '../../../util/itinerary'
import ItinerarySummary from './itin-summary'
import ItineraryBody from './connected-itinerary-body'
diff --git a/lib/components/narrative/tabbed-itineraries.js b/lib/components/narrative/tabbed-itineraries.js
index b707b822a..9b440aa3a 100644
--- a/lib/components/narrative/tabbed-itineraries.js
+++ b/lib/components/narrative/tabbed-itineraries.js
@@ -1,3 +1,4 @@
+import { calculateFares, calculatePhysicalActivity, getTimeZoneOffset } from '@opentripplanner/core-utils/lib/itinerary'
import { formatDuration, formatTime, getTimeFormat } from '@opentripplanner/core-utils/lib/time'
import PropTypes from 'prop-types'
import React, { Component } from 'react'
@@ -7,7 +8,6 @@ import { connect } from 'react-redux'
import { setActiveItinerary, setActiveLeg, setActiveStep, setUseRealtimeResponse } from '../../actions/narrative'
import DefaultItinerary from './default/default-itinerary'
import { getActiveSearch, getRealtimeEffects } from '../../util/state'
-import { calculateFares, calculatePhysicalActivity, getTimeZoneOffset } from '../../util/itinerary'
class TabbedItineraries extends Component {
static propTypes = {
diff --git a/lib/reducers/create-otp-reducer.js b/lib/reducers/create-otp-reducer.js
index 065f90270..4008e2f01 100644
--- a/lib/reducers/create-otp-reducer.js
+++ b/lib/reducers/create-otp-reducer.js
@@ -2,6 +2,7 @@ import clone from 'clone'
import update from 'immutability-helper'
import isEqual from 'lodash.isequal'
import objectPath from 'object-path'
+import { isTransit, getTransitModes } from '@opentripplanner/core-utils/lib/itinerary'
import { matchLatLon } from '@opentripplanner/core-utils/lib/map'
import { filterProfileOptions } from '@opentripplanner/core-utils/lib/profile'
import {
@@ -12,7 +13,6 @@ import {
import { getItem, removeItem, storeItem } from '@opentripplanner/core-utils/lib/storage'
import { getUserTimezone } from '@opentripplanner/core-utils/lib/time'
-import { isTransit, getTransitModes } from '../util/itinerary'
import { MainPanelContent, MobileScreens } from '../actions/ui'
const MAX_RECENT_STORAGE = 5
diff --git a/lib/util/itinerary.js b/lib/util/itinerary.js
index df4196484..e145dd9fa 100644
--- a/lib/util/itinerary.js
+++ b/lib/util/itinerary.js
@@ -8,16 +8,17 @@ import ModeIcon from '../components/icons/mode-icon'
// All OTP transit modes
export const transitModes = ['TRAM', 'BUS', 'SUBWAY', 'FERRY', 'RAIL', 'GONDOLA']
+// Good to go.
/**
* @param {config} config OTP-RR configuration object
* @return {Array} List of all transit modes defined in config; otherwise default mode list
*/
-
export function getTransitModes (config) {
if (!config || !config.modes || !config.modes.transitModes) return transitModes
return config.modes.transitModes.map(tm => tm.mode)
}
+// Good to go.
export function isTransit (mode) {
return transitModes.includes(mode) || mode === 'TRANSIT'
}
@@ -33,6 +34,7 @@ export function hasTransit (modesStr) {
return false
}
+// CHECK arg
/**
* @param {string} modesStr a comma-separated list of OTP modes
* @return {boolean} whether any of the modes are car-based modes
@@ -46,6 +48,7 @@ export function hasCar (modesStr) {
return false
}
+// CHECK arg
/**
* @param {string} modesStr a comma-separated list of OTP modes
* @return {boolean} whether any of the modes are bicycle-based modes
@@ -59,6 +62,7 @@ export function hasBike (modesStr) {
return false
}
+// CHECK arg
/**
* @param {string} modesStr a comma-separated list of OTP modes
* @return {boolean} whether any of the modes are micromobility-based modes
@@ -72,6 +76,7 @@ export function hasMicromobility (modesStr) {
return false
}
+// CHECK arg
/**
* @param {string} modesStr a comma-separated list of OTP modes
* @return {boolean} whether any of the modes is a hailing mode
@@ -85,6 +90,7 @@ export function hasHail (modesStr) {
return false
}
+// CHECK arg
/**
* @param {string} modesStr a comma-separated list of OTP modes
* @return {boolean} whether any of the modes is a rental mode
@@ -98,34 +104,40 @@ export function hasRental (modesStr) {
return false
}
+// Good to go.
export function isWalk (mode) {
if (!mode) return false
return mode === 'WALK'
}
+// Good to go.
export function isBicycle (mode) {
if (!mode) return false
return mode === 'BICYCLE'
}
+// Good to go.
export function isBicycleRent (mode) {
if (!mode) return false
return mode === 'BICYCLE_RENT'
}
+// Good to go.
export function isCar (mode) {
if (!mode) return false
return mode.startsWith('CAR')
}
+// Good to go.
export function isMicromobility (mode) {
if (!mode) return false
return mode.startsWith('MICROMOBILITY')
}
+// Good to go.
export function isAccessMode (mode) {
return isWalk(mode) ||
isBicycle(mode) ||
@@ -134,6 +146,7 @@ export function isAccessMode (mode) {
isMicromobility(mode)
}
+// Good to go.
export function getMapColor (mode) {
mode = mode || this.get('mode')
if (mode === 'WALK') return '#444'
@@ -148,6 +161,7 @@ export function getMapColor (mode) {
return '#aaa'
}
+// Good to go.
// TODO: temporary code; handle via migrated OTP i18n language table
export function getStepDirection (step) {
switch (step.relativeDirection) {
@@ -168,17 +182,20 @@ export function getStepDirection (step) {
return step.relativeDirection
}
+// Good to go.
export function getStepInstructions (step) {
const conjunction = step.relativeDirection === 'ELEVATOR' ? 'to' : 'on'
return `${getStepDirection(step)} ${conjunction} ${step.streetName}`
}
+// Good to go.
export function getStepStreetName (step) {
if (step.streetName === 'road') return 'Unnamed Road'
if (step.streetName === 'path') return 'Unnamed Path'
return step.streetName
}
+// Good to go.
export function getLegModeLabel (leg) {
switch (leg.mode) {
case 'BICYCLE_RENT': return 'Biketown'
@@ -217,6 +234,7 @@ export function getIcon (iconId, customIcons) {
return
}
+// DIFFERENT!!
export function getItineraryBounds (itinerary) {
let coords = []
itinerary.legs.forEach(leg => {
@@ -228,6 +246,7 @@ export function getItineraryBounds (itinerary) {
return latLngBounds(coords)
}
+// DIFFERENT!
/**
* Return a leaflet LatLngBounds object that encloses the given leg's geometry.
*/
@@ -245,6 +264,7 @@ export function getLegBounds (leg) {
return latLngBounds(coords)
}
+// CHECK THIS ONE
/**
* Gets the desired sort values according to an optional getter function. If the
* getter function is not defined, the original sort values are returned.
@@ -294,6 +314,7 @@ const routeTypeComparatorValue = {
12: modeComparatorValue.RAIL // - Monorail.
}
+// CHECK THIS ONE
// Gets a comparator value for a given route's type (OTP mode).
// Note: JSDoc format not used to avoid bug in documentationjs.
// ttps://github.com/documentationjs/documentation/issues/372
@@ -314,6 +335,7 @@ function getRouteTypeComparatorValue (route) {
}
}
+// CHANGED
/**
* Calculates the sort comparator value given two routes based off of route type
* (OTP mode).
@@ -334,7 +356,7 @@ function startsWithAlphabeticCharacter (val) {
}
return false
}
-
+// Check this one => Replace with routeComparator.
/**
* Sorts routes based off of whether the shortName begins with an alphabetic
* character. Routes with shortn that do start with an alphabetic character will
@@ -420,6 +442,7 @@ function makeStringValueComparator (objGetterFn) {
}
}
+// CHECK THIS ONE
/**
* OpenTripPlanner sets the routeSortOrder to -999 by default. So, if that value
* is encountered, assume that it actually means that the routeSortOrder is not
@@ -453,6 +476,7 @@ function makeMultiCriteriaSort (...criteria) {
}
}
+// Move this and dependent functions to OTP-UI.
/**
* Compares routes for the purposes of sorting and displaying in a user
* interface. Due to GTFS feeds having varying levels of data quality, a multi-
@@ -484,8 +508,8 @@ export const routeComparator = makeMultiCriteriaSort(
makeStringValueComparator(obj => obj.longName)
)
+// Good to go.
/* Returns an interpolated lat-lon at a specified distance along a leg */
-
export function legLocationAtDistance (leg, distance) {
if (!leg.legGeometry) return null
@@ -503,8 +527,8 @@ export function legLocationAtDistance (leg, distance) {
return null
}
+// Good to go.
/* Returns an interpolated elevation at a specified distance along a leg */
-
export function legElevationAtDistance (points, distance) {
// Iterate through the combined elevation profile
let traversed = 0
@@ -533,6 +557,7 @@ export function legElevationAtDistance (points, distance) {
return null
}
+// Good to go.
// Iterate through the steps, building the array of elevation points and
// keeping track of the minimum and maximum elevations reached
export function getElevationProfile (steps, unitConversion = 1) {
@@ -574,6 +599,7 @@ export function getElevationProfile (steps, unitConversion = 1) {
return { maxElev, minElev, points, traversed, gain, loss }
}
+// Good to go.
/**
* Uses canvas.measureText to compute and return the width of the given text of given font in pixels.
*
@@ -591,6 +617,7 @@ export function getTextWidth (text, font = '22px Arial') {
return metrics.width
}
+// Good to go.
export function toSentenceCase (str) {
if (str == null) {
return ''
@@ -634,6 +661,7 @@ export function getLegIcon (leg, customIcons) {
return getIcon(iconStr, customIcons)
}
+// Good to go.
/**
* Get the configured company object for the given network string if the company
* has been defined in the provided companies array config.
@@ -646,6 +674,7 @@ function getCompanyForNetwork (networkString, companies = []) {
return company
}
+// Good to go.
/**
* Get a string label to display from a list of vehicle rental networks.
*
@@ -660,6 +689,7 @@ export function getCompaniesLabelFromNetworks (networks, companies = []) {
.join('/')
}
+// Good to go.
/**
* Returns mode name by checking the vertex type (VertexType class in OTP) for
* the provided place. NOTE: this is currently only intended for vehicles at
@@ -684,6 +714,7 @@ export function getModeForPlace (place) {
}
}
+// Good to go.
export function getPlaceName (place, companies) {
// If address is provided (i.e. for carshare station, use it)
if (place.address) return place.address.split(',')[0]
@@ -701,11 +732,13 @@ export function getPlaceName (place, companies) {
return place.name
}
+// Good to go.
export function getTNCLocation (leg, type) {
const location = leg[type]
return `${location.lat.toFixed(5)},${location.lon.toFixed(5)}`
}
+// Good to go.
export function calculatePhysicalActivity (itinerary) {
let walkDuration = 0
let bikeDuration = 0
@@ -723,6 +756,7 @@ export function calculatePhysicalActivity (itinerary) {
}
}
+// Good to go.
export function calculateFares (itinerary) {
let transitFare = 0
let symbol = '$' // default to USD
@@ -756,6 +790,7 @@ export function calculateFares (itinerary) {
}
}
+// Good to go.
export function getTimeZoneOffset (itinerary) {
if (!itinerary.legs || !itinerary.legs.length) return 0
From 53ca03ced0db7f96989b12db83ecfbb2d480a37d Mon Sep 17 00:00:00 2001
From: binh-dam-ibigroup <56846598+binh-dam-ibigroup@users.noreply.github.com>
Date: Wed, 8 Apr 2020 15:29:09 -0400
Subject: [PATCH 22/31] refactor(util/itinerary): Remove unused code so far.
---
__tests__/util/itinerary.js | 4 +-
lib/util/itinerary.js | 471 +-----------------------------------
2 files changed, 5 insertions(+), 470 deletions(-)
diff --git a/__tests__/util/itinerary.js b/__tests__/util/itinerary.js
index 74e5d5a56..83b06f3db 100644
--- a/__tests__/util/itinerary.js
+++ b/__tests__/util/itinerary.js
@@ -1,4 +1,6 @@
-import {isTransit, routeComparator} from '../../lib/util/itinerary'
+import { isTransit } from '@opentripplanner/core-utils/lib/itinerary'
+
+import { routeComparator } from '../../lib/util/itinerary'
const {
route1,
diff --git a/lib/util/itinerary.js b/lib/util/itinerary.js
index 1e7461604..e58f1626a 100644
--- a/lib/util/itinerary.js
+++ b/lib/util/itinerary.js
@@ -1,210 +1,5 @@
import { latLngBounds } from 'leaflet'
import polyline from '@mapbox/polyline'
-import turfAlong from '@turf/along'
-
-// All OTP transit modes
-export const transitModes = ['TRAM', 'BUS', 'SUBWAY', 'FERRY', 'RAIL', 'GONDOLA']
-
-// Good to go.
-/**
- * @param {config} config OTP-RR configuration object
- * @return {Array} List of all transit modes defined in config; otherwise default mode list
- */
-export function getTransitModes (config) {
- if (!config || !config.modes || !config.modes.transitModes) return transitModes
- return config.modes.transitModes.map(tm => tm.mode)
-}
-
-// Good to go.
-export function isTransit (mode) {
- return transitModes.includes(mode) || mode === 'TRANSIT'
-}
-
-/**
- * @param {string} modesStr a comma-separated list of OTP modes
- * @return {boolean} whether any of the modes are transit modes
- */
-export function hasTransit (modesStr) {
- for (const mode of modesStr.split(',')) {
- if (isTransit(mode)) return true
- }
- return false
-}
-
-// CHECK arg
-/**
- * @param {string} modesStr a comma-separated list of OTP modes
- * @return {boolean} whether any of the modes are car-based modes
- */
-export function hasCar (modesStr) {
- if (modesStr) {
- for (const mode of modesStr.split(',')) {
- if (isCar(mode)) return true
- }
- }
- return false
-}
-
-// CHECK arg
-/**
- * @param {string} modesStr a comma-separated list of OTP modes
- * @return {boolean} whether any of the modes are bicycle-based modes
- */
-export function hasBike (modesStr) {
- if (modesStr) {
- for (const mode of modesStr.split(',')) {
- if (isBicycle(mode) || isBicycleRent(mode)) return true
- }
- }
- return false
-}
-
-// CHECK arg
-/**
- * @param {string} modesStr a comma-separated list of OTP modes
- * @return {boolean} whether any of the modes are micromobility-based modes
- */
-export function hasMicromobility (modesStr) {
- if (modesStr) {
- for (const mode of modesStr.split(',')) {
- if (isMicromobility(mode)) return true
- }
- }
- return false
-}
-
-// CHECK arg
-/**
- * @param {string} modesStr a comma-separated list of OTP modes
- * @return {boolean} whether any of the modes is a hailing mode
- */
-export function hasHail (modesStr) {
- if (modesStr) {
- for (const mode of modesStr.split(',')) {
- if (mode.indexOf('_HAIL') > -1) return true
- }
- }
- return false
-}
-
-// CHECK arg
-/**
- * @param {string} modesStr a comma-separated list of OTP modes
- * @return {boolean} whether any of the modes is a rental mode
- */
-export function hasRental (modesStr) {
- if (modesStr) {
- for (const mode of modesStr.split(',')) {
- if (mode.indexOf('_RENT') > -1) return true
- }
- }
- return false
-}
-
-// Good to go.
-export function isWalk (mode) {
- if (!mode) return false
-
- return mode === 'WALK'
-}
-
-// Good to go.
-export function isBicycle (mode) {
- if (!mode) return false
-
- return mode === 'BICYCLE'
-}
-
-// Good to go.
-export function isBicycleRent (mode) {
- if (!mode) return false
-
- return mode === 'BICYCLE_RENT'
-}
-
-// Good to go.
-export function isCar (mode) {
- if (!mode) return false
- return mode.startsWith('CAR')
-}
-
-// Good to go.
-export function isMicromobility (mode) {
- if (!mode) return false
- return mode.startsWith('MICROMOBILITY')
-}
-
-// Good to go.
-export function isAccessMode (mode) {
- return isWalk(mode) ||
- isBicycle(mode) ||
- isBicycleRent(mode) ||
- isCar(mode) ||
- isMicromobility(mode)
-}
-
-// Good to go.
-export function getMapColor (mode) {
- mode = mode || this.get('mode')
- if (mode === 'WALK') return '#444'
- if (mode === 'BICYCLE') return '#0073e5'
- if (mode === 'SUBWAY') return '#f00'
- if (mode === 'RAIL') return '#b00'
- if (mode === 'BUS') return '#080'
- if (mode === 'TRAM') return '#800'
- if (mode === 'FERRY') return '#008'
- if (mode === 'CAR') return '#444'
- if (mode === 'MICROMOBILITY') return '#f5a729'
- return '#aaa'
-}
-
-// Good to go.
-// TODO: temporary code; handle via migrated OTP i18n language table
-export function getStepDirection (step) {
- switch (step.relativeDirection) {
- case 'DEPART': return 'Head ' + step.absoluteDirection.toLowerCase()
- case 'LEFT': return 'Left'
- case 'HARD_LEFT': return 'Hard left'
- case 'SLIGHTLY_LEFT': return 'Slight left'
- case 'CONTINUE': return 'Continue'
- case 'SLIGHTLY_RIGHT': return 'Slight right'
- case 'RIGHT': return 'Right'
- case 'HARD_RIGHT': return 'Hard right'
- case 'CIRCLE_CLOCKWISE': return 'Follow circle clockwise'
- case 'CIRCLE_COUNTERCLOCKWISE': return 'Follow circle counterclockwise'
- case 'ELEVATOR': return 'Take elevator'
- case 'UTURN_LEFT': return 'Left U-turn'
- case 'UTURN_RIGHT': return 'Right U-turn'
- }
- return step.relativeDirection
-}
-
-// Good to go.
-export function getStepInstructions (step) {
- const conjunction = step.relativeDirection === 'ELEVATOR' ? 'to' : 'on'
- return `${getStepDirection(step)} ${conjunction} ${step.streetName}`
-}
-
-// Good to go.
-export function getStepStreetName (step) {
- if (step.streetName === 'road') return 'Unnamed Road'
- if (step.streetName === 'path') return 'Unnamed Path'
- return step.streetName
-}
-
-// Good to go.
-export function getLegModeLabel (leg) {
- switch (leg.mode) {
- case 'BICYCLE_RENT': return 'Biketown'
- case 'CAR': return leg.hailedCar ? 'Ride' : 'Drive'
- case 'GONDOLA': return 'Aerial Tram'
- case 'TRAM':
- if (leg.routeLongName.toLowerCase().indexOf('streetcar') !== -1) return 'Streetcar'
- return 'Light Rail'
- case 'MICROMOBILITY': return 'Ride'
- }
- return toSentenceCase(leg.mode)
-}
// DIFFERENT
export function getItineraryBounds (itinerary) {
@@ -218,7 +13,7 @@ export function getItineraryBounds (itinerary) {
return latLngBounds(coords)
}
-// DIFFERENT!
+// DIFFERENT
/**
* Return a leaflet LatLngBounds object that encloses the given leg's geometry.
*/
@@ -236,7 +31,6 @@ export function getLegBounds (leg) {
return latLngBounds(coords)
}
-// CHECK THIS ONE
/**
* Gets the desired sort values according to an optional getter function. If the
* getter function is not defined, the original sort values are returned.
@@ -286,7 +80,6 @@ const routeTypeComparatorValue = {
12: modeComparatorValue.RAIL // - Monorail.
}
-// CHECK THIS ONE
// Gets a comparator value for a given route's type (OTP mode).
// Note: JSDoc format not used to avoid bug in documentationjs.
// ttps://github.com/documentationjs/documentation/issues/372
@@ -307,7 +100,6 @@ function getRouteTypeComparatorValue (route) {
}
}
-// CHANGED
/**
* Calculates the sort comparator value given two routes based off of route type
* (OTP mode).
@@ -328,7 +120,7 @@ function startsWithAlphabeticCharacter (val) {
}
return false
}
-// Check this one => Replace with routeComparator.
+
/**
* Sorts routes based off of whether the shortName begins with an alphabetic
* character. Routes with shortn that do start with an alphabetic character will
@@ -414,7 +206,6 @@ function makeStringValueComparator (objGetterFn) {
}
}
-// CHECK THIS ONE
/**
* OpenTripPlanner sets the routeSortOrder to -999 by default. So, if that value
* is encountered, assume that it actually means that the routeSortOrder is not
@@ -448,7 +239,6 @@ function makeMultiCriteriaSort (...criteria) {
}
}
-// Move this and dependent functions to OTP-UI.
/**
* Compares routes for the purposes of sorting and displaying in a user
* interface. Due to GTFS feeds having varying levels of data quality, a multi-
@@ -479,260 +269,3 @@ export const routeComparator = makeMultiCriteriaSort(
makeStringValueComparator(obj => obj.shortName),
makeStringValueComparator(obj => obj.longName)
)
-
-// Good to go.
-/* Returns an interpolated lat-lon at a specified distance along a leg */
-export function legLocationAtDistance (leg, distance) {
- if (!leg.legGeometry) return null
-
- try {
- const line = polyline.toGeoJSON(leg.legGeometry.points)
- const pt = turfAlong(line, distance, 'meters')
- if (pt && pt.geometry && pt.geometry.coordinates) {
- return [
- pt.geometry.coordinates[1],
- pt.geometry.coordinates[0]
- ]
- }
- } catch (e) { }
-
- return null
-}
-
-// Good to go.
-/* Returns an interpolated elevation at a specified distance along a leg */
-export function legElevationAtDistance (points, distance) {
- // Iterate through the combined elevation profile
- let traversed = 0
- // If first point distance is not zero, insert starting point at zero with
- // null elevation. Encountering this value should trigger the warning below.
- if (points[0][0] > 0) {
- points.unshift([0, null])
- }
- for (let i = 1; i < points.length; i++) {
- const start = points[i - 1]
- const elevDistanceSpan = points[i][0] - start[0]
- if (distance >= traversed && distance <= traversed + elevDistanceSpan) {
- // Distance falls within this point and the previous one;
- // compute & return iterpolated elevation value
- if (start[1] === null) {
- console.warn('Elevation value does not exist for distance.', distance, traversed)
- return null
- }
- const pct = (distance - traversed) / elevDistanceSpan
- const elevSpan = points[i][1] - start[1]
- return start[1] + elevSpan * pct
- }
- traversed += elevDistanceSpan
- }
- console.warn('Elevation value does not exist for distance.', distance, traversed)
- return null
-}
-
-// Good to go.
-// Iterate through the steps, building the array of elevation points and
-// keeping track of the minimum and maximum elevations reached
-export function getElevationProfile (steps, unitConversion = 1) {
- let minElev = 100000
- let maxElev = -100000
- let traversed = 0
- let gain = 0
- let loss = 0
- let previous = null
- const points = []
- steps.forEach((step, stepIndex) => {
- if (!step.elevation || step.elevation.length === 0) {
- traversed += step.distance
- return
- }
- for (let i = 0; i < step.elevation.length; i++) {
- const elev = step.elevation[i]
- if (previous) {
- const diff = (elev.second - previous.second) * unitConversion
- if (diff > 0) gain += diff
- else loss += diff
- }
- if (i === 0 && elev.first !== 0) {
- // console.warn(`No elevation data available for step ${stepIndex}-${i} at beginning of segment`, elev)
- }
- const convertedElevation = elev.second * unitConversion
- if (convertedElevation < minElev) minElev = convertedElevation
- if (convertedElevation > maxElev) maxElev = convertedElevation
- points.push([traversed + elev.first, elev.second])
- // Insert "filler" point if the last point in elevation profile does not
- // reach the full distance of the step.
- if (i === step.elevation.length - 1 && elev.first !== step.distance) {
- // points.push([traversed + step.distance, elev.second])
- }
- previous = elev
- }
- traversed += step.distance
- })
- return { maxElev, minElev, points, traversed, gain, loss }
-}
-
-// Good to go.
-/**
- * Uses canvas.measureText to compute and return the width of the given text of given font in pixels.
- *
- * @param {string} text The text to be rendered.
- * @param {string} font The css font descriptor that text is to be rendered with (e.g. "bold 14px verdana").
- *
- * @see https://stackoverflow.com/questions/118241/calculate-text-width-with-javascript/21015393#21015393
- */
-export function getTextWidth (text, font = '22px Arial') {
- // re-use canvas object for better performance
- var canvas = getTextWidth.canvas || (getTextWidth.canvas = document.createElement('canvas'))
- var context = canvas.getContext('2d')
- context.font = font
- var metrics = context.measureText(text)
- return metrics.width
-}
-
-// Good to go.
-export function toSentenceCase (str) {
- if (str == null) {
- return ''
- }
- str = String(str)
- return str.charAt(0).toUpperCase() + str.substr(1).toLowerCase()
-}
-
-// Good to go.
-/**
- * Get the configured company object for the given network string if the company
- * has been defined in the provided companies array config.
- */
-function getCompanyForNetwork (networkString, companies = []) {
- const company = companies.find(co => co.id === networkString)
- if (!company) {
- console.warn(`No company found in config.yml that matches rented vehicle network: ${networkString}`, companies)
- }
- return company
-}
-
-// Good to go.
-/**
- * Get a string label to display from a list of vehicle rental networks.
- *
- * @param {Array
} networks A list of network ids.
- * @param {Array} [companies=[]] An optional list of the companies config.
- * @return {string} A label for use in presentation on a website.
- */
-export function getCompaniesLabelFromNetworks (networks, companies = []) {
- return networks.map(network => getCompanyForNetwork(network, companies))
- .filter(co => !!co)
- .map(co => co.label)
- .join('/')
-}
-
-// Good to go.
-/**
- * Returns mode name by checking the vertex type (VertexType class in OTP) for
- * the provided place. NOTE: this is currently only intended for vehicles at
- * the moment (not transit or walking).
- *
- * TODO: I18N
- * @param {string} place place from itinerary leg
- */
-export function getModeForPlace (place) {
- switch (place.vertexType) {
- case 'CARSHARE':
- return 'car'
- case 'VEHICLERENTAL':
- return 'E-scooter'
- // TODO: Should the type change depending on bike vertex type?
- case 'BIKESHARE':
- case 'BIKEPARK':
- return 'bike'
- // If company offers more than one mode, default to `vehicle` string.
- default:
- return 'vehicle'
- }
-}
-
-// Good to go.
-export function getPlaceName (place, companies) {
- // If address is provided (i.e. for carshare station, use it)
- if (place.address) return place.address.split(',')[0]
- if (place.networks && place.vertexType === 'VEHICLERENTAL') {
- // For vehicle rental pick up, do not use the place name. Rather, use
- // company name + vehicle type (e.g., SPIN E-scooter). Place name is often just
- // a UUID that has no relevance to the actual vehicle. For bikeshare, however,
- // there are often hubs or bikes that have relevant names to the user.
- const company = getCompanyForNetwork(place.networks[0], companies)
- if (company) {
- return `${company.label} ${getModeForPlace(place)}`
- }
- }
- // Default to place name
- return place.name
-}
-
-// Good to go.
-export function getTNCLocation (leg, type) {
- const location = leg[type]
- return `${location.lat.toFixed(5)},${location.lon.toFixed(5)}`
-}
-
-// Good to go.
-export function calculatePhysicalActivity (itinerary) {
- let walkDuration = 0
- let bikeDuration = 0
- for (const leg of itinerary.legs) {
- if (leg.mode.startsWith('WALK')) walkDuration += leg.duration
- if (leg.mode.startsWith('BICYCLE')) bikeDuration += leg.duration
- }
- const caloriesBurned =
- walkDuration / 3600 * 280 +
- bikeDuration / 3600 * 290
- return {
- bikeDuration,
- caloriesBurned,
- walkDuration
- }
-}
-
-// Good to go.
-export function calculateFares (itinerary) {
- let transitFare = 0
- let symbol = '$' // default to USD
- let dollarsToString = dollars => `${symbol}${dollars.toFixed(2)}`
- let centsToString = cents => `${symbol}${(cents / Math.pow(10, 2)).toFixed(2)}`
- if (itinerary.fare && itinerary.fare.fare && itinerary.fare.fare.regular) {
- const reg = itinerary.fare.fare.regular
- symbol = reg.currency.symbol
- transitFare = reg.cents
- centsToString = cents => `${symbol}${(cents / Math.pow(10, reg.currency.defaultFractionDigits)).toFixed(reg.currency.defaultFractionDigits)}`
- dollarsToString = dollars => `${symbol}${dollars.toFixed(2)}`
- }
-
- // Process any TNC fares
- let minTNCFare = 0
- let maxTNCFare = 0
- for (const leg of itinerary.legs) {
- if (leg.mode === 'CAR' && leg.hailedCar && leg.tncData) {
- const { maxCost, minCost } = leg.tncData
- // TODO: Support non-USD
- minTNCFare += minCost
- maxTNCFare += maxCost
- }
- }
- return {
- centsToString,
- dollarsToString,
- maxTNCFare,
- minTNCFare,
- transitFare
- }
-}
-
-// Good to go.
-export function getTimeZoneOffset (itinerary) {
- if (!itinerary.legs || !itinerary.legs.length) return 0
-
- // Determine if there is a DST offset between now and the itinerary start date
- const dstOffset = new Date(itinerary.startTime).getTimezoneOffset() - new Date().getTimezoneOffset()
-
- return itinerary.legs[0].agencyTimeZoneOffset + (new Date().getTimezoneOffset() + dstOffset) * 60000
-}
From 119268136e13bbd0db7c528679044a7a3b3b86cf Mon Sep 17 00:00:00 2001
From: binh-dam-ibigroup <56846598+binh-dam-ibigroup@users.noreply.github.com>
Date: Fri, 24 Apr 2020 10:17:13 -0400
Subject: [PATCH 23/31] refactor(core-utils): Initial migration over to OTP-ui
core-utils.
---
lib/components/form/default-search-form.js | 12 +-
.../narrative/default/transit-leg.js | 9 +-
.../narrative/itinerary-carousel.js | 39 +-
.../narrative/line-itin/itin-summary.js | 22 +-
.../narrative/tabbed-itineraries.js | 8 +-
lib/index.js | 2 +
lib/util/itinerary.js | 437 +-----------------
7 files changed, 40 insertions(+), 489 deletions(-)
diff --git a/lib/components/form/default-search-form.js b/lib/components/form/default-search-form.js
index 1f2578231..7dfe3a266 100644
--- a/lib/components/form/default-search-form.js
+++ b/lib/components/form/default-search-form.js
@@ -1,11 +1,17 @@
-import React, { Component } from 'react'
import PropTypes from 'prop-types'
+import React, { Component } from 'react'
import LocationField from './connected-location-field'
-import SwitchButton from './switch-button'
import TabbedFormPanel from './tabbed-form-panel'
+import SwitchButton from './switch-button'
import defaultIcons from '../icons'
+// Use the icons props to override icons for certain modes in the mode selector panel.
+// If no icon is provided for a specific mode, the default OTP-ui icon will be used.
+// const customIcons = {
+// TRANSIT:
+// }
+
export default class DefaultSearchForm extends Component {
static propTypes = {
icons: PropTypes.object,
@@ -13,7 +19,7 @@ export default class DefaultSearchForm extends Component {
}
static defaultProps = {
- icons: defaultIcons,
+ icons: defaultIcons, // customIcons,
showFrom: true,
showTo: true
}
diff --git a/lib/components/narrative/default/transit-leg.js b/lib/components/narrative/default/transit-leg.js
index 5809f3f1b..b6a6eefe0 100644
--- a/lib/components/narrative/default/transit-leg.js
+++ b/lib/components/narrative/default/transit-leg.js
@@ -1,14 +1,13 @@
-import Icon from '../icon'
-import React, { Component } from 'react'
+import { getMapColor } from '@opentripplanner/core-utils/lib/itinerary'
+import { formatDuration, formatTime } from '@opentripplanner/core-utils/lib/time'
import PropTypes from 'prop-types'
+import React, { Component } from 'react'
+import Icon from '../icon'
import ModeIcon from '../../icons/mode-icon'
import ViewTripButton from '../../viewers/view-trip-button'
import ViewStopButton from '../../viewers/view-stop-button'
-import { getMapColor } from '../../../util/itinerary'
-import { formatDuration, formatTime } from '../../../util/time'
-
export default class TransitLeg extends Component {
static propTypes = {
itinerary: PropTypes.object
diff --git a/lib/components/narrative/itinerary-carousel.js b/lib/components/narrative/itinerary-carousel.js
index ce7a373fa..0b9c828d4 100644
--- a/lib/components/narrative/itinerary-carousel.js
+++ b/lib/components/narrative/itinerary-carousel.js
@@ -1,5 +1,6 @@
-import React, { Component } from 'react'
+import { getTimeFormat } from '@opentripplanner/core-utils/lib/time'
import PropTypes from 'prop-types'
+import React, { Component } from 'react'
import { Button } from 'react-bootstrap'
import { connect } from 'react-redux'
import SwipeableViews from 'react-swipeable-views'
@@ -8,10 +9,7 @@ import { setActiveItinerary, setActiveLeg, setActiveStep } from '../../actions/n
import Icon from './icon'
import DefaultItinerary from './default/default-itinerary'
import Loading from './loading'
-import NarrativeProfileSummary from './narrative-profile-summary'
import { getActiveItineraries, getActiveSearch } from '../../util/state'
-import { profileOptionsToItineraries } from '../../util/profile'
-import { getTimeFormat } from '../../util/time'
class ItineraryCarousel extends Component {
state = {}
@@ -26,8 +24,6 @@ class ItineraryCarousel extends Component {
setActiveLeg: PropTypes.func,
setActiveStep: PropTypes.func,
expanded: PropTypes.bool,
- showProfileSummary: PropTypes.bool,
- profileOptions: PropTypes.array,
companies: PropTypes.string
}
@@ -54,18 +50,11 @@ class ItineraryCarousel extends Component {
}
render () {
- const { activeItinerary, itineraries, itineraryClass, hideHeader, pending, showProfileSummary } = this.props
+ const { activeItinerary, itineraries, itineraryClass, hideHeader, pending } = this.props
if (pending) return
if (!itineraries) return null
- let views = []
- if (showProfileSummary) {
- views.push(
-
Your Best Options (Swipe to View All)
-
-
)
- }
- views = views.concat(itineraries.map((itinerary, index) => {
+ const views = itineraries.map((itinerary, index) => {
return React.createElement(itineraryClass, {
itinerary,
index,
@@ -74,7 +63,7 @@ class ItineraryCarousel extends Component {
onClick: this._onItineraryClick,
...this.props
})
- }))
+ })
return (
@@ -112,23 +101,13 @@ class ItineraryCarousel extends Component {
const mapStateToProps = (state, ownProps) => {
const activeSearch = getActiveSearch(state.otp)
- let itineraries = null
- let profileOptions = null
- let showProfileSummary = false
- if (activeSearch && activeSearch.response && activeSearch.response.plan) {
- itineraries = getActiveItineraries(state.otp)
- } else if (activeSearch && activeSearch.response && activeSearch.response.otp) {
- profileOptions = activeSearch.response.otp.profile
- itineraries = profileOptionsToItineraries(profileOptions)
- showProfileSummary = true
- }
+ const itineraries = activeSearch && activeSearch.response && activeSearch.response.plan
+ ? getActiveItineraries(state.otp)
+ : null
- const pending = activeSearch && activeSearch.pending
return {
itineraries,
- profileOptions,
- pending,
- showProfileSummary,
+ pending: activeSearch && activeSearch.pending,
activeItinerary: activeSearch && activeSearch.activeItinerary,
activeLeg: activeSearch && activeSearch.activeLeg,
activeStep: activeSearch && activeSearch.activeStep,
diff --git a/lib/components/narrative/line-itin/itin-summary.js b/lib/components/narrative/line-itin/itin-summary.js
index 2e74575a7..955491975 100644
--- a/lib/components/narrative/line-itin/itin-summary.js
+++ b/lib/components/narrative/line-itin/itin-summary.js
@@ -4,12 +4,8 @@ import React, { Component } from 'react'
import styled from 'styled-components'
import {
- calculateFares,
- calculatePhysicalActivity,
- getLegIcon,
- isTransit
+ getLegIcon
} from '../../../util/itinerary'
-import { formatDuration, formatTime } from '../../../util/time'
// TODO: make this a prop
const defaultRouteColor = '#008'
@@ -48,7 +44,7 @@ const NonTransitSpacer = styled.div`
overflow: hidden
`
-const RoutePreivew = styled.div`
+const RoutePreview = styled.div`
display: inline-block;
margin-left: 8px;
vertical-align: top;
@@ -93,22 +89,22 @@ export default class ItinerarySummary extends Component {
maxTNCFare,
minTNCFare,
transitFare
- } = calculateFares(itinerary)
+ } = coreUtils.itinerary.calculateFares(itinerary)
// TODO: support non-USD
const minTotalFare = minTNCFare * 100 + transitFare
const maxTotalFare = maxTNCFare * 100 + transitFare
- const { caloriesBurned } = calculatePhysicalActivity(itinerary)
+ const { caloriesBurned } = coreUtils.itinerary.calculatePhysicalActivity(itinerary)
return (
{/* Travel time in hrs/mins */}
- {formatDuration(itinerary.duration)}
+ {coreUtils.time.formatDuration(itinerary.duration)}
{/* Duration as time range */}
- {formatTime(itinerary.startTime, timeOptions)} - {formatTime(itinerary.endTime, timeOptions)}
+ {coreUtils.time.formatTime(itinerary.startTime, timeOptions)} - {coreUtils.time.formatTime(itinerary.endTime, timeOptions)}
{/* Fare / Calories */}
@@ -134,9 +130,9 @@ export default class ItinerarySummary extends Component {
return !(leg.mode === 'WALK' && itinerary.transitTime > 0)
}).map((leg, k) => {
return (
-
+
{getLegIcon(leg, customIcons)}
- {isTransit(leg.mode)
+ {coreUtils.itinerary.isTransit(leg.mode)
? (
{getRouteNameForBadge(leg)}
@@ -144,7 +140,7 @@ export default class ItinerarySummary extends Component {
)
: ( )
}
-
+
)
})}
diff --git a/lib/components/narrative/tabbed-itineraries.js b/lib/components/narrative/tabbed-itineraries.js
index f3c4e2d76..9b440aa3a 100644
--- a/lib/components/narrative/tabbed-itineraries.js
+++ b/lib/components/narrative/tabbed-itineraries.js
@@ -1,13 +1,13 @@
-import React, { Component } from 'react'
+import { calculateFares, calculatePhysicalActivity, getTimeZoneOffset } from '@opentripplanner/core-utils/lib/itinerary'
+import { formatDuration, formatTime, getTimeFormat } from '@opentripplanner/core-utils/lib/time'
import PropTypes from 'prop-types'
-import { connect } from 'react-redux'
+import React, { Component } from 'react'
import { Button } from 'react-bootstrap'
+import { connect } from 'react-redux'
import { setActiveItinerary, setActiveLeg, setActiveStep, setUseRealtimeResponse } from '../../actions/narrative'
import DefaultItinerary from './default/default-itinerary'
import { getActiveSearch, getRealtimeEffects } from '../../util/state'
-import { calculateFares, calculatePhysicalActivity, getTimeZoneOffset } from '../../util/itinerary'
-import { formatDuration, formatTime, getTimeFormat } from '../../util/time'
class TabbedItineraries extends Component {
static propTypes = {
diff --git a/lib/index.js b/lib/index.js
index 5fb277044..4ed9f8b55 100644
--- a/lib/index.js
+++ b/lib/index.js
@@ -23,6 +23,7 @@ import SimpleRealtimeAnnotation from './components/narrative/simple-realtime-ann
import TransportationNetworkCompanyLeg from './components/narrative/default/tnc-leg'
import TripDetails from './components/narrative/connected-trip-details'
import TripTools from './components/narrative/trip-tools'
+import LineItinerary from './components/narrative/line-itin/line-itinerary'
import MobileMain from './components/mobile/main'
@@ -66,6 +67,7 @@ export {
// narrative components
LegDiagramPreview,
+ LineItinerary,
NarrativeItineraries,
NarrativeItinerary,
NarrativeRoutingResults,
diff --git a/lib/util/itinerary.js b/lib/util/itinerary.js
index df4196484..7134f7d55 100644
--- a/lib/util/itinerary.js
+++ b/lib/util/itinerary.js
@@ -1,196 +1,10 @@
-import React from 'react'
import { latLngBounds } from 'leaflet'
import polyline from '@mapbox/polyline'
-import turfAlong from '@turf/along'
+import React from 'react'
import ModeIcon from '../components/icons/mode-icon'
-// All OTP transit modes
-export const transitModes = ['TRAM', 'BUS', 'SUBWAY', 'FERRY', 'RAIL', 'GONDOLA']
-
-/**
- * @param {config} config OTP-RR configuration object
- * @return {Array} List of all transit modes defined in config; otherwise default mode list
- */
-
-export function getTransitModes (config) {
- if (!config || !config.modes || !config.modes.transitModes) return transitModes
- return config.modes.transitModes.map(tm => tm.mode)
-}
-
-export function isTransit (mode) {
- return transitModes.includes(mode) || mode === 'TRANSIT'
-}
-
-/**
- * @param {string} modesStr a comma-separated list of OTP modes
- * @return {boolean} whether any of the modes are transit modes
- */
-export function hasTransit (modesStr) {
- for (const mode of modesStr.split(',')) {
- if (isTransit(mode)) return true
- }
- return false
-}
-
-/**
- * @param {string} modesStr a comma-separated list of OTP modes
- * @return {boolean} whether any of the modes are car-based modes
- */
-export function hasCar (modesStr) {
- if (modesStr) {
- for (const mode of modesStr.split(',')) {
- if (isCar(mode)) return true
- }
- }
- return false
-}
-
-/**
- * @param {string} modesStr a comma-separated list of OTP modes
- * @return {boolean} whether any of the modes are bicycle-based modes
- */
-export function hasBike (modesStr) {
- if (modesStr) {
- for (const mode of modesStr.split(',')) {
- if (isBicycle(mode) || isBicycleRent(mode)) return true
- }
- }
- return false
-}
-
-/**
- * @param {string} modesStr a comma-separated list of OTP modes
- * @return {boolean} whether any of the modes are micromobility-based modes
- */
-export function hasMicromobility (modesStr) {
- if (modesStr) {
- for (const mode of modesStr.split(',')) {
- if (isMicromobility(mode)) return true
- }
- }
- return false
-}
-
-/**
- * @param {string} modesStr a comma-separated list of OTP modes
- * @return {boolean} whether any of the modes is a hailing mode
- */
-export function hasHail (modesStr) {
- if (modesStr) {
- for (const mode of modesStr.split(',')) {
- if (mode.indexOf('_HAIL') > -1) return true
- }
- }
- return false
-}
-
-/**
- * @param {string} modesStr a comma-separated list of OTP modes
- * @return {boolean} whether any of the modes is a rental mode
- */
-export function hasRental (modesStr) {
- if (modesStr) {
- for (const mode of modesStr.split(',')) {
- if (mode.indexOf('_RENT') > -1) return true
- }
- }
- return false
-}
-
-export function isWalk (mode) {
- if (!mode) return false
-
- return mode === 'WALK'
-}
-
-export function isBicycle (mode) {
- if (!mode) return false
-
- return mode === 'BICYCLE'
-}
-
-export function isBicycleRent (mode) {
- if (!mode) return false
-
- return mode === 'BICYCLE_RENT'
-}
-
-export function isCar (mode) {
- if (!mode) return false
- return mode.startsWith('CAR')
-}
-
-export function isMicromobility (mode) {
- if (!mode) return false
- return mode.startsWith('MICROMOBILITY')
-}
-
-export function isAccessMode (mode) {
- return isWalk(mode) ||
- isBicycle(mode) ||
- isBicycleRent(mode) ||
- isCar(mode) ||
- isMicromobility(mode)
-}
-
-export function getMapColor (mode) {
- mode = mode || this.get('mode')
- if (mode === 'WALK') return '#444'
- if (mode === 'BICYCLE') return '#0073e5'
- if (mode === 'SUBWAY') return '#f00'
- if (mode === 'RAIL') return '#b00'
- if (mode === 'BUS') return '#080'
- if (mode === 'TRAM') return '#800'
- if (mode === 'FERRY') return '#008'
- if (mode === 'CAR') return '#444'
- if (mode === 'MICROMOBILITY') return '#f5a729'
- return '#aaa'
-}
-
-// TODO: temporary code; handle via migrated OTP i18n language table
-export function getStepDirection (step) {
- switch (step.relativeDirection) {
- case 'DEPART': return 'Head ' + step.absoluteDirection.toLowerCase()
- case 'LEFT': return 'Left'
- case 'HARD_LEFT': return 'Hard left'
- case 'SLIGHTLY_LEFT': return 'Slight left'
- case 'CONTINUE': return 'Continue'
- case 'SLIGHTLY_RIGHT': return 'Slight right'
- case 'RIGHT': return 'Right'
- case 'HARD_RIGHT': return 'Hard right'
- case 'CIRCLE_CLOCKWISE': return 'Follow circle clockwise'
- case 'CIRCLE_COUNTERCLOCKWISE': return 'Follow circle counterclockwise'
- case 'ELEVATOR': return 'Take elevator'
- case 'UTURN_LEFT': return 'Left U-turn'
- case 'UTURN_RIGHT': return 'Right U-turn'
- }
- return step.relativeDirection
-}
-
-export function getStepInstructions (step) {
- const conjunction = step.relativeDirection === 'ELEVATOR' ? 'to' : 'on'
- return `${getStepDirection(step)} ${conjunction} ${step.streetName}`
-}
-
-export function getStepStreetName (step) {
- if (step.streetName === 'road') return 'Unnamed Road'
- if (step.streetName === 'path') return 'Unnamed Path'
- return step.streetName
-}
-
-export function getLegModeLabel (leg) {
- switch (leg.mode) {
- case 'BICYCLE_RENT': return 'Biketown'
- case 'CAR': return leg.hailedCar ? 'Ride' : 'Drive'
- case 'GONDOLA': return 'Aerial Tram'
- case 'TRAM':
- if (leg.routeLongName.toLowerCase().indexOf('streetcar') !== -1) return 'Streetcar'
- return 'Light Rail'
- case 'MICROMOBILITY': return 'Ride'
- }
- return toSentenceCase(leg.mode)
-}
+// DIFFERENT
/**
* Returns a react element of the desired icon. If customIcons are defined, then
@@ -228,6 +42,7 @@ export function getItineraryBounds (itinerary) {
return latLngBounds(coords)
}
+// DIFFERENT
/**
* Return a leaflet LatLngBounds object that encloses the given leg's geometry.
*/
@@ -484,121 +299,6 @@ export const routeComparator = makeMultiCriteriaSort(
makeStringValueComparator(obj => obj.longName)
)
-/* Returns an interpolated lat-lon at a specified distance along a leg */
-
-export function legLocationAtDistance (leg, distance) {
- if (!leg.legGeometry) return null
-
- try {
- const line = polyline.toGeoJSON(leg.legGeometry.points)
- const pt = turfAlong(line, distance, 'meters')
- if (pt && pt.geometry && pt.geometry.coordinates) {
- return [
- pt.geometry.coordinates[1],
- pt.geometry.coordinates[0]
- ]
- }
- } catch (e) { }
-
- return null
-}
-
-/* Returns an interpolated elevation at a specified distance along a leg */
-
-export function legElevationAtDistance (points, distance) {
- // Iterate through the combined elevation profile
- let traversed = 0
- // If first point distance is not zero, insert starting point at zero with
- // null elevation. Encountering this value should trigger the warning below.
- if (points[0][0] > 0) {
- points.unshift([0, null])
- }
- for (let i = 1; i < points.length; i++) {
- const start = points[i - 1]
- const elevDistanceSpan = points[i][0] - start[0]
- if (distance >= traversed && distance <= traversed + elevDistanceSpan) {
- // Distance falls within this point and the previous one;
- // compute & return iterpolated elevation value
- if (start[1] === null) {
- console.warn('Elevation value does not exist for distance.', distance, traversed)
- return null
- }
- const pct = (distance - traversed) / elevDistanceSpan
- const elevSpan = points[i][1] - start[1]
- return start[1] + elevSpan * pct
- }
- traversed += elevDistanceSpan
- }
- console.warn('Elevation value does not exist for distance.', distance, traversed)
- return null
-}
-
-// Iterate through the steps, building the array of elevation points and
-// keeping track of the minimum and maximum elevations reached
-export function getElevationProfile (steps, unitConversion = 1) {
- let minElev = 100000
- let maxElev = -100000
- let traversed = 0
- let gain = 0
- let loss = 0
- let previous = null
- const points = []
- steps.forEach((step, stepIndex) => {
- if (!step.elevation || step.elevation.length === 0) {
- traversed += step.distance
- return
- }
- for (let i = 0; i < step.elevation.length; i++) {
- const elev = step.elevation[i]
- if (previous) {
- const diff = (elev.second - previous.second) * unitConversion
- if (diff > 0) gain += diff
- else loss += diff
- }
- if (i === 0 && elev.first !== 0) {
- // console.warn(`No elevation data available for step ${stepIndex}-${i} at beginning of segment`, elev)
- }
- const convertedElevation = elev.second * unitConversion
- if (convertedElevation < minElev) minElev = convertedElevation
- if (convertedElevation > maxElev) maxElev = convertedElevation
- points.push([traversed + elev.first, elev.second])
- // Insert "filler" point if the last point in elevation profile does not
- // reach the full distance of the step.
- if (i === step.elevation.length - 1 && elev.first !== step.distance) {
- // points.push([traversed + step.distance, elev.second])
- }
- previous = elev
- }
- traversed += step.distance
- })
- return { maxElev, minElev, points, traversed, gain, loss }
-}
-
-/**
- * Uses canvas.measureText to compute and return the width of the given text of given font in pixels.
- *
- * @param {string} text The text to be rendered.
- * @param {string} font The css font descriptor that text is to be rendered with (e.g. "bold 14px verdana").
- *
- * @see https://stackoverflow.com/questions/118241/calculate-text-width-with-javascript/21015393#21015393
- */
-export function getTextWidth (text, font = '22px Arial') {
- // re-use canvas object for better performance
- var canvas = getTextWidth.canvas || (getTextWidth.canvas = document.createElement('canvas'))
- var context = canvas.getContext('2d')
- context.font = font
- var metrics = context.measureText(text)
- return metrics.width
-}
-
-export function toSentenceCase (str) {
- if (str == null) {
- return ''
- }
- str = String(str)
- return str.charAt(0).toUpperCase() + str.substr(1).toLowerCase()
-}
-
/**
* Return an icon depending on the leg info
*
@@ -633,134 +333,3 @@ export function getLegIcon (leg, customIcons) {
return getIcon(iconStr, customIcons)
}
-
-/**
- * Get the configured company object for the given network string if the company
- * has been defined in the provided companies array config.
- */
-function getCompanyForNetwork (networkString, companies = []) {
- const company = companies.find(co => co.id === networkString)
- if (!company) {
- console.warn(`No company found in config.yml that matches rented vehicle network: ${networkString}`, companies)
- }
- return company
-}
-
-/**
- * Get a string label to display from a list of vehicle rental networks.
- *
- * @param {Array} networks A list of network ids.
- * @param {Array} [companies=[]] An optional list of the companies config.
- * @return {string} A label for use in presentation on a website.
- */
-export function getCompaniesLabelFromNetworks (networks, companies = []) {
- return networks.map(network => getCompanyForNetwork(network, companies))
- .filter(co => !!co)
- .map(co => co.label)
- .join('/')
-}
-
-/**
- * Returns mode name by checking the vertex type (VertexType class in OTP) for
- * the provided place. NOTE: this is currently only intended for vehicles at
- * the moment (not transit or walking).
- *
- * TODO: I18N
- * @param {string} place place from itinerary leg
- */
-export function getModeForPlace (place) {
- switch (place.vertexType) {
- case 'CARSHARE':
- return 'car'
- case 'VEHICLERENTAL':
- return 'E-scooter'
- // TODO: Should the type change depending on bike vertex type?
- case 'BIKESHARE':
- case 'BIKEPARK':
- return 'bike'
- // If company offers more than one mode, default to `vehicle` string.
- default:
- return 'vehicle'
- }
-}
-
-export function getPlaceName (place, companies) {
- // If address is provided (i.e. for carshare station, use it)
- if (place.address) return place.address.split(',')[0]
- if (place.networks && place.vertexType === 'VEHICLERENTAL') {
- // For vehicle rental pick up, do not use the place name. Rather, use
- // company name + vehicle type (e.g., SPIN E-scooter). Place name is often just
- // a UUID that has no relevance to the actual vehicle. For bikeshare, however,
- // there are often hubs or bikes that have relevant names to the user.
- const company = getCompanyForNetwork(place.networks[0], companies)
- if (company) {
- return `${company.label} ${getModeForPlace(place)}`
- }
- }
- // Default to place name
- return place.name
-}
-
-export function getTNCLocation (leg, type) {
- const location = leg[type]
- return `${location.lat.toFixed(5)},${location.lon.toFixed(5)}`
-}
-
-export function calculatePhysicalActivity (itinerary) {
- let walkDuration = 0
- let bikeDuration = 0
- for (const leg of itinerary.legs) {
- if (leg.mode.startsWith('WALK')) walkDuration += leg.duration
- if (leg.mode.startsWith('BICYCLE')) bikeDuration += leg.duration
- }
- const caloriesBurned =
- walkDuration / 3600 * 280 +
- bikeDuration / 3600 * 290
- return {
- bikeDuration,
- caloriesBurned,
- walkDuration
- }
-}
-
-export function calculateFares (itinerary) {
- let transitFare = 0
- let symbol = '$' // default to USD
- let dollarsToString = dollars => `${symbol}${dollars.toFixed(2)}`
- let centsToString = cents => `${symbol}${(cents / Math.pow(10, 2)).toFixed(2)}`
- if (itinerary.fare && itinerary.fare.fare && itinerary.fare.fare.regular) {
- const reg = itinerary.fare.fare.regular
- symbol = reg.currency.symbol
- transitFare = reg.cents
- centsToString = cents => `${symbol}${(cents / Math.pow(10, reg.currency.defaultFractionDigits)).toFixed(reg.currency.defaultFractionDigits)}`
- dollarsToString = dollars => `${symbol}${dollars.toFixed(2)}`
- }
-
- // Process any TNC fares
- let minTNCFare = 0
- let maxTNCFare = 0
- for (const leg of itinerary.legs) {
- if (leg.mode === 'CAR' && leg.hailedCar && leg.tncData) {
- const { maxCost, minCost } = leg.tncData
- // TODO: Support non-USD
- minTNCFare += minCost
- maxTNCFare += maxCost
- }
- }
- return {
- centsToString,
- dollarsToString,
- maxTNCFare,
- minTNCFare,
- transitFare
- }
-}
-
-export function getTimeZoneOffset (itinerary) {
- if (!itinerary.legs || !itinerary.legs.length) return 0
-
- // Determine if there is a DST offset between now and the itinerary start date
- const dstOffset = new Date(itinerary.startTime).getTimezoneOffset() - new Date().getTimezoneOffset()
-
- return itinerary.legs[0].agencyTimeZoneOffset + (new Date().getTimezoneOffset() + dstOffset) * 60000
-}
From d00e8c94cc475f373587106d25d464804f911060 Mon Sep 17 00:00:00 2001
From: binh-dam-ibigroup <56846598+binh-dam-ibigroup@users.noreply.github.com>
Date: Fri, 24 Apr 2020 11:21:50 -0400
Subject: [PATCH 24/31] refactor(itinerary): Use OTP-ui itinerary getLegBounds
and getItineraryBounds.
---
lib/components/map/bounds-updating-overlay.js | 16 +++++-----
lib/util/itinerary.js | 30 ++++---------------
2 files changed, 13 insertions(+), 33 deletions(-)
diff --git a/lib/components/map/bounds-updating-overlay.js b/lib/components/map/bounds-updating-overlay.js
index 710b7e2d6..6472f62df 100644
--- a/lib/components/map/bounds-updating-overlay.js
+++ b/lib/components/map/bounds-updating-overlay.js
@@ -1,11 +1,11 @@
import isEqual from 'lodash.isequal'
-import { isMobile } from '@opentripplanner/core-utils/lib/ui'
-import { connect } from 'react-redux'
+import coreUtils from '@opentripplanner/core-utils'
import { MapLayer, withLeaflet } from 'react-leaflet'
+import { connect } from 'react-redux'
import {
- getItineraryBounds,
- getLegBounds
+ getLeafletItineraryBounds,
+ getLeafletLegBounds
} from '../../util/itinerary'
import { getActiveItinerary, getActiveSearch } from '../../util/state'
@@ -46,10 +46,10 @@ class BoundsUpdatingOverlay extends MapLayer {
// Fit map to to entire itinerary if active itinerary bounds changed
const newFrom = newProps.query && newProps.query.from
- const newItinBounds = newProps.itinerary && getItineraryBounds(newProps.itinerary)
+ const newItinBounds = newProps.itinerary && getLeafletItineraryBounds(newProps.itinerary)
const newTo = newProps.query && newProps.query.to
const oldFrom = oldProps.query && oldProps.query.from
- const oldItinBounds = oldProps.itinerary && getItineraryBounds(oldProps.itinerary)
+ const oldItinBounds = oldProps.itinerary && getLeafletItineraryBounds(oldProps.itinerary)
const oldTo = oldProps.query && oldProps.query.to
const fromChanged = !isEqual(oldFrom, newFrom)
const toChanged = !isEqual(oldTo, newTo)
@@ -65,7 +65,7 @@ class BoundsUpdatingOverlay extends MapLayer {
newProps.activeLeg !== null
) {
map.fitBounds(
- getLegBounds(newProps.itinerary.legs[newProps.activeLeg]),
+ getLeafletLegBounds(newProps.itinerary.legs[newProps.activeLeg]),
{ padding }
)
@@ -80,7 +80,7 @@ class BoundsUpdatingOverlay extends MapLayer {
// more info.
// TODO: Fix this so mobile devices will also update the bounds to the
// from/to locations.
- if (!isMobile()) {
+ if (!coreUtils.ui.isMobile()) {
map.fitBounds([
[newFrom.lat, newFrom.lon],
[newTo.lat, newTo.lon]
diff --git a/lib/util/itinerary.js b/lib/util/itinerary.js
index 7134f7d55..e2abbd442 100644
--- a/lib/util/itinerary.js
+++ b/lib/util/itinerary.js
@@ -1,11 +1,9 @@
import { latLngBounds } from 'leaflet'
-import polyline from '@mapbox/polyline'
+import coreUtils from '@opentripplanner/core-utils'
import React from 'react'
import ModeIcon from '../components/icons/mode-icon'
-// DIFFERENT
-
/**
* Returns a react element of the desired icon. If customIcons are defined, then
* the icon will be attempted to be used from that lookup of icons. Otherwise,
@@ -31,33 +29,15 @@ export function getIcon (iconId, customIcons) {
return
}
-export function getItineraryBounds (itinerary) {
- let coords = []
- itinerary.legs.forEach(leg => {
- const legCoords = polyline
- .toGeoJSON(leg.legGeometry.points)
- .coordinates.map(c => [c[1], c[0]])
- coords = [...coords, ...legCoords]
- })
- return latLngBounds(coords)
+export function getLeafletItineraryBounds (itinerary) {
+ return latLngBounds(coreUtils.itinerary.getItineraryBounds(itinerary))
}
-// DIFFERENT
/**
* Return a leaflet LatLngBounds object that encloses the given leg's geometry.
*/
-export function getLegBounds (leg) {
- const coords = polyline
- .toGeoJSON(leg.legGeometry.points)
- .coordinates.map(c => [c[1], c[0]])
-
- // in certain cases, there might be zero-length coordinates in the leg
- // geometry. In these cases, build us an array of coordinates using the from
- // and to data of the leg.
- if (coords.length === 0) {
- coords.push([leg.from.lat, leg.from.lon], [leg.to.lat, leg.to.lon])
- }
- return latLngBounds(coords)
+export function getLeafletLegBounds (leg) {
+ return latLngBounds(coreUtils.itinerary.getLegBounds(leg))
}
/**
From 966178cf1f3c3ed27c37fc726ae5dad686b1d74a Mon Sep 17 00:00:00 2001
From: binh-dam-ibigroup <56846598+binh-dam-ibigroup@users.noreply.github.com>
Date: Fri, 24 Apr 2020 12:58:30 -0400
Subject: [PATCH 25/31] refactor: Use `import coreUtils from
'@opentripplanner/core-utils' as much as possible.
---
__tests__/util/itinerary.js | 4 ++--
lib/actions/api.js | 10 +++++----
lib/actions/form.js | 20 ++++++++++--------
lib/actions/map.js | 4 ++--
lib/actions/narrative.js | 4 ++--
lib/actions/ui.js | 6 +++---
lib/components/app/responsive-webapp.js | 7 ++++---
lib/components/form/date-time-modal.js | 12 +++++------
lib/components/form/date-time-preview.js | 21 +++++++++++--------
lib/components/form/plan-trip-button.js | 4 ++--
lib/components/form/settings-preview.js | 4 ++--
lib/components/form/user-settings.js | 6 ++++--
lib/components/form/user-trip-settings.js | 6 +++---
.../map/connected-transitive-overlay.js | 4 ++--
lib/components/map/leg-diagram.js | 4 +++-
lib/components/map/stylized-map.js | 6 +++---
lib/components/mobile/results-screen.js | 4 ++--
.../narrative/connected-trip-details.js | 6 +++---
.../narrative/default/access-leg.js | 7 +++----
.../narrative/default/default-itinerary.js | 4 +++-
.../narrative/default/itinerary-details.js | 4 ++--
lib/components/narrative/default/tnc-leg.js | 8 ++++---
.../narrative/default/transit-leg.js | 6 ++++--
.../narrative/itinerary-carousel.js | 4 ++--
.../narrative/leg-diagram-preview.js | 4 ++--
.../narrative/line-itin/line-itinerary.js | 4 +++-
.../narrative/realtime-annotation.js | 4 ++--
.../narrative/tabbed-itineraries.js | 6 ++++--
lib/components/viewers/stop-viewer.js | 9 +++++++-
lib/components/viewers/trip-viewer.js | 6 +++---
lib/reducers/create-otp-reducer.js | 20 ++++++++++--------
lib/util/index.js | 2 --
lib/util/query.js | 15 -------------
lib/util/state.js | 13 ++++++++++++
lib/util/ui.js | 4 ++--
35 files changed, 139 insertions(+), 113 deletions(-)
delete mode 100644 lib/util/query.js
diff --git a/__tests__/util/itinerary.js b/__tests__/util/itinerary.js
index 83b06f3db..fcc0e709c 100644
--- a/__tests__/util/itinerary.js
+++ b/__tests__/util/itinerary.js
@@ -1,4 +1,4 @@
-import { isTransit } from '@opentripplanner/core-utils/lib/itinerary'
+import coreUtils from '@opentripplanner/core-utils'
import { routeComparator } from '../../lib/util/itinerary'
@@ -27,7 +27,7 @@ function sortRoutes (...routes) {
describe('util > itinerary', () => {
it('isTransit should work', () => {
- expect(isTransit('CAR')).toBeFalsy()
+ expect(coreUtils.itinerary.isTransit('CAR')).toBeFalsy()
})
describe('routeComparator', () => {
diff --git a/lib/actions/api.js b/lib/actions/api.js
index c13dec433..988e9900e 100644
--- a/lib/actions/api.js
+++ b/lib/actions/api.js
@@ -3,11 +3,8 @@ import { push, replace } from 'connected-react-router'
import haversine from 'haversine'
import moment from 'moment'
import hash from 'object-hash'
-import { hasCar } from '@opentripplanner/core-utils/lib/itinerary'
-import { getTripOptionsFromQuery, getUrlParams } from '@opentripplanner/core-utils/lib/query'
+import coreUtils from '@opentripplanner/core-utils'
import queryParams from '@opentripplanner/core-utils/lib/query-params'
-import { randId } from '@opentripplanner/core-utils/lib/storage'
-import { OTP_API_DATE_FORMAT, OTP_API_TIME_FORMAT } from '@opentripplanner/core-utils/lib/time'
import { createAction } from 'redux-actions'
import qs from 'qs'
@@ -15,6 +12,11 @@ import { rememberPlace } from './map'
import { getStopViewerConfig, queryIsValid } from '../util/state'
if (typeof (fetch) === 'undefined') require('isomorphic-fetch')
+const { hasCar } = coreUtils.itinerary
+const { getTripOptionsFromQuery, getUrlParams } = coreUtils.query
+const { randId } = coreUtils.storage
+const { OTP_API_DATE_FORMAT, OTP_API_TIME_FORMAT } = coreUtils.time
+
// Generic API actions
export const nonRealtimeRoutingResponse = createAction('NON_REALTIME_ROUTING_RESPONSE')
diff --git a/lib/actions/form.js b/lib/actions/form.js
index b1a1011d8..1916a2e3b 100644
--- a/lib/actions/form.js
+++ b/lib/actions/form.js
@@ -1,15 +1,7 @@
import debounce from 'lodash.debounce'
import isEqual from 'lodash.isequal'
import moment from 'moment'
-import {
- getDefaultQuery,
- getTripOptionsFromQuery,
- getUrlParams,
- planParamsToQuery
-} from '@opentripplanner/core-utils/lib/query'
-import { getItem, randId } from '@opentripplanner/core-utils/lib/storage'
-import { OTP_API_TIME_FORMAT } from '@opentripplanner/core-utils/lib/time'
-import { isMobile } from '@opentripplanner/core-utils/lib/ui'
+import coreUtils from '@opentripplanner/core-utils'
import { createAction } from 'redux-actions'
import { queryIsValid } from '../util/state'
@@ -21,6 +13,16 @@ import {
import { routingQuery } from './api'
+const {
+ getDefaultQuery,
+ getTripOptionsFromQuery,
+ getUrlParams,
+ planParamsToQuery
+} = coreUtils.query
+const { getItem, randId } = coreUtils.storage
+const { OTP_API_TIME_FORMAT } = coreUtils.time
+const { isMobile } = coreUtils.ui
+
export const settingQueryParam = createAction('SET_QUERY_PARAM')
export const clearActiveSearch = createAction('CLEAR_ACTIVE_SEARCH')
export const setActiveSearch = createAction('SET_ACTIVE_SEARCH')
diff --git a/lib/actions/map.js b/lib/actions/map.js
index 6e0e2bdc1..f3ec18447 100644
--- a/lib/actions/map.js
+++ b/lib/actions/map.js
@@ -1,4 +1,4 @@
-import { constructLocation } from '@opentripplanner/core-utils/lib/map'
+import coreUtils from '@opentripplanner/core-utils'
import getGeocoder from '@opentripplanner/geocoder'
import { createAction } from 'redux-actions'
@@ -116,7 +116,7 @@ export const setElevationPoint = createAction('SET_ELEVATION_POINT')
export const setMapPopupLocation = createAction('SET_MAP_POPUP_LOCATION')
export function setMapPopupLocationAndGeocode (mapEvent) {
- const location = constructLocation(mapEvent.latlng)
+ const location = coreUtils.map.constructLocation(mapEvent.latlng)
return function (dispatch, getState) {
dispatch(setMapPopupLocation({ location }))
getGeocoder(getState().otp.config.geocoder)
diff --git a/lib/actions/narrative.js b/lib/actions/narrative.js
index c69c78cc7..56cc5279c 100644
--- a/lib/actions/narrative.js
+++ b/lib/actions/narrative.js
@@ -1,4 +1,4 @@
-import { getUrlParams } from '@opentripplanner/core-utils/lib/query'
+import coreUtils from '@opentripplanner/core-utils'
import { createAction } from 'redux-actions'
import { setUrlSearch } from './api'
@@ -8,7 +8,7 @@ export function setActiveItinerary (payload) {
// Trigger change in store.
dispatch(settingActiveitinerary(payload))
// Update URL params.
- const urlParams = getUrlParams()
+ const urlParams = coreUtils.query.getUrlParams()
urlParams.ui_activeItinerary = payload.index
dispatch(setUrlSearch(urlParams))
}
diff --git a/lib/actions/ui.js b/lib/actions/ui.js
index 02f7374a8..9dc8decfe 100644
--- a/lib/actions/ui.js
+++ b/lib/actions/ui.js
@@ -1,5 +1,5 @@
import { push } from 'connected-react-router'
-import { getUrlParams } from '@opentripplanner/core-utils/lib/query'
+import coreUtils from '@opentripplanner/core-utils'
import { createAction } from 'redux-actions'
import { matchPath } from 'react-router'
@@ -8,7 +8,7 @@ import { setMapCenter, setMapZoom, setRouterId } from './config'
import { clearActiveSearch, parseUrlQueryString, setActiveSearch } from './form'
import { clearLocation } from './map'
import { setActiveItinerary } from './narrative'
-import { getUiUrlParams } from '../util/query'
+import { getUiUrlParams } from '../util/state'
/**
* Wrapper function for history#push that preserves the current search or, if
@@ -104,7 +104,7 @@ export function handleBackButtonPress (e) {
const uiUrlParams = getUiUrlParams(otpState)
// Get new search ID from URL after back button pressed.
// console.log('back button pressed', e)
- const urlParams = getUrlParams()
+ const urlParams = coreUtils.query.getUrlParams()
const previousSearchId = urlParams.ui_activeSearch
const previousItinIndex = +urlParams.ui_activeItinerary || 0
const previousSearch = otpState.searches[previousSearchId]
diff --git a/lib/components/app/responsive-webapp.js b/lib/components/app/responsive-webapp.js
index 233596914..464b10d18 100644
--- a/lib/components/app/responsive-webapp.js
+++ b/lib/components/app/responsive-webapp.js
@@ -1,8 +1,7 @@
import { ConnectedRouter } from 'connected-react-router'
import { createHashHistory } from 'history'
import isEqual from 'lodash.isequal'
-import { getUrlParams } from '@opentripplanner/core-utils/lib/query'
-import { isMobile } from '@opentripplanner/core-utils/lib/ui'
+import coreUtils from '@opentripplanner/core-utils'
import PropTypes from 'prop-types'
import React, { Component } from 'react'
import { connect } from 'react-redux'
@@ -17,6 +16,8 @@ import { handleBackButtonPress, matchContentToUrl } from '../../actions/ui'
import { getTitle } from '../../util/ui'
import { getActiveItinerary } from '../../util/state'
+const { isMobile } = coreUtils.ui
+
class ResponsiveWebapp extends Component {
static propTypes = {
desktopView: PropTypes.element,
@@ -30,7 +31,7 @@ class ResponsiveWebapp extends Component {
componentDidUpdate (prevProps) {
const { currentPosition, location, query, title } = this.props
document.title = title
- const urlParams = getUrlParams()
+ const urlParams = coreUtils.query.getUrlParams()
const newSearchId = urlParams.ui_activeSearch
// Determine if trip is being replanned by checking the active search ID
// against the ID found in the URL params. If they are different, a new one
diff --git a/lib/components/form/date-time-modal.js b/lib/components/form/date-time-modal.js
index 6b54176c4..0d934e8e5 100644
--- a/lib/components/form/date-time-modal.js
+++ b/lib/components/form/date-time-modal.js
@@ -1,8 +1,7 @@
-// import necessary React/Redux libraries
-import React, { Component } from 'react'
+import coreUtils from '@opentripplanner/core-utils'
import PropTypes from 'prop-types'
+import React, { Component } from 'react'
import { connect } from 'react-redux'
-import { getTimeFormat, getDateFormat } from '@opentripplanner/core-utils/lib/time'
import { setQueryParam } from '../../actions/form'
@@ -41,14 +40,15 @@ class DateTimeModal extends Component {
const mapStateToProps = (state, ownProps) => {
const { departArrive, date, time } = state.otp.currentQuery
+ const config = state.otp.config
return {
- config: state.otp.config,
+ config,
departArrive,
date,
time,
// These props below are for legacy browsers (see render method above).
- timeFormatLegacy: getTimeFormat(state.otp.config),
- dateFormatLegacy: getDateFormat(state.otp.config)
+ timeFormatLegacy: coreUtils.time.getTimeFormat(config),
+ dateFormatLegacy: coreUtils.time.getDateFormat(config)
}
}
diff --git a/lib/components/form/date-time-preview.js b/lib/components/form/date-time-preview.js
index 44754d044..846c8b974 100644
--- a/lib/components/form/date-time-preview.js
+++ b/lib/components/form/date-time-preview.js
@@ -1,15 +1,17 @@
import moment from 'moment'
-import {
- OTP_API_DATE_FORMAT,
- OTP_API_TIME_FORMAT,
- getTimeFormat,
- getDateFormat
-} from '@opentripplanner/core-utils/lib/time'
+import coreUtils from '@opentripplanner/core-utils'
import PropTypes from 'prop-types'
import React, { Component } from 'react'
import { Button } from 'react-bootstrap'
import { connect } from 'react-redux'
+const {
+ OTP_API_DATE_FORMAT,
+ OTP_API_TIME_FORMAT,
+ getTimeFormat,
+ getDateFormat
+} = coreUtils.time
+
class DateTimePreview extends Component {
static propTypes = {
caret: PropTypes.string,
@@ -81,16 +83,17 @@ class DateTimePreview extends Component {
const mapStateToProps = (state, ownProps) => {
const { departArrive, date, time, routingType, startTime, endTime } = state.otp.currentQuery
+ const config = state.otp.config
return {
- config: state.otp.config,
+ config,
routingType,
departArrive,
date,
time,
startTime,
endTime,
- timeFormat: getTimeFormat(state.otp.config),
- dateFormat: getDateFormat(state.otp.config)
+ timeFormat: getTimeFormat(config),
+ dateFormat: getDateFormat(config)
}
}
diff --git a/lib/components/form/plan-trip-button.js b/lib/components/form/plan-trip-button.js
index 73d2de18a..e2a091d0c 100644
--- a/lib/components/form/plan-trip-button.js
+++ b/lib/components/form/plan-trip-button.js
@@ -1,4 +1,4 @@
-import { isMobile } from '@opentripplanner/core-utils/lib/ui'
+import coreUtils from '@opentripplanner/core-utils'
import PropTypes from 'prop-types'
import React, { Component } from 'react'
import { Button } from 'react-bootstrap'
@@ -23,7 +23,7 @@ class PlanTripButton extends Component {
_onClick = () => {
this.props.routingQuery()
if (typeof this.props.onClick === 'function') this.props.onClick()
- if (!isMobile()) this.props.setMainPanelContent(null)
+ if (!coreUtils.ui.isMobile()) this.props.setMainPanelContent(null)
}
render () {
diff --git a/lib/components/form/settings-preview.js b/lib/components/form/settings-preview.js
index 4a3c78575..337c5d2b6 100644
--- a/lib/components/form/settings-preview.js
+++ b/lib/components/form/settings-preview.js
@@ -1,4 +1,4 @@
-import { isNotDefaultQuery } from '@opentripplanner/core-utils/lib/query'
+import coreUtils from '@opentripplanner/core-utils'
import PropTypes from 'prop-types'
import React, { Component } from 'react'
import { Button } from 'react-bootstrap'
@@ -27,7 +27,7 @@ class SettingsPreview extends Component {
render () {
const { config, query, caret, editButtonText } = this.props
// Show dot indicator if the current query differs from the default query.
- let showDot = isNotDefaultQuery(query, config)
+ let showDot = coreUtils.query.isNotDefaultQuery(query, config)
const button = (
diff --git a/lib/components/form/user-settings.js b/lib/components/form/user-settings.js
index c7878839b..71b80e41a 100644
--- a/lib/components/form/user-settings.js
+++ b/lib/components/form/user-settings.js
@@ -1,6 +1,5 @@
import moment from 'moment'
-import { getDetailText, formatStoredPlaceName, matchLatLon } from '@opentripplanner/core-utils/lib/map'
-import { summarizeQuery } from '@opentripplanner/core-utils/lib/query'
+import coreUtils from '@opentripplanner/core-utils'
import React, { Component } from 'react'
import { Button } from 'react-bootstrap'
import { connect } from 'react-redux'
@@ -11,6 +10,9 @@ import { setQueryParam } from '../../actions/form'
import { forgetPlace, forgetStop, setLocation } from '../../actions/map'
import { setViewedStop } from '../../actions/ui'
+const { getDetailText, formatStoredPlaceName, matchLatLon } = coreUtils.map
+const { summarizeQuery } = coreUtils.query
+
const BUTTON_WIDTH = 40
class UserSettings extends Component {
diff --git a/lib/components/form/user-trip-settings.js b/lib/components/form/user-trip-settings.js
index 5d00778f8..130992ccc 100644
--- a/lib/components/form/user-trip-settings.js
+++ b/lib/components/form/user-trip-settings.js
@@ -1,4 +1,4 @@
-import { getTripOptionsFromQuery, isNotDefaultQuery } from '@opentripplanner/core-utils/lib/query'
+import coreUtils from '@opentripplanner/core-utils'
import React, { Component } from 'react'
import { Button } from 'react-bootstrap'
import { connect } from 'react-redux'
@@ -18,7 +18,7 @@ import {
*/
class UserTripSettings extends Component {
_toggleStoredSettings = () => {
- const options = getTripOptionsFromQuery(this.props.query)
+ const options = coreUtils.query.getTripOptionsFromQuery(this.props.query)
// If user defaults are set, clear them. Otherwise, store them.
if (this.props.defaults) this.props.clearDefaultSettings()
else this.props.storeDefaultSettings(options)
@@ -34,7 +34,7 @@ class UserTripSettings extends Component {
// Do not permit remembering trip options if they do not differ from the
// defaults and nothing has been stored
- const queryIsDefault = !isNotDefaultQuery(query, config)
+ const queryIsDefault = !coreUtils.query.isNotDefaultQuery(query, config)
const rememberIsDisabled = queryIsDefault && !defaults
return (
diff --git a/lib/components/map/connected-transitive-overlay.js b/lib/components/map/connected-transitive-overlay.js
index 11f8c1f0e..aa7843fd2 100644
--- a/lib/components/map/connected-transitive-overlay.js
+++ b/lib/components/map/connected-transitive-overlay.js
@@ -1,4 +1,4 @@
-import { itineraryToTransitive } from '@opentripplanner/core-utils/lib/map'
+import coreUtils from '@opentripplanner/core-utils'
import TransitiveCanvasOverlay from '@opentripplanner/transitive-overlay'
import { connect } from 'react-redux'
@@ -17,7 +17,7 @@ const mapStateToProps = (state, ownProps) => {
) {
const itins = getActiveItineraries(state.otp)
// TODO: prevent itineraryToTransitive() from being called more than needed
- transitiveData = itineraryToTransitive(itins[activeSearch.activeItinerary])
+ transitiveData = coreUtils.map.itineraryToTransitive(itins[activeSearch.activeItinerary])
} else if (
activeSearch &&
activeSearch.response &&
diff --git a/lib/components/map/leg-diagram.js b/lib/components/map/leg-diagram.js
index 0f4ae9fd4..917d1f3bf 100644
--- a/lib/components/map/leg-diagram.js
+++ b/lib/components/map/leg-diagram.js
@@ -1,5 +1,5 @@
import memoize from 'lodash.memoize'
-import { getElevationProfile, getTextWidth, legElevationAtDistance } from '@opentripplanner/core-utils/lib/itinerary'
+import coreUtils from '@opentripplanner/core-utils'
import PropTypes from 'prop-types'
import React, {Component} from 'react'
import { Button } from 'react-bootstrap'
@@ -8,6 +8,8 @@ import ReactResizeDetector from 'react-resize-detector'
import { setElevationPoint, showLegDiagram } from '../../actions/map'
+const { getElevationProfile, getTextWidth, legElevationAtDistance } = coreUtils.itinerary
+
// Fixed dimensions for chart
const height = 160
const yAxisPanelWidth = 40 // width of y axis labels
diff --git a/lib/components/map/stylized-map.js b/lib/components/map/stylized-map.js
index f3635a5e8..54e25509c 100644
--- a/lib/components/map/stylized-map.js
+++ b/lib/components/map/stylized-map.js
@@ -1,6 +1,6 @@
import { select, event } from 'd3-selection'
import { zoom } from 'd3-zoom'
-import { isBikeshareStation, itineraryToTransitive } from '@opentripplanner/core-utils/lib/map'
+import coreUtils from '@opentripplanner/core-utils'
import PropTypes from 'prop-types'
import React, { Component } from 'react'
import { connect } from 'react-redux'
@@ -15,7 +15,7 @@ STYLES.places = {
if (
place.getId() !== 'from' &&
place.getId() !== 'to' &&
- !isBikeshareStation(place)
+ !coreUtils.map.isBikeshareStation(place)
) {
return 'none'
}
@@ -116,7 +116,7 @@ const mapStateToProps = (state, ownProps) => {
activeSearch.response.plan
) {
const itins = getActiveItineraries(state.otp)
- transitiveData = itineraryToTransitive(itins[activeSearch.activeItinerary])
+ transitiveData = coreUtils.map.itineraryToTransitive(itins[activeSearch.activeItinerary])
} else if (
activeSearch &&
activeSearch.response &&
diff --git a/lib/components/mobile/results-screen.js b/lib/components/mobile/results-screen.js
index fce9656cc..e62aa0a7c 100644
--- a/lib/components/mobile/results-screen.js
+++ b/lib/components/mobile/results-screen.js
@@ -1,4 +1,4 @@
-import { enableScrollForSelector } from '@opentripplanner/core-utils/lib/ui'
+import coreUtils from '@opentripplanner/core-utils'
import LocationIcon from '@opentripplanner/location-icon'
import PropTypes from 'prop-types'
import React, { Component } from 'react'
@@ -68,7 +68,7 @@ class MobileResultsScreen extends Component {
// Get the target element that we want to persist scrolling for
// FIXME Do we need to add something that removes the listeners when
// component unmounts?
- enableScrollForSelector('.mobile-narrative-container')
+ coreUtils.ui.enableScrollForSelector('.mobile-narrative-container')
}
componentDidUpdate (prevProps) {
diff --git a/lib/components/narrative/connected-trip-details.js b/lib/components/narrative/connected-trip-details.js
index daf54e076..f34205233 100644
--- a/lib/components/narrative/connected-trip-details.js
+++ b/lib/components/narrative/connected-trip-details.js
@@ -1,4 +1,4 @@
-import { getTimeFormat, getLongDateFormat } from '@opentripplanner/core-utils/lib/time'
+import coreUtils from '@opentripplanner/core-utils'
import TripDetailsBase from '@opentripplanner/trip-details'
import { connect } from 'react-redux'
import styled from 'styled-components'
@@ -16,8 +16,8 @@ const mapStateToProps = (state, ownProps) => {
return {
routingType: state.otp.currentQuery.routingType,
tnc: state.otp.tnc,
- timeFormat: getTimeFormat(state.otp.config),
- longDateFormat: getLongDateFormat(state.otp.config)
+ timeFormat: coreUtils.time.getTimeFormat(state.otp.config),
+ longDateFormat: coreUtils.time.getLongDateFormat(state.otp.config)
}
}
diff --git a/lib/components/narrative/default/access-leg.js b/lib/components/narrative/default/access-leg.js
index e40157677..7924038b7 100644
--- a/lib/components/narrative/default/access-leg.js
+++ b/lib/components/narrative/default/access-leg.js
@@ -1,5 +1,4 @@
-import { getStepInstructions } from '@opentripplanner/core-utils/lib/itinerary'
-import { formatDuration } from '@opentripplanner/core-utils/lib/time'
+import coreUtils from '@opentripplanner/core-utils'
import PropTypes from 'prop-types'
import React, {Component} from 'react'
@@ -47,7 +46,7 @@ export default class AccessLeg extends Component {
{leg.mode}
{' '}
- {formatDuration(leg.duration)}
+ {coreUtils.time.formatDuration(leg.duration)}
{' '}
({distanceString(leg.distance)})
@@ -62,7 +61,7 @@ export default class AccessLeg extends Component {
className={`step ${stepIsActive ? 'active' : ''}`}
onClick={(e) => this._onStepClick(e, step, stepIndex)}>
{distanceString(step.distance)}
-
{getStepInstructions(step)}
+
{coreUtils.itinerary.getStepInstructions(step)}
)
})}
diff --git a/lib/components/narrative/default/default-itinerary.js b/lib/components/narrative/default/default-itinerary.js
index 3eae4c049..efc740c3a 100644
--- a/lib/components/narrative/default/default-itinerary.js
+++ b/lib/components/narrative/default/default-itinerary.js
@@ -1,4 +1,4 @@
-import { formatDuration, formatTime } from '@opentripplanner/core-utils/lib/time'
+import coreUtils from '@opentripplanner/core-utils'
import React from 'react'
import NarrativeItinerary from '../narrative-itinerary'
@@ -7,6 +7,8 @@ import ItineraryDetails from './itinerary-details'
import TripDetails from '../connected-trip-details'
import TripTools from '../trip-tools'
+const { formatDuration, formatTime } = coreUtils.time
+
export default class DefaultItinerary extends NarrativeItinerary {
render () {
const {
diff --git a/lib/components/narrative/default/itinerary-details.js b/lib/components/narrative/default/itinerary-details.js
index b12d214b3..91537b8b6 100644
--- a/lib/components/narrative/default/itinerary-details.js
+++ b/lib/components/narrative/default/itinerary-details.js
@@ -1,4 +1,4 @@
-import { isTransit } from '@opentripplanner/core-utils/lib/itinerary'
+import coreUtils from '@opentripplanner/core-utils'
import PropTypes from 'prop-types'
import React, { Component } from 'react'
@@ -16,7 +16,7 @@ export default class ItineraryDetails extends Component {
{itinerary.legs.map((leg, index) => {
const legIsActive = activeLeg === index
- return isTransit(leg.mode)
+ return coreUtils.itinerary.isTransit(leg.mode)
?
{
activeLeg: activeSearch && activeSearch.activeLeg,
activeStep: activeSearch && activeSearch.activeStep,
companies: state.otp.currentQuery.companies,
- timeFormat: getTimeFormat(state.otp.config)
+ timeFormat: coreUtils.time.getTimeFormat(state.otp.config)
}
}
diff --git a/lib/components/narrative/leg-diagram-preview.js b/lib/components/narrative/leg-diagram-preview.js
index 6ce1ed09d..fd624d807 100644
--- a/lib/components/narrative/leg-diagram-preview.js
+++ b/lib/components/narrative/leg-diagram-preview.js
@@ -1,4 +1,4 @@
-import { getElevationProfile } from '@opentripplanner/core-utils/lib/itinerary'
+import coreUtils from '@opentripplanner/core-utils'
import PropTypes from 'prop-types'
import React, {Component} from 'react'
import { connect } from 'react-redux'
@@ -45,7 +45,7 @@ class LegDiagramPreview extends Component {
render () {
const { leg, showElevationProfile } = this.props
if (!showElevationProfile) return null
- const profile = getElevationProfile(leg.steps)
+ const profile = coreUtils.itinerary.getElevationProfile(leg.steps)
// Don't show for very short legs
if (leg.distance < 500 || leg.mode === 'CAR') return null
diff --git a/lib/components/narrative/line-itin/line-itinerary.js b/lib/components/narrative/line-itin/line-itinerary.js
index 8876d43ad..baf6034bd 100644
--- a/lib/components/narrative/line-itin/line-itinerary.js
+++ b/lib/components/narrative/line-itin/line-itinerary.js
@@ -1,4 +1,4 @@
-import { getLegModeLabel, getTimeZoneOffset, isTransit } from '@opentripplanner/core-utils/lib/itinerary'
+import coreUtils from '@opentripplanner/core-utils'
import React from 'react'
import styled from 'styled-components'
@@ -7,6 +7,8 @@ import ItinerarySummary from './itin-summary'
import NarrativeItinerary from '../narrative-itinerary'
import SimpleRealtimeAnnotation from '../simple-realtime-annotation'
+const { getLegModeLabel, getTimeZoneOffset, isTransit } = coreUtils.itinerary
+
export const LineItineraryContainer = styled.div`
margin-bottom: 20px;
`
diff --git a/lib/components/narrative/realtime-annotation.js b/lib/components/narrative/realtime-annotation.js
index d0ecd93d5..31ed7cd0e 100644
--- a/lib/components/narrative/realtime-annotation.js
+++ b/lib/components/narrative/realtime-annotation.js
@@ -1,4 +1,4 @@
-import { formatDuration } from '@opentripplanner/core-utils/lib/time'
+import coreUtils from '@opentripplanner/core-utils'
import PropTypes from 'prop-types'
import React, { Component } from 'react'
import { Button, OverlayTrigger, Popover } from 'react-bootstrap'
@@ -32,7 +32,7 @@ export default class RealtimeAnnotation extends Component {
?
Your trip results have been adjusted based on real-time
information. Under normal conditions, this trip would take{' '}
- {formatDuration(realtimeEffects.normalDuration)}
+ {coreUtils.time.formatDuration(realtimeEffects.normalDuration)}
using the following routes:{' '}
{filteredRoutes
.map((route, idx) => (
diff --git a/lib/components/narrative/tabbed-itineraries.js b/lib/components/narrative/tabbed-itineraries.js
index 9b440aa3a..94f38eeb8 100644
--- a/lib/components/narrative/tabbed-itineraries.js
+++ b/lib/components/narrative/tabbed-itineraries.js
@@ -1,5 +1,4 @@
-import { calculateFares, calculatePhysicalActivity, getTimeZoneOffset } from '@opentripplanner/core-utils/lib/itinerary'
-import { formatDuration, formatTime, getTimeFormat } from '@opentripplanner/core-utils/lib/time'
+import coreUtils from '@opentripplanner/core-utils'
import PropTypes from 'prop-types'
import React, { Component } from 'react'
import { Button } from 'react-bootstrap'
@@ -9,6 +8,9 @@ import { setActiveItinerary, setActiveLeg, setActiveStep, setUseRealtimeResponse
import DefaultItinerary from './default/default-itinerary'
import { getActiveSearch, getRealtimeEffects } from '../../util/state'
+const { calculateFares, calculatePhysicalActivity, getTimeZoneOffset } = coreUtils.itinerary
+const { formatDuration, formatTime, getTimeFormat } = coreUtils.time
+
class TabbedItineraries extends Component {
static propTypes = {
itineraries: PropTypes.array,
diff --git a/lib/components/viewers/stop-viewer.js b/lib/components/viewers/stop-viewer.js
index 1c04a1d80..07c9128ee 100644
--- a/lib/components/viewers/stop-viewer.js
+++ b/lib/components/viewers/stop-viewer.js
@@ -1,6 +1,6 @@
import moment from 'moment'
import 'moment-timezone'
-import { formatDuration, formatSecondsAfterMidnight, getTimeFormat, getUserTimezone } from '@opentripplanner/core-utils/lib/time'
+import coreUtils from '@opentripplanner/core-utils'
import FromToLocationPicker from '@opentripplanner/from-to-location-picker'
import PropTypes from 'prop-types'
import React, { Component } from 'react'
@@ -15,6 +15,13 @@ import { forgetStop, rememberStop, setLocation } from '../../actions/map'
import { routeComparator } from '../../util/itinerary'
import { getShowUserSettings, getStopViewerConfig } from '../../util/state'
+const {
+ formatDuration,
+ formatSecondsAfterMidnight,
+ getTimeFormat,
+ getUserTimezone
+} = coreUtils.time
+
class StopViewer extends Component {
state = {}
diff --git a/lib/components/viewers/trip-viewer.js b/lib/components/viewers/trip-viewer.js
index d517938aa..9ce414d29 100644
--- a/lib/components/viewers/trip-viewer.js
+++ b/lib/components/viewers/trip-viewer.js
@@ -1,4 +1,4 @@
-import { formatSecondsAfterMidnight, getTimeFormat } from '@opentripplanner/core-utils/lib/time'
+import coreUtils from '@opentripplanner/core-utils'
import PropTypes from 'prop-types'
import React, { Component } from 'react'
import { Button, Label } from 'react-bootstrap'
@@ -100,7 +100,7 @@ class TripViewer extends Component {
{/* the departure time */}
- {formatSecondsAfterMidnight(tripData.stopTimes[i].scheduledDeparture, timeFormat)}
+ {coreUtils.time.formatSecondsAfterMidnight(tripData.stopTimes[i].scheduledDeparture, timeFormat)}
{/* the vertical strip map */}
@@ -136,7 +136,7 @@ const mapStateToProps = (state, ownProps) => {
const viewedTrip = state.otp.ui.viewedTrip
return {
languageConfig: state.otp.config.language,
- timeFormat: getTimeFormat(state.otp.config),
+ timeFormat: coreUtils.time.getTimeFormat(state.otp.config),
tripData: state.otp.transitIndex.trips[viewedTrip.tripId],
viewedTrip
}
diff --git a/lib/reducers/create-otp-reducer.js b/lib/reducers/create-otp-reducer.js
index 4008e2f01..d18fbdb20 100644
--- a/lib/reducers/create-otp-reducer.js
+++ b/lib/reducers/create-otp-reducer.js
@@ -2,18 +2,20 @@ import clone from 'clone'
import update from 'immutability-helper'
import isEqual from 'lodash.isequal'
import objectPath from 'object-path'
-import { isTransit, getTransitModes } from '@opentripplanner/core-utils/lib/itinerary'
-import { matchLatLon } from '@opentripplanner/core-utils/lib/map'
-import { filterProfileOptions } from '@opentripplanner/core-utils/lib/profile'
-import {
+import coreUtils from '@opentripplanner/core-utils'
+
+import { MainPanelContent, MobileScreens } from '../actions/ui'
+
+const { isTransit, getTransitModes } = coreUtils.itinerary
+const { matchLatLon } = coreUtils.map
+const { filterProfileOptions } = coreUtils.profile
+const {
ensureSingleAccessMode,
getDefaultQuery,
getTripOptionsFromQuery
-} from '@opentripplanner/core-utils/lib/query'
-import { getItem, removeItem, storeItem } from '@opentripplanner/core-utils/lib/storage'
-import { getUserTimezone } from '@opentripplanner/core-utils/lib/time'
-
-import { MainPanelContent, MobileScreens } from '../actions/ui'
+} = coreUtils.query
+const { getItem, removeItem, storeItem } = coreUtils.storage
+const { getUserTimezone } = coreUtils.time
const MAX_RECENT_STORAGE = 5
diff --git a/lib/util/index.js b/lib/util/index.js
index 3cb72d8d0..4803c5931 100644
--- a/lib/util/index.js
+++ b/lib/util/index.js
@@ -1,13 +1,11 @@
import * as distance from './distance'
import * as itinerary from './itinerary'
-import * as query from './query'
import * as state from './state'
import * as ui from './ui'
const OtpUtils = {
distance,
itinerary,
- query,
state,
ui
}
diff --git a/lib/util/query.js b/lib/util/query.js
deleted file mode 100644
index c864e91c0..000000000
--- a/lib/util/query.js
+++ /dev/null
@@ -1,15 +0,0 @@
-import { getActiveSearch } from './state'
-
-// => Used in actions/ui/handleBackButtonPress()
-/**
- * Assemble any UI-state properties to be tracked via URL into a single object
- * TODO: Expand to include additional UI properties
- */
-export function getUiUrlParams (otpState) {
- const activeSearch = getActiveSearch(otpState)
- const uiParams = {
- ui_activeItinerary: activeSearch ? activeSearch.activeItinerary : 0,
- ui_activeSearch: otpState.activeSearchId
- }
- return uiParams
-}
diff --git a/lib/util/state.js b/lib/util/state.js
index 8019564e8..704c2e75f 100644
--- a/lib/util/state.js
+++ b/lib/util/state.js
@@ -135,3 +135,16 @@ export function getShowUserSettings (otpState) {
export function getStopViewerConfig (otpState) {
return otpState.config.stopViewer
}
+
+/**
+ * Assemble any UI-state properties to be tracked via URL into a single object
+ * TODO: Expand to include additional UI properties
+ */
+export function getUiUrlParams (otpState) {
+ const activeSearch = getActiveSearch(otpState)
+ const uiParams = {
+ ui_activeItinerary: activeSearch ? activeSearch.activeItinerary : 0,
+ ui_activeSearch: otpState.activeSearchId
+ }
+ return uiParams
+}
diff --git a/lib/util/ui.js b/lib/util/ui.js
index 47e452528..da40aa33e 100644
--- a/lib/util/ui.js
+++ b/lib/util/ui.js
@@ -1,4 +1,4 @@
-import { summarizeQuery } from '@opentripplanner/core-utils/lib/query'
+import coreUtils from '@opentripplanner/core-utils'
import { MainPanelContent } from '../actions/ui'
import { getActiveSearch } from './state'
@@ -23,7 +23,7 @@ export function getTitle (state) {
default:
const activeSearch = getActiveSearch(state.otp)
if (activeSearch) {
- title += ` | ${summarizeQuery(activeSearch.query, user.locations)}`
+ title += ` | ${coreUtils.query.summarizeQuery(activeSearch.query, user.locations)}`
}
break
}
From f54896eb74351a1de03d0a04e3e87f74e1f1de97 Mon Sep 17 00:00:00 2001
From: binh-dam-ibigroup <56846598+binh-dam-ibigroup@users.noreply.github.com>
Date: Fri, 24 Apr 2020 13:12:10 -0400
Subject: [PATCH 26/31] refactor(line-itinerary/itinerary.css): Should not have
brought back this file.
---
.../narrative/line-itin/itinerary.css | 375 ------------------
1 file changed, 375 deletions(-)
delete mode 100644 lib/components/narrative/line-itin/itinerary.css
diff --git a/lib/components/narrative/line-itin/itinerary.css b/lib/components/narrative/line-itin/itinerary.css
deleted file mode 100644
index 89df3acf0..000000000
--- a/lib/components/narrative/line-itin/itinerary.css
+++ /dev/null
@@ -1,375 +0,0 @@
-.otp .options.profile .itin-body .place-row {
- margin-left: 55px;
-}
-
-.otp .line-itin {
- margin-bottom: 20px;
-}
-
-/* Itinerary summary */
-
-.otp .line-itin .itin-summary {
- padding-right: 5px;
- height: 60px;
- display: table;
- width: 100%;
- margin-bottom: 15px;
-}
-
-.otp .desktop-narrative-container .options.itinerary .line-itin .itin-summary {
- display: none;
-}
-
-.otp .line-itin .itin-summary .details {
- display: table-cell;
- vertical-align: top;
-}
-
-.otp .line-itin .itin-summary .header {
- font-weight: bold;
- font-size: 18px;
- margin-top: -3px;
-}
-
-.otp .line-itin .itin-summary .detail {
- font-size: 13px;
- color: #999999;
-}
-
-.otp .line-itin .itin-summary .routes {
- display: table-cell;
- text-align: right;
-}
-
-.otp .line-itin .itin-summary .routes .route-preview {
- display: inline-block;
- margin-left: 8px;
- vertical-align: top;
-}
-
-.otp .line-itin .itin-summary .routes .route-preview .mode-icon {
- height: 30px;
- width: 30px;
-}
-
-.otp .line-itin .itin-summary .routes .route-preview .short-name {
- color: white;
- font-weight: 500;
- text-align: center;
- margin-top: 6px;
- font-size: 15px;
- padding-top: 2px;
- text-overflow: ellipsis;
- white-space: nowrap;
- overflow: hidden;
- width: 30px;
- height: 30px;
- border-radius: 15px;
- border: 2px solid white;
- box-shadow: 0 0 0.5em #000;
-}
-
-/* Itinerary main body */
-
-.otp .line-itin .itin-body {
- padding: 20px 0px;
-}
-
-.otp .line-itin .place-row {
- display: table;
- width: 100%;
-}
-
-
-/* Departure/arrival time (1st column in table) */
-
-.otp .line-itin .time {
- display: table-cell;
- width: 60px;
- font-size: 14px;
- color: #999999;
- text-align: right;
- padding-right: 4px;
- padding-top: 1px;
- vertical-align: top;
-}
-
-/* The place icon and line itself (2nd column in table) */
-.otp .line-itin .line-container {
- position: relative;
- display: table-cell;
- width: 20px;
- max-width: 20px;
-}
-
-.otp .line-itin .place-icon-group {
- position: absolute;
- font-size: 18px;
- left: -8px;
- top: -7px;
- z-index: 20;
-}
-
-.otp .line-itin .leg-line {
- position: absolute;
- top: 11px;
- bottom: -11px;
- z-index: 10;
-}
-
-// Internet explorer specific media query to apply the below styling to fix
-// rendering issues with table cell display with undefined heights.
-/*@media screen and (-ms-high-contrast: active), (-ms-high-contrast: none) {
- .otp .line-itin .line-container {
- overflow: hidden; // hack for IE to render table cell correctly.
- }
-
- .otp .line-itin .leg-line {
- height: 1000px; // hack for IE to render table cell correctly.
- }
-}*/
-
-.otp .line-itin .leg-line-walk {
- left: 6px;
- right: 6px;
- background: radial-gradient(ellipse at center, #87cefa 40%, transparent 10%);
- background-size: 12px 12px;
- background-repeat: repeat-y;
- background-position: center -5px;
-}
-
-.otp .line-itin .leg-line-bicycle {
- left: 7.5px;
- right: 7.5px;
- background: repeating-linear-gradient(
- 0deg,
- red,
- red 8px,
- white 8px,
- white 12.5px
- );
-}
-
-.otp .line-itin .leg-line-car {
- left: 7.5px;
- right: 7.5px;
- background: repeating-linear-gradient(
- 0deg,
- grey,
- grey 8px,
- white 8px,
- white 12.5px
- );
-}
-
-.otp .line-itin .leg-line-micromobility {
- left: 7.5px;
- right: 7.5px;
- background: repeating-linear-gradient(
- 0deg,
- #f5a729,
- #f5a729 8px,
- white 8px,
- white 12.5px
- );
-}
-
-.otp .line-itin .leg-line-transit {
- left: 5px;
- right: 5px;
- background-color: gray;
-}
-
-/* Place/Leg details (3rd column in table) */
-
-.otp .line-itin .place-details {
- font-size: 13px;
- display: table-cell;
- padding-top: 1px;
-}
-
-.otp .line-itin .place-name {
- font-size: 18px;
- line-height: 20px;
- padding-left: 4px;
- font-weight: 500;
- color: black;
-}
-
-.otp .line-itin .place-subheader {
- font-size: 12px;
- padding-left: 4px;
- padding-top: 1px;
- font-weight: 300;
- color: gray;
-}
-
-.otp .line-itin .interline-dot {
- position: relative;
- float: left;
- margin-left: -13.5px;
- z-index: 25;
- color: #fff;
-}
-
-.otp .line-itin .interline-name {
- font-size: 14px;
- font-weight: 400;
- line-height: 16px;
-}
-
-/* Leg body general */
-
-.otp .line-itin .leg-body {
- padding: 12px 0px 18px 4px;
- font-size: 13px;
- color: #999999;
-}
-
-.otp .line-itin .summary {
- cursor: pointer;
-}
-
-.otp .line-itin .leg-body .icon {
- height: 24px;
- width: 24px;
- float: left;
- margin-right: 6px;
-}
-
-.otp .line-itin .leg-body .leg-description {
- display: table;
-}
-
-.otp .line-itin .leg-body .leg-description > div {
- display: table-cell;
- vertical-align: middle;
-}
-
-/* Leg steps (for turn-by-turn) */
-
-.otp .line-itin .leg-body .steps-header {
- font-size: 13px;
- margin-top: 10px;
- color: #999999;
- font-style: normal;
- display: inline-block;
-}
-
-.otp .line-itin .leg-body .step-row {
- font-size: 13px;
- margin-top: 8px;
- color: #999999;
- font-style: normal;
-}
-
-/* Transit leg details */
-
-.otp .line-itin .leg-body .route-name {
- color: #999999;
- margin-top: 5px;
-}
-
-.otp .line-itin .leg-body .route-short-name {
- display: inline-block;
- background-color: #0f6aac;
- padding-top: 1px;
- color: white;
- font-weight: 500;
- font-size: 14px;
- margin-right: 6px;
- text-align: center;
- width: 24px;
- height: 24px;
- border-radius: 12px;
- border: 1px solid white;
- box-shadow: 0 0 0.25em #000;
- margin-right: 8px;
-}
-
-.otp .line-itin .leg-body .route-long-name {
- font-size: 13px;
- line-height: 16px;
- font-weight: 500;
-}
-
-.otp .line-itin .leg-body .transit-leg-details {
- margin-top: 5px;
-}
-
-.otp .line-itin .leg-body .agency-info {
- margin-top: 5px;
-
-}
-
-.otp .line-itin .leg-body .transit-leg-details .header {
- cursor: pointer;
- color: #999999;
- font-size: 13px;
-}
-
-/* Intermediate stops */
-
-.otp .line-itin .leg-body .transit-leg-details .intermediate-stops .stop-row {
- z-index: 30;
- position: relative;
-}
-
-.otp .line-itin .leg-body .transit-leg-details .intermediate-stops .stop-marker {
- float: left;
- margin-left: -17px;
- color: white;
-}
-
-.otp .line-itin .leg-body .transit-leg-details .intermediate-stops .stop-name {
- color: #999999;
- font-size: 14px;
- margin-top: 3px;
-}
-
-/* Transit alerts */
-
-.otp .line-itin .leg-body .transit-alerts-toggle {
- display: inline-block;
- margin-top: 8px;
- color: #D14727;
- font-weight: 400;
- cursor: pointer;
-}
-
-.otp .line-itin .leg-body .transit-alerts {
- margin-top: 3px;
-}
-
-.otp .line-itin .leg-body .transit-alerts .transit-alert {
- margin-top: 5px;
- background-color: #eee;
- padding: 8px;
- color: black;
- border-radius: 4px;
-}
-
-.otp .line-itin .leg-body .transit-alerts .transit-alert .alert-icon {
- float: left;
- font-size: 18px;
-}
-
-.otp .line-itin .leg-body .transit-alerts .transit-alert .alert-header {
- font-size: 14px;
- margin-left: 30px;
- font-weight: 600;
-}
-
-.otp .line-itin .leg-body .transit-alerts .transit-alert .alert-body {
- font-size: 12px;
- margin-left: 30px;
- /* white space pre-wrap is required to render line breaks correctly. */
- white-space: pre-wrap;
-}
-
-.otp .line-itin .leg-body .transit-alerts .transit-alert .effective-date {
- margin-top: 5px;
- margin-left: 30px;
- font-size: 12px;
- font-style: italic;
-}
From 0ccc86f6c65bc36e9e7850e9c8f2d06bb7366295 Mon Sep 17 00:00:00 2001
From: binh-dam-ibigroup <56846598+binh-dam-ibigroup@users.noreply.github.com>
Date: Fri, 24 Apr 2020 14:37:43 -0400
Subject: [PATCH 27/31] refactor(TriMetLegIcon): Import TriMetLegIcon from the
root of icons package.
---
lib/components/app/print-layout.js | 2 +-
lib/components/narrative/line-itin/connected-itinerary-body.js | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/lib/components/app/print-layout.js b/lib/components/app/print-layout.js
index 2fda1815f..724db3ee3 100644
--- a/lib/components/app/print-layout.js
+++ b/lib/components/app/print-layout.js
@@ -1,4 +1,4 @@
-import TriMetLegIcon from '@opentripplanner/icons/lib/trimet-leg-icon'
+import { TriMetLegIcon } from '@opentripplanner/icons'
import PrintableItinerary from '@opentripplanner/printable-itinerary'
import PropTypes from 'prop-types'
import React, { Component } from 'react'
diff --git a/lib/components/narrative/line-itin/connected-itinerary-body.js b/lib/components/narrative/line-itin/connected-itinerary-body.js
index 0c8774da3..e4c92a4b6 100644
--- a/lib/components/narrative/line-itin/connected-itinerary-body.js
+++ b/lib/components/narrative/line-itin/connected-itinerary-body.js
@@ -1,5 +1,5 @@
import isEqual from 'lodash.isequal'
-import TriMetLegIcon from '@opentripplanner/icons/lib/trimet-leg-icon'
+import { TriMetLegIcon } from '@opentripplanner/icons'
import TransitLegSummary from '@opentripplanner/itinerary-body/lib/defaults/transit-leg-summary'
import ItineraryBody from '@opentripplanner/itinerary-body/lib/otp-react-redux/itinerary-body'
import LineColumnContent from '@opentripplanner/itinerary-body/lib/otp-react-redux/line-column-content'
From ca56c603d130df1aa9804cc06f78445b3a91179a Mon Sep 17 00:00:00 2001
From: binh-dam-ibigroup <56846598+binh-dam-ibigroup@users.noreply.github.com>
Date: Fri, 24 Apr 2020 18:02:30 -0400
Subject: [PATCH 28/31] refactor: Address PR comments.
---
lib/actions/form.js | 16 ++++------
lib/components/app/responsive-webapp.js | 3 +-
lib/components/form/default-search-form.js | 8 +----
.../narrative/narrative-routing-results.js | 6 ++--
lib/util/index.js | 2 ++
lib/util/state.js | 31 ++++++++++++++++++
lib/util/ui.js | 32 -------------------
7 files changed, 45 insertions(+), 53 deletions(-)
delete mode 100644 lib/util/ui.js
diff --git a/lib/actions/form.js b/lib/actions/form.js
index 1916a2e3b..abaa4ff00 100644
--- a/lib/actions/form.js
+++ b/lib/actions/form.js
@@ -19,9 +19,6 @@ const {
getUrlParams,
planParamsToQuery
} = coreUtils.query
-const { getItem, randId } = coreUtils.storage
-const { OTP_API_TIME_FORMAT } = coreUtils.time
-const { isMobile } = coreUtils.ui
export const settingQueryParam = createAction('SET_QUERY_PARAM')
export const clearActiveSearch = createAction('CLEAR_ACTIVE_SEARCH')
@@ -37,7 +34,7 @@ export function resetForm () {
dispatch(settingQueryParam(otpState.user.defaults))
} else {
// Get user overrides and apply to default query
- const userOverrides = getItem('defaultQuery', {})
+ const userOverrides = coreUtils.storage.getItem('defaultQuery', {})
const defaultQuery = Object.assign(
getDefaultQuery(otpState.config),
userOverrides
@@ -71,7 +68,7 @@ export function parseUrlQueryString (params = getUrlParams()) {
Object.keys(params).forEach(key => {
if (!key.startsWith('ui_')) planParams[key] = params[key]
})
- const searchId = params.ui_activeSearch || randId()
+ const searchId = params.ui_activeSearch || coreUtils.storage.randId()
// Convert strings to numbers/objects and dispatch
dispatch(
setQueryParam(
@@ -91,10 +88,11 @@ let lastDebouncePlanTimeMs
export function formChanged (oldQuery, newQuery) {
return function (dispatch, getState) {
const otpState = getState().otp
+ const isMobile = coreUtils.ui.isMobile()
// If departArrive is set to 'NOW', update the query time to current
if (otpState.currentQuery && otpState.currentQuery.departArrive === 'NOW') {
- dispatch(settingQueryParam({ time: moment().format(OTP_API_TIME_FORMAT) }))
+ dispatch(settingQueryParam({ time: moment().format(coreUtils.time.OTP_API_TIME_FORMAT) }))
}
// Determine if either from/to location has changed
@@ -113,7 +111,7 @@ export function formChanged (oldQuery, newQuery) {
// either location changes only if not currently on welcome screen (otherwise
// when the current position is auto-set the screen will change unexpectedly).
if (
- isMobile() &&
+ isMobile &&
(fromChanged || toChanged) &&
otpState.ui.mobileScreen !== MobileScreens.WELCOME_SCREEN
) {
@@ -125,8 +123,8 @@ export function formChanged (oldQuery, newQuery) {
const { autoPlan, debouncePlanTimeMs } = otpState.config
const updatePlan =
autoPlan ||
- (!isMobile() && oneLocationChanged) || // TODO: make autoplan configurable at the parameter level?
- (isMobile() && fromChanged && toChanged)
+ (!isMobile && oneLocationChanged) || // TODO: make autoplan configurable at the parameter level?
+ (isMobile && fromChanged && toChanged)
if (updatePlan && queryIsValid(otpState)) { // trip plan should be made
// check if debouncing function needs to be (re)created
if (!debouncedPlanTrip || lastDebouncePlanTimeMs !== debouncePlanTimeMs) {
diff --git a/lib/components/app/responsive-webapp.js b/lib/components/app/responsive-webapp.js
index 464b10d18..eea5f49a7 100644
--- a/lib/components/app/responsive-webapp.js
+++ b/lib/components/app/responsive-webapp.js
@@ -13,8 +13,7 @@ import { formChanged, parseUrlQueryString } from '../../actions/form'
import { getCurrentPosition, receivedPositionResponse } from '../../actions/location'
import { setLocationToCurrent } from '../../actions/map'
import { handleBackButtonPress, matchContentToUrl } from '../../actions/ui'
-import { getTitle } from '../../util/ui'
-import { getActiveItinerary } from '../../util/state'
+import { getActiveItinerary, getTitle } from '../../util/state'
const { isMobile } = coreUtils.ui
diff --git a/lib/components/form/default-search-form.js b/lib/components/form/default-search-form.js
index 7dfe3a266..98be08f8a 100644
--- a/lib/components/form/default-search-form.js
+++ b/lib/components/form/default-search-form.js
@@ -6,12 +6,6 @@ import TabbedFormPanel from './tabbed-form-panel'
import SwitchButton from './switch-button'
import defaultIcons from '../icons'
-// Use the icons props to override icons for certain modes in the mode selector panel.
-// If no icon is provided for a specific mode, the default OTP-ui icon will be used.
-// const customIcons = {
-// TRANSIT:
-// }
-
export default class DefaultSearchForm extends Component {
static propTypes = {
icons: PropTypes.object,
@@ -19,7 +13,7 @@ export default class DefaultSearchForm extends Component {
}
static defaultProps = {
- icons: defaultIcons, // customIcons,
+ icons: defaultIcons,
showFrom: true,
showTo: true
}
diff --git a/lib/components/narrative/narrative-routing-results.js b/lib/components/narrative/narrative-routing-results.js
index 2047d4cfb..204cc245b 100644
--- a/lib/components/narrative/narrative-routing-results.js
+++ b/lib/components/narrative/narrative-routing-results.js
@@ -25,14 +25,14 @@ class NarrativeRoutingResults extends Component {
}
render () {
- const { customIcons, error, itineraryClass, itineraryFooter, pending, routingType, itineraries, mainPanelContent } = this.props
+ const { customIcons, error, itineraryClass, itineraryFooter, pending, itineraries, mainPanelContent } = this.props
if (pending) return
if (error) return
if (mainPanelContent) return null
return (
- routingType === 'ITINERARY' &&
-
+ // TODO: If multiple routing types exist, do the check here.
+
)
}
}
diff --git a/lib/util/index.js b/lib/util/index.js
index 4803c5931..2e060cdd3 100644
--- a/lib/util/index.js
+++ b/lib/util/index.js
@@ -1,9 +1,11 @@
+import coreUtils from '@opentripplanner/core-utils'
import * as distance from './distance'
import * as itinerary from './itinerary'
import * as state from './state'
import * as ui from './ui'
const OtpUtils = {
+ ...coreUtils,
distance,
itinerary,
state,
diff --git a/lib/util/state.js b/lib/util/state.js
index 704c2e75f..cc22fc24c 100644
--- a/lib/util/state.js
+++ b/lib/util/state.js
@@ -1,5 +1,8 @@
+import coreUtils from '@opentripplanner/core-utils'
import isEqual from 'lodash.isequal'
+import { MainPanelContent } from '../actions/ui'
+
/**
* Get the active search object
* @param {Object} otpState the OTP state object
@@ -148,3 +151,31 @@ export function getUiUrlParams (otpState) {
}
return uiParams
}
+
+// Set default title to the original document title (on load) set in index.html
+const DEFAULT_TITLE = document.title
+
+export function getTitle (state) {
+ // Override title can optionally be provided in config.yml
+ const { config, ui, user } = state.otp
+ let title = config.title || DEFAULT_TITLE
+ const { mainPanelContent, viewedRoute, viewedStop } = ui
+ switch (mainPanelContent) {
+ case MainPanelContent.ROUTE_VIEWER:
+ title += ' | Route'
+ if (viewedRoute && viewedRoute.routeId) title += ` ${viewedRoute.routeId}`
+ break
+ case MainPanelContent.STOP_VIEWER:
+ title += ' | Stop'
+ if (viewedStop && viewedStop.stopId) title += ` ${viewedStop.stopId}`
+ break
+ default:
+ const activeSearch = getActiveSearch(state.otp)
+ if (activeSearch) {
+ title += ` | ${coreUtils.query.summarizeQuery(activeSearch.query, user.locations)}`
+ }
+ break
+ }
+ // if (printView) title += ' | Print'
+ return title
+}
diff --git a/lib/util/ui.js b/lib/util/ui.js
deleted file mode 100644
index da40aa33e..000000000
--- a/lib/util/ui.js
+++ /dev/null
@@ -1,32 +0,0 @@
-import coreUtils from '@opentripplanner/core-utils'
-
-import { MainPanelContent } from '../actions/ui'
-import { getActiveSearch } from './state'
-
-// Set default title to the original document title (on load) set in index.html
-const DEFAULT_TITLE = document.title
-
-export function getTitle (state) {
- // Override title can optionally be provided in config.yml
- const { config, ui, user } = state.otp
- let title = config.title || DEFAULT_TITLE
- const { mainPanelContent, viewedRoute, viewedStop } = ui
- switch (mainPanelContent) {
- case MainPanelContent.ROUTE_VIEWER:
- title += ' | Route'
- if (viewedRoute && viewedRoute.routeId) title += ` ${viewedRoute.routeId}`
- break
- case MainPanelContent.STOP_VIEWER:
- title += ' | Stop'
- if (viewedStop && viewedStop.stopId) title += ` ${viewedStop.stopId}`
- break
- default:
- const activeSearch = getActiveSearch(state.otp)
- if (activeSearch) {
- title += ` | ${coreUtils.query.summarizeQuery(activeSearch.query, user.locations)}`
- }
- break
- }
- // if (printView) title += ' | Print'
- return title
-}
From 2690d3da16bcfa3d4685e006c67cc7b65adc8a5b Mon Sep 17 00:00:00 2001
From: binh-dam-ibigroup <56846598+binh-dam-ibigroup@users.noreply.github.com>
Date: Fri, 24 Apr 2020 18:14:08 -0400
Subject: [PATCH 29/31] refactor(util/index): Remove unused vars.
---
lib/util/index.js | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/lib/util/index.js b/lib/util/index.js
index 2e060cdd3..fdeac261c 100644
--- a/lib/util/index.js
+++ b/lib/util/index.js
@@ -2,14 +2,12 @@ import coreUtils from '@opentripplanner/core-utils'
import * as distance from './distance'
import * as itinerary from './itinerary'
import * as state from './state'
-import * as ui from './ui'
const OtpUtils = {
...coreUtils,
distance,
itinerary,
- state,
- ui
+ state
}
export default OtpUtils
From f9910e5297e2aec10be775b8fedb6e623bae5d02 Mon Sep 17 00:00:00 2001
From: binh-dam-ibigroup <56846598+binh-dam-ibigroup@users.noreply.github.com>
Date: Tue, 28 Apr 2020 10:01:10 -0400
Subject: [PATCH 30/31] fix(otp-ui version): Upgrade to OTP-ui 0.0.20.
---
lib/util/index.js | 2 -
package.json | 38 ++++----
yarn.lock | 221 +++++++++++++++++++++++-----------------------
3 files changed, 129 insertions(+), 132 deletions(-)
diff --git a/lib/util/index.js b/lib/util/index.js
index fdeac261c..70f3f81e0 100644
--- a/lib/util/index.js
+++ b/lib/util/index.js
@@ -1,10 +1,8 @@
-import coreUtils from '@opentripplanner/core-utils'
import * as distance from './distance'
import * as itinerary from './itinerary'
import * as state from './state'
const OtpUtils = {
- ...coreUtils,
distance,
itinerary,
state
diff --git a/package.json b/package.json
index b40050d7f..5a949fbd1 100644
--- a/package.json
+++ b/package.json
@@ -29,25 +29,25 @@
"dependencies": {
"@conveyal/lonlat": "^1.1.0",
"@mapbox/polyline": "^0.2.0",
- "@opentripplanner/base-map": "^0.0.19",
- "@opentripplanner/core-utils": "^0.0.19",
- "@opentripplanner/endpoints-overlay": "^0.0.19",
- "@opentripplanner/from-to-location-picker": "^0.0.19",
- "@opentripplanner/geocoder": "^0.0.19",
- "@opentripplanner/icons": "^0.0.19",
- "@opentripplanner/itinerary-body": "^0.0.19",
- "@opentripplanner/location-field": "^0.0.19",
- "@opentripplanner/location-icon": "^0.0.19",
- "@opentripplanner/park-and-ride-overlay": "^0.0.19",
- "@opentripplanner/printable-itinerary": "^0.0.19",
- "@opentripplanner/route-viewer-overlay": "^0.0.19",
- "@opentripplanner/stop-viewer-overlay": "^0.0.19",
- "@opentripplanner/stops-overlay": "^0.0.19",
- "@opentripplanner/transitive-overlay": "^0.0.19",
- "@opentripplanner/trip-details": "^0.0.19",
- "@opentripplanner/trip-form": "^0.0.19",
- "@opentripplanner/trip-viewer-overlay": "^0.0.19",
- "@opentripplanner/vehicle-rental-overlay": "^0.0.19",
+ "@opentripplanner/base-map": "^0.0.20",
+ "@opentripplanner/core-utils": "^0.0.20",
+ "@opentripplanner/endpoints-overlay": "^0.0.20",
+ "@opentripplanner/from-to-location-picker": "^0.0.20",
+ "@opentripplanner/geocoder": "^0.0.20",
+ "@opentripplanner/icons": "^0.0.20",
+ "@opentripplanner/itinerary-body": "^0.0.20",
+ "@opentripplanner/location-field": "^0.0.20",
+ "@opentripplanner/location-icon": "^0.0.20",
+ "@opentripplanner/park-and-ride-overlay": "^0.0.20",
+ "@opentripplanner/printable-itinerary": "^0.0.20",
+ "@opentripplanner/route-viewer-overlay": "^0.0.20",
+ "@opentripplanner/stop-viewer-overlay": "^0.0.20",
+ "@opentripplanner/stops-overlay": "^0.0.20",
+ "@opentripplanner/transitive-overlay": "^0.0.20",
+ "@opentripplanner/trip-details": "^0.0.20",
+ "@opentripplanner/trip-form": "^0.0.20",
+ "@opentripplanner/trip-viewer-overlay": "^0.0.20",
+ "@opentripplanner/vehicle-rental-overlay": "^0.0.20",
"@turf/along": "^6.0.1",
"bootstrap": "^3.3.7",
"bowser": "^1.9.3",
diff --git a/yarn.lock b/yarn.lock
index b477c125d..e2ad479a9 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1331,18 +1331,18 @@
universal-user-agent "^3.0.0"
url-template "^2.0.8"
-"@opentripplanner/base-map@^0.0.19":
- version "0.0.19"
- resolved "https://registry.yarnpkg.com/@opentripplanner/base-map/-/base-map-0.0.19.tgz#71b0d77c7e8265f742f5383c943663436eb3369b"
- integrity sha512-X/OtKsCoVOfJ4GrkDfvW5zufDE2dTzdGsagojrrTk0mzJTh1Kv+x+Oe3iXJfllg5U61yt06PDunFdsZE5kHr2w==
+"@opentripplanner/base-map@^0.0.20":
+ version "0.0.20"
+ resolved "https://registry.yarnpkg.com/@opentripplanner/base-map/-/base-map-0.0.20.tgz#35f1b81179080e5b2573a67b9ce9408dde390bd2"
+ integrity sha512-FR9C93sou4d+3b7wytDsMRZQ/Zeu7ZJGAoQ8WiHlPnCIS/grRTWeihQysK1zga9JAerpBocvIvLc2pF3DyJAIw==
dependencies:
- "@opentripplanner/core-utils" "^0.0.19"
+ "@opentripplanner/core-utils" "^0.0.20"
prop-types "^15.7.2"
-"@opentripplanner/core-utils@^0.0.19":
- version "0.0.19"
- resolved "https://registry.yarnpkg.com/@opentripplanner/core-utils/-/core-utils-0.0.19.tgz#152991efb07d578abf40649ce0dde1c62a8ec4e3"
- integrity sha512-9j0j8pGba+af5kz0K8+6bNLy/34BL7CEIHkLQyyLv3H30GpzJWQ+r9z6zIcwndVcoBqEcrn6gLBr1S2KrBscZA==
+"@opentripplanner/core-utils@^0.0.20":
+ version "0.0.20"
+ resolved "https://registry.yarnpkg.com/@opentripplanner/core-utils/-/core-utils-0.0.20.tgz#057914abe4f395cc9bb5468a97b620ad6e46efe4"
+ integrity sha512-nwUk/FCJ2X68SM8zN53SFGD2x3ooMirJ2JRcA22U2v8hsEU6NywaSiDDvG1/kjC+WWHbHSNLP5VACSnFc7UAWA==
dependencies:
"@mapbox/polyline" "^1.1.0"
"@turf/along" "^6.0.1"
@@ -1353,173 +1353,172 @@
prop-types "^15.7.2"
qs "^6.9.1"
-"@opentripplanner/endpoints-overlay@^0.0.19":
- version "0.0.19"
- resolved "https://registry.yarnpkg.com/@opentripplanner/endpoints-overlay/-/endpoints-overlay-0.0.19.tgz#667a70b8b0526cc3fd01e4f69e4839cf04a85ca5"
- integrity sha512-0Cd4dd5yYXP42udDAKGNHj00WuCXwoWThj03IWagKOpbr7T5g7ag7B1RkbMJQICYsFvqg9stQJ3AnOmNrwBBPw==
+"@opentripplanner/endpoints-overlay@^0.0.20":
+ version "0.0.20"
+ resolved "https://registry.yarnpkg.com/@opentripplanner/endpoints-overlay/-/endpoints-overlay-0.0.20.tgz#386835b7ab0fb18d68eb5035ab4984f55717363d"
+ integrity sha512-1miuJBESWRBXR5TH2EUrUyn/zKeTngcoitWfWUbX322rRv3D6soNd7BdOSqQ1waxKHobqWKC1Tq/Az2RbfZhIg==
dependencies:
- "@opentripplanner/core-utils" "^0.0.19"
- "@opentripplanner/location-icon" "^0.0.19"
+ "@opentripplanner/core-utils" "^0.0.20"
+ "@opentripplanner/location-icon" "^0.0.20"
prop-types "^15.7.2"
styled-icons "^9.1.0"
-"@opentripplanner/from-to-location-picker@^0.0.19":
- version "0.0.19"
- resolved "https://registry.yarnpkg.com/@opentripplanner/from-to-location-picker/-/from-to-location-picker-0.0.19.tgz#5dd78fff068c84c256fa504dd163ca70e51b2cd9"
- integrity sha512-ZNPJVRO2OIOKjdRLOX4fnOvWTX07ccTXEuUfXPpITOf8QBHnJZPTFBgBSMmfqxMfcuLf6NRD4+YzFcllIO4opQ==
+"@opentripplanner/from-to-location-picker@^0.0.20":
+ version "0.0.20"
+ resolved "https://registry.yarnpkg.com/@opentripplanner/from-to-location-picker/-/from-to-location-picker-0.0.20.tgz#e945a286ae39077b3fbd3ddf1f31cbb38ea4a067"
+ integrity sha512-b+bLWcDu9y5jYUz078isXGnyhTlO0gSXBTtYoEOsm0Y7RNDIfvrytKDxSKAyPnaRnaftkbsUcXTmUfUTXCw2PQ==
dependencies:
- "@opentripplanner/core-utils" "^0.0.19"
- "@opentripplanner/location-icon" "^0.0.19"
+ "@opentripplanner/core-utils" "^0.0.20"
+ "@opentripplanner/location-icon" "^0.0.20"
prop-types "^15.7.2"
-"@opentripplanner/geocoder@^0.0.19":
- version "0.0.19"
- resolved "https://registry.yarnpkg.com/@opentripplanner/geocoder/-/geocoder-0.0.19.tgz#4ff8b1baf3c322491f472db31c3fbd7ed576b2a1"
- integrity sha512-BOkOY85fj6E2CAFemlMH3qu/e4t9xG3llKrvasm8Vh23PI3FwQRtDQoN8qz3vK4s/pjZsd0D/TpS8+bQGI9HQQ==
+"@opentripplanner/geocoder@^0.0.20":
+ version "0.0.20"
+ resolved "https://registry.yarnpkg.com/@opentripplanner/geocoder/-/geocoder-0.0.20.tgz#479eed134f4bb68cde9442c049b2630e5eaa499c"
+ integrity sha512-EkTLmdrBzw0ABFiOrJCEM6ajK5D2T+KFD3FcTowTi7e1esGWpXzEDb7VvbobMaMhwDCztenv1s0APd9J9o0B0g==
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.19":
- version "0.0.19"
- resolved "https://registry.yarnpkg.com/@opentripplanner/humanize-distance/-/humanize-distance-0.0.19.tgz#30d445e9f586afcf0488a8fe27157d62b29fd563"
- integrity sha512-gEDH3oB8XZoraPWfsmVfEZYqPN/aqh+Z3Pjc35asJmdOCVKuWWnSem/W4qyK6hBnpMV3RUl9TBKl3B5ubnqBLA==
+"@opentripplanner/humanize-distance@^0.0.20":
+ version "0.0.20"
+ resolved "https://registry.yarnpkg.com/@opentripplanner/humanize-distance/-/humanize-distance-0.0.20.tgz#06eab437c92b8eea5d9596957d7fbcc8c2bd4500"
+ integrity sha512-m+3gpoSDGY13f8WRIx8fSkVi6Qhv23fG3zbY6oymFQ+j5bMPow4f6XJO2nIY+pI0EbipPEKWbpeRwmXZWlWspg==
-"@opentripplanner/icons@^0.0.19":
- version "0.0.19"
- resolved "https://registry.yarnpkg.com/@opentripplanner/icons/-/icons-0.0.19.tgz#7681ad2b202e18f361cc4ae32b9c14e162500e50"
- integrity sha512-yGNBamoCzvdzcc86RFfZGW5SsktOsXV2G+USPr9goWoP1Hw1IukSn2gEWP8s8qvBCulAMr7HZdLHSXAT9TXk9w==
+"@opentripplanner/icons@^0.0.20":
+ version "0.0.20"
+ resolved "https://registry.yarnpkg.com/@opentripplanner/icons/-/icons-0.0.20.tgz#951c75ed093fb9d74e4b4fc7d2af45ced446b856"
+ integrity sha512-vV81bsB7b3XN8lED3A55Qrjx84lUJyiVY99f13W1oqRlaP1xFIk4MSspg6hHoyanLiZBGp+vdcwWYnKJk4LLtw==
dependencies:
- "@opentripplanner/core-utils" "^0.0.19"
+ "@opentripplanner/core-utils" "^0.0.20"
prop-types "^15.7.2"
-"@opentripplanner/itinerary-body@^0.0.19":
- version "0.0.19"
- resolved "https://registry.yarnpkg.com/@opentripplanner/itinerary-body/-/itinerary-body-0.0.19.tgz#44c7858f848a625c7327de38850adc2f0a086667"
- integrity sha512-f7H8eXWUAArlqBUkvg9IqN+hbQgtVSqcLtwu+EMjNmO9/grU6qR1z9guyXudNi5BS+jsngIla8mNNC60+8l7tA==
+"@opentripplanner/itinerary-body@^0.0.20":
+ version "0.0.20"
+ resolved "https://registry.yarnpkg.com/@opentripplanner/itinerary-body/-/itinerary-body-0.0.20.tgz#0f24a4ac0ccd4de21451c5255ec673450bc8198c"
+ integrity sha512-u3MQUg3SAYs5hMHf2sIPZDF8VLHmeWpXaDW33Pi7WJyn5fJ5AYXsdisEwc87+inOoG0zB6d5usTUkB8Ldlx/rA==
dependencies:
- "@opentripplanner/core-utils" "^0.0.19"
- "@opentripplanner/humanize-distance" "^0.0.19"
- "@opentripplanner/icons" "^0.0.19"
- "@opentripplanner/location-icon" "^0.0.19"
+ "@opentripplanner/core-utils" "^0.0.20"
+ "@opentripplanner/humanize-distance" "^0.0.20"
+ "@opentripplanner/icons" "^0.0.20"
+ "@opentripplanner/location-icon" "^0.0.20"
currency-formatter "^1.5.5"
moment "^2.24.0"
prop-types "^15.7.2"
react-resize-detector "^4.2.1"
velocity-react "^1.4.3"
-"@opentripplanner/location-field@^0.0.19":
- version "0.0.19"
- resolved "https://registry.yarnpkg.com/@opentripplanner/location-field/-/location-field-0.0.19.tgz#70db6c081139320cd29b58b2580a6e3178f5c844"
- integrity sha512-yCq+VnwaJLPy9CC623I6sq08dEUxJHb/x0wWPXN6A7ZmiltAZdDIPmYnLJAkvRzEfLi1jv8pt1PO4nSYxctI0A==
+"@opentripplanner/location-field@^0.0.20":
+ version "0.0.20"
+ resolved "https://registry.yarnpkg.com/@opentripplanner/location-field/-/location-field-0.0.20.tgz#f2b019bde39dfdb570789afc078e1bb1808941d0"
+ integrity sha512-+SC9IHpJ49KzvAw03IIH8HlvRcGx9kNGdIdJ6PtGSNCsOd/91/LkfKTdLeI/Z24axWQpdSPM6BhGCyilIoVqfg==
dependencies:
- "@opentripplanner/core-utils" "^0.0.19"
- "@opentripplanner/geocoder" "^0.0.19"
- "@opentripplanner/humanize-distance" "^0.0.19"
- "@opentripplanner/location-icon" "^0.0.19"
+ "@opentripplanner/core-utils" "^0.0.20"
+ "@opentripplanner/geocoder" "^0.0.20"
+ "@opentripplanner/humanize-distance" "^0.0.20"
+ "@opentripplanner/location-icon" "^0.0.20"
prop-types "^15.7.2"
styled-icons "^9.1.0"
throttle-debounce "^2.1.0"
-"@opentripplanner/location-icon@^0.0.19":
- version "0.0.19"
- resolved "https://registry.yarnpkg.com/@opentripplanner/location-icon/-/location-icon-0.0.19.tgz#19d121cd7b0d0d1588321912fe0674ac6641046e"
- integrity sha512-vtqTMORk0xLBVbBLFUzXqPf4acQSDIe0kxbA+VbpYc2NQD8vZDcnIVFL9e73zXAaKNj/uATAolubZjX6Jvyh3Q==
+"@opentripplanner/location-icon@^0.0.20":
+ version "0.0.20"
+ resolved "https://registry.yarnpkg.com/@opentripplanner/location-icon/-/location-icon-0.0.20.tgz#8f88522cec37e0c37b051421ba315e2065d464d7"
+ integrity sha512-TTtoV7s4moNQ++h1TRQhFFTRueRfoNgVnV8fnLhE77T0rf6UXHDhbZNlt1nm/wyHcYF1MbTynQmZmID85V9UMg==
dependencies:
styled-icons "^9.1.0"
-"@opentripplanner/park-and-ride-overlay@^0.0.19":
- version "0.0.19"
- resolved "https://registry.yarnpkg.com/@opentripplanner/park-and-ride-overlay/-/park-and-ride-overlay-0.0.19.tgz#6f448eccb8ffb86bf9844ec778a6d9111f7575d7"
- integrity sha512-9+ia0f2rl2Rkln46tmIGuyb19lYwUPTLGPSOSRRXr1/Qe9OiZD7dNrf4Zif/HnW6l+1Z4fexYA5nN6TN/clOaA==
+"@opentripplanner/park-and-ride-overlay@^0.0.20":
+ version "0.0.20"
+ resolved "https://registry.yarnpkg.com/@opentripplanner/park-and-ride-overlay/-/park-and-ride-overlay-0.0.20.tgz#0342a798f9a147143f8821062d477751d6145999"
+ integrity sha512-SiJMZnhD8mG8771pbryfYa+a8T+UnBoFMocu6SB4S911CnRwoFDnaMNosIH6hVrzZquisBWnrsTdJHRMnCkI3w==
dependencies:
- "@opentripplanner/core-utils" "^0.0.19"
- "@opentripplanner/from-to-location-picker" "^0.0.19"
+ "@opentripplanner/core-utils" "^0.0.20"
+ "@opentripplanner/from-to-location-picker" "^0.0.20"
prop-types "^15.7.2"
-"@opentripplanner/printable-itinerary@^0.0.19":
- version "0.0.19"
- resolved "https://registry.yarnpkg.com/@opentripplanner/printable-itinerary/-/printable-itinerary-0.0.19.tgz#a224cae07e1459c455f7684eaebbac2eca66ea48"
- integrity sha512-9Ow6YXKuxDJ5dnwlDBXXMEmyLriEtZtetk7IkRiAOXUNgo00un9uGbb0Zu6gYBbTVuLpjLMsZNpzUsnO27DbYw==
+"@opentripplanner/printable-itinerary@^0.0.20":
+ version "0.0.20"
+ resolved "https://registry.yarnpkg.com/@opentripplanner/printable-itinerary/-/printable-itinerary-0.0.20.tgz#d48b9f78ba41827d820bc496c0300a7cd2839c64"
+ integrity sha512-KuZA0Z6S3Nn35uPoZGChlEOjRSmgBmIcG+bdSBscHo5TbdoX3D1WLfGtIYeph7adLnFljSMHIyATvS1d6Hn7Mw==
dependencies:
- "@opentripplanner/core-utils" "^0.0.19"
- "@opentripplanner/humanize-distance" "^0.0.19"
- moment "^2.24.0"
+ "@opentripplanner/core-utils" "^0.0.20"
+ "@opentripplanner/humanize-distance" "^0.0.20"
prop-types "^15.7.2"
-"@opentripplanner/route-viewer-overlay@^0.0.19":
- version "0.0.19"
- resolved "https://registry.yarnpkg.com/@opentripplanner/route-viewer-overlay/-/route-viewer-overlay-0.0.19.tgz#d6f8080ec4106ae8d90cfebcd02edd39a7ae2d27"
- integrity sha512-6DUumUOC33X4FauUVJNucaHoZBvCDVLizZLbU2hjDuS+ZrdCfckEy6wJz8j5x4lfi0pr8jUZEWK+pl3P+sFjaw==
+"@opentripplanner/route-viewer-overlay@^0.0.20":
+ version "0.0.20"
+ resolved "https://registry.yarnpkg.com/@opentripplanner/route-viewer-overlay/-/route-viewer-overlay-0.0.20.tgz#61e9fdbfc248d84b77733a31fbb7c5d5a0c27f1e"
+ integrity sha512-Vrejj8DFUfLWt/AN8ogepEH+wRlEyfLQosBA5ynEg/xaExSSDaiRA7Ite2CHvpuJfbDKZfTtWLrP6k4Gf0bL/A==
dependencies:
"@mapbox/polyline" "^1.1.0"
- "@opentripplanner/core-utils" "^0.0.19"
+ "@opentripplanner/core-utils" "^0.0.20"
prop-types "^15.7.2"
-"@opentripplanner/stop-viewer-overlay@^0.0.19":
- version "0.0.19"
- resolved "https://registry.yarnpkg.com/@opentripplanner/stop-viewer-overlay/-/stop-viewer-overlay-0.0.19.tgz#1484864fcad81b9fa3ea9726845b3a7383e78db5"
- integrity sha512-fdfBiUOrcKiDFDVo5upj7tl2jN6CPxIF7OoYtR/EoSf4A8pCSkCY4pxRL3VE0z7O103fJFP67BCu8axKptaEsA==
+"@opentripplanner/stop-viewer-overlay@^0.0.20":
+ version "0.0.20"
+ resolved "https://registry.yarnpkg.com/@opentripplanner/stop-viewer-overlay/-/stop-viewer-overlay-0.0.20.tgz#8448757238081feace0c0d4852fd39247cd795e2"
+ integrity sha512-UmBs0xLW4/rTOCrasg53vqIZZM/EVNrCDJJmbhGN/y8ZWZpzpWowlpzo2S/qZiSrLhc00+KdluBwRVcnA+Lx4A==
dependencies:
- "@opentripplanner/core-utils" "^0.0.19"
+ "@opentripplanner/core-utils" "^0.0.20"
prop-types "^15.7.2"
-"@opentripplanner/stops-overlay@^0.0.19":
- version "0.0.19"
- resolved "https://registry.yarnpkg.com/@opentripplanner/stops-overlay/-/stops-overlay-0.0.19.tgz#b3cc17bbbb7d64fd44da17c01955b4069f0868a6"
- integrity sha512-tlr/2S2E7zYjEHla3hIMQc0tpdgJMolY4jUqBPEFOohP1NCf4VQWyO8cY0D2CyjPI9eQkW96eU2be8WuUtwyXQ==
+"@opentripplanner/stops-overlay@^0.0.20":
+ version "0.0.20"
+ resolved "https://registry.yarnpkg.com/@opentripplanner/stops-overlay/-/stops-overlay-0.0.20.tgz#1fcbce27a0d9438616cb861169d4a6ec3d5ea0e9"
+ integrity sha512-3m7p7eSWYu8mil7qy/DqqK7eOK26ccQEuvbIhur/btyYaKpKYLodIXoO3mH3UarJfTpQzRMdeQ+W3YTobMYgZg==
dependencies:
- "@opentripplanner/core-utils" "^0.0.19"
- "@opentripplanner/from-to-location-picker" "^0.0.19"
+ "@opentripplanner/core-utils" "^0.0.20"
+ "@opentripplanner/from-to-location-picker" "^0.0.20"
-"@opentripplanner/transitive-overlay@^0.0.19":
- version "0.0.19"
- resolved "https://registry.yarnpkg.com/@opentripplanner/transitive-overlay/-/transitive-overlay-0.0.19.tgz#096c30b08e94161cc8522f3a01ff147f473a40d7"
- integrity sha512-+UYbDcGlODHxAZQuoX6WeiDVTZsCcrzCfphQmkoQERdd3xukJpPwzjSSjeIEbP+8gTGPtlM+i7qu00mu3C0ynw==
+"@opentripplanner/transitive-overlay@^0.0.20":
+ version "0.0.20"
+ resolved "https://registry.yarnpkg.com/@opentripplanner/transitive-overlay/-/transitive-overlay-0.0.20.tgz#93f30afcd248e1705feac08e0a385683dcdc84fd"
+ integrity sha512-lOuWjwb6LlhjMRKjSVeNmBjrsdNewwNe3pnLJjpAnWhSTeunLATiv8aYQk8TYGJz2AclSgYYzySgBWHXnF6Pzw==
dependencies:
- "@opentripplanner/core-utils" "^0.0.19"
+ "@opentripplanner/core-utils" "^0.0.20"
lodash.isequal "^4.5.0"
transitive-js "^0.13.0"
-"@opentripplanner/trip-details@^0.0.19":
- version "0.0.19"
- resolved "https://registry.yarnpkg.com/@opentripplanner/trip-details/-/trip-details-0.0.19.tgz#3379a13188b7fb12387be5abd0b0d071231b366a"
- integrity sha512-ItRywhXMikvOv+13/qWwYueX1eC57IZnzukDy4Gukd/MtJheQOzwDU2W5pWwK1MmMEikxjdsSCw4vt2m6biTyw==
+"@opentripplanner/trip-details@^0.0.20":
+ version "0.0.20"
+ resolved "https://registry.yarnpkg.com/@opentripplanner/trip-details/-/trip-details-0.0.20.tgz#ef80eee732e24d6c17d771f6f7d9f9d83deb27cd"
+ integrity sha512-nZDXHyBgghQZAdu2mLg51Lc5M6OraK6Vp5aYesXVa1ARBwug2hr0W2R/N6F4nQmU5SI0RQAN/b5irGplsKnnXw==
dependencies:
- "@opentripplanner/core-utils" "^0.0.19"
- "@opentripplanner/humanize-distance" "^0.0.19"
+ "@opentripplanner/core-utils" "^0.0.20"
+ "@opentripplanner/humanize-distance" "^0.0.20"
moment "^2.24.0"
prop-types "^15.7.2"
styled-icons "^9.1.0"
velocity-react "^1.4.3"
-"@opentripplanner/trip-form@^0.0.19":
- version "0.0.19"
- resolved "https://registry.yarnpkg.com/@opentripplanner/trip-form/-/trip-form-0.0.19.tgz#f34995eee51401012d9fa81a1138de9627d2bc78"
- integrity sha512-x2zRAUDYPZlZF1hsVH4wVEdjRspBNU+P1d5a5m0J4OYfS7prnWlVKQl5+b5ktcLiY3mbdGtDHtYv+2knQt0gnQ==
+"@opentripplanner/trip-form@^0.0.20":
+ version "0.0.20"
+ resolved "https://registry.yarnpkg.com/@opentripplanner/trip-form/-/trip-form-0.0.20.tgz#823e23ef8e332f5aa3fe85306ee65a0bee17f914"
+ integrity sha512-GZOZj4mCyPWx64OO1klZpsJ0JEggxmG5Qx264fwue9l8pun4D9DuCJFbclw51Tu/vLJ0VUuFZJBlECRCKeussg==
dependencies:
- "@opentripplanner/core-utils" "^0.0.19"
- "@opentripplanner/icons" "^0.0.19"
+ "@opentripplanner/core-utils" "^0.0.20"
+ "@opentripplanner/icons" "^0.0.20"
moment "^2.17.1"
-"@opentripplanner/trip-viewer-overlay@^0.0.19":
- version "0.0.19"
- resolved "https://registry.yarnpkg.com/@opentripplanner/trip-viewer-overlay/-/trip-viewer-overlay-0.0.19.tgz#ab608699720f3ab090f64aadae01a12434188f18"
- integrity sha512-Nyta8qagZib/tQE/h57HB+O1nUzHi2ougDCEn6I4upqM6OUn6bYSC+V048VGXUHwa8rnnFT9jf8ryKUd6tVEfQ==
+"@opentripplanner/trip-viewer-overlay@^0.0.20":
+ version "0.0.20"
+ resolved "https://registry.yarnpkg.com/@opentripplanner/trip-viewer-overlay/-/trip-viewer-overlay-0.0.20.tgz#f65ed3527edea2e2304b5e02394b62ac69de7c0e"
+ integrity sha512-neLU+iO1dTYSXefW00IltdO0vdxtkEJpMG9GiFOUCgVAvLhyHuJca1aofgKZmcsArLhRo7eV2T8YzEHf3EiOCQ==
dependencies:
"@mapbox/polyline" "^1.1.0"
- "@opentripplanner/core-utils" "^0.0.19"
+ "@opentripplanner/core-utils" "^0.0.20"
prop-types "^15.7.2"
-"@opentripplanner/vehicle-rental-overlay@^0.0.19":
- version "0.0.19"
- resolved "https://registry.yarnpkg.com/@opentripplanner/vehicle-rental-overlay/-/vehicle-rental-overlay-0.0.19.tgz#d0efc0d653c45da8e2fd8f835eb059f7173aa3fe"
- integrity sha512-gZnqoZlZznGeCykfynVkC9pMq4AAotV0DJaNkX4z9sHVGUFgk+mcaiAkrIhPLWLyOiOTnLQnnuPw8T26yOqzng==
+"@opentripplanner/vehicle-rental-overlay@^0.0.20":
+ version "0.0.20"
+ resolved "https://registry.yarnpkg.com/@opentripplanner/vehicle-rental-overlay/-/vehicle-rental-overlay-0.0.20.tgz#ef30b97f8c1080497056246a59f371f96efabc11"
+ integrity sha512-7ujSgc2mG/hZpZEL3DW+v3fIWSBUY3BOxoyqPlE0KhoE805KQi99LMxUYre+ovcEyIhcr0OKGSig0Br0X6banw==
dependencies:
- "@opentripplanner/core-utils" "^0.0.19"
- "@opentripplanner/from-to-location-picker" "^0.0.19"
+ "@opentripplanner/core-utils" "^0.0.20"
+ "@opentripplanner/from-to-location-picker" "^0.0.20"
lodash.memoize "^4.1.2"
prop-types "^15.7.2"
styled-icons "^9.1.0"
From 5404f9822a109a04ed69c1d716c8353a37404583 Mon Sep 17 00:00:00 2001
From: binh-dam-ibigroup <56846598+binh-dam-ibigroup@users.noreply.github.com>
Date: Tue, 28 Apr 2020 10:49:33 -0400
Subject: [PATCH 31/31] refactor(routeComparator): Use routeComparator from
OTP-UI.
---
__tests__/util/__mocks__/itinerary.json | 91 -------
.../util/__snapshots__/itinerary.js.snap | 247 ------------------
__tests__/util/itinerary.js | 90 -------
lib/components/viewers/route-viewer.js | 4 +-
lib/components/viewers/stop-viewer.js | 3 +-
lib/util/itinerary.js | 239 -----------------
6 files changed, 3 insertions(+), 671 deletions(-)
delete mode 100644 __tests__/util/__mocks__/itinerary.json
delete mode 100644 __tests__/util/__snapshots__/itinerary.js.snap
delete mode 100644 __tests__/util/itinerary.js
diff --git a/__tests__/util/__mocks__/itinerary.json b/__tests__/util/__mocks__/itinerary.json
deleted file mode 100644
index c00a605a4..000000000
--- a/__tests__/util/__mocks__/itinerary.json
+++ /dev/null
@@ -1,91 +0,0 @@
-{
- "route1": {
- "longName": "Across town",
- "mode": "BUS",
- "shortName": "10",
- "sortOrder": 10
- },
- "route2": {
- "longName": "Around town",
- "mode": "BUS",
- "shortName": "20",
- "sortOrder": 2
- },
- "route3": {
- "longName": "Around another town",
- "shortName": "3",
- "sortOrder": -999,
- "type": 3
- },
- "route4": {
- "longName": "Loop route",
- "mode": "BUS",
- "shortName": "2",
- "sortOrder": -999
- },
- "route5": {
- "longName": "A-line",
- "mode": "BUS",
- "shortName": "A",
- "sortOrder": -999
- },
- "route6": {
- "longName": "B-line",
- "mode": "BUS",
- "shortName": "B",
- "sortOrder": -999
- },
- "route7": {
- "longName": "A meandering route",
- "mode": "BUS",
- "sortOrder": -999
- },
- "route8": {
- "longName": "Zig-zagging route",
- "mode": "BUS",
- "shortName": "30",
- "sortOrder": 2
- },
- "route9": {
- "longName": "Express route",
- "mode": "BUS",
- "shortName": "30",
- "sortOrder": 2
- },
- "route10": {
- "longName": "Variation of express route",
- "mode": "BUS",
- "shortName": "30",
- "sortOrder": 2
- },
- "route11": {
- "longName": "Local route",
- "mode": "BUS",
- "shortName": "6",
- "sortOrder": 2
- },
- "route12": {
- "longName": "Intercity Train",
- "mode": "RAIL",
- "shortName": "IC",
- "sortOrder": 2
- },
- "route13": {
- "longName": "Yellow line Subway",
- "mode": "SUBWAY",
- "shortName": "Yellow",
- "sortOrder": 2
- },
- "route14": {
- "longName": "Xpress route C",
- "mode": "BUS",
- "shortName": "30C",
- "sortOrder": 2
- },
- "route15": {
- "longName": "Express route X",
- "mode": "BUS",
- "shortName": "30X",
- "sortOrder": 2
- }
-}
diff --git a/__tests__/util/__snapshots__/itinerary.js.snap b/__tests__/util/__snapshots__/itinerary.js.snap
deleted file mode 100644
index 6887d0868..000000000
--- a/__tests__/util/__snapshots__/itinerary.js.snap
+++ /dev/null
@@ -1,247 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`util > itinerary routeComparator should prioritize routes with integer shortNames over alphabetic shortNames 1`] = `
-Array [
- Object {
- "longName": "A-line",
- "mode": "BUS",
- "shortName": "A",
- "sortOrder": -999,
- },
- Object {
- "longName": "Loop route",
- "mode": "BUS",
- "shortName": "2",
- "sortOrder": -999,
- },
-]
-`;
-
-exports[`util > itinerary routeComparator should prioritize routes with shortNames over those with just longNames 1`] = `
-Array [
- Object {
- "longName": "B-line",
- "mode": "BUS",
- "shortName": "B",
- "sortOrder": -999,
- },
- Object {
- "longName": "A meandering route",
- "mode": "BUS",
- "sortOrder": -999,
- },
-]
-`;
-
-exports[`util > itinerary routeComparator should prioritize routes with valid sortOrder 1`] = `
-Array [
- Object {
- "longName": "Around town",
- "mode": "BUS",
- "shortName": "20",
- "sortOrder": 2,
- },
- Object {
- "longName": "Around another town",
- "shortName": "3",
- "sortOrder": -999,
- "type": 3,
- },
-]
-`;
-
-exports[`util > itinerary routeComparator should sort based off of route type 1`] = `
-Array [
- Object {
- "longName": "Yellow line Subway",
- "mode": "SUBWAY",
- "shortName": "Yellow",
- "sortOrder": 2,
- },
- Object {
- "longName": "Intercity Train",
- "mode": "RAIL",
- "shortName": "IC",
- "sortOrder": 2,
- },
-]
-`;
-
-exports[`util > itinerary routeComparator should sort routes based off of integer shortName 1`] = `
-Array [
- Object {
- "longName": "Loop route",
- "mode": "BUS",
- "shortName": "2",
- "sortOrder": -999,
- },
- Object {
- "longName": "Around another town",
- "shortName": "3",
- "sortOrder": -999,
- "type": 3,
- },
-]
-`;
-
-exports[`util > itinerary routeComparator should sort routes based off of longNames 1`] = `
-Array [
- Object {
- "longName": "Express route",
- "mode": "BUS",
- "shortName": "30",
- "sortOrder": 2,
- },
- Object {
- "longName": "Variation of express route",
- "mode": "BUS",
- "shortName": "30",
- "sortOrder": 2,
- },
-]
-`;
-
-exports[`util > itinerary routeComparator should sort routes based off of shortNames 1`] = `
-Array [
- Object {
- "longName": "A-line",
- "mode": "BUS",
- "shortName": "A",
- "sortOrder": -999,
- },
- Object {
- "longName": "B-line",
- "mode": "BUS",
- "shortName": "B",
- "sortOrder": -999,
- },
-]
-`;
-
-exports[`util > itinerary routeComparator should sort routes based off of sortOrder 1`] = `
-Array [
- Object {
- "longName": "Around town",
- "mode": "BUS",
- "shortName": "20",
- "sortOrder": 2,
- },
- Object {
- "longName": "Across town",
- "mode": "BUS",
- "shortName": "10",
- "sortOrder": 10,
- },
-]
-`;
-
-exports[`util > itinerary routeComparator should sort routes on all of the criteria at once 1`] = `
-Array [
- Object {
- "longName": "Yellow line Subway",
- "mode": "SUBWAY",
- "shortName": "Yellow",
- "sortOrder": 2,
- },
- Object {
- "longName": "Intercity Train",
- "mode": "RAIL",
- "shortName": "IC",
- "sortOrder": 2,
- },
- Object {
- "longName": "Local route",
- "mode": "BUS",
- "shortName": "6",
- "sortOrder": 2,
- },
- Object {
- "longName": "Around town",
- "mode": "BUS",
- "shortName": "20",
- "sortOrder": 2,
- },
- Object {
- "longName": "Express route",
- "mode": "BUS",
- "shortName": "30",
- "sortOrder": 2,
- },
- Object {
- "longName": "Variation of express route",
- "mode": "BUS",
- "shortName": "30",
- "sortOrder": 2,
- },
- Object {
- "longName": "Zig-zagging route",
- "mode": "BUS",
- "shortName": "30",
- "sortOrder": 2,
- },
- Object {
- "longName": "Xpress route C",
- "mode": "BUS",
- "shortName": "30C",
- "sortOrder": 2,
- },
- Object {
- "longName": "Express route X",
- "mode": "BUS",
- "shortName": "30X",
- "sortOrder": 2,
- },
- Object {
- "longName": "Across town",
- "mode": "BUS",
- "shortName": "10",
- "sortOrder": 10,
- },
- Object {
- "longName": "A-line",
- "mode": "BUS",
- "shortName": "A",
- "sortOrder": -999,
- },
- Object {
- "longName": "B-line",
- "mode": "BUS",
- "shortName": "B",
- "sortOrder": -999,
- },
- Object {
- "longName": "Loop route",
- "mode": "BUS",
- "shortName": "2",
- "sortOrder": -999,
- },
- Object {
- "longName": "Around another town",
- "shortName": "3",
- "sortOrder": -999,
- "type": 3,
- },
- Object {
- "longName": "A meandering route",
- "mode": "BUS",
- "sortOrder": -999,
- },
-]
-`;
-
-exports[`util > itinerary routeComparator should sort routes with alphanumeric shortNames 1`] = `
-Array [
- Object {
- "longName": "Xpress route C",
- "mode": "BUS",
- "shortName": "30C",
- "sortOrder": 2,
- },
- Object {
- "longName": "Express route X",
- "mode": "BUS",
- "shortName": "30X",
- "sortOrder": 2,
- },
-]
-`;
diff --git a/__tests__/util/itinerary.js b/__tests__/util/itinerary.js
deleted file mode 100644
index fcc0e709c..000000000
--- a/__tests__/util/itinerary.js
+++ /dev/null
@@ -1,90 +0,0 @@
-import coreUtils from '@opentripplanner/core-utils'
-
-import { routeComparator } from '../../lib/util/itinerary'
-
-const {
- route1,
- route2,
- route3,
- route4,
- route5,
- route6,
- route7,
- route8,
- route9,
- route10,
- route11,
- route12,
- route13,
- route14,
- route15
-} = require('./__mocks__/itinerary.json')
-
-function sortRoutes (...routes) {
- routes.sort(routeComparator)
- return routes
-}
-
-describe('util > itinerary', () => {
- it('isTransit should work', () => {
- expect(coreUtils.itinerary.isTransit('CAR')).toBeFalsy()
- })
-
- describe('routeComparator', () => {
- it('should sort routes based off of sortOrder', () => {
- expect(sortRoutes(route1, route2)).toMatchSnapshot()
- })
-
- it('should prioritize routes with valid sortOrder', () => {
- expect(sortRoutes(route2, route3)).toMatchSnapshot()
- })
-
- it('should sort routes based off of integer shortName', () => {
- expect(sortRoutes(route3, route4)).toMatchSnapshot()
- })
-
- it('should prioritize routes with integer shortNames over alphabetic shortNames', () => {
- expect(sortRoutes(route4, route5)).toMatchSnapshot()
- })
-
- it('should sort routes based off of shortNames', () => {
- expect(sortRoutes(route5, route6)).toMatchSnapshot()
- })
-
- it('should sort routes with alphanumeric shortNames', () => {
- expect(sortRoutes(route14, route15)).toMatchSnapshot()
- })
-
- it('should prioritize routes with shortNames over those with just longNames', () => {
- expect(sortRoutes(route6, route7)).toMatchSnapshot()
- })
-
- it('should sort routes based off of longNames', () => {
- expect(sortRoutes(route9, route10)).toMatchSnapshot()
- })
-
- it('should sort routes on all of the criteria at once', () => {
- expect(sortRoutes(
- route1,
- route2,
- route3,
- route4,
- route5,
- route6,
- route7,
- route8,
- route9,
- route10,
- route11,
- route12,
- route13,
- route14,
- route15
- )).toMatchSnapshot()
- })
-
- it('should sort based off of route type', () => {
- expect(sortRoutes(route12, route13)).toMatchSnapshot()
- })
- })
-})
diff --git a/lib/components/viewers/route-viewer.js b/lib/components/viewers/route-viewer.js
index c298d5a50..3cb3e6df5 100644
--- a/lib/components/viewers/route-viewer.js
+++ b/lib/components/viewers/route-viewer.js
@@ -1,3 +1,4 @@
+import coreUtils from '@opentripplanner/core-utils'
import React, { Component, PureComponent } from 'react'
import PropTypes from 'prop-types'
import { Label, Button } from 'react-bootstrap'
@@ -8,7 +9,6 @@ import Icon from '../narrative/icon'
import { setMainPanelContent, setViewedRoute } from '../../actions/ui'
import { findRoutes, findRoute } from '../../actions/api'
-import { routeComparator } from '../../util/itinerary'
function operatorIndexForRoute (transitOperators, route) {
if (!route.agency) return 0
@@ -58,7 +58,7 @@ class RouteViewer extends Component {
viewedRoute
} = this.props
const sortedRoutes = routes
- ? Object.values(routes).sort(routeComparator)
+ ? Object.values(routes).sort(coreUtils.itinerary.routeComparator)
: []
const agencySortedRoutes = transitOperators.length > 0
? sortedRoutes.sort((a, b) => {
diff --git a/lib/components/viewers/stop-viewer.js b/lib/components/viewers/stop-viewer.js
index 07c9128ee..ac668f353 100644
--- a/lib/components/viewers/stop-viewer.js
+++ b/lib/components/viewers/stop-viewer.js
@@ -12,7 +12,6 @@ import Icon from '../narrative/icon'
import { setMainPanelContent, toggleAutoRefresh } from '../../actions/ui'
import { findStop, findStopTimesForStop } from '../../actions/api'
import { forgetStop, rememberStop, setLocation } from '../../actions/map'
-import { routeComparator } from '../../util/itinerary'
import { getShowUserSettings, getStopViewerConfig } from '../../util/state'
const {
@@ -231,7 +230,7 @@ class StopViewer extends Component {
{stopData.stopTimes && stopData.routes && (
{Object.values(stopTimesByPattern)
- .sort((a, b) => routeComparator(a.route, b.route))
+ .sort((a, b) => coreUtils.itinerary.routeComparator(a.route, b.route))
.map(patternTimes => {
// Only add pattern row if route is found.
// FIXME: there is currently a bug with the alernative transit index
diff --git a/lib/util/itinerary.js b/lib/util/itinerary.js
index e2abbd442..6a65f5f13 100644
--- a/lib/util/itinerary.js
+++ b/lib/util/itinerary.js
@@ -40,245 +40,6 @@ export function getLeafletLegBounds (leg) {
return latLngBounds(coreUtils.itinerary.getLegBounds(leg))
}
-/**
- * Gets the desired sort values according to an optional getter function. If the
- * getter function is not defined, the original sort values are returned.
- */
-function getSortValues (getterFn, a, b) {
- let aVal
- let bVal
- if (typeof getterFn === 'function') {
- aVal = getterFn(a)
- bVal = getterFn(b)
- } else {
- aVal = a
- bVal = b
- }
- return { aVal, bVal }
-}
-
-// Lookup for the sort values associated with various OTP modes.
-// Note: JSDoc format not used to avoid bug in documentationjs.
-// https://github.com/documentationjs/documentation/issues/372
-const modeComparatorValue = {
- SUBWAY: 1,
- TRAM: 2,
- RAIL: 3,
- GONDOLA: 4,
- FERRY: 5,
- CABLE_CAR: 6,
- FUNICULAR: 7,
- BUS: 8
-}
-
-// Lookup that maps route types to the OTP mode sort values.
-// Note: JSDoc format not used to avoid bug in documentationjs.
-// https://github.com/documentationjs/documentation/issues/372
-const routeTypeComparatorValue = {
- 0: modeComparatorValue.TRAM, // - Tram, Streetcar, Light rail.
- 1: modeComparatorValue.SUBWAY, // - Subway, Metro.
- 2: modeComparatorValue.RAIL, // - Rail. Used for intercity or long-distance travel.
- 3: modeComparatorValue.BUS, // - Bus.
- 4: modeComparatorValue.FERRY, // - Ferry.
- 5: modeComparatorValue.CABLE_CAR, // - Cable tram.
- 6: modeComparatorValue.GONDOLA, // - Gondola, etc.
- 7: modeComparatorValue.FUNICULAR, // - Funicular.
- // TODO: 11 and 12 are not a part of OTP as of 2019-02-14, but for now just
- // associate them with bus/rail.
- 11: modeComparatorValue.BUS, // - Trolleybus.
- 12: modeComparatorValue.RAIL // - Monorail.
-}
-
-// Gets a comparator value for a given route's type (OTP mode).
-// Note: JSDoc format not used to avoid bug in documentationjs.
-// ttps://github.com/documentationjs/documentation/issues/372
-function getRouteTypeComparatorValue (route) {
- // For some strange reason, the short route response in OTP returns the
- // string-based modes, but the long route response returns the
- // integer route type. This attempts to account for both of those cases.
- if (!route) throw new Error('Route is undefined.', route)
- if (typeof modeComparatorValue[route.mode] !== 'undefined') {
- return modeComparatorValue[route.mode]
- } else if (typeof routeTypeComparatorValue[route.type] !== 'undefined') {
- return routeTypeComparatorValue[route.type]
- } else {
- // Default the comparator value to a large number (placing the route at the
- // end of the list).
- console.warn('no mode/route type found for route', route)
- return 9999
- }
-}
-
-/**
- * Calculates the sort comparator value given two routes based off of route type
- * (OTP mode).
- */
-function routeTypeComparator (a, b) {
- return getRouteTypeComparatorValue(a) - getRouteTypeComparatorValue(b)
-}
-
-/**
- * Determines whether a value is a string that starts with an alphabetic
- * ascii character.
- */
-function startsWithAlphabeticCharacter (val) {
- if (typeof val === 'string' && val.length > 0) {
- const firstCharCode = val.charCodeAt(0)
- return (firstCharCode >= 65 && firstCharCode <= 90) ||
- (firstCharCode >= 97 && firstCharCode <= 122)
- }
- return false
-}
-
-/**
- * Sorts routes based off of whether the shortName begins with an alphabetic
- * character. Routes with shortn that do start with an alphabetic character will
- * be prioritized over those that don't.
- */
-function alphabeticShortNameComparator (a, b) {
- const aStartsWithAlphabeticCharacter = startsWithAlphabeticCharacter(
- a.shortName
- )
- const bStartsWithAlphabeticCharacter = startsWithAlphabeticCharacter(
- b.shortName
- )
-
- if (aStartsWithAlphabeticCharacter && bStartsWithAlphabeticCharacter) {
- // both start with an alphabetic character, return equivalence
- return 0
- }
- // a does start with an alphabetic character, but b does not. Prioritize a
- if (aStartsWithAlphabeticCharacter) return -1
- // b does start with an alphabetic character, but a does not. Prioritize b
- if (bStartsWithAlphabeticCharacter) return 1
- // neither route has a shortName that starts with an alphabetic character.
- // Return equivalence
- return 0
-}
-
-/**
- * Checks whether an appropriate comparison of numeric values can be made for
- * sorting purposes. If both values are not valid numbers according to the
- * isNaN check, then this function returns undefined which indicates that a
- * secondary sorting criteria should be used instead. If one value is valid and
- * the other is not, then the valid value will be given sorting priority. If
- * both values are valid numbers, the difference is obtained as the sort value.
- *
- * An optional argument can be provided which will be used to obtain the
- * comparison value from the comparison function arguments.
- *
- * IMPORTANT: the comparison values must be numeric values or at least be
- * attempted to be converted to numeric values! If one of the arguments is
- * something crazy like an empty string, unexpected behavior will occur because
- * JavaScript.
- *
- * @param {function} [objGetterFn] An optional function to obtain the
- * comparison value from the comparator function arguments
- */
-function makeNumericValueComparator (objGetterFn) {
- return (a, b) => {
- const { aVal, bVal } = getSortValues(objGetterFn, a, b)
- // if both values aren't valid numbers, use the next sort criteria
- if (isNaN(aVal) && isNaN(bVal)) return 0
- // b is a valid number, b gets priority
- if (isNaN(aVal)) return 1
- // a is a valid number, a gets priority
- if (isNaN(bVal)) return -1
- // a and b are valid numbers, return the sort value
- return aVal - bVal
- }
-}
-
-/**
- * Create a comparator function that compares string values. The comparison
- * values feed to the sort comparator function are assumed to be objects that
- * will have either undefined, null or string values at the given key. If one
- * object has undefined, null or an empty string, but the other does have a
- * string with length > 0, then that string will get priority.
- *
- * @param {function} [objGetterFn] An optional function to obtain the
- * comparison value from the comparator function arguments
- */
-function makeStringValueComparator (objGetterFn) {
- return (a, b) => {
- const { aVal, bVal } = getSortValues(objGetterFn, a, b)
- // both a and b are uncomparable strings, return equivalent value
- if (!aVal && !bVal) return 0
- // a is not a comparable string, b gets priority
- if (!aVal) return 1
- // b is not a comparable string, a gets priority
- if (!bVal) return -1
- // a and b are comparable strings, return the sort value
- if (aVal < bVal) return -1
- if (aVal > bVal) return 1
- return 0
- }
-}
-
-/**
- * OpenTripPlanner sets the routeSortOrder to -999 by default. So, if that value
- * is encountered, assume that it actually means that the routeSortOrder is not
- * set in the GTFS.
- *
- * See https://github.com/opentripplanner/OpenTripPlanner/issues/2938
- * Also see https://github.com/opentripplanner/otp-react-redux/issues/122
- */
-function getRouteSortOrderValue (val) {
- return val === -999 ? undefined : val
-}
-
-/**
- * Create a multi-criteria sort comparator function composed of other sort
- * comparator functions. Each comparator function will be ran in the order given
- * until a non-zero comparison value is obtained which is then immediately
- * returned. If all comparison functions return equivalance, then the values
- * are assumed to be equivalent.
- */
-function makeMultiCriteriaSort (...criteria) {
- return (a, b) => {
- for (let i = 0; i < criteria.length; i++) {
- const curCriteriaComparatorValue = criteria[i](a, b)
- // if the comparison objects are not equivalent, return the value obtained
- // in this current criteria comparison
- if (curCriteriaComparatorValue !== 0) {
- return curCriteriaComparatorValue
- }
- }
- return 0
- }
-}
-
-/**
- * Compares routes for the purposes of sorting and displaying in a user
- * interface. Due to GTFS feeds having varying levels of data quality, a multi-
- * criteria sort is needed to account for various differences. The criteria
- * included here are each applied to the routes in the order listed. If a given
- * sort criterion yields equivalence (e.g., two routes have the short name
- * "20"), the comparator falls back onto the next sort criterion (e.g., long
- * name). If desired, the criteria of sorting based off of integer shortName can
- * be disabled. The sort operates on the following values (in order):
- *
- * 1. sortOrder. Routes that do not have a valid sortOrder will be placed
- * beneath those that do.
- * 2. route type (OTP mode). See routeTypeComparator code for prioritization of
- * route types.
- * 3. shortNames that begin with alphabetic characters. shortNames that do not
- * start with alphabetic characters will be place beneath those that do.
- * 4. shortName as integer. shortNames that cannot be parsed as integers will
- * be placed beneath those that are valid.
- * 5. shortName as string. Routes without shortNames will be placed beneath
- * those with shortNames.
- * 6. longName as string.
- */
-export const routeComparator = makeMultiCriteriaSort(
- makeNumericValueComparator(obj => getRouteSortOrderValue(obj.sortOrder)),
- routeTypeComparator,
- alphabeticShortNameComparator,
- makeNumericValueComparator(obj => parseInt(obj.shortName)),
- makeStringValueComparator(obj => obj.shortName),
- makeStringValueComparator(obj => obj.longName)
-)
-
/**
* Return an icon depending on the leg info
*