From 1d850c29e4d99823ec8418d8758d3b3486dcb67e Mon Sep 17 00:00:00 2001 From: binh-dam-ibigroup <56846598+binh-dam-ibigroup@users.noreply.github.com> Date: Fri, 22 Sep 2023 15:28:35 -0400 Subject: [PATCH 01/64] perf(state): Don't include calltaker state or reducer if not config-enabled. --- lib/reducers/call-taker.js | 14 ++++++++++---- lib/util/state.js | 4 ++-- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/lib/reducers/call-taker.js b/lib/reducers/call-taker.js index 202bc22c0..9953484ef 100644 --- a/lib/reducers/call-taker.js +++ b/lib/reducers/call-taker.js @@ -6,11 +6,17 @@ import { FETCH_STATUS } from '../util/constants' import { getISOLikeTimestamp } from '../util/state' import { getModuleConfig, Modules } from '../util/config' +function getCalltakerConfig(config) { + return getModuleConfig({ otp: { config } }, Modules.CALL_TAKER) +} + function createCallTakerReducer(config) { - const calltakerConfig = getModuleConfig( - { otp: { config } }, - Modules.CALL_TAKER - ) + const calltakerConfig = getCalltakerConfig(config) + if (!calltakerConfig) { + // Don't include the calltaker reducer at all if calltaker is not enabled in config. + return undefined + } + const initialState = { activeCall: null, callHistory: { diff --git a/lib/util/state.js b/lib/util/state.js index c25b0b615..dee8fd604 100644 --- a/lib/util/state.js +++ b/lib/util/state.js @@ -245,8 +245,8 @@ function getActiveSearchRealtimeResponse(state) { * https://decembersoft.com/posts/error-selector-creators-expect-all-input-selectors-to-be-functions/ */ export const getActiveFieldTripRequest = createSelector( - (state) => state.callTaker?.fieldTrip.activeId, - (state) => state.callTaker?.fieldTrip.requests, + (state) => state.callTaker?.fieldTrip?.activeId, + (state) => state.callTaker?.fieldTrip?.requests, (activeId, requests) => { if (!activeId || !requests) return return requests.data.find((req) => req.id === activeId) From a20d0d24bc69685eb27be1462cee31bec4066623 Mon Sep 17 00:00:00 2001 From: binh-dam-ibigroup <56846598+binh-dam-ibigroup@users.noreply.github.com> Date: Fri, 22 Sep 2023 16:03:30 -0400 Subject: [PATCH 02/64] refactor(app): Remove unneeded calltaker config. --- lib/app.js | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/lib/app.js b/lib/app.js index 4ea733227..b56facafa 100644 --- a/lib/app.js +++ b/lib/app.js @@ -21,12 +21,7 @@ import { BatchResultsScreen, BatchRoutingPanel, BatchSearchScreen, - CallHistoryWindow, - CallTakerControls, - CallTakerPanel, DefaultItinerary, - FieldTripWindows, - MailablesWindow, ResponsiveWebapp } from './index' @@ -178,17 +173,7 @@ const components = { ItineraryBody: DefaultItinerary, - MainControls: isCallTakerModuleEnabled ? CallTakerControls : null, - - MainPanel: isCallTakerModuleEnabled ? CallTakerPanel : BatchRoutingPanel, - - MapWindows: isCallTakerModuleEnabled ? ( - <> - - - - - ) : null, + MainPanel: BatchRoutingPanel, MobileResultsScreen: BatchResultsScreen, From 932d8354b2379b3d6b7cde847f376e3cfef19580 Mon Sep 17 00:00:00 2001 From: binh-dam-ibigroup <56846598+binh-dam-ibigroup@users.noreply.github.com> Date: Fri, 22 Sep 2023 16:32:03 -0400 Subject: [PATCH 03/64] perf(index): Remove calltaker components from index --- lib/index.js | 12 ------------ percy/har-mock-config-call-taker.js | 10 ++++++---- 2 files changed, 6 insertions(+), 16 deletions(-) diff --git a/lib/index.js b/lib/index.js index 9b8180f8a..f7d142a80 100644 --- a/lib/index.js +++ b/lib/index.js @@ -1,9 +1,5 @@ /* eslint-disable prettier/prettier */ /* eslint-disable sort-imports-es6-autofix/sort-imports-es6 */ -import CallTakerControls from './components/admin/call-taker-controls' -import CallHistoryWindow from './components/admin/call-history-window' -import FieldTripWindows from './components/admin/field-trip-windows' -import MailablesWindow from './components/admin/mailables-window' import DateTimeModal from './components/form/date-time-modal' import DateTimePreview from './components/form/date-time-preview' import ErrorMessage from './components/form/error-message' @@ -29,7 +25,6 @@ import ViewStopButton from './components/viewers/view-stop-button' import ViewerContainer from './components/viewers/viewer-container' import ResponsiveWebapp from './components/app/responsive-webapp' import AppMenu from './components/app/app-menu' -import CallTakerPanel from './components/app/call-taker-panel' import DesktopNav from './components/app/desktop-nav' import BatchRoutingPanel from './components/app/batch-routing-panel' import BatchResultsScreen from './components/mobile/batch-results-screen' @@ -50,12 +45,6 @@ const MobileResultsScreen = BatchResultsScreen const MobileSearchScreen = BatchSearchScreen export { - // module components - CallHistoryWindow, - CallTakerControls, - FieldTripWindows, - MailablesWindow, - // form components DateTimeModal, DateTimePreview, @@ -96,7 +85,6 @@ export { // app components, ResponsiveWebapp, AppMenu, - CallTakerPanel, DesktopNav, // batch routing components diff --git a/percy/har-mock-config-call-taker.js b/percy/har-mock-config-call-taker.js index f1e892114..31cd154f1 100644 --- a/percy/har-mock-config-call-taker.js +++ b/percy/har-mock-config-call-taker.js @@ -14,14 +14,16 @@ import React from 'react' import { BatchResultsScreen, BatchSearchScreen, - CallHistoryWindow, - CallTakerPanel, - FieldTripWindows, - MailablesWindow, MetroItinerary // Webpack sets this file to run from a subdirectory within otp-react-redux // ../lib points to the index file of otp-react-redux's source code } from '../lib' +import { + CallHistoryWindow, + FieldTripWindows, + MailablesWindow +} from '../lib/components/admin' +import { CallTakerPanel } from '../lib/components/app' /** * Custom itinerary footer for this deployment. From 2c111bb294b4347558ff2fc35073dca61e23e81f Mon Sep 17 00:00:00 2001 From: binh-dam-ibigroup <56846598+binh-dam-ibigroup@users.noreply.github.com> Date: Fri, 22 Sep 2023 16:46:16 -0400 Subject: [PATCH 04/64] ci(percy): Update paths for percy calltaker config. --- percy/har-mock-config-call-taker.js | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/percy/har-mock-config-call-taker.js b/percy/har-mock-config-call-taker.js index 31cd154f1..418f5f6c9 100644 --- a/percy/har-mock-config-call-taker.js +++ b/percy/har-mock-config-call-taker.js @@ -18,12 +18,10 @@ import { // Webpack sets this file to run from a subdirectory within otp-react-redux // ../lib points to the index file of otp-react-redux's source code } from '../lib' -import { - CallHistoryWindow, - FieldTripWindows, - MailablesWindow -} from '../lib/components/admin' -import { CallTakerPanel } from '../lib/components/app' +import CallHistoryWindow from '../lib/components/admin/call-history-window' +import CallTakerPanel from '../lib/components/app/call-taker-panel' +import FieldTripWindows from '../lib/components/admin/field-trip-windows' +import MailablesWindow from '../lib/components/admin/mailables-window' /** * Custom itinerary footer for this deployment. From 42b52eccfd5a38c4f826d14dade11aa867bf9760 Mon Sep 17 00:00:00 2001 From: binh-dam-ibigroup <56846598+binh-dam-ibigroup@users.noreply.github.com> Date: Mon, 25 Sep 2023 16:52:39 -0400 Subject: [PATCH 05/64] ci(percy): Use separate YML config for calltaker. --- .github/workflows/percy.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/percy.yml b/.github/workflows/percy.yml index c5e878b72..9684cb875 100644 --- a/.github/workflows/percy.yml +++ b/.github/workflows/percy.yml @@ -52,7 +52,7 @@ jobs: - name: Download OTP2 config file run: curl $PERCY_OTP2_CONFIG_URL --output /tmp/otp2config.yml env: - PERCY_OTP2_CONFIG_URL: ${{ secrets.PERCY_MOCK_OTP2_GEOCODER_CONFIG }} + PERCY_OTP2_CONFIG_URL: ${{ secrets.PERCY_MOCK_OTP2_GEOCODER_CALLTAKER_CONFIG }} - name: Build OTP-RR Calltaker # Calltaker has a separate config file, so another build should be produced. run: yarn build 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 06/64] 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 07/64] 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 08/64] 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 09/64] 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 10/64] 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 11/64] 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 cd1930819866c530f57a1fc7d7b43b5381e85583 Mon Sep 17 00:00:00 2001 From: binh-dam-ibigroup <56846598+binh-dam-ibigroup@users.noreply.github.com> Date: Tue, 3 Oct 2023 10:52:18 -0400 Subject: [PATCH 12/64] ci(dependabot): Checkout repo before using any git/gh commands. --- .github/workflows/dependabot.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/dependabot.yml b/.github/workflows/dependabot.yml index f9da5d0b0..77e770925 100644 --- a/.github/workflows/dependabot.yml +++ b/.github/workflows/dependabot.yml @@ -12,6 +12,7 @@ jobs: pull-requests: write if: github.actor == 'dependabot[bot]' steps: + - uses: actions/checkout@v2 - name: Auto-approve PR uses: hmarr/auto-approve-action@v3 - name: Enable auto-merge 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 13/64] 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 14/64] 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 15/64] 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 16/64] 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 17/64] 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 18/64] 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 f3d2f6a1055bcd085ba49654def77da67145e8b3 Mon Sep 17 00:00:00 2001 From: amy-corson-ibigroup <115499534+amy-corson-ibigroup@users.noreply.github.com> Date: Fri, 6 Oct 2023 14:48:24 -0500 Subject: [PATCH 19/64] Add configurable strict mode to itinerary filter --- lib/actions/apiV2.js | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/lib/actions/apiV2.js b/lib/actions/apiV2.js index ae64d539c..dd77fbfc8 100644 --- a/lib/actions/apiV2.js +++ b/lib/actions/apiV2.js @@ -45,7 +45,8 @@ import { RoutingQueryCallResult } from './api-constants' import { setItineraryView } from './ui' import { zoomToPlace } from './map' -const { generateCombinations, generateOtp2Query } = coreUtils.queryGen +const { generateCombinations, generateOtp2Query, SIMPLIFICATIONS } = + coreUtils.queryGen const { getTripOptionsFromQuery, getUrlParams } = coreUtils.query const { convertGraphQLResponseToLegacy } = coreUtils.itinerary const { randId } = coreUtils.storage @@ -824,6 +825,8 @@ export function routingQuery(searchId = null, updateSearchInReducer) { config?.modes?.initialState?.enabledModeButtons || {} + const strictModes = config?.itinerary?.strictItineraryFiltering + // Filter mode definitions based on active mode keys const activeModeButtons = config.modes?.modeButtons.filter((mb) => activeModeKeys.includes(mb.key) @@ -920,11 +923,28 @@ export function routingQuery(searchId = null, updateSearchInReducer) { routingError, { rewritePayload: (response, dispatch, getState) => { - const withCollapsedShortNames = - response.data?.plan?.itineraries?.map((itin) => ({ + const itineraries = response.data?.plan?.itineraries + const activeModeStrings = activeModes.map( + (am) => SIMPLIFICATIONS[am.mode] + ) + let filteredItineraries + + if (strictModes) { + filteredItineraries = itineraries.filter((itin) => + itin.legs.some((leg) => + activeModeStrings.includes(SIMPLIFICATIONS[leg.mode]) + ) + ) + } else { + filteredItineraries = itineraries + } + + const withCollapsedShortNames = filteredItineraries.map( + (itin) => ({ ...itin, legs: itin.legs?.map(convertGraphQLResponseToLegacy) - })) + }) + ) /* It is possible for a NO_TRANSIT_CONNECTION error to be returned even if trips were returned, since it is on a mode-by-mode basis. From 413217c675239e8d3904239077a36b20b01b14ec Mon Sep 17 00:00:00 2001 From: binh-dam-ibigroup <56846598+binh-dam-ibigroup@users.noreply.github.com> Date: Fri, 6 Oct 2023 16:23:28 -0400 Subject: [PATCH 20/64] refactor(util/ui): Extract method for determining next itin view. --- __tests__/util/ui.ts | 34 +++++++++++++++++++++++++++++++++- lib/util/ui.ts | 22 +++++++++++++++++++++- 2 files changed, 54 insertions(+), 2 deletions(-) diff --git a/__tests__/util/ui.ts b/__tests__/util/ui.ts index 813f90d2e..0eb9c61ce 100644 --- a/__tests__/util/ui.ts +++ b/__tests__/util/ui.ts @@ -1,4 +1,8 @@ -import { getItineraryView, ItineraryView } from '../../lib/util/ui' +import { + getItineraryView, + getMapToggleNewItineraryView, + ItineraryView +} from '../../lib/util/ui' describe('util > ui', () => { describe('getItineraryView', () => { @@ -29,6 +33,18 @@ describe('util > ui', () => { ui_itineraryView: ItineraryView.LEG }) ).toBe(ItineraryView.LIST) + expect( + getItineraryView({ + ui_activeItinerary: -1, + ui_itineraryView: ItineraryView.LEG_HIDDEN + }) + ).toBe(ItineraryView.LIST) + expect( + getItineraryView({ + ui_activeItinerary: -1, + ui_itineraryView: ItineraryView.LIST_HIDDEN + }) + ).toBe(ItineraryView.LIST_HIDDEN) }) it('returns the specified view mode when set in URL', () => { expect( @@ -39,4 +55,20 @@ describe('util > ui', () => { ).toBe(ItineraryView.LEG) }) }) + describe('getMapToggleNewItineraryView', () => { + it('should obtain the new itinerary view value', () => { + expect(getMapToggleNewItineraryView(ItineraryView.LEG)).toBe( + ItineraryView.LEG_HIDDEN + ) + expect(getMapToggleNewItineraryView(ItineraryView.LIST)).toBe( + ItineraryView.LIST_HIDDEN + ) + expect(getMapToggleNewItineraryView(ItineraryView.LEG_HIDDEN)).toBe( + ItineraryView.LEG + ) + expect(getMapToggleNewItineraryView(ItineraryView.LIST_HIDDEN)).toBe( + ItineraryView.LIST + ) + }) + }) }) diff --git a/lib/util/ui.ts b/lib/util/ui.ts index 54dba6d99..e2dd8bd7e 100644 --- a/lib/util/ui.ts +++ b/lib/util/ui.ts @@ -113,9 +113,29 @@ export function getItineraryView({ ((ui_activeItinerary === null || ui_activeItinerary === undefined || `${ui_activeItinerary}` === '-1') && - ItineraryView.LIST) || + (ui_itineraryView === ItineraryView.LIST_HIDDEN + ? ItineraryView.LIST_HIDDEN + : ItineraryView.LIST)) || ui_itineraryView || (isDefinedAndNotEqual(ui_activeItinerary, -1) && ItineraryView.FULL) || ItineraryView.LIST ) } + +/** + * Gets the new itinerary view to display based on current state and URL params. + */ +export function getMapToggleNewItineraryView( + currentView: ItineraryView +): ItineraryView { + switch (currentView) { + case ItineraryView.LEG: + return ItineraryView.LEG_HIDDEN + case ItineraryView.LIST: + return ItineraryView.LIST_HIDDEN + case ItineraryView.LEG_HIDDEN: + return ItineraryView.LEG + default: + return ItineraryView.LIST + } +} From a200fcf29f05d41c316dafb5fa5d8941ee88a162 Mon Sep 17 00:00:00 2001 From: binh-dam-ibigroup <56846598+binh-dam-ibigroup@users.noreply.github.com> Date: Fri, 6 Oct 2023 16:29:53 -0400 Subject: [PATCH 21/64] fix(actions/ui): Correctly set the next itin view state. --- lib/actions/apiV2.js | 2 -- lib/actions/ui.js | 33 +++++++------------ lib/components/mobile/batch-results-screen.js | 2 +- lib/reducers/create-otp-reducer.js | 4 +-- 4 files changed, 15 insertions(+), 26 deletions(-) diff --git a/lib/actions/apiV2.js b/lib/actions/apiV2.js index ae64d539c..3fdd4c714 100644 --- a/lib/actions/apiV2.js +++ b/lib/actions/apiV2.js @@ -878,8 +878,6 @@ export function routingQuery(searchId = null, updateSearchInReducer) { }) ) - dispatch(setItineraryView(ItineraryView.LIST)) - combinations.forEach((combo, index) => { const query = generateOtp2Query(combo) dispatch( diff --git a/lib/actions/ui.js b/lib/actions/ui.js index 3b254fa61..e50013218 100644 --- a/lib/actions/ui.js +++ b/lib/actions/ui.js @@ -9,12 +9,14 @@ import { getMatchingLocaleString, loadLocaleData } from '../util/i18n' -import { getModesForActiveAgencyFilter, getUiUrlParams } from '../util/state' import { + getItineraryView, + getMapToggleNewItineraryView, getPathFromParts, isDefinedAndNotEqual, ItineraryView } from '../util/ui' +import { getModesForActiveAgencyFilter, getUiUrlParams } from '../util/state' import { clearActiveSearch, @@ -39,7 +41,7 @@ export const setHoveredStop = createAction('SET_HOVERED_STOP') const viewTrip = createAction('SET_VIEWED_TRIP') const viewRoute = createAction('SET_VIEWED_ROUTE') export const toggleAutoRefresh = createAction('TOGGLE_AUTO_REFRESH') -const setPreviousItineraryView = createAction('SET_PREVIOUS_ITINERARY_VIEW') +const settingItineraryView = createAction('SET_ITINERARY_VIEW') export const setPopupContent = createAction('SET_POPUP_CONTENT') // This code-less action calls the reducer code @@ -314,21 +316,15 @@ export function handleBackButtonPress(e) { export function setItineraryView(value) { return function (dispatch, getState) { const urlParams = coreUtils.query.getUrlParams() - const prevItineraryView = urlParams.ui_itineraryView || ItineraryView.LIST // If the itinerary value is changed, - // set the desired ui query param + // set the desired ui query param (even if LIST, so it replaces the current value) // and store the current view as previousItineraryView. - if (value !== urlParams.ui_itineraryView) { - if (value !== ItineraryView.LIST) { - urlParams.ui_itineraryView = value - } else if (urlParams.ui_itineraryView) { - // Remove the ui_itineraryView param if it is set to LIST (default). - delete urlParams.ui_itineraryView - } + if (value !== getItineraryView(urlParams)) { + urlParams.ui_itineraryView = value dispatch(setUrlSearch(urlParams)) - dispatch(setPreviousItineraryView(prevItineraryView)) + dispatch(settingItineraryView(value)) } } } @@ -340,16 +336,11 @@ export function setItineraryView(value) { export function toggleBatchResultsMap() { return function (dispatch, getState) { const urlParams = coreUtils.query.getUrlParams() - const itineraryView = urlParams.ui_itineraryView || ItineraryView.LIST + const itineraryView = getItineraryView(urlParams) - if (itineraryView === ItineraryView.LEG) { - dispatch(setItineraryView(ItineraryView.LEG_HIDDEN)) - } else if (itineraryView === ItineraryView.LIST) { - dispatch(setItineraryView(ItineraryView.LIST_HIDDEN)) - } else { - const { previousItineraryView } = getState().otp.ui - dispatch(setItineraryView(previousItineraryView)) - } + const newView = getMapToggleNewItineraryView(itineraryView) + console.log(`itin view: ${itineraryView}=>${newView}`) + dispatch(setItineraryView(newView)) } } diff --git a/lib/components/mobile/batch-results-screen.js b/lib/components/mobile/batch-results-screen.js index 2e88d01e9..69119f1c3 100644 --- a/lib/components/mobile/batch-results-screen.js +++ b/lib/components/mobile/batch-results-screen.js @@ -143,7 +143,7 @@ const mapStateToProps = (state) => { activeLeg: activeSearch ? activeSearch.activeLeg : null, errors: getResponsesWithErrors(state), itineraries: getActiveItineraries(state), - itineraryView: getItineraryView(urlParams) + itineraryView: getItineraryView(urlParams) || state.otp.ui.itineraryView } } diff --git a/lib/reducers/create-otp-reducer.js b/lib/reducers/create-otp-reducer.js index 0888474e9..8e7afa35b 100644 --- a/lib/reducers/create-otp-reducer.js +++ b/lib/reducers/create-otp-reducer.js @@ -1053,9 +1053,9 @@ function createOtpReducer(config) { }) case 'UPDATE_ITINERARY_FILTER': return update(state, { filter: { $set: action.payload } }) - case 'SET_PREVIOUS_ITINERARY_VIEW': + case 'SET_ITINERARY_VIEW': return update(state, { - ui: { previousItineraryView: { $set: action.payload } } + ui: { itineraryView: { $set: action.payload } } }) case 'UPDATE_LOCALE': return update(state, { From 2419489228061a810887d8f7a722ad7c7e86aad9 Mon Sep 17 00:00:00 2001 From: binh-dam-ibigroup <56846598+binh-dam-ibigroup@users.noreply.github.com> Date: Fri, 6 Oct 2023 16:58:17 -0400 Subject: [PATCH 22/64] test(util/ui): Refactor test. --- __tests__/util/ui.ts | 60 ++++++++++++++++++-------------------------- 1 file changed, 24 insertions(+), 36 deletions(-) diff --git a/__tests__/util/ui.ts b/__tests__/util/ui.ts index 0eb9c61ce..314e604e4 100644 --- a/__tests__/util/ui.ts +++ b/__tests__/util/ui.ts @@ -21,30 +21,21 @@ describe('util > ui', () => { ) }) it('returns an itinerary list view if URL contains ui_activeItinerary=-1 regardless of ui_itineraryView', () => { - expect( - getItineraryView({ - ui_activeItinerary: -1, - ui_itineraryView: ItineraryView.FULL - }) - ).toBe(ItineraryView.LIST) - expect( - getItineraryView({ - ui_activeItinerary: -1, - ui_itineraryView: ItineraryView.LEG - }) - ).toBe(ItineraryView.LIST) - expect( - getItineraryView({ - ui_activeItinerary: -1, - ui_itineraryView: ItineraryView.LEG_HIDDEN - }) - ).toBe(ItineraryView.LIST) - expect( - getItineraryView({ - ui_activeItinerary: -1, - ui_itineraryView: ItineraryView.LIST_HIDDEN - }) - ).toBe(ItineraryView.LIST_HIDDEN) + const expectedValues = { + [ItineraryView.FULL]: ItineraryView.LIST, + [ItineraryView.LEG]: ItineraryView.LIST, + [ItineraryView.LEG_HIDDEN]: ItineraryView.LIST, + [ItineraryView.LIST]: ItineraryView.LIST, + [ItineraryView.LIST_HIDDEN]: ItineraryView.LIST_HIDDEN + } + Object.entries(expectedValues).forEach(([k, v]) => { + expect( + getItineraryView({ + ui_activeItinerary: -1, + ui_itineraryView: k + }) + ).toBe(v) + }) }) it('returns the specified view mode when set in URL', () => { expect( @@ -57,18 +48,15 @@ describe('util > ui', () => { }) describe('getMapToggleNewItineraryView', () => { it('should obtain the new itinerary view value', () => { - expect(getMapToggleNewItineraryView(ItineraryView.LEG)).toBe( - ItineraryView.LEG_HIDDEN - ) - expect(getMapToggleNewItineraryView(ItineraryView.LIST)).toBe( - ItineraryView.LIST_HIDDEN - ) - expect(getMapToggleNewItineraryView(ItineraryView.LEG_HIDDEN)).toBe( - ItineraryView.LEG - ) - expect(getMapToggleNewItineraryView(ItineraryView.LIST_HIDDEN)).toBe( - ItineraryView.LIST - ) + const expectedValues = { + [ItineraryView.LEG]: ItineraryView.LEG_HIDDEN, + [ItineraryView.LEG_HIDDEN]: ItineraryView.LEG, + [ItineraryView.LIST]: ItineraryView.LIST_HIDDEN, + [ItineraryView.LIST_HIDDEN]: ItineraryView.LIST + } + Object.entries(expectedValues).forEach(([k, v]) => { + expect(getMapToggleNewItineraryView(k)).toBe(v) + }) }) }) }) From 6687464d5375b08ca324fe45d791fa58b60a6de0 Mon Sep 17 00:00:00 2001 From: binh-dam-ibigroup <56846598+binh-dam-ibigroup@users.noreply.github.com> Date: Fri, 6 Oct 2023 17:17:47 -0400 Subject: [PATCH 23/64] refactor(util/ui): Tweak comment [skip ci] --- lib/util/ui.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/util/ui.ts b/lib/util/ui.ts index e2dd8bd7e..ed992e860 100644 --- a/lib/util/ui.ts +++ b/lib/util/ui.ts @@ -123,7 +123,7 @@ export function getItineraryView({ } /** - * Gets the new itinerary view to display based on current state and URL params. + * Gets the new itinerary view to display based on current view. */ export function getMapToggleNewItineraryView( currentView: ItineraryView From 15b71fc61007ac7ecc59175566d53e96f758d3cb Mon Sep 17 00:00:00 2001 From: amy-corson-ibigroup <115499534+amy-corson-ibigroup@users.noreply.github.com> Date: Mon, 9 Oct 2023 09:22:37 -0500 Subject: [PATCH 24/64] Add comments and example config variable --- example-config.yml | 3 +++ lib/actions/apiV2.js | 1 + 2 files changed, 4 insertions(+) diff --git a/example-config.yml b/example-config.yml index cc270ada0..2bae9c943 100644 --- a/example-config.yml +++ b/example-config.yml @@ -310,6 +310,9 @@ itinerary: # Whether the plan first/previous/next/last buttons should be shown along with # plan trip itineraries. showPlanFirstLastButtons: false + # Filters out trips returned by OTP by default, unless specifically requested. + # e.g. filters out walk-only itineraries if user has not explicitly asked for them. + strictItineraryFiltering: false # Whether to render route names and colors in the blocks inside # the batch ui rows renderRouteNamesInBlocks: true diff --git a/lib/actions/apiV2.js b/lib/actions/apiV2.js index dd77fbfc8..9f7b60b75 100644 --- a/lib/actions/apiV2.js +++ b/lib/actions/apiV2.js @@ -939,6 +939,7 @@ export function routingQuery(searchId = null, updateSearchInReducer) { filteredItineraries = itineraries } + // Filter itineraries to collapse short names and hide unnecessary errors. const withCollapsedShortNames = filteredItineraries.map( (itin) => ({ ...itin, From 14fe67998dbdcb275471224baa3bca20c858b4c5 Mon Sep 17 00:00:00 2001 From: binh-dam-ibigroup <56846598+binh-dam-ibigroup@users.noreply.github.com> Date: Mon, 9 Oct 2023 13:41:38 -0400 Subject: [PATCH 25/64] refactor(actions/ui): Remove console statement. --- lib/actions/ui.js | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/actions/ui.js b/lib/actions/ui.js index e50013218..21856fd9b 100644 --- a/lib/actions/ui.js +++ b/lib/actions/ui.js @@ -339,7 +339,6 @@ export function toggleBatchResultsMap() { const itineraryView = getItineraryView(urlParams) const newView = getMapToggleNewItineraryView(itineraryView) - console.log(`itin view: ${itineraryView}=>${newView}`) dispatch(setItineraryView(newView)) } } From ddf8156a43d8feefbccb4b28ef90f6dae3a56b09 Mon Sep 17 00:00:00 2001 From: amy-corson-ibigroup <115499534+amy-corson-ibigroup@users.noreply.github.com> Date: Mon, 9 Oct 2023 15:18:27 -0500 Subject: [PATCH 26/64] Add additional comments for clarity --- lib/actions/apiV2.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/actions/apiV2.js b/lib/actions/apiV2.js index 9f7b60b75..57c6d141d 100644 --- a/lib/actions/apiV2.js +++ b/lib/actions/apiV2.js @@ -924,17 +924,21 @@ export function routingQuery(searchId = null, updateSearchInReducer) { { rewritePayload: (response, dispatch, getState) => { const itineraries = response.data?.plan?.itineraries + + // Convert user-selected transit modes from mode selector into modes recognized by OTP. const activeModeStrings = activeModes.map( (am) => SIMPLIFICATIONS[am.mode] ) - let filteredItineraries + let filteredItineraries + // If "strictItineraryFiltering" is enabled, only return itineraries that contain at least one explicitly requested mode... if (strictModes) { filteredItineraries = itineraries.filter((itin) => itin.legs.some((leg) => activeModeStrings.includes(SIMPLIFICATIONS[leg.mode]) ) ) + // ... Otherwise return all itineraries. } else { filteredItineraries = itineraries } From 4968d66a026a19d9efc87f02a784bf8d8f306dfb Mon Sep 17 00:00:00 2001 From: miles-grant-ibigroup Date: Wed, 11 Oct 2023 11:29:16 -0400 Subject: [PATCH 27/64] refactor: route viewer always use route color overrides --- lib/actions/apiV2.js | 53 +++++++++++++++++++++++++------------------- lib/util/viewer.js | 2 +- 2 files changed, 31 insertions(+), 24 deletions(-) diff --git a/lib/actions/apiV2.js b/lib/actions/apiV2.js index ae64d539c..544f5aec5 100644 --- a/lib/actions/apiV2.js +++ b/lib/actions/apiV2.js @@ -12,8 +12,13 @@ import { generateModeSettingValues } from '../util/api' import { getActiveItineraries, getActiveItinerary, + getRouteOperator, queryIsValid } from '../util/state' +import { + getColorAndNameFromRoute, + getRouteColorBasedOnSettings +} from '../util/viewer' import { ItineraryView } from '../util/ui' import { @@ -669,6 +674,10 @@ export const findRoute = (params) => newRoute.patterns = routePatterns // TODO: avoid explicit behavior shift like this newRoute.v2 = true + newRoute.color = getColorAndNameFromRoute( + getRouteOperator(route, getState().otp.config.transitOperators), + route + ).backgroundColor.split('#')[1] newRoute.mode = checkForRouteModeOverride( newRoute, getState().otp.config?.routeModeOverrides @@ -716,29 +725,27 @@ export function findRoutes() { const { config } = getState().otp // To initialize the route viewer, // convert the routes array to a dictionary indexed by route ids. - return routes.reduce( - ( - result, - { agency, color, id, longName, mode, shortName, type } - ) => { - result[id] = { - agencyId: agency.id, - agencyName: agency.name, - color, - id, - longName, - mode: checkForRouteModeOverride( - { id, mode }, - config?.routeModeOverrides - ), - shortName, - type, - v2: true - } - return result - }, - {} - ) + return routes.reduce((result, route) => { + const { agency, id, longName, mode, shortName, type } = route + result[id] = { + agencyId: agency.id, + agencyName: agency.name, + color: getColorAndNameFromRoute( + getRouteOperator(route, config.transitOperators), + route + ).backgroundColor.split('#')[1], + id, + longName, + mode: checkForRouteModeOverride( + { id, mode }, + config?.routeModeOverrides + ), + shortName, + type, + v2: true + } + return result + }, {}) } } ) diff --git a/lib/util/viewer.js b/lib/util/viewer.js index 9f1f9ef9d..b2e9df92e 100644 --- a/lib/util/viewer.js +++ b/lib/util/viewer.js @@ -383,7 +383,7 @@ export function getColorAndNameFromRoute(operator, route) { const modeColors = operator?.modeColors?.[getModeFromRoute(route)] const backgroundColor = `#${ - modeColors?.color || defaultRouteColor || route.color || '333333' + modeColors?.color || defaultRouteColor || route?.color || '333333' }` // NOTE: text color is not a part of short response route object, so there // is no way to determine from OTP what the text color should be if the From bbf852217a715dee506ed0a73a3adaade1911224 Mon Sep 17 00:00:00 2001 From: miles-grant-ibigroup Date: Wed, 11 Oct 2023 11:35:43 -0400 Subject: [PATCH 28/64] use cleaner method --- lib/actions/apiV2.js | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/lib/actions/apiV2.js b/lib/actions/apiV2.js index 544f5aec5..15644d947 100644 --- a/lib/actions/apiV2.js +++ b/lib/actions/apiV2.js @@ -15,10 +15,7 @@ import { getRouteOperator, queryIsValid } from '../util/state' -import { - getColorAndNameFromRoute, - getRouteColorBasedOnSettings -} from '../util/viewer' +import { getRouteColorBasedOnSettings } from '../util/viewer' import { ItineraryView } from '../util/ui' import { @@ -674,10 +671,10 @@ export const findRoute = (params) => newRoute.patterns = routePatterns // TODO: avoid explicit behavior shift like this newRoute.v2 = true - newRoute.color = getColorAndNameFromRoute( + newRoute.color = getRouteColorBasedOnSettings( getRouteOperator(route, getState().otp.config.transitOperators), route - ).backgroundColor.split('#')[1] + ).split('#')[1] newRoute.mode = checkForRouteModeOverride( newRoute, getState().otp.config?.routeModeOverrides @@ -730,10 +727,10 @@ export function findRoutes() { result[id] = { agencyId: agency.id, agencyName: agency.name, - color: getColorAndNameFromRoute( + color: getRouteColorBasedOnSettings( getRouteOperator(route, config.transitOperators), route - ).backgroundColor.split('#')[1], + ).split('#')[1], id, longName, mode: checkForRouteModeOverride( From 6f97b7701ab9bcfaf33eec4b3081bb747ce05d2a Mon Sep 17 00:00:00 2001 From: miles-grant-ibigroup Date: Wed, 11 Oct 2023 15:16:42 -0400 Subject: [PATCH 29/64] refactor: use getRouteColorBasedOnSettings in itinerary result --- lib/actions/apiV2.js | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/lib/actions/apiV2.js b/lib/actions/apiV2.js index 15644d947..318c77eb6 100644 --- a/lib/actions/apiV2.js +++ b/lib/actions/apiV2.js @@ -927,7 +927,26 @@ export function routingQuery(searchId = null, updateSearchInReducer) { const withCollapsedShortNames = response.data?.plan?.itineraries?.map((itin) => ({ ...itin, - legs: itin.legs?.map(convertGraphQLResponseToLegacy) + legs: itin.legs + ?.map((leg) => { + return { + ...leg, + route: { + ...leg.route, + color: getRouteColorBasedOnSettings( + getRouteOperator( + { + agencyId: leg?.agency?.id, + id: leg?.route?.id + }, + config.transitOperators + ), + { color: leg?.route?.color, mode: leg.mode } + ).split('#')?.[1] + } + } + }) + ?.map(convertGraphQLResponseToLegacy) })) /* It is possible for a NO_TRANSIT_CONNECTION error to be From 8a26d355c975049c9c15ce4c20f51ffabb6b2551 Mon Sep 17 00:00:00 2001 From: amy-corson-ibigroup <115499534+amy-corson-ibigroup@users.noreply.github.com> Date: Wed, 11 Oct 2023 17:42:00 -0500 Subject: [PATCH 30/64] refactor: remove else block from strict filtering --- lib/actions/apiV2.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/actions/apiV2.js b/lib/actions/apiV2.js index 57c6d141d..032032b2a 100644 --- a/lib/actions/apiV2.js +++ b/lib/actions/apiV2.js @@ -930,7 +930,7 @@ export function routingQuery(searchId = null, updateSearchInReducer) { (am) => SIMPLIFICATIONS[am.mode] ) - let filteredItineraries + let filteredItineraries = itineraries // If "strictItineraryFiltering" is enabled, only return itineraries that contain at least one explicitly requested mode... if (strictModes) { filteredItineraries = itineraries.filter((itin) => @@ -939,8 +939,6 @@ export function routingQuery(searchId = null, updateSearchInReducer) { ) ) // ... Otherwise return all itineraries. - } else { - filteredItineraries = itineraries } // Filter itineraries to collapse short names and hide unnecessary errors. 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 31/64] 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 32/64] 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 + + +
+ +
+ + + + + + + + + + + + + + components.StopViewer.noStopsFound + + +
+
+
+
+
viewers > stop viewer should render countdown times for st + + +
+ +
+ + + + + + + + + + + + + + components.StopViewer.noStopsFound + + +
+
+
+
+
viewers > stop viewer should render times after midnight w + + +
+ +
+ + + + + + + + + + + + + + components.StopViewer.noStopsFound + + +
+
+
+
+
viewers > stop viewer should render with OTP transit index + + +
+ +
+ + + + + + + + + + + + + + components.StopViewer.noStopsFound + + +
+
+
+
+
viewers > stop viewer should render with TriMet transit in + + +
+ +
+ + + + + + + + + + + + + + components.StopViewer.noStopsFound + + +
+
+
+
+
+ + + + + ) + } + return (
- ) + if (this._isDateWithinRange(date)) { + contents = ( + + ) + } } else { contents = ( <> From ecefdba44d5b27abe14b0ca5bec8318a3295966e Mon Sep 17 00:00:00 2001 From: miles-grant-ibigroup Date: Thu, 12 Oct 2023 19:50:31 -0400 Subject: [PATCH 33/64] use brand colors in date-time-picker --- lib/components/form/date-time-button.tsx | 2 ++ lib/components/form/styled.ts | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/components/form/date-time-button.tsx b/lib/components/form/date-time-button.tsx index 3d6065c3e..3a0bdf1a7 100644 --- a/lib/components/form/date-time-button.tsx +++ b/lib/components/form/date-time-button.tsx @@ -25,8 +25,10 @@ const ButtonWrapper = styled.span` position: relative; & > button { + background-color: var(--main-base-color, white); border-radius: 5px; border: none; + color: var(--main-color, white); cursor: pointer; font-size: 12px; height: ${buttonPixels}px; diff --git a/lib/components/form/styled.ts b/lib/components/form/styled.ts index 28938a89c..1538bdc93 100644 --- a/lib/components/form/styled.ts +++ b/lib/components/form/styled.ts @@ -24,9 +24,10 @@ const commonButtonCss = css` user-select: none; &.active { - background-color: rgb(173, 216, 230); + background-color: var(--main-base-color, rgb(173, 216, 230)); border: 2px solid rgb(0, 0, 0); box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); + color: var(--main-color, black); font-weight: 600; } ` From 510c5add14ab4495a9f85b9110bfb3174b0969c1 Mon Sep 17 00:00:00 2001 From: miles-grant-ibigroup Date: Thu, 12 Oct 2023 20:23:16 -0400 Subject: [PATCH 34/64] correct default colors --- lib/components/form/date-time-button.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/components/form/date-time-button.tsx b/lib/components/form/date-time-button.tsx index 3a0bdf1a7..26d554322 100644 --- a/lib/components/form/date-time-button.tsx +++ b/lib/components/form/date-time-button.tsx @@ -25,7 +25,7 @@ const ButtonWrapper = styled.span` position: relative; & > button { - background-color: var(--main-base-color, white); + background-color: var(--main-base-color, rgba(0, 0, 0, 0.5)); border-radius: 5px; border: none; color: var(--main-color, white); From 6ac23111b01a8517414b7451ce4132bee1b93882 Mon Sep 17 00:00:00 2001 From: binh-dam-ibigroup <56846598+binh-dam-ibigroup@users.noreply.github.com> Date: Fri, 13 Oct 2023 09:24:10 -0400 Subject: [PATCH 35/64] chore(deps): Update @opentripplanner/trip-form to 3.3.4. --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index a57707877..e25487124 100644 --- a/package.json +++ b/package.json @@ -58,7 +58,7 @@ "@opentripplanner/transit-vehicle-overlay": "^4.0.6", "@opentripplanner/transitive-overlay": "^3.0.16", "@opentripplanner/trip-details": "^5.0.4", - "@opentripplanner/trip-form": "^3.3.3", + "@opentripplanner/trip-form": "^3.3.4", "@opentripplanner/trip-viewer-overlay": "^2.0.7", "@opentripplanner/vehicle-rental-overlay": "^2.1.3", "@styled-icons/fa-regular": "^10.34.0", diff --git a/yarn.lock b/yarn.lock index 2f581aacf..61aeaa722 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2561,10 +2561,10 @@ flat "^5.0.2" react-animate-height "^3.0.4" -"@opentripplanner/trip-form@^3.3.3": - version "3.3.3" - resolved "https://registry.yarnpkg.com/@opentripplanner/trip-form/-/trip-form-3.3.3.tgz#a7975eb219c7e23876e603132145365eedbb2638" - integrity sha512-frS1pdaOicVaGMenf25H12/Ne9KATHJ71ojLqvpSj1qA2MDHYXko07iymhgZ5kJw6wjdkRcIPQxc+rES9OZ3Sw== +"@opentripplanner/trip-form@^3.3.4": + version "3.3.4" + resolved "https://registry.yarnpkg.com/@opentripplanner/trip-form/-/trip-form-3.3.4.tgz#12847736515aa11e1c69c8db627a54c1ad5e7e89" + integrity sha512-adEjAJ+2ygkc6vptiD7tHI3O+1tEIvoDsM3+/DFIgvtKxkSKuRzzTNXn67CI2pmEev75aiiTyT97PiWbDKRTJw== dependencies: "@floating-ui/react" "^0.19.2" "@opentripplanner/core-utils" "^11.0.2" From caf24a02b5fbd00f059c07d33b90f5464cc4e02a Mon Sep 17 00:00:00 2001 From: miles-grant-ibigroup Date: Fri, 13 Oct 2023 09:46:33 -0400 Subject: [PATCH 36/64] correct default colors --- lib/components/form/styled.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/components/form/styled.ts b/lib/components/form/styled.ts index 1538bdc93..1067cfafa 100644 --- a/lib/components/form/styled.ts +++ b/lib/components/form/styled.ts @@ -27,7 +27,7 @@ const commonButtonCss = css` background-color: var(--main-base-color, rgb(173, 216, 230)); border: 2px solid rgb(0, 0, 0); box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); - color: var(--main-color, black); + color: var(--main-color, white); font-weight: 600; } ` From 8f8f7f52272ff77de108b3b07e40b6b80dfb30c4 Mon Sep 17 00:00:00 2001 From: binh-dam-ibigroup <56846598+binh-dam-ibigroup@users.noreply.github.com> Date: Fri, 13 Oct 2023 10:56:25 -0400 Subject: [PATCH 37/64] ci(dependabot): Attempt to use automerge with default GH token. --- .github/workflows/dependabot.yml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/.github/workflows/dependabot.yml b/.github/workflows/dependabot.yml index 77e770925..75176a3a1 100644 --- a/.github/workflows/dependabot.yml +++ b/.github/workflows/dependabot.yml @@ -12,10 +12,9 @@ jobs: pull-requests: write if: github.actor == 'dependabot[bot]' steps: - - uses: actions/checkout@v2 - name: Auto-approve PR uses: hmarr/auto-approve-action@v3 - name: Enable auto-merge - run: gh pr merge --merge --auto ${{ github.event.pull_request.number }} - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + uses: alexwilson/enable-github-automerge-action@main + with: + github-token: "${{ secrets.GITHUB_TOKEN }}" \ No newline at end of file From 5a58b4baf7e6b999bc647c95ece981da78423e33 Mon Sep 17 00:00:00 2001 From: binh-dam-ibigroup <56846598+binh-dam-ibigroup@users.noreply.github.com> Date: Fri, 13 Oct 2023 10:57:16 -0400 Subject: [PATCH 38/64] ci(dependabot): Update workflow comment [skip ci] --- .github/workflows/dependabot.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/dependabot.yml b/.github/workflows/dependabot.yml index 75176a3a1..3337f3acb 100644 --- a/.github/workflows/dependabot.yml +++ b/.github/workflows/dependabot.yml @@ -6,6 +6,7 @@ jobs: auto-approve-and-automerge: # sources: # https://github.com/hmarr/auto-approve-action + # https://github.com/marketplace/actions/enable-github-automerge # https://github.com/marketplace/actions/enable-pull-request-automerge#dependabot-example runs-on: ubuntu-latest permissions: From 7c5ca4ce4cffcafb03b8b9904af5e30abf464d32 Mon Sep 17 00:00:00 2001 From: gallegonovato Date: Sat, 23 Sep 2023 11:50:46 +0000 Subject: [PATCH 39/64] Translated using Weblate (Spanish) Currently translated at 100.0% (517 of 517 strings) Translation: OTP-react-redux/OTP-RR Main UI Translate-URL: https://hosted.weblate.org/projects/otp-react-redux/otp-rr-main-ui/es/ --- i18n/es.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/i18n/es.yml b/i18n/es.yml index 63e8913cd..abb769580 100644 --- a/i18n/es.yml +++ b/i18n/es.yml @@ -63,6 +63,8 @@ actions: smsVerificationFailed: >- Su teléfono no ha podido ser verificado. Quizás el código que has introducido ha caducado. Solicita un nuevo código e inténtalo de nuevo. + mustBeLoggedInToSavePlace: Por favor, inicia la sesión para guardar las ubicaciones. + placeRemembered: La configuración de este lugar se ha guardado. common: coordinates: "{lat}; {lon}" dateExpressions: From 00a0e2f8e066c4843387042848f3614cb04974c2 Mon Sep 17 00:00:00 2001 From: gallegonovato Date: Mon, 25 Sep 2023 20:04:54 +0000 Subject: [PATCH 40/64] Translated using Weblate (Spanish) Currently translated at 100.0% (516 of 516 strings) Translation: OTP-react-redux/OTP-RR Main UI Translate-URL: https://hosted.weblate.org/projects/otp-react-redux/otp-rr-main-ui/es/ --- i18n/es.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/i18n/es.yml b/i18n/es.yml index abb769580..4df1c29df 100644 --- a/i18n/es.yml +++ b/i18n/es.yml @@ -491,6 +491,7 @@ components: operatedBy: Servicio operado por {agencyName} selectADirection: Seleccione una dirección… stopsTo: Hacia + headsignTo: '{headsign} ({lastStop})' RouteViewer: agencyFilter: Filtro de agencia allAgencies: Todas las agencias From 18c6c4377f648d4e07bfde172314f10fbabaff5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mustafa=20Kemal=20S=C3=BCrmeneli?= Date: Fri, 13 Oct 2023 12:42:31 +0200 Subject: [PATCH 41/64] Added translation using Weblate (Turkish) --- i18n/tr.yml | 1 + 1 file changed, 1 insertion(+) create mode 100644 i18n/tr.yml diff --git a/i18n/tr.yml b/i18n/tr.yml new file mode 100644 index 000000000..0967ef424 --- /dev/null +++ b/i18n/tr.yml @@ -0,0 +1 @@ +{} From 64971785803103988c1e0364f0a398792d43593c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mustafa=20Kemal=20S=C3=BCrmeneli?= Date: Fri, 13 Oct 2023 11:23:34 +0000 Subject: [PATCH 42/64] Translated using Weblate (Turkish) Currently translated at 19.9% (103 of 516 strings) Translation: OTP-react-redux/OTP-RR Main UI Translate-URL: https://hosted.weblate.org/projects/otp-react-redux/otp-rr-main-ui/tr/ --- i18n/tr.yml | 136 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 135 insertions(+), 1 deletion(-) diff --git a/i18n/tr.yml b/i18n/tr.yml index 0967ef424..d3363dd05 100644 --- a/i18n/tr.yml +++ b/i18n/tr.yml @@ -1 +1,135 @@ -{} +_id: en-US +actions: + fieldTrip: + saveItinerariesError: 'Seyahat planları kaydedilemedi: {err}' + setDateError: 'Tarih ayarlanırken hata oluştu:' + fetchFieldTripError: '' + setGroupSizeError: 'Grup boyutu ayarlanırken hata oluştu:' + maxTripRequestsExceeded: Geçerli sonuçlar olmadan yolculuk isteklerinin sayısı + aşıldı + setPaymentError: 'Ödeme bilgileri ayarlanırken hata oluştu:' + setRequestStatusError: 'İstek durumu ayarlanırken hata oluştu:' + editSubmitterNotesError: 'Gönderenin notları düzenlenirken hata oluştu:' + user: + emailVerificationResent: E-posta doğrulama mesajı yeniden gönderildi. + genericError: 'Bir hata ile karşılaşıldı: {err}' + smsVerificationFailed: Telefonunuz doğrulanamadı. Girdiğiniz kodun süresi dolmuş + olabilir. Lütfen yeni bir kod isteyin ve tekrar deneyin. + authTokenError: Yetkilendirme anahtarı alınırken hata oluştu. + mustBeLoggedInToSavePlace: Konumları kaydetmek için lütfen giriş yapın. + itineraryExistenceCheckFailed: Seçtiğiniz seyahatin mümkün olup olmadığı kontrol + edilirken hata oluştu. + smsInvalidCode: Girdiğiniz kod geçersiz. Lütfen tekrar deneyin. + accountDeleted: Kullanıcı hesabınız ({email}) silindi. + preferencesSaved: Tercihleriniz kaydedilmiştir. + placeRemembered: Bu yerin ayarları kaydedildi. + confirmDeletePlace: Bu yeri kaldırmak ister misiniz? + smsResendThrottled: Belirtilen telefon numarasına bir dakikadan kısa süre önce + bir doğrulama SMS'i gönderildi. Lütfen birkaç dakika sonra tekrar deneyin. + location: + userDeniedPermission: Kullanıcı izni reddetti + deniedAccessAlert: "Konumunuza erişim engellendi.\nMevcut konumunuzu kullanmak + için tarayıcınızdan konum izinlerini etkinleştirin ve sayfayı yeniden yükleyin. + \n" + unknownPositionError: Konum alınırken bilinmeyen hata + geolocationNotSupportedError: Coğrafi konum tarayıcınız tarafından desteklenmiyor + callTaker: + fetchCallsError: 'Çağrılar alınırken hata oluştu: {err}' + queryFetchError: 'Sorgular alınırken hata oluştu: {err}' + map: + currentLocation: (Mevcut Konum) +common: + daysOfWeekPlural: + thursday: Perşembeler + tuesday: Salılar + saturday: Cumartesileri + friday: Cumalar + monday: Pazartesileri + wednesday: Çarşambalar + sunday: Pazarları + modes: + car: Araba + micromobility_rent: E-Skutır + subway: Metro + micromobility: E-Skutır + rent: Kiralama seçenekleri + walk: Yürümek + funicular: Füniküler + car_park: Park Et Devam Et + flex: Esnek Rotalar + ferry: Feribot + bike: Bisiklet + tram: Tramvay + gondola: Gondol + drive: Sürücü + cable_car: Teleferik + rail: Demiryolu + bus: Otobüs + bicycle_rent: Bisiklet paylaşımı + notifications: + email: eposta + push: bildirimler + sms: SMS + daysOfWeekCompact: + wednesday: Çar + thursday: Per + sunday: Paz + tuesday: Sal + saturday: Cmt + friday: Cum + monday: Pzt + itineraryDescriptions: + fareUnknown: Ücret bilgisi yok + forms: + "yes": Evet + print: Yazdır + "no": Hayır + finish: Bitiş + submitting: Gönderiliyor… + startOver: Baştan Başla + close: Kapat + edit: Düzenle + delete: Sil + save: Kaydet + cancel: İptal + back: Geri + error: hata! + next: Sonraki + defaultValue: '{value} (varsayılan)' + daysOfWeek: + sunday: Pazar + wednesday: Çarşamba + saturday: Cumartesi + friday: Cuma + monday: Pazartesi + tuesday: Salı + thursday: Perşembe + dateExpressions: + tomorrow: Yarın + yesterday: Dün + today: Bugün + coordinates: '{lat}, {lon}' + linkOpensNewWindow: (Yeni pencere açar) + places: + home: ev + dining: yemek + work: iş + searchForms: + click: tıkla + time: + duration: + aFewSeconds: birkaç saniye +components: + AddPlaceButton: + addPlace: Yer ekle + tooManyPlaces: Maksimum ara yerlere ulaşıldı + needOriginDestination: Ara yerler eklemek için başlangıç/bitiş noktasını tanımlayın + AfterSignInScreen: + mainTitle: Yönlendiriliyor... + A11yPrefs: + accessibilityRoutingByDefault: Varsayılan olarak erişilebilir seyahatleri tercih + et + AdvancedOptions: + preferredRoutes: Tercih edilen rotaları seçin... + bannedRoutes: Yasaklanan rotaları seç… +_name: İngilizce From 6f7b943245bedff010ab5518bfedb36810135fe4 Mon Sep 17 00:00:00 2001 From: binh-dam-ibigroup <56846598+binh-dam-ibigroup@users.noreply.github.com> Date: Tue, 17 Oct 2023 14:12:54 -0400 Subject: [PATCH 43/64] fix(mobile/location-search): Make location suggestions visible. --- lib/components/mobile/location-search.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/components/mobile/location-search.js b/lib/components/mobile/location-search.js index 2b7ca0390..b58b22536 100644 --- a/lib/components/mobile/location-search.js +++ b/lib/components/mobile/location-search.js @@ -1,7 +1,6 @@ import { connect } from 'react-redux' import { injectIntl } from 'react-intl' import { - MenuItemA, MenuItemLi, MenuItemList } from '@opentripplanner/location-field/lib/styled' @@ -20,7 +19,7 @@ const MobileLocationField = styled(LocationField)` ${MenuItemList} { width: 100%; } - ${MenuItemA}, ${MenuItemLi} { + ${MenuItemLi} { overflow: hidden; padding-left: 5px; padding-right: 5px; From 21306af043212b639927efcbce09a1443123a3e8 Mon Sep 17 00:00:00 2001 From: binh-dam-ibigroup <56846598+binh-dam-ibigroup@users.noreply.github.com> Date: Tue, 17 Oct 2023 14:39:30 -0400 Subject: [PATCH 44/64] fix: Remove unneeded word wrap for itin times. --- .../narrative/line-itin/connected-itinerary-body.js | 6 +++++- lib/components/narrative/metro/metro-itinerary.tsx | 1 - 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/components/narrative/line-itin/connected-itinerary-body.js b/lib/components/narrative/line-itin/connected-itinerary-body.js index 81cdb475a..12c51897a 100644 --- a/lib/components/narrative/line-itin/connected-itinerary-body.js +++ b/lib/components/narrative/line-itin/connected-itinerary-body.js @@ -5,7 +5,8 @@ import { LegDescriptionHeadsignPrefix, PlaceName as PlaceNameWrapper, PlaceRowWrapper, - PlaceSubheader + PlaceSubheader, + TimeColumn } from '@opentripplanner/itinerary-body/lib/styled' import { PlaceName } from '@opentripplanner/itinerary-body/lib/otp-react-redux' import clone from 'clone' @@ -53,6 +54,9 @@ const StyledItineraryBody = styled(ItineraryBody)` ${PlaceRowWrapper} { max-width: inherit; } + ${TimeColumn} { + white-space: nowrap; + } ` class ConnectedItineraryBody extends Component { diff --git a/lib/components/narrative/metro/metro-itinerary.tsx b/lib/components/narrative/metro/metro-itinerary.tsx index cbd0f7194..6eff07f40 100644 --- a/lib/components/narrative/metro/metro-itinerary.tsx +++ b/lib/components/narrative/metro/metro-itinerary.tsx @@ -75,7 +75,6 @@ const ItineraryDetails = styled.ul` margin: 0; overflow: hidden; padding: 0; - width: 90%; ` const PrimaryInfo = styled.li` color: #000000cc; From 353fe4efa0e5f7d515a602a5914eed14ed469512 Mon Sep 17 00:00:00 2001 From: binh-dam-ibigroup <56846598+binh-dam-ibigroup@users.noreply.github.com> Date: Tue, 17 Oct 2023 16:58:11 -0400 Subject: [PATCH 45/64] fix(trip-tools): Localize header. --- i18n/en-US.yml | 1 + i18n/es.yml | 7 ++++--- i18n/fr.yml | 1 + i18n/ko.yml | 1 + i18n/vi.yml | 1 + i18n/zh.yml | 1 + lib/components/narrative/trip-tools.js | 9 ++++----- 7 files changed, 13 insertions(+), 8 deletions(-) diff --git a/i18n/en-US.yml b/i18n/en-US.yml index 32c9b46f1..eafbba0db 100644 --- a/i18n/en-US.yml +++ b/i18n/en-US.yml @@ -677,6 +677,7 @@ components: notificationsDisabled: "Notifications: Disabled" TripTools: copyLink: Copy Link + header: Trip Tools linkCopied: Copied reportEmailSubject: Reporting an Issue with OpenTripPlanner reportEmailTemplate: > diff --git a/i18n/es.yml b/i18n/es.yml index 4df1c29df..0cce495b2 100644 --- a/i18n/es.yml +++ b/i18n/es.yml @@ -55,6 +55,8 @@ actions: emailVerificationResent: El mensaje de verificación de correo electrónico ha sido reenviado. genericError: "Se ha encontrado un error: {err}" itineraryExistenceCheckFailed: Comprobación de errores para ver si el viaje seleccionado es posible. + mustBeLoggedInToSavePlace: Por favor, inicia la sesión para guardar las ubicaciones. + placeRemembered: La configuración de este lugar se ha guardado. preferencesSaved: Sus preferencias se han guardado. smsInvalidCode: El código introducido no es válido. Por favor, inténtelo de nuevo. smsResendThrottled: >- @@ -63,8 +65,6 @@ actions: smsVerificationFailed: >- Su teléfono no ha podido ser verificado. Quizás el código que has introducido ha caducado. Solicita un nuevo código e inténtalo de nuevo. - mustBeLoggedInToSavePlace: Por favor, inicia la sesión para guardar las ubicaciones. - placeRemembered: La configuración de este lugar se ha guardado. common: coordinates: "{lat}; {lon}" dateExpressions: @@ -487,11 +487,11 @@ components: tripsFound: Encontramos {count, plural, one {# opción} other {# opciones}} waiting: Espera... RouteDetails: + headsignTo: "{headsign} ({lastStop})" moreDetails: Más detalles operatedBy: Servicio operado por {agencyName} selectADirection: Seleccione una dirección… stopsTo: Hacia - headsignTo: '{headsign} ({lastStop})' RouteViewer: agencyFilter: Filtro de agencia allAgencies: Todas las agencias @@ -703,6 +703,7 @@ components: notificationsDisabled: "Notificaciones: Disabled" TripTools: copyLink: Copiar enlace + header: Herramientas linkCopied: Copiado reportEmailSubject: Informar un problema con OpenTripPlanner reportEmailTemplate: > diff --git a/i18n/fr.yml b/i18n/fr.yml index 6e7c7d6ba..1ef6fd89a 100644 --- a/i18n/fr.yml +++ b/i18n/fr.yml @@ -703,6 +703,7 @@ components: notificationsDisabled: "Notifications : Désactivées" TripTools: copyLink: Copier le lien + header: Outils linkCopied: Copié reportEmailSubject: Signaler un problème avec OpenTripPlanner reportEmailTemplate: > diff --git a/i18n/ko.yml b/i18n/ko.yml index c36644127..e04f7e8f2 100644 --- a/i18n/ko.yml +++ b/i18n/ko.yml @@ -561,6 +561,7 @@ components: notificationsDisabled: "알림: 비활성화됨" TripTools: copyLink: 링크 복사 + header: 도구 linkCopied: 복사됨 reportEmailSubject: OpenTripPlanner로 문제 보고 reportEmailTemplate: | diff --git a/i18n/vi.yml b/i18n/vi.yml index e31f08271..471a3e7cb 100644 --- a/i18n/vi.yml +++ b/i18n/vi.yml @@ -602,6 +602,7 @@ components: notificationsDisabled: "Thông báo: Đã tắt" TripTools: copyLink: Sao chép URL + header: Công cụ linkCopied: Đã sao chép reportEmailSubject: Báo cáo sự cố với OpenTripPlanner reportEmailTemplate: | diff --git a/i18n/zh.yml b/i18n/zh.yml index 021e91a97..99ec4cacb 100644 --- a/i18n/zh.yml +++ b/i18n/zh.yml @@ -559,6 +559,7 @@ components: notificationsDisabled: "通知: 已禁用" TripTools: copyLink: 复制链接 + header: 工具 linkCopied: 已复制 reportEmailSubject: 报告OpenTripPlanner的问题 reportEmailTemplate: | diff --git a/lib/components/narrative/trip-tools.js b/lib/components/narrative/trip-tools.js index 449e63f3c..ecd3518bc 100644 --- a/lib/components/narrative/trip-tools.js +++ b/lib/components/narrative/trip-tools.js @@ -185,7 +185,6 @@ LinkButton.propTypes = { const TripTools = ({ buttonTypes, - intl, location, popupTarget, reactRouterConfig, @@ -224,7 +223,6 @@ const TripTools = ({ location?.search ) buttonComponents.push( - // FIXME: The Spanish string does not fit in button width. } @@ -250,7 +248,9 @@ const TripTools = ({ return (
-

Trip Tools

+

+ +

{buttonComponents.map((btn, i) => (
@@ -264,7 +264,6 @@ const TripTools = ({ TripTools.propTypes = { buttonTypes: PropTypes.arrayOf(PropTypes.string), - intl: PropTypes.object, location: PropTypes.object, popupTarget: PropTypes.string, reactRouterConfig: PropTypes.object, @@ -290,5 +289,5 @@ const mapDispatchToProps = { } export default withRouter( - connect(mapStateToProps, mapDispatchToProps)(injectIntl(TripTools)) + connect(mapStateToProps, mapDispatchToProps)(TripTools) ) From b3d1313325fefa5bcf3d690df2eb15d1560800ab Mon Sep 17 00:00:00 2001 From: binh-dam-ibigroup <56846598+binh-dam-ibigroup@users.noreply.github.com> Date: Wed, 18 Oct 2023 11:19:23 -0400 Subject: [PATCH 46/64] fix(i18n): Correctly load OTP-UI's Chinese (simplified) files. --- lib/util/i18n.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/util/i18n.js b/lib/util/i18n.js index 9dfe53126..deb7c88e6 100644 --- a/lib/util/i18n.js +++ b/lib/util/i18n.js @@ -117,6 +117,7 @@ async function loadOtpUiLocaleData(matchedLocale) { */ export async function loadLocaleData(matchedLocale, customMessages) { let messages + let otpUiLocale = matchedLocale switch (matchedLocale) { case 'es': // Spanish translation is not specific to a region messages = await import('../../i18n/es.yml') @@ -130,15 +131,18 @@ export async function loadLocaleData(matchedLocale, customMessages) { case 'vi': // Vietnamese translation is not specific to a region messages = await import('../../i18n/vi.yml') break - case 'zh': // Chinese translation is not specific to a region + case 'zh': // Chinese (Simplified) translation is not specific to a region messages = await import('../../i18n/zh.yml') + // The OTP-UI files for Chinese (Simplified) are (correclty) named `zh_Hans`. + // TODO: Rename this repo's zh files to zh_Hans + otpUiLocale = 'zh_Hans' break default: messages = await import('../../i18n/en-US.yml') break } - const otpUiMessages = await loadOtpUiLocaleData(matchedLocale) + const otpUiMessages = await loadOtpUiLocaleData(otpUiLocale) // Merge custom strings into the standard language strings. const mergedMessages = { From bae420f9851c321948f7c4b01a6f7dbeaefaf311 Mon Sep 17 00:00:00 2001 From: binh-dam-ibigroup <56846598+binh-dam-ibigroup@users.noreply.github.com> Date: Wed, 18 Oct 2023 11:23:55 -0400 Subject: [PATCH 47/64] docs(i18n): Fix comment typo. --- lib/util/i18n.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/util/i18n.js b/lib/util/i18n.js index deb7c88e6..2674a781e 100644 --- a/lib/util/i18n.js +++ b/lib/util/i18n.js @@ -133,7 +133,7 @@ export async function loadLocaleData(matchedLocale, customMessages) { break case 'zh': // Chinese (Simplified) translation is not specific to a region messages = await import('../../i18n/zh.yml') - // The OTP-UI files for Chinese (Simplified) are (correclty) named `zh_Hans`. + // The OTP-UI files for Chinese (Simplified) are (correctly) named `zh_Hans`. // TODO: Rename this repo's zh files to zh_Hans otpUiLocale = 'zh_Hans' break From 150bc857b32a55e8be5370140e884049ea76d50f Mon Sep 17 00:00:00 2001 From: binh-dam-ibigroup <56846598+binh-dam-ibigroup@users.noreply.github.com> Date: Thu, 19 Oct 2023 11:30:40 -0400 Subject: [PATCH 48/64] fix(nav-login-button-auth0): Request the correct Chinese language variant to Auth0. --- lib/components/user/nav-login-button-auth0.tsx | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/components/user/nav-login-button-auth0.tsx b/lib/components/user/nav-login-button-auth0.tsx index cdc60bf44..e4a44bf14 100644 --- a/lib/components/user/nav-login-button-auth0.tsx +++ b/lib/components/user/nav-login-button-auth0.tsx @@ -28,14 +28,18 @@ const NavLoginButtonAuth0 = ({ }: NavLoginButtonAuth0Props): JSX.Element => { const { isAuthenticated, loginWithRedirect, logout, user } = useAuth0() + // For Chinese (Chinese (Simplified)), we must pass 'zh-CN' to auth0. + // Unlike 'fr', 'zh' alone is not recognized and falls back to English. + const auth0Locale = locale === 'zh' ? 'zh-CN' : locale + // On login, preserve the current trip query if any. const handleLogin = useCallback( () => loginWithRedirect({ appState: { returnTo: getCurrentRoute() }, - ui_locales: locale + ui_locales: auth0Locale }), - [locale, loginWithRedirect] + [auth0Locale, loginWithRedirect] ) const handleLogout = useCallback( () => From 64b4c72e4cf52c68bf3cfbf7fa95d1379169e516 Mon Sep 17 00:00:00 2001 From: binh-dam-ibigroup <56846598+binh-dam-ibigroup@users.noreply.github.com> Date: Thu, 19 Oct 2023 13:59:15 -0400 Subject: [PATCH 49/64] refactor(app): Prevent call history from appearing if datastore is not configured. --- lib/app.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/app.js b/lib/app.js index b56facafa..fda84a81f 100644 --- a/lib/app.js +++ b/lib/app.js @@ -175,6 +175,8 @@ const components = { MainPanel: BatchRoutingPanel, + MapWindows: isCallTakerModuleEnabled ? jsConfig.MapWindows : null, + MobileResultsScreen: BatchResultsScreen, MobileSearchScreen: BatchSearchScreen, From 0c42746563a1417034dd86a4799ef0e0a057fc31 Mon Sep 17 00:00:00 2001 From: Binh Dam Date: Fri, 20 Oct 2023 14:15:32 +0000 Subject: [PATCH 50/64] Translated using Weblate (Spanish) Currently translated at 100.0% (517 of 517 strings) Translation: OTP-react-redux/OTP-RR Main UI Translate-URL: https://hosted.weblate.org/projects/otp-react-redux/otp-rr-main-ui/es/ --- i18n/es.yml | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/i18n/es.yml b/i18n/es.yml index 0cce495b2..be9f8314a 100644 --- a/i18n/es.yml +++ b/i18n/es.yml @@ -30,7 +30,8 @@ actions: No se puede guardar el plan: este plan no se pudo guardar debido a la falta de capacidad en uno o más vehículos. Por favor, vuelva a planificar su viaje. - maxTripRequestsExceeded: Número de solicitudes de viaje superadas sin resultados válidos + maxTripRequestsExceeded: Número de solicitudes de viaje superadas sin resultados + válidos saveItinerariesError: "No se pudieron guardar los itinerarios: {err}" setDateError: "Error al establecer la fecha:" setGroupSizeError: "No se pudo establecer el tamaño del grupo:" @@ -52,9 +53,11 @@ actions: authTokenError: Error al obtener un token de autorización. confirmDeleteMonitoredTrip: ¿Desea eliminar este viaje? confirmDeletePlace: ¿Quiere eliminar este lugar? - emailVerificationResent: El mensaje de verificación de correo electrónico ha sido reenviado. + emailVerificationResent: El mensaje de verificación de correo electrónico ha sido + reenviado. genericError: "Se ha encontrado un error: {err}" - itineraryExistenceCheckFailed: Comprobación de errores para ver si el viaje seleccionado es posible. + itineraryExistenceCheckFailed: Comprobación de errores para ver si el viaje seleccionado + es posible. mustBeLoggedInToSavePlace: Por favor, inicia la sesión para guardar las ubicaciones. placeRemembered: La configuración de este lugar se ha guardado. preferencesSaved: Sus preferencias se han guardado. @@ -245,7 +248,8 @@ components: a incluir el transporte publico en la selección de modos. origin: origen planTripTooltip: Planificar viaje - validationMessage: "Por favor, defina los siguientes campos para planificar un viaje: {issues}" + validationMessage: "Por favor, defina los siguientes campos para planificar un + viaje: {issues}" BeforeSignInScreen: mainTitle: Iniciando sesión message: > @@ -547,7 +551,8 @@ components: header: ¡La sesión está a punto de terminar! keepSession: Continuar sesión SimpleRealtimeAnnotation: - usingRealtimeInfo: Este viaje utiliza información de tráfico y retrasos en tiempo real + usingRealtimeInfo: Este viaje utiliza información de tráfico y retrasos en tiempo + real StackedPaneDisplay: savePreferences: Guardar preferencias StopScheduleTable: @@ -610,16 +615,19 @@ components: travelingAt: Viajando a {milesPerHour} vehicleName: Vehículo {vehicleNumber} TripBasicsPane: - checkingItineraryExistence: Comprobación de la existencia de itinerarios para cada día de la semana… + checkingItineraryExistence: Comprobación de la existencia de itinerarios para + cada día de la semana… selectAtLeastOneDay: Por favor, seleccione al menos un día para el seguimiento. tripDaysPrompt: ¿Qué días hace este viaje? - tripIsAvailableOnDaysIndicated: Su viaje está disponible en los días de la semana indicados anteriormente. + tripIsAvailableOnDaysIndicated: Su viaje está disponible en los días de la semana + indicados anteriormente. tripNamePrompt: "Por favor, indique un nombre para este viaje:" tripNotAvailableOnDay: El viaje no está disponible el {repeatedDay} unsavedChangesExistingTrip: >- Todavía no ha guardado su viaje. Si abandona la página, los cambios se perderán. - unsavedChangesNewTrip: Todavía no ha guardado su nuevo viaje. Si abandona la página, se perderá. + unsavedChangesNewTrip: Todavía no ha guardado su nuevo viaje. Si abandona la página, + se perderá. TripNotificationsPane: advancedSettings: Configuración avanzada altRouteRecommended: Se recomienda una ruta alternativa o un punto de transferencia @@ -700,7 +708,7 @@ components: notifications: >- Notificaciones: {leadTimeInMinutes} minutos antes de la salida programada - notificationsDisabled: "Notificaciones: Disabled" + notificationsDisabled: "Notificaciones: Desactivadas" TripTools: copyLink: Copiar enlace header: Herramientas From 1e216b84f4d11dcea4c595aa0e826f6265467f39 Mon Sep 17 00:00:00 2001 From: Binh Dam Date: Fri, 20 Oct 2023 14:16:54 +0000 Subject: [PATCH 51/64] Translated using Weblate (Korean) Currently translated at 83.7% (433 of 517 strings) Translation: OTP-react-redux/OTP-RR Main UI Translate-URL: https://hosted.weblate.org/projects/otp-react-redux/otp-rr-main-ui/ko/ --- i18n/ko.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/i18n/ko.yml b/i18n/ko.yml index e04f7e8f2..53bfc40c3 100644 --- a/i18n/ko.yml +++ b/i18n/ko.yml @@ -22,7 +22,8 @@ actions: fetchFieldTripsError: "트립을 가져오는 중에 오류가 발생했습니다: {err}" fetchTripsForDateError: "필트 트립 날짜에 대한 트립을 가져오는 중에 오류가 발생했습니다: {err}" incompatibleTripDateError: 계획한 트립 날짜({tripDate})가 요청한 트립 날짜({requestDate})가 아닙니다 - itineraryCapacityError: "플랜을 저장할 수 없습니다: 하나 이상의 차량의 용량이 부족하여 이 플랜을 저장할 수 없습니다. 트립을 다시 계획하세요." + itineraryCapacityError: "플랜을 저장할 수 없습니다: 하나 이상의 차량의 용량이 부족하여 이 플랜을 저장할 수 없습니다. + 트립을 다시 계획하세요." maxTripRequestsExceeded: 유효한 결과없이 초과된 트립 요청의 개수 saveItinerariesError: "트립을 저장하는 데 실패했습니다: {err}" setDateError: "날짜를 설정하는 중에 오류가 발생했습니다:" @@ -504,6 +505,7 @@ components: notifyViaChannelWhen: "다음의 경우, {channel}을 통해 알려주세요:" oneHour: 1 시간 realtimeAlertFlagged: 내 트립 일정에 실시간 경고가 있습니다 + timeBefore: '{time} 전' TripStatus: alerts: "{alerts, plural, one {# 경고!} other {# 경고!}}" deleteTrip: 트립 삭제 @@ -641,5 +643,6 @@ util: networkUnavailable: 현재 {network} 네트워크를 사용할 수 없습니다. noTripFound: 트립을 찾을 수 없습니다. noTripFoundForMode: "{modes}의 트립을 찾을 수 없습니다." - noTripFoundReason: 지정된 최대 거리 내 또는 지정된 시간에 대중 교통 서비스가 없거나, 출발지 또는 도착지가 안전하게 접근가능하지 못할 수 있습니다. + noTripFoundReason: 지정된 최대 거리 내 또는 지정된 시간에 대중 교통 서비스가 없거나, 출발지 또는 도착지가 안전하게 접근가능하지 + 못할 수 있습니다. noTripFoundWithReason: "{noTripFound} {reason}" From a1069ea3593344110261b17373fa789b8c86f3dc Mon Sep 17 00:00:00 2001 From: Binh Dam Date: Fri, 20 Oct 2023 14:16:16 +0000 Subject: [PATCH 52/64] Translated using Weblate (Chinese (Simplified)) Currently translated at 84.5% (437 of 517 strings) Translation: OTP-react-redux/OTP-RR Main UI Translate-URL: https://hosted.weblate.org/projects/otp-react-redux/otp-rr-main-ui/zh_Hans/ --- i18n/zh.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/i18n/zh.yml b/i18n/zh.yml index 99ec4cacb..d487fa672 100644 --- a/i18n/zh.yml +++ b/i18n/zh.yml @@ -502,6 +502,7 @@ components: notifyViaChannelWhen: "通过 {channel} 通知我当:" oneHour: 1小时 realtimeAlertFlagged: 在我的行程中有一个实时警报标志着 + timeBefore: '{time} 前' TripStatus: alerts: "{alerts, plural, one {# 警报!} other {# 警报!}}" deleteTrip: 删除行程 From acafa1c3ba9b0625fa7a659199c70afeee588e2b Mon Sep 17 00:00:00 2001 From: binh-dam-ibigroup <56846598+binh-dam-ibigroup@users.noreply.github.com> Date: Thu, 19 Oct 2023 11:30:40 -0400 Subject: [PATCH 53/64] fix(nav-login-button-auth0): Request the correct Chinese language variant to Auth0. --- lib/components/user/nav-login-button-auth0.tsx | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/components/user/nav-login-button-auth0.tsx b/lib/components/user/nav-login-button-auth0.tsx index cdc60bf44..e4a44bf14 100644 --- a/lib/components/user/nav-login-button-auth0.tsx +++ b/lib/components/user/nav-login-button-auth0.tsx @@ -28,14 +28,18 @@ const NavLoginButtonAuth0 = ({ }: NavLoginButtonAuth0Props): JSX.Element => { const { isAuthenticated, loginWithRedirect, logout, user } = useAuth0() + // For Chinese (Chinese (Simplified)), we must pass 'zh-CN' to auth0. + // Unlike 'fr', 'zh' alone is not recognized and falls back to English. + const auth0Locale = locale === 'zh' ? 'zh-CN' : locale + // On login, preserve the current trip query if any. const handleLogin = useCallback( () => loginWithRedirect({ appState: { returnTo: getCurrentRoute() }, - ui_locales: locale + ui_locales: auth0Locale }), - [locale, loginWithRedirect] + [auth0Locale, loginWithRedirect] ) const handleLogout = useCallback( () => From 7e965328d1511b7cc76c83c5ac81d22e6d3f57b0 Mon Sep 17 00:00:00 2001 From: binh-dam-ibigroup <56846598+binh-dam-ibigroup@users.noreply.github.com> Date: Tue, 17 Oct 2023 16:58:11 -0400 Subject: [PATCH 54/64] fix(trip-tools): Localize header. --- i18n/en-US.yml | 1 + i18n/es.yml | 7 ++++--- i18n/fr.yml | 1 + i18n/ko.yml | 1 + i18n/vi.yml | 1 + i18n/zh.yml | 1 + lib/components/narrative/trip-tools.js | 9 ++++----- 7 files changed, 13 insertions(+), 8 deletions(-) diff --git a/i18n/en-US.yml b/i18n/en-US.yml index 32c9b46f1..eafbba0db 100644 --- a/i18n/en-US.yml +++ b/i18n/en-US.yml @@ -677,6 +677,7 @@ components: notificationsDisabled: "Notifications: Disabled" TripTools: copyLink: Copy Link + header: Trip Tools linkCopied: Copied reportEmailSubject: Reporting an Issue with OpenTripPlanner reportEmailTemplate: > diff --git a/i18n/es.yml b/i18n/es.yml index 4df1c29df..0cce495b2 100644 --- a/i18n/es.yml +++ b/i18n/es.yml @@ -55,6 +55,8 @@ actions: emailVerificationResent: El mensaje de verificación de correo electrónico ha sido reenviado. genericError: "Se ha encontrado un error: {err}" itineraryExistenceCheckFailed: Comprobación de errores para ver si el viaje seleccionado es posible. + mustBeLoggedInToSavePlace: Por favor, inicia la sesión para guardar las ubicaciones. + placeRemembered: La configuración de este lugar se ha guardado. preferencesSaved: Sus preferencias se han guardado. smsInvalidCode: El código introducido no es válido. Por favor, inténtelo de nuevo. smsResendThrottled: >- @@ -63,8 +65,6 @@ actions: smsVerificationFailed: >- Su teléfono no ha podido ser verificado. Quizás el código que has introducido ha caducado. Solicita un nuevo código e inténtalo de nuevo. - mustBeLoggedInToSavePlace: Por favor, inicia la sesión para guardar las ubicaciones. - placeRemembered: La configuración de este lugar se ha guardado. common: coordinates: "{lat}; {lon}" dateExpressions: @@ -487,11 +487,11 @@ components: tripsFound: Encontramos {count, plural, one {# opción} other {# opciones}} waiting: Espera... RouteDetails: + headsignTo: "{headsign} ({lastStop})" moreDetails: Más detalles operatedBy: Servicio operado por {agencyName} selectADirection: Seleccione una dirección… stopsTo: Hacia - headsignTo: '{headsign} ({lastStop})' RouteViewer: agencyFilter: Filtro de agencia allAgencies: Todas las agencias @@ -703,6 +703,7 @@ components: notificationsDisabled: "Notificaciones: Disabled" TripTools: copyLink: Copiar enlace + header: Herramientas linkCopied: Copiado reportEmailSubject: Informar un problema con OpenTripPlanner reportEmailTemplate: > diff --git a/i18n/fr.yml b/i18n/fr.yml index 6e7c7d6ba..1ef6fd89a 100644 --- a/i18n/fr.yml +++ b/i18n/fr.yml @@ -703,6 +703,7 @@ components: notificationsDisabled: "Notifications : Désactivées" TripTools: copyLink: Copier le lien + header: Outils linkCopied: Copié reportEmailSubject: Signaler un problème avec OpenTripPlanner reportEmailTemplate: > diff --git a/i18n/ko.yml b/i18n/ko.yml index c36644127..e04f7e8f2 100644 --- a/i18n/ko.yml +++ b/i18n/ko.yml @@ -561,6 +561,7 @@ components: notificationsDisabled: "알림: 비활성화됨" TripTools: copyLink: 링크 복사 + header: 도구 linkCopied: 복사됨 reportEmailSubject: OpenTripPlanner로 문제 보고 reportEmailTemplate: | diff --git a/i18n/vi.yml b/i18n/vi.yml index e31f08271..471a3e7cb 100644 --- a/i18n/vi.yml +++ b/i18n/vi.yml @@ -602,6 +602,7 @@ components: notificationsDisabled: "Thông báo: Đã tắt" TripTools: copyLink: Sao chép URL + header: Công cụ linkCopied: Đã sao chép reportEmailSubject: Báo cáo sự cố với OpenTripPlanner reportEmailTemplate: | diff --git a/i18n/zh.yml b/i18n/zh.yml index 021e91a97..99ec4cacb 100644 --- a/i18n/zh.yml +++ b/i18n/zh.yml @@ -559,6 +559,7 @@ components: notificationsDisabled: "通知: 已禁用" TripTools: copyLink: 复制链接 + header: 工具 linkCopied: 已复制 reportEmailSubject: 报告OpenTripPlanner的问题 reportEmailTemplate: | diff --git a/lib/components/narrative/trip-tools.js b/lib/components/narrative/trip-tools.js index 449e63f3c..ecd3518bc 100644 --- a/lib/components/narrative/trip-tools.js +++ b/lib/components/narrative/trip-tools.js @@ -185,7 +185,6 @@ LinkButton.propTypes = { const TripTools = ({ buttonTypes, - intl, location, popupTarget, reactRouterConfig, @@ -224,7 +223,6 @@ const TripTools = ({ location?.search ) buttonComponents.push( - // FIXME: The Spanish string does not fit in button width. } @@ -250,7 +248,9 @@ const TripTools = ({ return (
-

Trip Tools

+

+ +

{buttonComponents.map((btn, i) => (
@@ -264,7 +264,6 @@ const TripTools = ({ TripTools.propTypes = { buttonTypes: PropTypes.arrayOf(PropTypes.string), - intl: PropTypes.object, location: PropTypes.object, popupTarget: PropTypes.string, reactRouterConfig: PropTypes.object, @@ -290,5 +289,5 @@ const mapDispatchToProps = { } export default withRouter( - connect(mapStateToProps, mapDispatchToProps)(injectIntl(TripTools)) + connect(mapStateToProps, mapDispatchToProps)(TripTools) ) From dde52e43e118aac7c9ae46bf99b7a78e1819d388 Mon Sep 17 00:00:00 2001 From: binh-dam-ibigroup <56846598+binh-dam-ibigroup@users.noreply.github.com> Date: Fri, 22 Sep 2023 15:28:35 -0400 Subject: [PATCH 55/64] perf(state): Don't include calltaker state or reducer if not config-enabled. --- lib/reducers/call-taker.js | 14 ++++++++++---- lib/util/state.js | 4 ++-- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/lib/reducers/call-taker.js b/lib/reducers/call-taker.js index 202bc22c0..9953484ef 100644 --- a/lib/reducers/call-taker.js +++ b/lib/reducers/call-taker.js @@ -6,11 +6,17 @@ import { FETCH_STATUS } from '../util/constants' import { getISOLikeTimestamp } from '../util/state' import { getModuleConfig, Modules } from '../util/config' +function getCalltakerConfig(config) { + return getModuleConfig({ otp: { config } }, Modules.CALL_TAKER) +} + function createCallTakerReducer(config) { - const calltakerConfig = getModuleConfig( - { otp: { config } }, - Modules.CALL_TAKER - ) + const calltakerConfig = getCalltakerConfig(config) + if (!calltakerConfig) { + // Don't include the calltaker reducer at all if calltaker is not enabled in config. + return undefined + } + const initialState = { activeCall: null, callHistory: { diff --git a/lib/util/state.js b/lib/util/state.js index c25b0b615..dee8fd604 100644 --- a/lib/util/state.js +++ b/lib/util/state.js @@ -245,8 +245,8 @@ function getActiveSearchRealtimeResponse(state) { * https://decembersoft.com/posts/error-selector-creators-expect-all-input-selectors-to-be-functions/ */ export const getActiveFieldTripRequest = createSelector( - (state) => state.callTaker?.fieldTrip.activeId, - (state) => state.callTaker?.fieldTrip.requests, + (state) => state.callTaker?.fieldTrip?.activeId, + (state) => state.callTaker?.fieldTrip?.requests, (activeId, requests) => { if (!activeId || !requests) return return requests.data.find((req) => req.id === activeId) From 6301c915dee4cae040281ade39c29fe937e0138c Mon Sep 17 00:00:00 2001 From: binh-dam-ibigroup <56846598+binh-dam-ibigroup@users.noreply.github.com> Date: Fri, 22 Sep 2023 16:03:30 -0400 Subject: [PATCH 56/64] refactor(app): Remove unneeded calltaker config. --- lib/app.js | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/lib/app.js b/lib/app.js index 4ea733227..b56facafa 100644 --- a/lib/app.js +++ b/lib/app.js @@ -21,12 +21,7 @@ import { BatchResultsScreen, BatchRoutingPanel, BatchSearchScreen, - CallHistoryWindow, - CallTakerControls, - CallTakerPanel, DefaultItinerary, - FieldTripWindows, - MailablesWindow, ResponsiveWebapp } from './index' @@ -178,17 +173,7 @@ const components = { ItineraryBody: DefaultItinerary, - MainControls: isCallTakerModuleEnabled ? CallTakerControls : null, - - MainPanel: isCallTakerModuleEnabled ? CallTakerPanel : BatchRoutingPanel, - - MapWindows: isCallTakerModuleEnabled ? ( - <> - - - - - ) : null, + MainPanel: BatchRoutingPanel, MobileResultsScreen: BatchResultsScreen, From face9d645fe96b4cf7fb6d9d99cdb76a03066a32 Mon Sep 17 00:00:00 2001 From: binh-dam-ibigroup <56846598+binh-dam-ibigroup@users.noreply.github.com> Date: Fri, 22 Sep 2023 16:32:03 -0400 Subject: [PATCH 57/64] perf(index): Remove calltaker components from index --- lib/index.js | 12 ------------ percy/har-mock-config-call-taker.js | 10 ++++++---- 2 files changed, 6 insertions(+), 16 deletions(-) diff --git a/lib/index.js b/lib/index.js index 9b8180f8a..f7d142a80 100644 --- a/lib/index.js +++ b/lib/index.js @@ -1,9 +1,5 @@ /* eslint-disable prettier/prettier */ /* eslint-disable sort-imports-es6-autofix/sort-imports-es6 */ -import CallTakerControls from './components/admin/call-taker-controls' -import CallHistoryWindow from './components/admin/call-history-window' -import FieldTripWindows from './components/admin/field-trip-windows' -import MailablesWindow from './components/admin/mailables-window' import DateTimeModal from './components/form/date-time-modal' import DateTimePreview from './components/form/date-time-preview' import ErrorMessage from './components/form/error-message' @@ -29,7 +25,6 @@ import ViewStopButton from './components/viewers/view-stop-button' import ViewerContainer from './components/viewers/viewer-container' import ResponsiveWebapp from './components/app/responsive-webapp' import AppMenu from './components/app/app-menu' -import CallTakerPanel from './components/app/call-taker-panel' import DesktopNav from './components/app/desktop-nav' import BatchRoutingPanel from './components/app/batch-routing-panel' import BatchResultsScreen from './components/mobile/batch-results-screen' @@ -50,12 +45,6 @@ const MobileResultsScreen = BatchResultsScreen const MobileSearchScreen = BatchSearchScreen export { - // module components - CallHistoryWindow, - CallTakerControls, - FieldTripWindows, - MailablesWindow, - // form components DateTimeModal, DateTimePreview, @@ -96,7 +85,6 @@ export { // app components, ResponsiveWebapp, AppMenu, - CallTakerPanel, DesktopNav, // batch routing components diff --git a/percy/har-mock-config-call-taker.js b/percy/har-mock-config-call-taker.js index f1e892114..31cd154f1 100644 --- a/percy/har-mock-config-call-taker.js +++ b/percy/har-mock-config-call-taker.js @@ -14,14 +14,16 @@ import React from 'react' import { BatchResultsScreen, BatchSearchScreen, - CallHistoryWindow, - CallTakerPanel, - FieldTripWindows, - MailablesWindow, MetroItinerary // Webpack sets this file to run from a subdirectory within otp-react-redux // ../lib points to the index file of otp-react-redux's source code } from '../lib' +import { + CallHistoryWindow, + FieldTripWindows, + MailablesWindow +} from '../lib/components/admin' +import { CallTakerPanel } from '../lib/components/app' /** * Custom itinerary footer for this deployment. From f9901891606c2bc55452e23c30cd1db918737093 Mon Sep 17 00:00:00 2001 From: binh-dam-ibigroup <56846598+binh-dam-ibigroup@users.noreply.github.com> Date: Fri, 22 Sep 2023 16:46:16 -0400 Subject: [PATCH 58/64] ci(percy): Update paths for percy calltaker config. --- percy/har-mock-config-call-taker.js | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/percy/har-mock-config-call-taker.js b/percy/har-mock-config-call-taker.js index 31cd154f1..418f5f6c9 100644 --- a/percy/har-mock-config-call-taker.js +++ b/percy/har-mock-config-call-taker.js @@ -18,12 +18,10 @@ import { // Webpack sets this file to run from a subdirectory within otp-react-redux // ../lib points to the index file of otp-react-redux's source code } from '../lib' -import { - CallHistoryWindow, - FieldTripWindows, - MailablesWindow -} from '../lib/components/admin' -import { CallTakerPanel } from '../lib/components/app' +import CallHistoryWindow from '../lib/components/admin/call-history-window' +import CallTakerPanel from '../lib/components/app/call-taker-panel' +import FieldTripWindows from '../lib/components/admin/field-trip-windows' +import MailablesWindow from '../lib/components/admin/mailables-window' /** * Custom itinerary footer for this deployment. From c7b5a9f37ebd33550a7883876e8b154f211a0da5 Mon Sep 17 00:00:00 2001 From: binh-dam-ibigroup <56846598+binh-dam-ibigroup@users.noreply.github.com> Date: Mon, 25 Sep 2023 16:52:39 -0400 Subject: [PATCH 59/64] ci(percy): Use separate YML config for calltaker. --- .github/workflows/percy.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/percy.yml b/.github/workflows/percy.yml index c5e878b72..9684cb875 100644 --- a/.github/workflows/percy.yml +++ b/.github/workflows/percy.yml @@ -52,7 +52,7 @@ jobs: - name: Download OTP2 config file run: curl $PERCY_OTP2_CONFIG_URL --output /tmp/otp2config.yml env: - PERCY_OTP2_CONFIG_URL: ${{ secrets.PERCY_MOCK_OTP2_GEOCODER_CONFIG }} + PERCY_OTP2_CONFIG_URL: ${{ secrets.PERCY_MOCK_OTP2_GEOCODER_CALLTAKER_CONFIG }} - name: Build OTP-RR Calltaker # Calltaker has a separate config file, so another build should be produced. run: yarn build From b38e37e0900aa6d644ce76ed67354ab3926edaaf Mon Sep 17 00:00:00 2001 From: binh-dam-ibigroup <56846598+binh-dam-ibigroup@users.noreply.github.com> Date: Thu, 19 Oct 2023 13:59:15 -0400 Subject: [PATCH 60/64] refactor(app): Prevent call history from appearing if datastore is not configured. --- lib/app.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/app.js b/lib/app.js index b56facafa..fda84a81f 100644 --- a/lib/app.js +++ b/lib/app.js @@ -175,6 +175,8 @@ const components = { MainPanel: BatchRoutingPanel, + MapWindows: isCallTakerModuleEnabled ? jsConfig.MapWindows : null, + MobileResultsScreen: BatchResultsScreen, MobileSearchScreen: BatchSearchScreen, From b8271bf2c08eed0571d0c3e4081f24ad0057f72a Mon Sep 17 00:00:00 2001 From: Binh Dam Date: Fri, 20 Oct 2023 14:15:32 +0000 Subject: [PATCH 61/64] Translated using Weblate (Spanish) Currently translated at 100.0% (517 of 517 strings) Translation: OTP-react-redux/OTP-RR Main UI Translate-URL: https://hosted.weblate.org/projects/otp-react-redux/otp-rr-main-ui/es/ --- i18n/es.yml | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/i18n/es.yml b/i18n/es.yml index 0cce495b2..be9f8314a 100644 --- a/i18n/es.yml +++ b/i18n/es.yml @@ -30,7 +30,8 @@ actions: No se puede guardar el plan: este plan no se pudo guardar debido a la falta de capacidad en uno o más vehículos. Por favor, vuelva a planificar su viaje. - maxTripRequestsExceeded: Número de solicitudes de viaje superadas sin resultados válidos + maxTripRequestsExceeded: Número de solicitudes de viaje superadas sin resultados + válidos saveItinerariesError: "No se pudieron guardar los itinerarios: {err}" setDateError: "Error al establecer la fecha:" setGroupSizeError: "No se pudo establecer el tamaño del grupo:" @@ -52,9 +53,11 @@ actions: authTokenError: Error al obtener un token de autorización. confirmDeleteMonitoredTrip: ¿Desea eliminar este viaje? confirmDeletePlace: ¿Quiere eliminar este lugar? - emailVerificationResent: El mensaje de verificación de correo electrónico ha sido reenviado. + emailVerificationResent: El mensaje de verificación de correo electrónico ha sido + reenviado. genericError: "Se ha encontrado un error: {err}" - itineraryExistenceCheckFailed: Comprobación de errores para ver si el viaje seleccionado es posible. + itineraryExistenceCheckFailed: Comprobación de errores para ver si el viaje seleccionado + es posible. mustBeLoggedInToSavePlace: Por favor, inicia la sesión para guardar las ubicaciones. placeRemembered: La configuración de este lugar se ha guardado. preferencesSaved: Sus preferencias se han guardado. @@ -245,7 +248,8 @@ components: a incluir el transporte publico en la selección de modos. origin: origen planTripTooltip: Planificar viaje - validationMessage: "Por favor, defina los siguientes campos para planificar un viaje: {issues}" + validationMessage: "Por favor, defina los siguientes campos para planificar un + viaje: {issues}" BeforeSignInScreen: mainTitle: Iniciando sesión message: > @@ -547,7 +551,8 @@ components: header: ¡La sesión está a punto de terminar! keepSession: Continuar sesión SimpleRealtimeAnnotation: - usingRealtimeInfo: Este viaje utiliza información de tráfico y retrasos en tiempo real + usingRealtimeInfo: Este viaje utiliza información de tráfico y retrasos en tiempo + real StackedPaneDisplay: savePreferences: Guardar preferencias StopScheduleTable: @@ -610,16 +615,19 @@ components: travelingAt: Viajando a {milesPerHour} vehicleName: Vehículo {vehicleNumber} TripBasicsPane: - checkingItineraryExistence: Comprobación de la existencia de itinerarios para cada día de la semana… + checkingItineraryExistence: Comprobación de la existencia de itinerarios para + cada día de la semana… selectAtLeastOneDay: Por favor, seleccione al menos un día para el seguimiento. tripDaysPrompt: ¿Qué días hace este viaje? - tripIsAvailableOnDaysIndicated: Su viaje está disponible en los días de la semana indicados anteriormente. + tripIsAvailableOnDaysIndicated: Su viaje está disponible en los días de la semana + indicados anteriormente. tripNamePrompt: "Por favor, indique un nombre para este viaje:" tripNotAvailableOnDay: El viaje no está disponible el {repeatedDay} unsavedChangesExistingTrip: >- Todavía no ha guardado su viaje. Si abandona la página, los cambios se perderán. - unsavedChangesNewTrip: Todavía no ha guardado su nuevo viaje. Si abandona la página, se perderá. + unsavedChangesNewTrip: Todavía no ha guardado su nuevo viaje. Si abandona la página, + se perderá. TripNotificationsPane: advancedSettings: Configuración avanzada altRouteRecommended: Se recomienda una ruta alternativa o un punto de transferencia @@ -700,7 +708,7 @@ components: notifications: >- Notificaciones: {leadTimeInMinutes} minutos antes de la salida programada - notificationsDisabled: "Notificaciones: Disabled" + notificationsDisabled: "Notificaciones: Desactivadas" TripTools: copyLink: Copiar enlace header: Herramientas From 769823d315e65430cd0fcef6e9edc6e59d9b78ea Mon Sep 17 00:00:00 2001 From: Binh Dam Date: Fri, 20 Oct 2023 14:16:54 +0000 Subject: [PATCH 62/64] Translated using Weblate (Korean) Currently translated at 83.7% (433 of 517 strings) Translation: OTP-react-redux/OTP-RR Main UI Translate-URL: https://hosted.weblate.org/projects/otp-react-redux/otp-rr-main-ui/ko/ --- i18n/ko.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/i18n/ko.yml b/i18n/ko.yml index e04f7e8f2..53bfc40c3 100644 --- a/i18n/ko.yml +++ b/i18n/ko.yml @@ -22,7 +22,8 @@ actions: fetchFieldTripsError: "트립을 가져오는 중에 오류가 발생했습니다: {err}" fetchTripsForDateError: "필트 트립 날짜에 대한 트립을 가져오는 중에 오류가 발생했습니다: {err}" incompatibleTripDateError: 계획한 트립 날짜({tripDate})가 요청한 트립 날짜({requestDate})가 아닙니다 - itineraryCapacityError: "플랜을 저장할 수 없습니다: 하나 이상의 차량의 용량이 부족하여 이 플랜을 저장할 수 없습니다. 트립을 다시 계획하세요." + itineraryCapacityError: "플랜을 저장할 수 없습니다: 하나 이상의 차량의 용량이 부족하여 이 플랜을 저장할 수 없습니다. + 트립을 다시 계획하세요." maxTripRequestsExceeded: 유효한 결과없이 초과된 트립 요청의 개수 saveItinerariesError: "트립을 저장하는 데 실패했습니다: {err}" setDateError: "날짜를 설정하는 중에 오류가 발생했습니다:" @@ -504,6 +505,7 @@ components: notifyViaChannelWhen: "다음의 경우, {channel}을 통해 알려주세요:" oneHour: 1 시간 realtimeAlertFlagged: 내 트립 일정에 실시간 경고가 있습니다 + timeBefore: '{time} 전' TripStatus: alerts: "{alerts, plural, one {# 경고!} other {# 경고!}}" deleteTrip: 트립 삭제 @@ -641,5 +643,6 @@ util: networkUnavailable: 현재 {network} 네트워크를 사용할 수 없습니다. noTripFound: 트립을 찾을 수 없습니다. noTripFoundForMode: "{modes}의 트립을 찾을 수 없습니다." - noTripFoundReason: 지정된 최대 거리 내 또는 지정된 시간에 대중 교통 서비스가 없거나, 출발지 또는 도착지가 안전하게 접근가능하지 못할 수 있습니다. + noTripFoundReason: 지정된 최대 거리 내 또는 지정된 시간에 대중 교통 서비스가 없거나, 출발지 또는 도착지가 안전하게 접근가능하지 + 못할 수 있습니다. noTripFoundWithReason: "{noTripFound} {reason}" From 7a5f118b2fd8df404bd6c405a63e120c69a0dfc4 Mon Sep 17 00:00:00 2001 From: Binh Dam Date: Fri, 20 Oct 2023 14:16:16 +0000 Subject: [PATCH 63/64] Translated using Weblate (Chinese (Simplified)) Currently translated at 84.5% (437 of 517 strings) Translation: OTP-react-redux/OTP-RR Main UI Translate-URL: https://hosted.weblate.org/projects/otp-react-redux/otp-rr-main-ui/zh_Hans/ --- i18n/zh.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/i18n/zh.yml b/i18n/zh.yml index 99ec4cacb..d487fa672 100644 --- a/i18n/zh.yml +++ b/i18n/zh.yml @@ -502,6 +502,7 @@ components: notifyViaChannelWhen: "通过 {channel} 通知我当:" oneHour: 1小时 realtimeAlertFlagged: 在我的行程中有一个实时警报标志着 + timeBefore: '{time} 前' TripStatus: alerts: "{alerts, plural, one {# 警报!} other {# 警报!}}" deleteTrip: 删除行程 From 00b28fb5dc53e773a0043777580183430f25822e Mon Sep 17 00:00:00 2001 From: miles-grant-ibigroup Date: Fri, 20 Oct 2023 14:33:45 -0400 Subject: [PATCH 64/64] update otp-ui --- package.json | 6 +++--- yarn.lock | 48 ++++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 45 insertions(+), 9 deletions(-) diff --git a/package.json b/package.json index e25487124..75253a754 100644 --- a/package.json +++ b/package.json @@ -39,13 +39,13 @@ "@bugsnag/plugin-react": "^7.17.0", "@floating-ui/react": "^0.19.2", "@opentripplanner/base-map": "^3.0.15", - "@opentripplanner/core-utils": "^11.0.6", + "@opentripplanner/core-utils": "^11.1.2", "@opentripplanner/endpoints-overlay": "^2.0.9", "@opentripplanner/from-to-location-picker": "^2.1.9", "@opentripplanner/geocoder": "^1.4.2", "@opentripplanner/humanize-distance": "^1.2.0", "@opentripplanner/icons": "^2.0.6", - "@opentripplanner/itinerary-body": "^5.1.0", + "@opentripplanner/itinerary-body": "^5.1.1", "@opentripplanner/location-field": "^2.0.11", "@opentripplanner/location-icon": "^1.4.1", "@opentripplanner/map-popup": "^2.0.6", @@ -58,7 +58,7 @@ "@opentripplanner/transit-vehicle-overlay": "^4.0.6", "@opentripplanner/transitive-overlay": "^3.0.16", "@opentripplanner/trip-details": "^5.0.4", - "@opentripplanner/trip-form": "^3.3.4", + "@opentripplanner/trip-form": "^3.3.5", "@opentripplanner/trip-viewer-overlay": "^2.0.7", "@opentripplanner/vehicle-rental-overlay": "^2.1.3", "@styled-icons/fa-regular": "^10.34.0", diff --git a/yarn.lock b/yarn.lock index 61aeaa722..c7eee4146 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2353,7 +2353,7 @@ maplibre-gl "^2.1.9" react-map-gl "^7.0.15" -"@opentripplanner/core-utils@^11.0.2", "@opentripplanner/core-utils@^11.0.6": +"@opentripplanner/core-utils@^11.0.2": version "11.0.6" resolved "https://registry.yarnpkg.com/@opentripplanner/core-utils/-/core-utils-11.0.6.tgz#f8bd9796b4a9bc7490fb7fdca9ce661ed785bab1" integrity sha512-ullRWOhvx4TzCmNk97Fk3FefX5jVlk0oYaLUsSfZNJJSiO0WKQadHBaxXBHQ6JHv7pk9SPuEP7xXfjz8YV6vRA== @@ -2371,6 +2371,24 @@ lodash.isequal "^4.5.0" qs "^6.9.1" +"@opentripplanner/core-utils@^11.1.2": + version "11.1.2" + resolved "https://registry.yarnpkg.com/@opentripplanner/core-utils/-/core-utils-11.1.2.tgz#a99d1fa4fb1f587d58fae8fcfd70a3bfe4eed424" + integrity sha512-Rn1tBm5F+nt/A4/0cpq6cyNTprSsxfFslujMoZ4P4r6fZ7YTx0d25di+MZ/CZgSlCzHJIiGAfi8DsfJ7yStcTA== + dependencies: + "@conveyal/lonlat" "^1.4.1" + "@mapbox/polyline" "^1.1.0" + "@opentripplanner/geocoder" "^1.4.2" + "@styled-icons/foundation" "^10.34.0" + "@turf/along" "^6.0.1" + chroma-js "^2.4.2" + date-fns "^2.28.0" + date-fns-tz "^1.2.2" + graphql "^16.6.0" + lodash.clonedeep "^4.5.0" + lodash.isequal "^4.5.0" + qs "^6.9.1" + "@opentripplanner/endpoints-overlay@^2.0.9": version "2.0.9" resolved "https://registry.yarnpkg.com/@opentripplanner/endpoints-overlay/-/endpoints-overlay-2.0.9.tgz#74a5bab257686130dea768dc921ac197dc0a7c0d" @@ -2413,7 +2431,7 @@ "@opentripplanner/core-utils" "^11.0.2" prop-types "^15.7.2" -"@opentripplanner/itinerary-body@^5.0.2", "@opentripplanner/itinerary-body@^5.0.7", "@opentripplanner/itinerary-body@^5.1.0": +"@opentripplanner/itinerary-body@^5.0.2", "@opentripplanner/itinerary-body@^5.0.7": version "5.1.0" resolved "https://registry.yarnpkg.com/@opentripplanner/itinerary-body/-/itinerary-body-5.1.0.tgz#29bba91db379bb4f63d13ec95c1cb058248d0683" integrity sha512-DTS4KlbqokS/ZA+gL0QCuPFORoPq/GVcHlRv0s9YqKmr0aS5eBBLg4f4mOuv1CcNeHKyZc6lNb/Ro3epjshd5A== @@ -2431,6 +2449,24 @@ react-resize-detector "^4.2.1" string-similarity "^4.0.4" +"@opentripplanner/itinerary-body@^5.1.1": + version "5.1.1" + resolved "https://registry.yarnpkg.com/@opentripplanner/itinerary-body/-/itinerary-body-5.1.1.tgz#bcd76d6bc079c6407088223d021a5777358ab060" + integrity sha512-obsPBhgvpvVkJuTsgNhQFN+3QKpxlzrNU3FGUZT+PAkgUHQxFo/6FQ0LNGSC+dTBBS1t7EKDfC0czQz4KZPQiw== + dependencies: + "@opentripplanner/core-utils" "^11.0.2" + "@opentripplanner/humanize-distance" "^1.2.0" + "@opentripplanner/icons" "^2.0.5" + "@opentripplanner/location-icon" "^1.4.1" + "@styled-icons/fa-solid" "^10.34.0" + "@styled-icons/foundation" "^10.34.0" + date-fns "^2.28.0" + date-fns-tz "^1.2.2" + flat "^5.0.2" + react-animate-height "^3.0.4" + react-resize-detector "^4.2.1" + string-similarity "^4.0.4" + "@opentripplanner/location-field@^2.0.11": version "2.0.11" resolved "https://registry.yarnpkg.com/@opentripplanner/location-field/-/location-field-2.0.11.tgz#06a31ec2e62cf5b542d3392281bc28b9dd1ea416" @@ -2561,10 +2597,10 @@ flat "^5.0.2" react-animate-height "^3.0.4" -"@opentripplanner/trip-form@^3.3.4": - version "3.3.4" - resolved "https://registry.yarnpkg.com/@opentripplanner/trip-form/-/trip-form-3.3.4.tgz#12847736515aa11e1c69c8db627a54c1ad5e7e89" - integrity sha512-adEjAJ+2ygkc6vptiD7tHI3O+1tEIvoDsM3+/DFIgvtKxkSKuRzzTNXn67CI2pmEev75aiiTyT97PiWbDKRTJw== +"@opentripplanner/trip-form@^3.3.5": + version "3.3.5" + resolved "https://registry.yarnpkg.com/@opentripplanner/trip-form/-/trip-form-3.3.5.tgz#0c27191f6c3bfb491130d0f849a4086f199d9f20" + integrity sha512-rDfHWqaL9RTskgJPoV2acu7nRbxwtji5yposOVTzx4LK4GVOxczbpAD6KxXXLbx8nYwp+L6y2vqX97GmlogHKQ== dependencies: "@floating-ui/react" "^0.19.2" "@opentripplanner/core-utils" "^11.0.2"