From 9eb732c74cc58e0bfb96888d849d69b383d21c6f Mon Sep 17 00:00:00 2001
From: binh-dam-ibigroup <56846598+binh-dam-ibigroup@users.noreply.github.com>
Date: Fri, 29 Sep 2023 10:46:47 -0400
Subject: [PATCH 01/14] feat(service-time-range-retriever): Introduce service
time range retriever component, action, and re
---
lib/actions/apiV2.js | 28 ++++++++++++++++
.../util/service-time-range-retriever.ts | 32 +++++++++++++++++++
lib/reducers/create-otp-reducer.js | 4 +++
3 files changed, 64 insertions(+)
create mode 100644 lib/components/util/service-time-range-retriever.ts
diff --git a/lib/actions/apiV2.js b/lib/actions/apiV2.js
index ae64d539c..4710cc6f0 100644
--- a/lib/actions/apiV2.js
+++ b/lib/actions/apiV2.js
@@ -2,6 +2,7 @@ import {
aggregateModes,
populateSettingWithValue
} from '@opentripplanner/trip-form'
+import { createAction } from 'redux-actions'
import { decodeQueryParams, DelimitedArrayParam } from 'use-query-params'
import clone from 'clone'
import coreUtils from '@opentripplanner/core-utils'
@@ -976,6 +977,32 @@ export function routingQuery(searchId = null, updateSearchInReducer) {
}
}
+const receivedServiceTimeRange = createAction('SERVICE_TIME_RANGE_RESPONSE')
+// Not handled
+const receivedServiceTimeRangeError = createAction(
+ 'SERVICE_TIME_RANGE_RESPONSE_ERROR'
+)
+
+/** Queries for service time range. */
+const retrieveServiceTimeRangeIfNeeded = () =>
+ function (dispatch, getState) {
+ if (getState().otp.serviceTimeRange) return
+ return dispatch(
+ createGraphQLQueryAction(
+ `{
+ serviceTimeRange {
+ start
+ end
+ }
+ }`,
+ {},
+ receivedServiceTimeRange,
+ receivedServiceTimeRangeError,
+ {}
+ )
+ )
+ }
+
export default {
fetchStopInfo,
findPatternsForRoute,
@@ -983,6 +1010,7 @@ export default {
findRoutes,
findTrip,
getVehiclePositionsForRoute,
+ retrieveServiceTimeRangeIfNeeded,
routingQuery,
vehicleRentalQuery
}
diff --git a/lib/components/util/service-time-range-retriever.ts b/lib/components/util/service-time-range-retriever.ts
new file mode 100644
index 000000000..2707ceb16
--- /dev/null
+++ b/lib/components/util/service-time-range-retriever.ts
@@ -0,0 +1,32 @@
+import { connect } from 'react-redux'
+import { useEffect } from 'react'
+
+import * as apiActionsV2 from '../../actions/apiV2'
+
+interface Props {
+ retrieveServiceTimeRangeIfNeeded: () => void
+}
+
+/**
+ * Invisible component that retrieves the date range available
+ * for OTP planning and schedule retrieval.
+ */
+const ServiceTimeRangeRetriever = ({
+ retrieveServiceTimeRangeIfNeeded
+}: Props): null => {
+ // If not already done, retrieve the OTP available date range on mount.
+ useEffect(retrieveServiceTimeRangeIfNeeded, [
+ retrieveServiceTimeRangeIfNeeded
+ ])
+
+ // Component renders nothing
+ return null
+}
+
+// Connect to redux
+const mapDispatchToProps = {
+ retrieveServiceTimeRangeIfNeeded:
+ apiActionsV2.retrieveServiceTimeRangeIfNeeded
+}
+
+export default connect(null, mapDispatchToProps)(ServiceTimeRangeRetriever)
diff --git a/lib/reducers/create-otp-reducer.js b/lib/reducers/create-otp-reducer.js
index 0888474e9..7c33ebe0c 100644
--- a/lib/reducers/create-otp-reducer.js
+++ b/lib/reducers/create-otp-reducer.js
@@ -1088,6 +1088,10 @@ function createOtpReducer(config) {
}
}
})
+ case 'SERVICE_TIME_RANGE_RESPONSE':
+ return update(state, {
+ serviceTimeRange: { $set: action.payload }
+ })
default:
return state
}
From 4961f16a34429a301f0258ea2e647804bdf2425a Mon Sep 17 00:00:00 2001
From: binh-dam-ibigroup <56846598+binh-dam-ibigroup@users.noreply.github.com>
Date: Fri, 29 Sep 2023 11:00:19 -0400
Subject: [PATCH 02/14] refactor(service-time-range-retriever): Fix import and
redux update.
---
lib/components/util/service-time-range-retriever.ts | 2 +-
lib/components/viewers/stop-viewer.js | 2 ++
lib/reducers/create-otp-reducer.js | 2 +-
3 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/lib/components/util/service-time-range-retriever.ts b/lib/components/util/service-time-range-retriever.ts
index 2707ceb16..c52ffb48f 100644
--- a/lib/components/util/service-time-range-retriever.ts
+++ b/lib/components/util/service-time-range-retriever.ts
@@ -1,7 +1,7 @@
import { connect } from 'react-redux'
import { useEffect } from 'react'
-import * as apiActionsV2 from '../../actions/apiV2'
+import apiActionsV2 from '../../actions/apiV2'
interface Props {
retrieveServiceTimeRangeIfNeeded: () => void
diff --git a/lib/components/viewers/stop-viewer.js b/lib/components/viewers/stop-viewer.js
index f907f0d88..923d9dde1 100644
--- a/lib/components/viewers/stop-viewer.js
+++ b/lib/components/viewers/stop-viewer.js
@@ -28,6 +28,7 @@ import { navigateBack } from '../../util/ui'
import { stopIsFlex } from '../../util/viewer'
import OperatorLogo from '../util/operator-logo'
import PageTitle from '../util/page-title'
+import ServiceTimeRangeRetriever from '../util/service-time-range-retriever'
import Strong from '../util/strong-text'
import withMap from '../map/with-map'
@@ -453,6 +454,7 @@ class StopViewer extends Component {
return (
+
{/* Header Block */}
{this._renderHeader(agencyCount)}
diff --git a/lib/reducers/create-otp-reducer.js b/lib/reducers/create-otp-reducer.js
index 7c33ebe0c..ea9d52304 100644
--- a/lib/reducers/create-otp-reducer.js
+++ b/lib/reducers/create-otp-reducer.js
@@ -1090,7 +1090,7 @@ function createOtpReducer(config) {
})
case 'SERVICE_TIME_RANGE_RESPONSE':
return update(state, {
- serviceTimeRange: { $set: action.payload }
+ serviceTimeRange: { $set: action.payload.data.serviceTimeRange }
})
default:
return state
From 456810cd0492ac890ecbae74e4cda2637a3b840c Mon Sep 17 00:00:00 2001
From: binh-dam-ibigroup <56846598+binh-dam-ibigroup@users.noreply.github.com>
Date: Fri, 29 Sep 2023 11:38:11 -0400
Subject: [PATCH 03/14] refactor(otp-reducer): Add logic to handle pending and
error retrieving service time range.
---
lib/actions/apiV2.js | 7 +++----
lib/components/util/service-time-range-retriever.ts | 6 +++---
lib/reducers/create-otp-reducer.js | 8 ++++++++
3 files changed, 14 insertions(+), 7 deletions(-)
diff --git a/lib/actions/apiV2.js b/lib/actions/apiV2.js
index 4710cc6f0..a1577ee7a 100644
--- a/lib/actions/apiV2.js
+++ b/lib/actions/apiV2.js
@@ -977,16 +977,15 @@ export function routingQuery(searchId = null, updateSearchInReducer) {
}
}
+const requestingServiceTimeRange = createAction('SERVICE_TIME_RANGE_REQUEST')
const receivedServiceTimeRange = createAction('SERVICE_TIME_RANGE_RESPONSE')
-// Not handled
-const receivedServiceTimeRangeError = createAction(
- 'SERVICE_TIME_RANGE_RESPONSE_ERROR'
-)
+const receivedServiceTimeRangeError = createAction('SERVICE_TIME_RANGE_ERROR')
/** Queries for service time range. */
const retrieveServiceTimeRangeIfNeeded = () =>
function (dispatch, getState) {
if (getState().otp.serviceTimeRange) return
+ dispatch(requestingServiceTimeRange)
return dispatch(
createGraphQLQueryAction(
`{
diff --git a/lib/components/util/service-time-range-retriever.ts b/lib/components/util/service-time-range-retriever.ts
index c52ffb48f..6a0625fb7 100644
--- a/lib/components/util/service-time-range-retriever.ts
+++ b/lib/components/util/service-time-range-retriever.ts
@@ -15,9 +15,9 @@ const ServiceTimeRangeRetriever = ({
retrieveServiceTimeRangeIfNeeded
}: Props): null => {
// If not already done, retrieve the OTP available date range on mount.
- useEffect(retrieveServiceTimeRangeIfNeeded, [
- retrieveServiceTimeRangeIfNeeded
- ])
+ useEffect(() => {
+ retrieveServiceTimeRangeIfNeeded()
+ }, [retrieveServiceTimeRangeIfNeeded])
// Component renders nothing
return null
diff --git a/lib/reducers/create-otp-reducer.js b/lib/reducers/create-otp-reducer.js
index ea9d52304..6fc02bb58 100644
--- a/lib/reducers/create-otp-reducer.js
+++ b/lib/reducers/create-otp-reducer.js
@@ -1088,10 +1088,18 @@ function createOtpReducer(config) {
}
}
})
+ case 'SERVICE_TIME_RANGE_REQUEST':
+ return update(state, {
+ serviceTimeRange: { $set: { pending: true } }
+ })
case 'SERVICE_TIME_RANGE_RESPONSE':
return update(state, {
serviceTimeRange: { $set: action.payload.data.serviceTimeRange }
})
+ case 'SERVICE_TIME_RANGE_ERROR':
+ return update(state, {
+ serviceTimeRange: { $set: { error: true } }
+ })
default:
return state
}
From f5ee9c258dc5478b6180117963c2d01f2cfd4a32 Mon Sep 17 00:00:00 2001
From: binh-dam-ibigroup <56846598+binh-dam-ibigroup@users.noreply.github.com>
Date: Fri, 29 Sep 2023 15:53:59 -0400
Subject: [PATCH 04/14] improvement(StopViewer): Apply serviceTimeRange to date
picker in schedule view.
---
.../viewers/__snapshots__/stop-viewer.js.snap | 42 +++++++++++++++++++
lib/components/viewers/stop-viewer.js | 35 ++++++++++++++--
2 files changed, 74 insertions(+), 3 deletions(-)
diff --git a/__tests__/components/viewers/__snapshots__/stop-viewer.js.snap b/__tests__/components/viewers/__snapshots__/stop-viewer.js.snap
index 411b2ec9d..323d9a7b5 100644
--- a/__tests__/components/viewers/__snapshots__/stop-viewer.js.snap
+++ b/__tests__/components/viewers/__snapshots__/stop-viewer.js.snap
@@ -101,6 +101,8 @@ exports[`components > viewers > stop viewer should render countdown times after
>
viewers > stop viewer should render countdown times after
}
/>
+
+
+
@@ -3056,6 +3063,8 @@ exports[`components > viewers > stop viewer should render countdown times for st
>
viewers > stop viewer should render countdown times for st
}
/>
+
+
+
@@ -4866,6 +4880,8 @@ exports[`components > viewers > stop viewer should render times after midnight w
>
viewers > stop viewer should render times after midnight w
}
/>
+
+
+
@@ -7864,6 +7885,8 @@ exports[`components > viewers > stop viewer should render with OTP transit index
>
viewers > stop viewer should render with OTP transit index
}
/>
+
+
+
@@ -14937,6 +14965,8 @@ exports[`components > viewers > stop viewer should render with TriMet transit in
>
viewers > stop viewer should render with TriMet transit in
}
/>
+
+
+
@@ -19706,6 +19741,8 @@ exports[`components > viewers > stop viewer should render with initial stop id a
>
viewers > stop viewer should render with initial stop id a
}
/>
+
+
+
diff --git a/lib/components/viewers/stop-viewer.js b/lib/components/viewers/stop-viewer.js
index 923d9dde1..1e3573382 100644
--- a/lib/components/viewers/stop-viewer.js
+++ b/lib/components/viewers/stop-viewer.js
@@ -4,12 +4,13 @@ import { ArrowLeft } from '@styled-icons/fa-solid/ArrowLeft'
import { Calendar } from '@styled-icons/fa-solid/Calendar'
import { Clock } from '@styled-icons/fa-regular/Clock'
import { connect } from 'react-redux'
-import { format } from 'date-fns-tz'
+import { format } from 'date-fns'
import { FormattedMessage, injectIntl } from 'react-intl'
import { InfoCircle } from '@styled-icons/fa-solid/InfoCircle'
import { Search } from '@styled-icons/fa-solid/Search'
import { Star as StarRegular } from '@styled-icons/fa-regular/Star'
import { Star as StarSolid } from '@styled-icons/fa-solid/Star'
+import { utcToZonedTime } from 'date-fns-tz'
import coreUtils from '@opentripplanner/core-utils'
import dateFnsUSLocale from 'date-fns/locale/en-US'
import FromToLocationPicker from '@opentripplanner/from-to-location-picker'
@@ -276,7 +277,8 @@ class StopViewer extends Component {
* TODO: Can this use SetFromToButtons?
*/
_renderControls = () => {
- const { homeTimezone, intl, stopData } = this.props
+ const { calendarMax, calendarMin, homeTimezone, intl, stopData } =
+ this.props
const { isShowingSchedule } = this.state
const inHomeTimezone = homeTimezone && homeTimezone === getUserTimezone()
@@ -362,6 +364,8 @@ class StopViewer extends Component {
id: 'components.StopViewer.findSchedule'
})}
className="pull-right"
+ max={calendarMax}
+ min={calendarMin}
onChange={this.handleDateChange}
onKeyDown={this.props.onKeyDown}
required
@@ -477,7 +481,7 @@ class StopViewer extends Component {
const mapStateToProps = (state) => {
const showUserSettings = getShowUserSettings(state)
const stopViewerConfig = getStopViewerConfig(state)
- const { config, transitIndex, ui } = state.otp
+ const { config, serviceTimeRange = {}, transitIndex, ui } = state.otp
const { homeTimezone, language, persistence, stopViewer, transitOperators } =
config
const { autoRefreshStopTimes = true, favoriteStops } = state.user.localUser
@@ -486,8 +490,33 @@ const mapStateToProps = (state) => {
const nearbyStops = Array.from(new Set(stopData?.nearbyStops))?.map(
(stopId) => stopLookup[stopId]
)
+ const now = new Date()
+ const thisYear = now.getFullYear()
+ const { end = 0, start = 0 } = serviceTimeRange
+ // If start is not provided, default to the first day of the current calendar year in the user's timezone.
+ // (No timezone conversion is needed in this case.)
+ // If start is provided in OTP, convert that date in the agency's home time zone.
+ const calendarMin = format(
+ start
+ ? utcToZonedTime(start * 1000, homeTimezone)
+ : new Date(thisYear, 0, 1),
+ 'yyyy-MM-dd'
+ )
+ // If end is not provided, default to the last day of the next calendar year in the user's timezone.
+ // (No timezone conversion is needed in this case.)
+ // If end date is provided and falls at midnight agency time,
+ // use the previous second to get the last service day available.
+ const calendarMax = format(
+ end
+ ? utcToZonedTime((end - 1) * 1000, homeTimezone)
+ : new Date(thisYear + 1, 11, 31),
+ 'yyyy-MM-dd'
+ )
+
return {
autoRefreshStopTimes,
+ calendarMax,
+ calendarMin,
enableFavoriteStops: getPersistenceMode(persistence).isLocalStorage,
favoriteStops,
homeTimezone,
From 19eb1e70df7bf71f2129afb06e0626e5891c8a36 Mon Sep 17 00:00:00 2001
From: binh-dam-ibigroup <56846598+binh-dam-ibigroup@users.noreply.github.com>
Date: Fri, 29 Sep 2023 16:09:54 -0400
Subject: [PATCH 05/14] refactor(stop-viewer): Add TODOs for upcoming tasks
[skip ci]
---
lib/components/viewers/stop-viewer.js | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/lib/components/viewers/stop-viewer.js b/lib/components/viewers/stop-viewer.js
index 1e3573382..60e109629 100644
--- a/lib/components/viewers/stop-viewer.js
+++ b/lib/components/viewers/stop-viewer.js
@@ -182,6 +182,9 @@ class StopViewer extends Component {
}
handleDateChange = (evt) => {
+ // TODO: check for empty date and that date is within range.
+ // (Users can enter a date outside of the range using the Up/Down arrow keys in Firefox and Safari.)
+ console.log('Date changed to ' + evt.target.value)
const date = evt.target.value
this._findStopTimesForDate(date)
this.setState({ date })
@@ -458,6 +461,7 @@ class StopViewer extends Component {
return (
+ {/* TODO: Add the corresponding mock query in percy tests. */}
{/* Header Block */}
{this._renderHeader(agencyCount)}
From 38dc85e90a49088715a4f455f70c4c2f571e4685 Mon Sep 17 00:00:00 2001
From: binh-dam-ibigroup <56846598+binh-dam-ibigroup@users.noreply.github.com>
Date: Mon, 2 Oct 2023 19:49:03 -0400
Subject: [PATCH 06/14] docs: Fix typos
---
lib/components/viewers/next-arrival-for-pattern.tsx | 2 +-
lib/util/viewer.js | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/lib/components/viewers/next-arrival-for-pattern.tsx b/lib/components/viewers/next-arrival-for-pattern.tsx
index 2fceb4cf8..bed35582c 100644
--- a/lib/components/viewers/next-arrival-for-pattern.tsx
+++ b/lib/components/viewers/next-arrival-for-pattern.tsx
@@ -21,7 +21,7 @@ type Props = {
pattern: Pattern
// Not the true operator type, but the one that's used here
// It is annoying to shoehorn the operator in here like this, but passing
- // it in indvidually would cause a situation where a list of routes
+ // it in individually would cause a situation where a list of routes
// needs to be matched up with a list of operators
route: Route & { operator?: { colorMode?: string } }
routeColor: string
diff --git a/lib/util/viewer.js b/lib/util/viewer.js
index bdb27b3cb..9f1f9ef9d 100644
--- a/lib/util/viewer.js
+++ b/lib/util/viewer.js
@@ -40,7 +40,7 @@ function excludeLastStop(stopTime) {
* Checks that the given route object from an OTP pattern is valid.
* If it is not, logs a warning message.
*
- * FIXME: there is currently a bug with the alernative transit index
+ * FIXME: there is currently a bug with the alternative transit index
* where routes are not associated with the stop if the only stoptimes
* for the stop are drop off only. See https://github.com/ibi-group/trimet-mod-otp/issues/217
*
From f982d0d8fd9f22c39f834c25db27c3f8090710fa Mon Sep 17 00:00:00 2001
From: binh-dam-ibigroup <56846598+binh-dam-ibigroup@users.noreply.github.com>
Date: Tue, 3 Oct 2023 15:16:43 -0400
Subject: [PATCH 07/14] improvement(StopViewer): Send schedule request only
with date within range.
---
lib/components/viewers/stop-viewer.js | 14 +++++++++-----
1 file changed, 9 insertions(+), 5 deletions(-)
diff --git a/lib/components/viewers/stop-viewer.js b/lib/components/viewers/stop-viewer.js
index 60e109629..519fd0fb6 100644
--- a/lib/components/viewers/stop-viewer.js
+++ b/lib/components/viewers/stop-viewer.js
@@ -25,7 +25,7 @@ import * as userActions from '../../actions/user'
import { getPersistenceMode } from '../../util/user'
import { getShowUserSettings, getStopViewerConfig } from '../../util/state'
import { Icon, IconWithText, StyledIconWrapper } from '../util/styledIcon'
-import { navigateBack } from '../../util/ui'
+import { isBlank, navigateBack } from '../../util/ui'
import { stopIsFlex } from '../../util/viewer'
import OperatorLogo from '../util/operator-logo'
import PageTitle from '../util/page-title'
@@ -182,11 +182,16 @@ class StopViewer extends Component {
}
handleDateChange = (evt) => {
- // TODO: check for empty date and that date is within range.
+ // Check for non-empty date, and that date is within range before making request.
// (Users can enter a date outside of the range using the Up/Down arrow keys in Firefox and Safari.)
- console.log('Date changed to ' + evt.target.value)
const date = evt.target.value
- this._findStopTimesForDate(date)
+ if (!isBlank(date)) {
+ const { calendarMax, calendarMin } = this.props
+ // Lazily using lexicographic order ("2023-04-01" > "2023-01-01")
+ if (date >= calendarMin && date <= calendarMax) {
+ this._findStopTimesForDate(date)
+ }
+ }
this.setState({ date })
}
@@ -277,7 +282,6 @@ class StopViewer extends Component {
/**
* Plan trip from/to here buttons, plus the schedule/next arrivals toggle.
- * TODO: Can this use SetFromToButtons?
*/
_renderControls = () => {
const { calendarMax, calendarMin, homeTimezone, intl, stopData } =
From 8e8edde8ef2561ae05187aabd0270307aa07e1e4 Mon Sep 17 00:00:00 2001
From: binh-dam-ibigroup <56846598+binh-dam-ibigroup@users.noreply.github.com>
Date: Tue, 3 Oct 2023 15:45:35 -0400
Subject: [PATCH 08/14] test(percy): Update mock.har
---
percy/mock.har | 36 ++++++++++++++++++++++++++++++++++++
1 file changed, 36 insertions(+)
diff --git a/percy/mock.har b/percy/mock.har
index 168b2f6c5..5762498e1 100644
--- a/percy/mock.har
+++ b/percy/mock.har
@@ -327,6 +327,42 @@
"_blocked_queueing": 8.100999999442138
}
},
+ {
+ "request": {
+ "bodySize": 118,
+ "method": "POST",
+ "url": "http://localhost:9999/otp2/routers/default/index/graphql",
+ "httpVersion": "HTTP/2",
+ "queryString": [],
+ "postData": {
+ "mimeType": "application/json",
+ "text": "{\"query\":\"{\\n serviceTimeRange {\\n start\\n end\\n }\\n }\",\"variables\":{}}"
+ }
+ },
+ "response": {
+ "status": 200,
+ "statusText": "",
+ "httpVersion": "HTTP/2",
+ "content": {
+ "mimeType": "application/json",
+ "size": 67,
+ "text": "{\"data\":{\"serviceTimeRange\":{\"start\":1661745600,\"end\":1735707600}}}"
+ },
+ "headersSize": 502,
+ "bodySize": 569
+ },
+ "cache": {},
+ "timings": {
+ "blocked": -1,
+ "dns": 0,
+ "connect": 0,
+ "ssl": 0,
+ "send": 0,
+ "wait": 204,
+ "receive": 0
+ },
+ "time": 204
+ },
{
"request": {
"method": "GET",
From 4c84ef3f2268ab487e0d02b86b2b9f45e280ae6c Mon Sep 17 00:00:00 2001
From: binh-dam-ibigroup <56846598+binh-dam-ibigroup@users.noreply.github.com>
Date: Tue, 3 Oct 2023 16:27:33 -0400
Subject: [PATCH 09/14] refactor(StopViewer): Use the date-fns format functions
correctly.
---
lib/components/viewers/stop-viewer.js | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/lib/components/viewers/stop-viewer.js b/lib/components/viewers/stop-viewer.js
index 519fd0fb6..34066ced5 100644
--- a/lib/components/viewers/stop-viewer.js
+++ b/lib/components/viewers/stop-viewer.js
@@ -6,11 +6,11 @@ import { Clock } from '@styled-icons/fa-regular/Clock'
import { connect } from 'react-redux'
import { format } from 'date-fns'
import { FormattedMessage, injectIntl } from 'react-intl'
+import { format as formatTz, utcToZonedTime } from 'date-fns-tz'
import { InfoCircle } from '@styled-icons/fa-solid/InfoCircle'
import { Search } from '@styled-icons/fa-solid/Search'
import { Star as StarRegular } from '@styled-icons/fa-regular/Star'
import { Star as StarSolid } from '@styled-icons/fa-solid/Star'
-import { utcToZonedTime } from 'date-fns-tz'
import coreUtils from '@opentripplanner/core-utils'
import dateFnsUSLocale from 'date-fns/locale/en-US'
import FromToLocationPicker from '@opentripplanner/from-to-location-picker'
@@ -302,7 +302,7 @@ class StopViewer extends Component {
let timezoneWarning
if (!inHomeTimezone) {
- const timezoneCode = format(Date.now(), 'z', {
+ const timezoneCode = formatTz(Date.now(), 'z', {
// To avoid ambiguities for now, use the English-US timezone abbreviations ("EST", "PDT", etc.)
locale: dateFnsUSLocale,
timeZone: homeTimezone
@@ -465,7 +465,6 @@ class StopViewer extends Component {
return (
- {/* TODO: Add the corresponding mock query in percy tests. */}
{/* Header Block */}
{this._renderHeader(agencyCount)}
From 929e91dcaa3a6469130f92973cc1e03bb1328b21 Mon Sep 17 00:00:00 2001
From: binh-dam-ibigroup <56846598+binh-dam-ibigroup@users.noreply.github.com>
Date: Tue, 3 Oct 2023 16:49:22 -0400
Subject: [PATCH 10/14] improvement(StopViewer): Make the sched view tz code
based on input date.
---
lib/components/viewers/stop-viewer.js | 32 +++++++++++++++++++--------
1 file changed, 23 insertions(+), 9 deletions(-)
diff --git a/lib/components/viewers/stop-viewer.js b/lib/components/viewers/stop-viewer.js
index 34066ced5..680f10c3d 100644
--- a/lib/components/viewers/stop-viewer.js
+++ b/lib/components/viewers/stop-viewer.js
@@ -4,7 +4,7 @@ import { ArrowLeft } from '@styled-icons/fa-solid/ArrowLeft'
import { Calendar } from '@styled-icons/fa-solid/Calendar'
import { Clock } from '@styled-icons/fa-regular/Clock'
import { connect } from 'react-redux'
-import { format } from 'date-fns'
+import { format, parse } from 'date-fns'
import { FormattedMessage, injectIntl } from 'react-intl'
import { format as formatTz, utcToZonedTime } from 'date-fns-tz'
import { InfoCircle } from '@styled-icons/fa-solid/InfoCircle'
@@ -38,9 +38,13 @@ import StopScheduleTable from './stop-schedule-table'
const { getCurrentDate, getUserTimezone } = coreUtils.time
+/** The native date format used with elements */
+const inputDateFormat = 'yyyy-MM-dd'
+
function getDefaultState(timeZone) {
return {
// Compare dates/times in the stop viewer based on the agency's timezone.
+ // TODO: mock this date for percy tests.
date: getCurrentDate(timeZone),
isShowingSchedule: false
}
@@ -286,7 +290,7 @@ class StopViewer extends Component {
_renderControls = () => {
const { calendarMax, calendarMin, homeTimezone, intl, stopData } =
this.props
- const { isShowingSchedule } = this.state
+ const { date, isShowingSchedule } = this.state
const inHomeTimezone = homeTimezone && homeTimezone === getUserTimezone()
// Rewrite stop ID to not include Agency prefix, if present
@@ -302,11 +306,21 @@ class StopViewer extends Component {
let timezoneWarning
if (!inHomeTimezone) {
- const timezoneCode = formatTz(Date.now(), 'z', {
- // To avoid ambiguities for now, use the English-US timezone abbreviations ("EST", "PDT", etc.)
- locale: dateFnsUSLocale,
- timeZone: homeTimezone
- })
+ // In schedule view, the time zone code should be that of the entered date,
+ // or the current day in the live view.
+ // This is to account for daylight time changes, especially when the liva and
+ // schedule views are in different daylight saving periods.
+ const timezoneCode = formatTz(
+ isShowingSchedule
+ ? parse(date, inputDateFormat, new Date())
+ : new Date(), // TODO: mock for percy tests,
+ 'z',
+ {
+ // To avoid ambiguities for now, use the English-US timezone abbreviations ("EST", "PDT", etc.)
+ locale: dateFnsUSLocale,
+ timeZone: homeTimezone
+ }
+ )
// Display a banner about the departure timezone if user's timezone is not the configured 'homeTimezone'
// (e.g. cases where a user in New York looks at a schedule in Los Angeles).
@@ -507,7 +521,7 @@ const mapStateToProps = (state) => {
start
? utcToZonedTime(start * 1000, homeTimezone)
: new Date(thisYear, 0, 1),
- 'yyyy-MM-dd'
+ inputDateFormat
)
// If end is not provided, default to the last day of the next calendar year in the user's timezone.
// (No timezone conversion is needed in this case.)
@@ -517,7 +531,7 @@ const mapStateToProps = (state) => {
end
? utcToZonedTime((end - 1) * 1000, homeTimezone)
: new Date(thisYear + 1, 11, 31),
- 'yyyy-MM-dd'
+ inputDateFormat
)
return {
From d4c5ac291e6938f60d9f7c0ee6ce638491af4e24 Mon Sep 17 00:00:00 2001
From: binh-dam-ibigroup <56846598+binh-dam-ibigroup@users.noreply.github.com>
Date: Tue, 3 Oct 2023 22:41:04 -0400
Subject: [PATCH 11/14] fix(StopViewer): Compute schedule TZ only if valid date
is entered.
---
lib/components/viewers/stop-viewer.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/components/viewers/stop-viewer.js b/lib/components/viewers/stop-viewer.js
index 680f10c3d..c714b3010 100644
--- a/lib/components/viewers/stop-viewer.js
+++ b/lib/components/viewers/stop-viewer.js
@@ -311,7 +311,7 @@ class StopViewer extends Component {
// This is to account for daylight time changes, especially when the liva and
// schedule views are in different daylight saving periods.
const timezoneCode = formatTz(
- isShowingSchedule
+ isShowingSchedule && date
? parse(date, inputDateFormat, new Date())
: new Date(), // TODO: mock for percy tests,
'z',
From 0388ec440548f1e41ca85da3e382ded5cb1ab94f Mon Sep 17 00:00:00 2001
From: binh-dam-ibigroup <56846598+binh-dam-ibigroup@users.noreply.github.com>
Date: Tue, 3 Oct 2023 22:51:55 -0400
Subject: [PATCH 12/14] docs(StopViewer): Fix typo [skip ci]
---
lib/components/viewers/stop-viewer.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/components/viewers/stop-viewer.js b/lib/components/viewers/stop-viewer.js
index c714b3010..0a712812d 100644
--- a/lib/components/viewers/stop-viewer.js
+++ b/lib/components/viewers/stop-viewer.js
@@ -308,7 +308,7 @@ class StopViewer extends Component {
if (!inHomeTimezone) {
// In schedule view, the time zone code should be that of the entered date,
// or the current day in the live view.
- // This is to account for daylight time changes, especially when the liva and
+ // This is to account for daylight time changes, especially when the live and
// schedule views are in different daylight saving periods.
const timezoneCode = formatTz(
isShowingSchedule && date
From 4d1e6153d292e5f4458d7e873458fe3afd3442f2 Mon Sep 17 00:00:00 2001
From: binh-dam-ibigroup <56846598+binh-dam-ibigroup@users.noreply.github.com>
Date: Thu, 12 Oct 2023 16:50:10 -0400
Subject: [PATCH 13/14] improvement(stop-viewer): Hide timezone warning if date
is invalid.
---
lib/components/viewers/stop-viewer.js | 15 ++++++++-------
1 file changed, 8 insertions(+), 7 deletions(-)
diff --git a/lib/components/viewers/stop-viewer.js b/lib/components/viewers/stop-viewer.js
index 0a712812d..48d91d3cb 100644
--- a/lib/components/viewers/stop-viewer.js
+++ b/lib/components/viewers/stop-viewer.js
@@ -185,16 +185,17 @@ class StopViewer extends Component {
}
}
+ _isDateWithinRange = (date) => {
+ const { calendarMax, calendarMin } = this.props
+ return !isBlank(date) && date >= calendarMin && date <= calendarMax
+ }
+
handleDateChange = (evt) => {
// Check for non-empty date, and that date is within range before making request.
// (Users can enter a date outside of the range using the Up/Down arrow keys in Firefox and Safari.)
const date = evt.target.value
- if (!isBlank(date)) {
- const { calendarMax, calendarMin } = this.props
- // Lazily using lexicographic order ("2023-04-01" > "2023-01-01")
- if (date >= calendarMin && date <= calendarMax) {
- this._findStopTimesForDate(date)
- }
+ if (this._isDateWithinRange(date)) {
+ this._findStopTimesForDate(date)
}
this.setState({ date })
}
@@ -305,7 +306,7 @@ class StopViewer extends Component {
const isFlex = stopIsFlex(stopData)
let timezoneWarning
- if (!inHomeTimezone) {
+ if (!inHomeTimezone && this._isDateWithinRange(date)) {
// In schedule view, the time zone code should be that of the entered date,
// or the current day in the live view.
// This is to account for daylight time changes, especially when the live and
From cc7e5038fc25fb883d8d4a657e695e3bf2bd653e Mon Sep 17 00:00:00 2001
From: binh-dam-ibigroup <56846598+binh-dam-ibigroup@users.noreply.github.com>
Date: Thu, 12 Oct 2023 17:28:58 -0400
Subject: [PATCH 14/14] improvement(stop-viewer): Show message and hide
schedule for invalid date.
---
.../viewers/__snapshots__/stop-viewer.js.snap | 425 ++++++++++++++++++
lib/components/viewers/stop-viewer.js | 29 +-
2 files changed, 446 insertions(+), 8 deletions(-)
diff --git a/__tests__/components/viewers/__snapshots__/stop-viewer.js.snap b/__tests__/components/viewers/__snapshots__/stop-viewer.js.snap
index 98d4f6a63..4cf2c86dd 100644
--- a/__tests__/components/viewers/__snapshots__/stop-viewer.js.snap
+++ b/__tests__/components/viewers/__snapshots__/stop-viewer.js.snap
@@ -832,6 +832,91 @@ exports[`components > viewers > stop viewer should render countdown times after
+
+
+