{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)
)
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(
() =>
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/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/i18n.js b/lib/util/i18n.js
index 9dfe53126..2674a781e 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 (correctly) 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 = {
diff --git a/lib/util/state.js b/lib/util/state.js
index eac0ef907..187ed0c77 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)
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
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/percy/har-mock-config-call-taker.js b/percy/har-mock-config-call-taker.js
index f1e892114..418f5f6c9 100644
--- a/percy/har-mock-config-call-taker.js
+++ b/percy/har-mock-config-call-taker.js
@@ -14,14 +14,14 @@ 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 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.
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"