diff --git a/i18n/en-US.yml b/i18n/en-US.yml index 80815f847..6999b1ade 100644 --- a/i18n/en-US.yml +++ b/i18n/en-US.yml @@ -234,6 +234,9 @@ components: modeSelectorLabel: Select a transit mode BatchSettings: destination: destination + invalidModeSelection: >- + Cannot plan a trip using the selected modes. Try including transit in your + mode selection. origin: origin planTripTooltip: Plan trip validationMessage: "Please define the following fields to plan a trip: {issues}" diff --git a/i18n/es.yml b/i18n/es.yml index ab2d2ec11..a8624868d 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:" @@ -39,6 +40,10 @@ actions: location: geolocationNotSupportedError: Su navegador no admite la geolocalización unknownPositionError: Error desconocido al obtener la posición + userDeniedPermission: Usuario sin permiso + deniedAccessAlert: "El acceso a tu ubicación está bloqueado.\nPara utilizar tu + ubicación actual, activa los permisos de ubicación desde tu navegador y vuelve + a cargar la página. \n" map: currentLocation: (Ubicación actual) user: @@ -46,9 +51,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. preferencesSaved: Sus preferencias se han guardado. smsInvalidCode: El código introducido no es válido. Por favor, inténtelo de nuevo. smsResendThrottled: >- @@ -110,6 +117,7 @@ common: {co2} de CO₂ en {isMore, select, true {más} other {menos} } que conducir solo transfers: "{transfers, plural, =0 {} one {# transferencia} other {# transferencias}}" + fareUnknown: No hay información de las tarifas linkOpensNewWindow: (Abre una nueva ventana) modes: bicycle_rent: Compartir bicicleta @@ -171,6 +179,8 @@ components: AdvancedOptions: bannedRoutes: Seleccionar rutas prohibidas… preferredRoutes: Seleccionar rutas preferidas… + bikeTolerance: Tolerancia de las bicicletas + walkTolerance: Tolerancia al andar AfterSignInScreen: mainTitle: Redirigiendo… message: >- @@ -226,11 +236,13 @@ components: shortTitle: Planificar viaje BatchSearchScreen: header: Planifique su viaje + modeSelectorLabel: Seleccione un modo de transporte BatchSettings: destination: destino 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: > @@ -359,11 +371,8 @@ components: description: El contenido que ha solicitado no está disponible. header: No se encontró el contenido NotificationPrefsPane: - description: Puede recibir notificaciones sobre los viajes que realiza con frecuencia. noDeviceForPush: Regístrese con la aplicación móvil para acceder a esta configuración. - noneSelect: No enviar notificaciones notificationChannelPrompt: "Recibir notificaciones para sus viajes guardados por:" - notificationEmailDetail: "Los correos electrónicos de notificación se enviarán a:" PhoneNumberEditor: changeNumber: Cambiar número de teléfono invalidCode: Introduzca 6 dígitos para el código de validación. @@ -493,7 +502,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: @@ -556,16 +566,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 @@ -725,6 +738,41 @@ components: switcher: Botón de cambio WelcomeScreen: prompt: ¿A donde quiere ir? + OTP2ErrorRenderer: + SYSTEM_ERROR: + header: Error en el planificador de los viajes + body: Se ha producido un error desconocido en la búsqueda. + LOCATION_NOT_FOUND: + body: '{inputFieldsCount, plural, =0 {} one {localización es} other {localizaciones + son}} no están cerca de ninguna calle.' + header: No se puede acceder a la ubicación + NO_STOPS_IN_RANGE: + header: Sin paradas cerca + body: '{inputFieldsCount, plural, =0 {} one {ubicación es} other {ubicaciones + son}} no están cerca de ninguna parada del transporte.' + NO_TRANSIT_CONNECTION: + body: No se encontró ninguna conexión entre tu origen y destino en el día seleccionado, + utilizando los tipos de vehículos que seleccionaste. + header: Sin conexiones + inputFields: + FROM: Procedencia + TO: Destino + WALKING_BETTER_THAN_TRANSIT: + body: Puede completar esta ruta más rápido caminando. + header: El transporte público no es la forma más rápida de hacer este viaje + OUTSIDE_SERVICE_PERIOD: + header: Fuera de plazo + body: La fecha específicada está fuera del rango de los datos disponibles para + la búsqueda de los viajes. + OUTSIDE_BOUNDS: + header: Ubicación fuera de los límites + body: '{inputFieldsCount, plural, =0 {} one {localización es} other {localizaciones + son}} no están en los límites del planificador de viajes.' + NO_TRANSIT_CONNECTION_IN_SEARCH_WINDOW: + body: Se encontró una conexión, pero estaba fuera de las opciones de la búsqueda, + intenta ajustar las opciones de la búsqueda, usando los tipos de vehículos + que seleccionaste. + header: Sin conexiones por el criterio de la búsqueda config: accessModes: bicycle: Tránsito + Bicicleta Personal diff --git a/i18n/fr.yml b/i18n/fr.yml index 7c07ce285..08d7f03f9 100644 --- a/i18n/fr.yml +++ b/i18n/fr.yml @@ -2,7 +2,8 @@ _id: fr _name: Exemple de traduction pour OTP-react-redux en français actions: callTaker: - callQuerySaveError: "Erreur lors de l'enregistrement des requêtes pour l'appel : {err}" + callQuerySaveError: "Erreur lors de l'enregistrement des requêtes pour l'appel + : {err}" callSaveError: "Impossible d'enregistrer l'appel : {err}" checkSessionError: "Erreur durant la session d'authentification : {err}" couldNotFindCallError: >- @@ -17,9 +18,11 @@ actions: true {aller} other {retour} } planifié préalablement pour cette demande. Voulez-vous continuer ? - deleteItinerariesError: "Erreur lors de la suppression du trajet pour le groupe :" + deleteItinerariesError: "Erreur lors de la suppression du trajet pour le groupe + :" deleteNoteError: "Erreur lors de la suppression d'une note sur le groupe :" - editSubmitterNotesError: "Erreur lors de la modification des notes du demandeur :" + editSubmitterNotesError: "Erreur lors de la modification des notes du demandeur + :" fetchFieldTripError: "Erreur de chargement du groupe scolaire : {err}" fetchFieldTripsError: "Erreur lors du chargement des groupes scolaires : {err}" fetchTripsForDateError: >- @@ -43,7 +46,8 @@ actions: Pour utiliser votre emplacement actuel, permettez-en l'accès depuis votre navigateur, et ouvrez de nouveau cette page. - geolocationNotSupportedError: La géolocalisation n'est pas prise en charge par votre navigateur. + geolocationNotSupportedError: La géolocalisation n'est pas prise en charge par + votre navigateur. unknownPositionError: Erreur inconnue lors de la détection de votre emplacement. userDeniedPermission: Refusé par l'utilisateur map: @@ -57,7 +61,8 @@ actions: Le message de vérification de votre adresse e-mail a été envoyé de nouveau. genericError: "Une erreur s'est produite : {err}" - itineraryExistenceCheckFailed: Erreur lors de la vérification de la validité du trajet choisi. + itineraryExistenceCheckFailed: Erreur lors de la vérification de la validité du + trajet choisi. preferencesSaved: Vos préférences ont été enregistrées. smsInvalidCode: Le code saisi est incorrect. Veuillez réessayer. smsResendThrottled: >- @@ -245,6 +250,9 @@ components: modeSelectorLabel: Sélectionnez un mode de transport BatchSettings: destination: destination + invalidModeSelection: >- + Impossible de planifier un trajet avec les modes sélectionnés. Réessayez + en ajoutant les transports publics. origin: point de départ planTripTooltip: Planifier le trajet validationMessage: >- @@ -343,8 +351,10 @@ components: header: Options de recherche NarrativeItinerariesHeader: changeSortDir: Changer l'ordre de tri - howToFindResults: Pour afficher les résultats, utilisez l'en-tête Trajets trouvés plus bas. - itinerariesFound: "{itineraryNum, plural, one {# trajet trouvé} other {# trajets trouvés} }" + howToFindResults: Pour afficher les résultats, utilisez l'en-tête Trajets trouvés + plus bas. + itinerariesFound: "{itineraryNum, plural, one {# trajet trouvé} other {# trajets + trouvés} }" numIssues: "{issueNum, plural, one {# problème} other {# problèmes} }" resultsSortedBy: >- Résultats triés par {sortSelected}. Pour modifier l'ordre, utilisez le @@ -411,9 +421,8 @@ components: header: Echec de la recherche WALKING_BETTER_THAN_TRANSIT: body: >- - Vous pouvez effectuer ce trajet plus rapidement en évitant les - transports. - header: Transports moins rapides + Vous pouvez effectuer ce trajet plus rapidement sans prendre les transports. + header: Moins rapide en transports inputFields: FROM: point de départ TO: destination @@ -658,7 +667,8 @@ components: unknownState: État du trajet inconnu untogglePause: Reprendre inactive: - description: Reprenez le suivi pour obtenir des dernières conditions de votre trajet. + description: Reprenez le suivi pour obtenir des dernières conditions de votre + trajet. heading: Suivi suspendu nextTripNotPossible: description: > @@ -677,7 +687,8 @@ components: déterminées. heading: Conditions du trajet indéterminées snoozed: - description: Reprenez le suivi pour obtenir des dernières conditions de votre trajet. + description: Reprenez le suivi pour obtenir des dernières conditions de votre + trajet. heading: Suivi suspendu jusqu'à demain upcoming: nextTripBegins: >- diff --git a/lib/actions/api-constants.ts b/lib/actions/api-constants.ts new file mode 100644 index 000000000..bfa917885 --- /dev/null +++ b/lib/actions/api-constants.ts @@ -0,0 +1,5 @@ +export const RoutingQueryCallResult = { + INVALID_MODE_SELECTION: 2, + INVALID_QUERY: 1, + SUCCESS: 0 +} diff --git a/lib/actions/apiV2.js b/lib/actions/apiV2.js index 0edb46d0e..ae64d539c 100644 --- a/lib/actions/apiV2.js +++ b/lib/actions/apiV2.js @@ -41,6 +41,7 @@ import { updateOtpUrlParams } from './api' import { rememberPlace } from './user' +import { RoutingQueryCallResult } from './api-constants' import { setItineraryView } from './ui' import { zoomToPlace } from './map' @@ -800,7 +801,7 @@ export function routingQuery(searchId = null, updateSearchInReducer) { // Don't permit a routing query if the query is invalid if (!queryIsValid(state)) { console.warn('Query is invalid. Aborting routing query', currentQuery) - return + return RoutingQueryCallResult.INVALID_QUERY } const { @@ -968,6 +969,10 @@ export function routingQuery(searchId = null, updateSearchInReducer) { if (isNewSearch || params.ui_activeSearch !== searchId) { dispatch(updateOtpUrlParams(state, searchId)) } + + return combinations.length === 0 + ? RoutingQueryCallResult.INVALID_MODE_SELECTION + : RoutingQueryCallResult.SUCCESS } } diff --git a/lib/components/form/batch-settings.tsx b/lib/components/form/batch-settings.tsx index 6cc65fce4..15e3f95e8 100644 --- a/lib/components/form/batch-settings.tsx +++ b/lib/components/form/batch-settings.tsx @@ -26,6 +26,7 @@ import { ComponentContext } from '../../util/contexts' import { generateModeSettingValues } from '../../util/api' import { getActiveSearch, hasValidLocation } from '../../util/state' import { getFormattedMode } from '../../util/i18n' +import { RoutingQueryCallResult } from '../../actions/api-constants' import { StyledIconWrapper } from '../util/styledIcon' import { @@ -165,7 +166,16 @@ function BatchSettings({ // Plan trip. updateQueryTimeIfLeavingNow() - routingQuery() + const routingQueryResult = routingQuery() + + // If mode combination is not valid (i.e. produced no query), alert the user. + if (routingQueryResult === RoutingQueryCallResult.INVALID_MODE_SELECTION) { + window.alert( + intl.formatMessage({ + id: 'components.BatchSettings.invalidModeSelection' + }) + ) + } }, [ currentQuery, intl, diff --git a/package.json b/package.json index 46e9ff69a..4f7774ef8 100644 --- a/package.json +++ b/package.json @@ -39,7 +39,7 @@ "@bugsnag/plugin-react": "^7.17.0", "@floating-ui/react": "^0.19.2", "@opentripplanner/base-map": "^3.0.14", - "@opentripplanner/core-utils": "^11.0.2", + "@opentripplanner/core-utils": "^11.0.3", "@opentripplanner/endpoints-overlay": "^2.0.8", "@opentripplanner/from-to-location-picker": "^2.1.8", "@opentripplanner/geocoder": "^1.4.2", @@ -132,7 +132,7 @@ "@craco/craco": "^6.3.0", "@jackwilsdon/craco-use-babelrc": "^1.0.0", "@opentripplanner/scripts": "^1.2.0", - "@opentripplanner/types": "^6.1.0", + "@opentripplanner/types": "^6.1.1", "@percy/cli": "^1.20.3", "@percy/puppeteer": "^2.0.2", "@pmmmwh/react-refresh-webpack-plugin": "^0.5.1", diff --git a/yarn.lock b/yarn.lock index d24a5c104..1521f2a66 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2439,10 +2439,10 @@ lodash.isequal "^4.5.0" qs "^6.9.1" -"@opentripplanner/core-utils@^11.0.2": - version "11.0.2" - resolved "https://registry.yarnpkg.com/@opentripplanner/core-utils/-/core-utils-11.0.2.tgz#ebfa939c3b7b266e3bf47dcaddda88e093430a9d" - integrity sha512-3oQYvnhFHY88K61j2tUkU2fm8tDci5qaMVGEgqTzxpE5NmBTUdAWU1V7W9snJoRATzz3zy+K9qrtIhGjwbwlnA== +"@opentripplanner/core-utils@^11.0.3": + version "11.0.3" + resolved "https://registry.yarnpkg.com/@opentripplanner/core-utils/-/core-utils-11.0.3.tgz#b8aa21f81be420c07128e78c20a74d32d0034476" + integrity sha512-hTLZwU8YyokTA86tIa+iy46g0lqcjBX/HDxyzwxvbm6lFnUvUhHgWRPKvr8fzUA5aE0vYzwlj16WygQ43n4ubQ== dependencies: "@conveyal/lonlat" "^1.4.1" "@mapbox/polyline" "^1.1.0" @@ -2771,10 +2771,10 @@ "@opentripplanner/base-map" "^3.0.13" "@opentripplanner/core-utils" "^9.0.0" -"@opentripplanner/types@^6.1.0": - version "6.1.0" - resolved "https://registry.yarnpkg.com/@opentripplanner/types/-/types-6.1.0.tgz#dd5b88cc0b73939cd1eb5bd44d4768e21bedaacc" - integrity sha512-fFuNMJLrSCIoIWJ7VugM1Jb7HfIcRDzb8o2LNsASExWAEYDuONFxyGYT/98g82/70Grl8kCSMSAFi0lEiQ/cPQ== +"@opentripplanner/types@^6.1.1": + version "6.1.1" + resolved "https://registry.yarnpkg.com/@opentripplanner/types/-/types-6.1.1.tgz#ed28406d71b48d5299edc7ac884583d00917edc9" + integrity sha512-VNqWQI8hQfQQZQZFHrUbxGZzldNODMls3wXM9aawUJ7OJRjjmNOhkgTjohMcpvA3Ed3wUAkzOXByBQO3MTVH6Q== "@opentripplanner/vehicle-rental-overlay@^2.1.2": version "2.1.2"