From c2164803280b0d05da452330e613f040b3202949 Mon Sep 17 00:00:00 2001 From: binh-dam-ibigroup <56846598+binh-dam-ibigroup@users.noreply.github.com> Date: Fri, 7 Aug 2020 18:50:19 -0400 Subject: [PATCH 01/12] feat(TimeColumnWithDelays): Add component to display transit leg realtime time changes. --- .../line-itin/time-column-with-delays.js | 164 ++++++++++++++++++ 1 file changed, 164 insertions(+) create mode 100644 lib/components/narrative/line-itin/time-column-with-delays.js diff --git a/lib/components/narrative/line-itin/time-column-with-delays.js b/lib/components/narrative/line-itin/time-column-with-delays.js new file mode 100644 index 000000000..18fe29e9f --- /dev/null +++ b/lib/components/narrative/line-itin/time-column-with-delays.js @@ -0,0 +1,164 @@ +import { isTransit } from '@opentripplanner/core-utils/lib/itinerary' +import { + legType, + timeOptionsType +} from '@opentripplanner/core-utils/lib/types' +import { formatTime } from '@opentripplanner/core-utils/lib/time' +import PropTypes from 'prop-types' +import React from 'react' +import styled from 'styled-components' + +const StatusText = styled.div` + background-color: #bbb; + color: #fff; + font-size: 80%; + line-height: 1em; + padding: 2px; + text-align: center; + text-transform: uppercase; +` +const TimeText = styled.div`` + +const TimeStruck = styled.div` + text-decoration: line-through; +` + +const TimeBlock = styled.div` + line-height: 1em; + margin-bottom: 4px; +` + +const TimeColumnBase = styled.div`` + +// Reusing stop viewer colors. +/* +const TimeColumnOnTime = styled(TimeColumnBase)` + ${TimeText}, ${StatusText} { + color: #5cb85c; + } +`; +const TimeColumnEarly = styled(TimeColumnBase)` + ${TimeText}, ${StatusText} { + color: #337ab7; + } +`; +const TimeColumnLate = styled(TimeColumnBase)` + ${TimeText}, ${StatusText} { + color: #d9534f; + } +`; +*/ + +const TimeColumnOnTime = styled(TimeColumnBase)` + ${TimeText} { + color: #5cb85c; + } + ${StatusText} { + background-color: #5cb85c; + } +` +const TimeColumnEarly = styled(TimeColumnBase)` + ${TimeText} { + color: #337ab7; + } + ${StatusText} { + background-color: #337ab7; + } +` +const TimeColumnLate = styled(TimeColumnBase)` + ${TimeText} { + color: #d9534f; + } + ${StatusText} { + background-color: #d9534f; + } +` + +/** + * This component displays the scheduled departure/arrival time for a leg, + * and, for transit legs, displays any delays or earliness where applicable. + */ +export default function TimeColumnWithDelays ({ + isDestination, + leg, + timeOptions +}) { + const time = isDestination ? leg.endTime : leg.startTime + const formattedTime = time && formatTime(time, timeOptions) + const isTransitLeg = isTransit(leg.mode) + + if (leg.realTime) { + // Delay in seconds. + const delay = isDestination ? leg.arrivalDelay : leg.departureDelay + // Time is in milliseconds. + const originalTime = time - delay * 1000 + const originalFormattedTime = + originalTime && formatTime(originalTime, timeOptions) + + // TODO: refine on-time thresholds. + // const isOnTime = delay >= -60 && delay <= 120; + const isOnTime = delay === 0 + + let statusText + let TimeColumn = TimeColumnBase + if (isOnTime) { + statusText = 'on time' + TimeColumn = TimeColumnOnTime + } else if (delay < 0) { + statusText = 'early' + TimeColumn = TimeColumnEarly + } else if (delay > 0) { + statusText = 'late' + TimeColumn = TimeColumnLate + } + + // Absolute delay in rounded minutes, for display purposes. + const delayInMinutes = Math.abs( + Math.round((isDestination ? leg.arrivalDelay : leg.departureDelay) / 60) + ) + + let renderedTime + if (!isOnTime) { + // If the transit vehicle is not on time, strike the original scheduled time + // and display the updated time underneath. + renderedTime = ( + + {!isOnTime && {originalFormattedTime}} + {formattedTime} + + ) + } else { + renderedTime = {formattedTime} + } + + return ( + + {renderedTime} + + {!isOnTime && <>{delayInMinutes} min} + {'\n'} + {statusText} + + + ) + } + + // Non-real-time leg. + return ( + <> + {formattedTime} + {/* Add the scheduled mention for transit legs only. */} + {isTransitLeg && scheduled} + + ) +} + +TimeColumnWithDelays.propTypes = { + isDestination: PropTypes.bool.isRequired, + leg: legType.isRequired, + timeOptions: timeOptionsType +} + +TimeColumnWithDelays.defaultProps = { + timeOptions: null +} From b8c0b44ea5a20d07684986f4bf837c63b8d2be52 Mon Sep 17 00:00:00 2001 From: binh-dam-ibigroup <56846598+binh-dam-ibigroup@users.noreply.github.com> Date: Tue, 18 Aug 2020 17:54:53 -0400 Subject: [PATCH 02/12] feat(TimeColumnWithDelays): Add support for real-time delays/updates to line-itin/ConnectedItinerary --- .../line-itin/connected-itinerary-body.js | 5 ++- .../line-itin/time-column-with-delays.js | 33 +++++++++++-------- package.json | 2 +- yarn.lock | 24 +++++++++++--- 4 files changed, 43 insertions(+), 21 deletions(-) diff --git a/lib/components/narrative/line-itin/connected-itinerary-body.js b/lib/components/narrative/line-itin/connected-itinerary-body.js index d1cef245a..b808b0f1b 100644 --- a/lib/components/narrative/line-itin/connected-itinerary-body.js +++ b/lib/components/narrative/line-itin/connected-itinerary-body.js @@ -12,6 +12,7 @@ import styled from 'styled-components' import { showLegDiagram } from '../../../actions/map' import { setViewedTrip } from '../../../actions/ui' import TransitLegSubheader from './connected-transit-leg-subheader' +import TimeColumnWithDelays from './time-column-with-delays' import TripDetails from '../connected-trip-details' import TripTools from '../trip-tools' @@ -41,7 +42,8 @@ class ConnectedItineraryBody extends Component { LegIcon, setActiveLeg, setViewedTrip, - showLegDiagram + showLegDiagram, + TimeColumnContent } = this.props return ( @@ -65,6 +67,7 @@ class ConnectedItineraryBody extends Component { toRouteAbbreviation={noop} TransitLegSubheader={TransitLegSubheader} TransitLegSummary={TransitLegSummary} + TimeColumnContent={TimeColumnWithDelays} /> diff --git a/lib/components/narrative/line-itin/time-column-with-delays.js b/lib/components/narrative/line-itin/time-column-with-delays.js index 18fe29e9f..6d5c952cf 100644 --- a/lib/components/narrative/line-itin/time-column-with-delays.js +++ b/lib/components/narrative/line-itin/time-column-with-delays.js @@ -8,15 +8,6 @@ import PropTypes from 'prop-types' import React from 'react' import styled from 'styled-components' -const StatusText = styled.div` - background-color: #bbb; - color: #fff; - font-size: 80%; - line-height: 1em; - padding: 2px; - text-align: center; - text-transform: uppercase; -` const TimeText = styled.div`` const TimeStruck = styled.div` @@ -31,7 +22,12 @@ const TimeBlock = styled.div` const TimeColumnBase = styled.div`` // Reusing stop viewer colors. -/* + +const StatusText = styled.div` + color: #bbb; + font-size: 80%; + line-height: 1em; +` const TimeColumnOnTime = styled(TimeColumnBase)` ${TimeText}, ${StatusText} { color: #5cb85c; @@ -47,8 +43,17 @@ const TimeColumnLate = styled(TimeColumnBase)` color: #d9534f; } `; -*/ +/* +const StatusText = styled.div` + background-color: #bbb; + color: #fff; + font-size: 80%; + line-height: 1em; + padding: 2px; + text-align: center; + text-transform: uppercase; +` const TimeColumnOnTime = styled(TimeColumnBase)` ${TimeText} { color: #5cb85c; @@ -73,7 +78,7 @@ const TimeColumnLate = styled(TimeColumnBase)` background-color: #d9534f; } ` - +*/ /** * This component displays the scheduled departure/arrival time for a leg, * and, for transit legs, displays any delays or earliness where applicable. @@ -87,7 +92,7 @@ export default function TimeColumnWithDelays ({ const formattedTime = time && formatTime(time, timeOptions) const isTransitLeg = isTransit(leg.mode) - if (leg.realTime) { +// if (leg.realTime) { // Delay in seconds. const delay = isDestination ? leg.arrivalDelay : leg.departureDelay // Time is in milliseconds. @@ -141,7 +146,7 @@ export default function TimeColumnWithDelays ({ ) - } + // } // Non-real-time leg. return ( diff --git a/package.json b/package.json index 527561bb0..9f7a5732b 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,7 @@ "@opentripplanner/geocoder": "^1.0.2", "@opentripplanner/humanize-distance": "^0.0.22", "@opentripplanner/icons": "^1.0.1", - "@opentripplanner/itinerary-body": "^1.0.2", + "@opentripplanner/itinerary-body": "^1.1.0", "@opentripplanner/location-field": "^1.0.1", "@opentripplanner/location-icon": "^1.0.0", "@opentripplanner/park-and-ride-overlay": "^1.0.1", diff --git a/yarn.lock b/yarn.lock index 051fc2355..2c4d35bf6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1275,6 +1275,20 @@ prop-types "^15.7.2" qs "^6.9.1" +"@opentripplanner/core-utils@^2.1.0": + version "2.1.0" + resolved "https://registry.yarnpkg.com/@opentripplanner/core-utils/-/core-utils-2.1.0.tgz#ab7271a2b560168b21b0dd26c78532f24fd031f5" + integrity sha512-sQ3oiZB7f01kCVuTj5SzqsPe4uchupNbla+onLWH+aO3wH+OLZNuLRZZ/7oFFFnvpcFBakyg4TePPxyyEyJlMA== + dependencies: + "@mapbox/polyline" "^1.1.0" + "@turf/along" "^6.0.1" + bowser "^2.7.0" + lodash.isequal "^4.5.0" + moment "^2.24.0" + moment-timezone "^0.5.27" + prop-types "^15.7.2" + qs "^6.9.1" + "@opentripplanner/endpoints-overlay@^1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@opentripplanner/endpoints-overlay/-/endpoints-overlay-1.0.1.tgz#d95f0bbfddc9382b593845799b963340eece2742" @@ -1317,12 +1331,12 @@ "@opentripplanner/core-utils" "^1.2.0" prop-types "^15.7.2" -"@opentripplanner/itinerary-body@^1.0.2": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@opentripplanner/itinerary-body/-/itinerary-body-1.0.2.tgz#f280932a13723f49bac92c79feb83a088d14329b" - integrity sha512-3x8UvtkL3WmUeNTeWsWTJJtR2FqcWU42xw4833+6pMMzPoS2U4bYzSbw7ucQT64vqcoRQ0ykUjE7as32W+VgGg== +"@opentripplanner/itinerary-body@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@opentripplanner/itinerary-body/-/itinerary-body-1.1.0.tgz#6fabc389ad25f6f14db5a5861603a127530e0d9e" + integrity sha512-svu2A0z+CnL5vrkDXuaMjJaDoSC4d52utzdGfgkXdfMaK9prO1D/6SHWiVILXmaDJExdBAoF3mxSuA7xPItTTA== dependencies: - "@opentripplanner/core-utils" "^1.2.0" + "@opentripplanner/core-utils" "^2.1.0" "@opentripplanner/humanize-distance" "^0.0.22" "@opentripplanner/icons" "^1.0.0" "@opentripplanner/location-icon" "^1.0.0" From b1570b25361497e0845510cb396463a563cfc0ee Mon Sep 17 00:00:00 2001 From: binh-dam-ibigroup <56846598+binh-dam-ibigroup@users.noreply.github.com> Date: Tue, 18 Aug 2020 18:08:27 -0400 Subject: [PATCH 03/12] refactor(TimeColumnWithDelays): Cleanup --- .../line-itin/connected-itinerary-body.js | 3 +- .../line-itin/time-column-with-delays.js | 49 +++---------------- 2 files changed, 8 insertions(+), 44 deletions(-) diff --git a/lib/components/narrative/line-itin/connected-itinerary-body.js b/lib/components/narrative/line-itin/connected-itinerary-body.js index b808b0f1b..88e65dec0 100644 --- a/lib/components/narrative/line-itin/connected-itinerary-body.js +++ b/lib/components/narrative/line-itin/connected-itinerary-body.js @@ -42,8 +42,7 @@ class ConnectedItineraryBody extends Component { LegIcon, setActiveLeg, setViewedTrip, - showLegDiagram, - TimeColumnContent + showLegDiagram } = this.props return ( diff --git a/lib/components/narrative/line-itin/time-column-with-delays.js b/lib/components/narrative/line-itin/time-column-with-delays.js index 6d5c952cf..22fb2aeeb 100644 --- a/lib/components/narrative/line-itin/time-column-with-delays.js +++ b/lib/components/narrative/line-itin/time-column-with-delays.js @@ -21,64 +21,29 @@ const TimeBlock = styled.div` const TimeColumnBase = styled.div`` -// Reusing stop viewer colors. - const StatusText = styled.div` color: #bbb; font-size: 80%; line-height: 1em; ` -const TimeColumnOnTime = styled(TimeColumnBase)` - ${TimeText}, ${StatusText} { - color: #5cb85c; - } -`; -const TimeColumnEarly = styled(TimeColumnBase)` - ${TimeText}, ${StatusText} { - color: #337ab7; - } -`; -const TimeColumnLate = styled(TimeColumnBase)` - ${TimeText}, ${StatusText} { - color: #d9534f; - } -`; -/* -const StatusText = styled.div` - background-color: #bbb; - color: #fff; - font-size: 80%; - line-height: 1em; - padding: 2px; - text-align: center; - text-transform: uppercase; -` +// Reusing stop viewer colors. const TimeColumnOnTime = styled(TimeColumnBase)` - ${TimeText} { + ${TimeText}, ${StatusText} { color: #5cb85c; } - ${StatusText} { - background-color: #5cb85c; - } ` const TimeColumnEarly = styled(TimeColumnBase)` - ${TimeText} { + ${TimeText}, ${StatusText} { color: #337ab7; } - ${StatusText} { - background-color: #337ab7; - } ` const TimeColumnLate = styled(TimeColumnBase)` - ${TimeText} { + ${TimeText}, ${StatusText} { color: #d9534f; } - ${StatusText} { - background-color: #d9534f; - } ` -*/ + /** * This component displays the scheduled departure/arrival time for a leg, * and, for transit legs, displays any delays or earliness where applicable. @@ -92,7 +57,7 @@ export default function TimeColumnWithDelays ({ const formattedTime = time && formatTime(time, timeOptions) const isTransitLeg = isTransit(leg.mode) -// if (leg.realTime) { + if (leg.realTime) { // Delay in seconds. const delay = isDestination ? leg.arrivalDelay : leg.departureDelay // Time is in milliseconds. @@ -146,7 +111,7 @@ export default function TimeColumnWithDelays ({ ) - // } + } // Non-real-time leg. return ( From aa18d7eb73c1bef663569df91a827001de422b7c Mon Sep 17 00:00:00 2001 From: binh-dam-ibigroup <56846598+binh-dam-ibigroup@users.noreply.github.com> Date: Fri, 21 Aug 2020 19:15:32 -0400 Subject: [PATCH 04/12] fix(SavedTripScreen): Remove wizard mode, pass isCreating prop to panes to tweak layout. --- lib/components/user/saved-trip-editor.js | 48 +++++++++----- lib/components/user/saved-trip-screen.js | 35 ++++------ lib/components/user/saved-trip-wizard.js | 43 ------------ .../user/trip-notifications-pane.js | 66 ++++++++++--------- 4 files changed, 78 insertions(+), 114 deletions(-) delete mode 100644 lib/components/user/saved-trip-wizard.js diff --git a/lib/components/user/saved-trip-editor.js b/lib/components/user/saved-trip-editor.js index 17d949445..c17165f14 100644 --- a/lib/components/user/saved-trip-editor.js +++ b/lib/components/user/saved-trip-editor.js @@ -7,6 +7,7 @@ import StackedPaneDisplay from './stacked-pane-display' * This component handles editing of an existing trip. */ const SavedTripEditor = ({ + isCreating, monitoredTrip, onCancel, onComplete, @@ -14,24 +15,39 @@ const SavedTripEditor = ({ panes }) => { if (monitoredTrip) { - const paneSequence = [ - { - pane: panes.basics, - title: 'Trip overview' - }, - { - pane: panes.notifications, - title: 'Trip notifications' - }, - { - // TODO: Find a better place for this. - pane: () => , - title: 'Danger zone' - } - ] + let paneSequence + if (isCreating) { + paneSequence = [ + { + pane: panes.basics, + title: 'Trip information' + }, + { + pane: panes.notifications, + title: 'Trip notifications' + } + ] + } else { + paneSequence = [ + { + pane: panes.basics, + title: 'Trip overview' + }, + { + pane: panes.notifications, + title: 'Trip notifications' + }, + { + // TODO: Find a better place for this. + pane: () => , + title: 'Danger zone' + } + ] + } + return ( <> -

{monitoredTrip.tripName}

+

{isCreating ? 'Save Trip' : monitoredTrip.tripName}

props => { + const { isCreating } = this.props const { monitoredTrip } = this.state return ( - ) - } else { - content = ( - - ) - } - return (
{/* TODO: Do mobile view. */}
- {content} +
) diff --git a/lib/components/user/saved-trip-wizard.js b/lib/components/user/saved-trip-wizard.js deleted file mode 100644 index bd38c0a7a..000000000 --- a/lib/components/user/saved-trip-wizard.js +++ /dev/null @@ -1,43 +0,0 @@ -import React from 'react' - -import LinkButton from './link-button' -import SequentialPaneDisplay from './sequential-pane-display' - -/** - * This component shows a step-by-step progression of screens to build a MonitoredTrip. - */ -const SavedTripWizard = ({ monitoredTrip, onComplete, panes }) => { - const paneSequence = { - basics: { - disableNext: !monitoredTrip.tripName, - nextId: 'notifications', - pane: panes.basics, - title: 'Trip information' - }, - notifications: { - nextId: 'summary', - pane: panes.notifications, - prevId: 'basics', - title: 'Trip notification preferences' - }, - summary: { - pane: panes.summary, - prevId: 'notifications', - title: 'Trip summary' - } - } - - return ( -
- {/* TODO: Improve navigation. */} -

Back to Trip Planner

- -
- ) -} - -export default SavedTripWizard diff --git a/lib/components/user/trip-notifications-pane.js b/lib/components/user/trip-notifications-pane.js index cccff2229..203d9e894 100644 --- a/lib/components/user/trip-notifications-pane.js +++ b/lib/components/user/trip-notifications-pane.js @@ -23,7 +23,7 @@ class TripNotificationsPane extends Component { } render () { - const { monitoredTrip } = this.props + const { isCreating, monitoredTrip } = this.props return (
@@ -52,40 +52,44 @@ class TripNotificationsPane extends Component { - - When would you like to receive notifications about delays or disruptions to your trip? + {!isCreating && ( + <> + + When would you like to receive notifications about delays or disruptions to your trip? - - Check for delays or disruptions: - - - - - - - + + Check for delays or disruptions: + + + + + + + - - Under construction! - - Notify me if: - A different route or transfer point is recommended - There is an alert for a route or stop that is part of my journey + + Under construction! + + Notify me if: + A different route or transfer point is recommended + There is an alert for a route or stop that is part of my journey - Your arrival or departure time changes by more than: - - - - - + Your arrival or departure time changes by more than: + + + + + + + - - + + )}
) From 2115c7befadd6d7ecc1fd0e02d54a2a462f2774e Mon Sep 17 00:00:00 2001 From: binh-dam-ibigroup <56846598+binh-dam-ibigroup@users.noreply.github.com> Date: Tue, 25 Aug 2020 10:40:34 -0400 Subject: [PATCH 05/12] refactor(TimeColumnWithDelays): Format delay using template string. --- .../narrative/line-itin/time-column-with-delays.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/components/narrative/line-itin/time-column-with-delays.js b/lib/components/narrative/line-itin/time-column-with-delays.js index 22fb2aeeb..85ff2499c 100644 --- a/lib/components/narrative/line-itin/time-column-with-delays.js +++ b/lib/components/narrative/line-itin/time-column-with-delays.js @@ -105,8 +105,9 @@ export default function TimeColumnWithDelays ({ {renderedTime} - {!isOnTime && <>{delayInMinutes} min} - {'\n'} + {/* Keep the '5 min' string on the same line. */} + {/* Append space before printing statusText. (statusText can be displayed on same line or new line.) */} + {!isOnTime && `${delayInMinutes}\xa0min `} {statusText} From 3ef29f3f43f2f8829b397499d15d98ce3bcbe17b Mon Sep 17 00:00:00 2001 From: binh-dam-ibigroup <56846598+binh-dam-ibigroup@users.noreply.github.com> Date: Tue, 25 Aug 2020 12:27:27 -0400 Subject: [PATCH 06/12] refactor(RealtimeTimeColumn): Rename component, address PR comments. --- .../line-itin/connected-itinerary-body.js | 4 +- .../line-itin/realtime-time-column.js | 135 ++++++++++++++++++ .../line-itin/time-column-with-delays.js | 135 ------------------ 3 files changed, 137 insertions(+), 137 deletions(-) create mode 100644 lib/components/narrative/line-itin/realtime-time-column.js delete mode 100644 lib/components/narrative/line-itin/time-column-with-delays.js diff --git a/lib/components/narrative/line-itin/connected-itinerary-body.js b/lib/components/narrative/line-itin/connected-itinerary-body.js index 4c40e6749..ce38a6f73 100644 --- a/lib/components/narrative/line-itin/connected-itinerary-body.js +++ b/lib/components/narrative/line-itin/connected-itinerary-body.js @@ -12,7 +12,7 @@ import styled from 'styled-components' import { showLegDiagram } from '../../../actions/map' import { setViewedTrip } from '../../../actions/ui' import TransitLegSubheader from './connected-transit-leg-subheader' -import TimeColumnWithDelays from './time-column-with-delays' +import RealtimeTimeColumn from './realtime-time-column' import TripDetails from '../connected-trip-details' import TripTools from '../trip-tools' @@ -68,7 +68,7 @@ class ConnectedItineraryBody extends Component { toRouteAbbreviation={noop} TransitLegSubheader={TransitLegSubheader} TransitLegSummary={TransitLegSummary} - TimeColumnContent={TimeColumnWithDelays} + TimeColumnContent={RealtimeTimeColumn} /> diff --git a/lib/components/narrative/line-itin/realtime-time-column.js b/lib/components/narrative/line-itin/realtime-time-column.js new file mode 100644 index 000000000..8ab6f1550 --- /dev/null +++ b/lib/components/narrative/line-itin/realtime-time-column.js @@ -0,0 +1,135 @@ +import { isTransit } from '@opentripplanner/core-utils/lib/itinerary' +import { + legType, + timeOptionsType +} from '@opentripplanner/core-utils/lib/types' +import { formatTime } from '@opentripplanner/core-utils/lib/time' +import PropTypes from 'prop-types' +import React from 'react' +import styled from 'styled-components' + +const TimeText = styled.div`` + +const TimeStruck = styled.div` + text-decoration: line-through; +` + +const TimeBlock = styled.div` + line-height: 1em; + margin-bottom: 4px; +` + +const TimeColumnBase = styled.div`` + +const StatusText = styled.div` + color: #bbb; + font-size: 80%; + line-height: 1em; +` + +// Reusing stop viewer colors. +const TimeColumnOnTime = styled(TimeColumnBase)` + ${TimeText}, ${StatusText} { + color: #5cb85c; + } +` +const TimeColumnEarly = styled(TimeColumnBase)` + ${TimeText}, ${StatusText} { + color: #337ab7; + } +` +const TimeColumnLate = styled(TimeColumnBase)` + ${TimeText}, ${StatusText} { + color: #d9534f; + } +` + +/** + * This component displays the scheduled departure/arrival time for a leg, + * and, for transit legs, displays any delays or earliness where applicable. + */ +export default function RealtimeTimeColumn ({ + isDestination, + leg, + timeOptions +}) { + const time = isDestination ? leg.endTime : leg.startTime + const formattedTime = time && formatTime(time, timeOptions) + const isTransitLeg = isTransit(leg.mode) + + // For non-real-time legs, show only the scheduled time, + // except for transit legs where we add the "scheduled" text underneath. + if (!leg.realTime) { + return ( + <> + {formattedTime} + {isTransitLeg && scheduled} + + ) + } + + // Delay in seconds. + const delay = isDestination ? leg.arrivalDelay : leg.departureDelay + // Time is in milliseconds. + const originalTime = time - delay * 1000 + const originalFormattedTime = + originalTime && formatTime(originalTime, timeOptions) + + // TODO: refine on-time thresholds. + // const isOnTime = delay >= -60 && delay <= 120; + const isOnTime = delay === 0 + + let statusText + let TimeColumn = TimeColumnBase + if (isOnTime) { + statusText = 'on time' + TimeColumn = TimeColumnOnTime + } else if (delay < 0) { + statusText = 'early' + TimeColumn = TimeColumnEarly + } else if (delay > 0) { + statusText = 'late' + TimeColumn = TimeColumnLate + } + + // Absolute delay in rounded minutes, for display purposes. + const delayInMinutes = Math.abs( + Math.round((isDestination ? leg.arrivalDelay : leg.departureDelay) / 60) + ) + + let renderedTime + if (!isOnTime) { + // If the transit vehicle is not on time, strike the original scheduled time + // and display the updated time underneath. + renderedTime = ( + + {!isOnTime && {originalFormattedTime}} + {formattedTime} + + ) + } else { + renderedTime = {formattedTime} + } + + return ( + + {renderedTime} + + {/* Keep the '5 min' string on the same line. */} + {/* Append space before printing statusText. (statusText can be displayed on same line or new line.) */} + {!isOnTime && `${delayInMinutes}\xa0min `} + {statusText} + + + ) +} + +RealtimeTimeColumn.propTypes = { + isDestination: PropTypes.bool.isRequired, + leg: legType.isRequired, + timeOptions: timeOptionsType +} + +RealtimeTimeColumn.defaultProps = { + timeOptions: null +} diff --git a/lib/components/narrative/line-itin/time-column-with-delays.js b/lib/components/narrative/line-itin/time-column-with-delays.js deleted file mode 100644 index 85ff2499c..000000000 --- a/lib/components/narrative/line-itin/time-column-with-delays.js +++ /dev/null @@ -1,135 +0,0 @@ -import { isTransit } from '@opentripplanner/core-utils/lib/itinerary' -import { - legType, - timeOptionsType -} from '@opentripplanner/core-utils/lib/types' -import { formatTime } from '@opentripplanner/core-utils/lib/time' -import PropTypes from 'prop-types' -import React from 'react' -import styled from 'styled-components' - -const TimeText = styled.div`` - -const TimeStruck = styled.div` - text-decoration: line-through; -` - -const TimeBlock = styled.div` - line-height: 1em; - margin-bottom: 4px; -` - -const TimeColumnBase = styled.div`` - -const StatusText = styled.div` - color: #bbb; - font-size: 80%; - line-height: 1em; -` - -// Reusing stop viewer colors. -const TimeColumnOnTime = styled(TimeColumnBase)` - ${TimeText}, ${StatusText} { - color: #5cb85c; - } -` -const TimeColumnEarly = styled(TimeColumnBase)` - ${TimeText}, ${StatusText} { - color: #337ab7; - } -` -const TimeColumnLate = styled(TimeColumnBase)` - ${TimeText}, ${StatusText} { - color: #d9534f; - } -` - -/** - * This component displays the scheduled departure/arrival time for a leg, - * and, for transit legs, displays any delays or earliness where applicable. - */ -export default function TimeColumnWithDelays ({ - isDestination, - leg, - timeOptions -}) { - const time = isDestination ? leg.endTime : leg.startTime - const formattedTime = time && formatTime(time, timeOptions) - const isTransitLeg = isTransit(leg.mode) - - if (leg.realTime) { - // Delay in seconds. - const delay = isDestination ? leg.arrivalDelay : leg.departureDelay - // Time is in milliseconds. - const originalTime = time - delay * 1000 - const originalFormattedTime = - originalTime && formatTime(originalTime, timeOptions) - - // TODO: refine on-time thresholds. - // const isOnTime = delay >= -60 && delay <= 120; - const isOnTime = delay === 0 - - let statusText - let TimeColumn = TimeColumnBase - if (isOnTime) { - statusText = 'on time' - TimeColumn = TimeColumnOnTime - } else if (delay < 0) { - statusText = 'early' - TimeColumn = TimeColumnEarly - } else if (delay > 0) { - statusText = 'late' - TimeColumn = TimeColumnLate - } - - // Absolute delay in rounded minutes, for display purposes. - const delayInMinutes = Math.abs( - Math.round((isDestination ? leg.arrivalDelay : leg.departureDelay) / 60) - ) - - let renderedTime - if (!isOnTime) { - // If the transit vehicle is not on time, strike the original scheduled time - // and display the updated time underneath. - renderedTime = ( - - {!isOnTime && {originalFormattedTime}} - {formattedTime} - - ) - } else { - renderedTime = {formattedTime} - } - - return ( - - {renderedTime} - - {/* Keep the '5 min' string on the same line. */} - {/* Append space before printing statusText. (statusText can be displayed on same line or new line.) */} - {!isOnTime && `${delayInMinutes}\xa0min `} - {statusText} - - - ) - } - - // Non-real-time leg. - return ( - <> - {formattedTime} - {/* Add the scheduled mention for transit legs only. */} - {isTransitLeg && scheduled} - - ) -} - -TimeColumnWithDelays.propTypes = { - isDestination: PropTypes.bool.isRequired, - leg: legType.isRequired, - timeOptions: timeOptionsType -} - -TimeColumnWithDelays.defaultProps = { - timeOptions: null -} From 60f4ad69336cd89193ac0a4888859f1708439572 Mon Sep 17 00:00:00 2001 From: binh-dam-ibigroup <56846598+binh-dam-ibigroup@users.noreply.github.com> Date: Tue, 25 Aug 2020 14:09:06 -0400 Subject: [PATCH 07/12] refactor(RealtimeTimeColumn): Extract styles for delay display. --- .../narrative/line-itin/realtime-time-column.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/components/narrative/line-itin/realtime-time-column.js b/lib/components/narrative/line-itin/realtime-time-column.js index 8ab6f1550..41efc3aec 100644 --- a/lib/components/narrative/line-itin/realtime-time-column.js +++ b/lib/components/narrative/line-itin/realtime-time-column.js @@ -27,6 +27,11 @@ const StatusText = styled.div` line-height: 1em; ` +const DelayText = styled.span` + display: block; + white-space: nowrap; +` + // Reusing stop viewer colors. const TimeColumnOnTime = styled(TimeColumnBase)` ${TimeText}, ${StatusText} { @@ -116,8 +121,7 @@ export default function RealtimeTimeColumn ({ {renderedTime} {/* Keep the '5 min' string on the same line. */} - {/* Append space before printing statusText. (statusText can be displayed on same line or new line.) */} - {!isOnTime && `${delayInMinutes}\xa0min `} + {!isOnTime && {`${delayInMinutes} min`}} {statusText} From 83c201230c65b8c61915b5dd0498da1a4959e145 Mon Sep 17 00:00:00 2001 From: binh-dam-ibigroup <56846598+binh-dam-ibigroup@users.noreply.github.com> Date: Tue, 25 Aug 2020 14:41:08 -0400 Subject: [PATCH 08/12] refactor(RealtimeTimeColumn): Remove template string --- lib/components/narrative/line-itin/realtime-time-column.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/components/narrative/line-itin/realtime-time-column.js b/lib/components/narrative/line-itin/realtime-time-column.js index 41efc3aec..3cf031fee 100644 --- a/lib/components/narrative/line-itin/realtime-time-column.js +++ b/lib/components/narrative/line-itin/realtime-time-column.js @@ -121,7 +121,7 @@ export default function RealtimeTimeColumn ({ {renderedTime} {/* Keep the '5 min' string on the same line. */} - {!isOnTime && {`${delayInMinutes} min`}} + {!isOnTime && {delayInMinutes} min} {statusText} From ab2badb8e3e5439a327f1d778ea875148520e355 Mon Sep 17 00:00:00 2001 From: binh-dam-ibigroup <56846598+binh-dam-ibigroup@users.noreply.github.com> Date: Tue, 25 Aug 2020 18:29:50 -0400 Subject: [PATCH 09/12] fix(ItineraryBody): Pass time/date format to TripDetails component. --- .../narrative/line-itin/connected-itinerary-body.js | 6 +++++- 1 file changed, 5 insertions(+), 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 5c6ba0148..540afdc63 100644 --- a/lib/components/narrative/line-itin/connected-itinerary-body.js +++ b/lib/components/narrative/line-itin/connected-itinerary-body.js @@ -68,7 +68,11 @@ class ConnectedItineraryBody extends Component { TransitLegSubheader={TransitLegSubheader} TransitLegSummary={TransitLegSummary} /> - + ) From 38cdbc37fd5296341ded917cc3f3be2fb72b912b Mon Sep 17 00:00:00 2001 From: binh-dam-ibigroup <56846598+binh-dam-ibigroup@users.noreply.github.com> Date: Thu, 27 Aug 2020 19:08:55 -0400 Subject: [PATCH 10/12] refactor(TripNotificationsPane): Remove isCreating options. --- lib/components/user/saved-trip-editor.js | 2 +- lib/components/user/saved-trip-screen.js | 2 - .../user/trip-notifications-pane.js | 62 +++++++++---------- 3 files changed, 30 insertions(+), 36 deletions(-) diff --git a/lib/components/user/saved-trip-editor.js b/lib/components/user/saved-trip-editor.js index c17165f14..d2cc9b21e 100644 --- a/lib/components/user/saved-trip-editor.js +++ b/lib/components/user/saved-trip-editor.js @@ -47,7 +47,7 @@ const SavedTripEditor = ({ return ( <> -

{isCreating ? 'Save Trip' : monitoredTrip.tripName}

+

{isCreating ? 'Save trip' : monitoredTrip.tripName}

props => { - const { isCreating } = this.props const { monitoredTrip } = this.state return ( @@ -52,44 +52,40 @@ class TripNotificationsPane extends Component { - {!isCreating && ( - <> - - When would you like to receive notifications about delays or disruptions to your trip? + + When would you like to receive notifications about delays or disruptions to your trip? - - Check for delays or disruptions: - - - - - - - + + Check for delays or disruptions: + + + + + + + - + Under construction! - - Notify me if: - A different route or transfer point is recommended - There is an alert for a route or stop that is part of my journey + + Notify me if: + A different route or transfer point is recommended + There is an alert for a route or stop that is part of my journey Your arrival or departure time changes by more than: - - - - - - - + + + + + - - )} + + ) From 404f516ae299fe905d1a8bdc325c911af310bfc8 Mon Sep 17 00:00:00 2001 From: binh-dam-ibigroup <56846598+binh-dam-ibigroup@users.noreply.github.com> Date: Tue, 8 Sep 2020 10:40:00 -0400 Subject: [PATCH 11/12] feat(ItineraryBody): Add fare info in each transit leg body (new config) --- .../line-itin/connected-itinerary-body.js | 1 + package.json | 2 +- yarn.lock | 24 +++++++++++++++---- 3 files changed, 21 insertions(+), 6 deletions(-) diff --git a/lib/components/narrative/line-itin/connected-itinerary-body.js b/lib/components/narrative/line-itin/connected-itinerary-body.js index a9af23488..aa316bddb 100644 --- a/lib/components/narrative/line-itin/connected-itinerary-body.js +++ b/lib/components/narrative/line-itin/connected-itinerary-body.js @@ -63,6 +63,7 @@ class ConnectedItineraryBody extends Component { showElevationProfile showLegIcon showMapButtonColumn={false} + showRouteFares={config.itinerary && config.itinerary.showRouteFares} showViewTripButton timeOptions={timeOptions} toRouteAbbreviation={noop} diff --git a/package.json b/package.json index 8e1aa9ac6..e816419cf 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,7 @@ "@opentripplanner/geocoder": "^1.0.2", "@opentripplanner/humanize-distance": "^0.0.22", "@opentripplanner/icons": "^1.0.1", - "@opentripplanner/itinerary-body": "^1.1.0", + "@opentripplanner/itinerary-body": "^1.2.0", "@opentripplanner/location-field": "^1.0.2", "@opentripplanner/location-icon": "^1.0.0", "@opentripplanner/park-and-ride-overlay": "^1.0.1", diff --git a/yarn.lock b/yarn.lock index e49301f97..78bbf2c4e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1289,6 +1289,20 @@ prop-types "^15.7.2" qs "^6.9.1" +"@opentripplanner/core-utils@^2.1.1": + version "2.1.2" + resolved "https://registry.yarnpkg.com/@opentripplanner/core-utils/-/core-utils-2.1.2.tgz#a19d5d788704f0a6c2aece5206a2c8997c251d16" + integrity sha512-i+ADDdHhC+oJNYPrk7o9eu3F/2IMMZ5YAOXR2QGBJbS97kQOYeTAN4pVGfWKTm7ClTTIBG9/NDnVyQMzGuYInw== + dependencies: + "@mapbox/polyline" "^1.1.0" + "@turf/along" "^6.0.1" + bowser "^2.7.0" + lodash.isequal "^4.5.0" + moment "^2.24.0" + moment-timezone "^0.5.27" + prop-types "^15.7.2" + qs "^6.9.1" + "@opentripplanner/endpoints-overlay@^1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@opentripplanner/endpoints-overlay/-/endpoints-overlay-1.0.1.tgz#d95f0bbfddc9382b593845799b963340eece2742" @@ -1331,12 +1345,12 @@ "@opentripplanner/core-utils" "^1.2.0" prop-types "^15.7.2" -"@opentripplanner/itinerary-body@^1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@opentripplanner/itinerary-body/-/itinerary-body-1.1.0.tgz#6fabc389ad25f6f14db5a5861603a127530e0d9e" - integrity sha512-svu2A0z+CnL5vrkDXuaMjJaDoSC4d52utzdGfgkXdfMaK9prO1D/6SHWiVILXmaDJExdBAoF3mxSuA7xPItTTA== +"@opentripplanner/itinerary-body@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@opentripplanner/itinerary-body/-/itinerary-body-1.2.0.tgz#96d8b832f26c6918ee2c0e122fce6a57a6e5df1a" + integrity sha512-LG8SRTTXdYD8M/7+peJPfuqRFbZlbxilqUBRyGw60efZcnWbAenQW/o5aznuucLHiafDUzVUQpy9SEd0gIqRSQ== dependencies: - "@opentripplanner/core-utils" "^2.1.0" + "@opentripplanner/core-utils" "^2.1.1" "@opentripplanner/humanize-distance" "^0.0.22" "@opentripplanner/icons" "^1.0.0" "@opentripplanner/location-icon" "^1.0.0" From 7cc0bb74bd96faf15e24a3afa23821480a48a33a Mon Sep 17 00:00:00 2001 From: binh-dam-ibigroup <56846598+binh-dam-ibigroup@users.noreply.github.com> Date: Tue, 8 Sep 2020 10:58:40 -0400 Subject: [PATCH 12/12] chore(example-config): Add itinerary#showRouteFares to example-config.yml. --- example-config.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/example-config.yml b/example-config.yml index 18d6b4fc2..719aaf23b 100644 --- a/example-config.yml +++ b/example-config.yml @@ -124,6 +124,12 @@ routingTypes: - key: ITINERARY text: Exact Time +# Itinerary options +itinerary: + # Show fares for each transit leg (false if omitted). + # (Requires using LineItinerary.) + showRouteFares: false + ### Use this config for the standard mode selector # modeGroups: # - name: Transit