Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
3c4a12c
Move bike rental query to graphQL
alec-georgoff Jul 8, 2025
95a31c5
Update bike rental response reducer
alec-georgoff Jul 8, 2025
5f66024
Remove comment
alec-georgoff Jul 10, 2025
814d420
Update car rental query and consolidate rental vehicle query logic
alec-georgoff Jul 14, 2025
915413f
Fix carRentalQuery
alec-georgoff Jul 14, 2025
e9bb584
Merge remote-tracking branch 'origin/dev' into vehicle-rental-overlay…
alec-georgoff Jul 14, 2025
d5f97ea
Update vehicle rental queries to use graphQL and new types
alec-georgoff Jul 16, 2025
b3cf826
Merge remote-tracking branch 'origin/dev' into vehicle-rental-overlay…
alec-georgoff Jul 16, 2025
8511d5c
Merge remote-tracking branch 'origin/new-maplibre-nopublish' into veh…
alec-georgoff Aug 7, 2025
a57cd26
Merge remote-tracking branch 'origin/dev' into vehicle-rental-overlay…
alec-georgoff Aug 7, 2025
fbd6599
Remove changes to package.json that introduced locally built tarballs
alec-georgoff Aug 8, 2025
348cb88
Remove local types version
alec-georgoff Aug 8, 2025
0ee6823
Merge remote-tracking branch 'origin/new-maplibre' into vehicle-renta…
alec-georgoff Aug 8, 2025
f82f316
remove outdated fare config
miles-grant-ibigroup Aug 13, 2025
2440192
Merge remote-tracking branch 'origin/dev' into vehicle-rental-overlay…
alec-georgoff Aug 19, 2025
5fe9d95
update package versions
miles-grant-ibigroup Aug 27, 2025
8f379f4
update documentation
miles-grant-ibigroup Aug 27, 2025
a5cd41c
Merge branch 'dev' into fares-v2-table
miles-grant-ibigroup Aug 27, 2025
9255f0a
correct types
miles-grant-ibigroup Aug 27, 2025
1a88d47
simplify types
miles-grant-ibigroup Aug 27, 2025
e4339ae
complete otp-ui upgrade
miles-grant-ibigroup Aug 27, 2025
145061a
add an empty string handler for jest gql
danielhep Aug 27, 2025
5e87b43
Merge branch 'dev' into fares-v2-table
miles-grant-ibigroup Aug 28, 2025
bfc56ab
ensure percy always responds with features
miles-grant-ibigroup Aug 28, 2025
6f11705
update otp schema
miles-grant-ibigroup Aug 28, 2025
12816d5
override empty feature lists in calltaker har
miles-grant-ibigroup Aug 28, 2025
5fcddc7
Merge pull request #1464 from opentripplanner/percy-fix-attempt
miles-grant-ibigroup Aug 28, 2025
157aefb
Merge branch 'dev' into fares-v2-table
miles-grant-ibigroup Sep 4, 2025
c0d4520
support multiple fares applying
miles-grant-ibigroup Sep 4, 2025
4809399
add missing french
miles-grant-ibigroup Sep 4, 2025
47e7f33
don’t display multiple fares apply unless there are mutliple fares
miles-grant-ibigroup Sep 4, 2025
3734792
Merge remote-tracking branch 'origin/dev' into vehicle-rental-overlay…
alec-georgoff Sep 5, 2025
0ba399b
Update packages
alec-georgoff Sep 5, 2025
99e7281
Fix type mismatch
alec-georgoff Sep 5, 2025
684dcc2
add an empty string handler for jest gql
danielhep Aug 27, 2025
faf4ccb
Merge branch 'dev' into fares-v2-table
miles-grant-ibigroup Sep 8, 2025
e14ac3f
ensure percy always responds with features
miles-grant-ibigroup Aug 28, 2025
4f9c2d3
update otp schema
miles-grant-ibigroup Aug 28, 2025
a2743e7
override empty feature lists in calltaker har
miles-grant-ibigroup Aug 28, 2025
41f6198
Merge remote-tracking branch 'origin/fares-v2-table' into vehicle-ren…
alec-georgoff Sep 9, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions __tests__/test-utils/mock-data/empty-string.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = ''
8 changes: 2 additions & 6 deletions example/example-config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -383,12 +383,8 @@ itinerary:
fillModeIcons: true
# Allow user to collapse alerts in itinerary body
allowUserAlertCollapsing: true
# If multiple fares are returned by OTP, assign names to the fare keys here
#fareKeyNameMap:
# regular: "Transit Fare"
# electronicRegular: "SmartCard Fare"
# student: "Student Fare"
# One fare will always be shown by default
# The medium and rider category selected here will be used to render the total itinerary fare
# when there is only room to display a single fare.
defaultFareType: { mediumId: null, riderCategoryId: null }

# List of OTP2 errors to not display. Can be a list
Expand Down
1 change: 1 addition & 0 deletions i18n/en-US.yml
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ common:
"yes": "Yes"
itineraryDescriptions:
fareUnknown: No fare information
noDefaultFareTypeConfigured: Multiple fares apply
noItineraryToDisplay: No itinerary to display.
relativeCo2: |
{co2} {isMore, select, true {more} other {less} } CO₂ than driving alone
Expand Down
1 change: 1 addition & 0 deletions i18n/fr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ common:
"yes": Oui
itineraryDescriptions:
fareUnknown: Tarif inconnu
noDefaultFareTypeConfigured: Multiple fares apply
noItineraryToDisplay: Aucun trajet à afficher.
relativeCo2: |
{co2} de CO₂ en {isMore, select, true {plus} other {moins} } qu'en voiture
Expand Down
45 changes: 7 additions & 38 deletions lib/actions/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -317,50 +317,19 @@ export function parkAndRideQuery(

// bike rental station query

export const bikeRentalError = createAction('BIKE_RENTAL_ERROR')
export const bikeRentalResponse = createAction('BIKE_RENTAL_RESPONSE')

export function bikeRentalQuery(
params,
responseAction = bikeRentalResponse,
errorAction = bikeRentalError,
options = {}
) {
const paramsString = qs.stringify(params)
const endpoint = `bike_rental${paramsString ? `?${paramsString}` : ''}`
return createQueryAction(endpoint, responseAction, errorAction, options)
export function bikeRentalQuery() {
return executeOTPAction('findBikeRentalStations')
}

// Car rental (e.g. car2go) locations lookup query

export const carRentalResponse = createAction('CAR_RENTAL_RESPONSE')
export const carRentalError = createAction('CAR_RENTAL_ERROR')

export function carRentalQuery(params) {
return createQueryAction('car_rental', carRentalResponse, carRentalError)
export function carRentalQuery() {
return executeOTPAction('findCarRentalStations')
}

// Vehicle rental locations lookup query. For now, there are 3 separate
// "vehicle" rental endpoints - 1 for cars, 1 for bicycle rentals and another
// for micromobility. In the future, the hope is to consolidate these 3
// endpoints into one.

export const vehicleRentalResponse = createAction('VEHICLE_RENTAL_RESPONSE')
export const vehicleRentalError = createAction('VEHICLE_RENTAL_ERROR')

export function vehicleRentalQuery(
params,
responseAction = vehicleRentalResponse,
errorAction = vehicleRentalError,
options = {}
) {
return executeOTPAction(
'vehicleRentalQuery',
params,
responseAction,
errorAction,
options
)
// Free-floating rental vehicles lookup query
export function rentalVehicleQuery() {
return executeOTPAction('findRentalVehicles')
}

// Nearby view lookup query
Expand Down
181 changes: 125 additions & 56 deletions lib/actions/apiV2.js
Original file line number Diff line number Diff line change
Expand Up @@ -184,60 +184,6 @@ const findTrip = (params) =>
}
)

export const vehicleRentalQuery = (
params,
responseAction,
errorAction,
options
) =>
// TODO: ErrorsByNetwork is missing
createGraphQLQueryAction(
`{
rentalVehicles {
vehicleId
id
name
lat
lon
allowPickupNow
vehicleType {
formFactor
}
network
}
}
`,
{},
responseAction,
errorAction,
{
noThrottle: true,
postprocess: (payload, dispatch) => {
if (payload.errors) {
return errorAction(payload.errors)
}
},
// TODO: most of this rewrites the OTP2 response to match OTP1.
// we should re-write the rest of the UI to match OTP's behavior instead
rewritePayload: (payload) => {
return {
stations: payload?.data?.rentalVehicles?.map((vehicle) => {
return {
allowPickup: vehicle.allowPickupNow,
id: vehicle.vehicleId,
isFloatingBike: vehicle?.vehicleType?.formFactor === 'BICYCLE',
isFloatingVehicle: vehicle?.vehicleType?.formFactor === 'SCOOTER',
name: vehicle.name,
networks: [vehicle.network],
x: vehicle.lon,
y: vehicle.lat
}
})
}
}
}
)

// TODO: numberOfDepartures needs to come from config!
const stopTimeGraphQLQuery = `
stopTimes: stoptimesForPatterns(numberOfDepartures: 3) {
Expand Down Expand Up @@ -687,6 +633,127 @@ const getVehiclePositionsForRoute = (routeId) =>
)
}

const vehicleRentalStationsQuery = `
query VehicleRentalStations {
vehicleRentalStations {
id
name
lat
lon
allowDropoff
allowPickup
rentalNetwork {
networkId
}
availableVehicles {
total
byType {
vehicleType {
formFactor
}
}
}
availableSpaces {
total
byType {
vehicleType {
formFactor
}
}
}
realtime
}
}`

const vehicleRentalStationFilter = (formFactor) => (station) =>
(station.availableVehicles &&
station.availableVehicles.byType.some(
(av) => av.vehicleType.formFactor === formFactor
)) ||
(station.availableSpaces &&
station.availableSpaces.byType.some(
(as) => as.vehicleType.formFactor === formFactor
))

const bikeRentalError = createAction('BIKE_RENTAL_ERROR')
const bikeRentalResponse = createAction('BIKE_RENTAL_RESPONSE')

export function findBikeRentalStations() {
return function (dispatch) {
dispatch(
createGraphQLQueryAction(
vehicleRentalStationsQuery,
{},
bikeRentalResponse,
bikeRentalError,
{
rewritePayload: (payload) =>
payload.data.vehicleRentalStations.filter(
vehicleRentalStationFilter('BICYCLE')
)
}
)
)
}
}

export const carRentalResponse = createAction('CAR_RENTAL_RESPONSE')
export const carRentalError = createAction('CAR_RENTAL_ERROR')

export function findCarRentalStations() {
return function (dispatch) {
dispatch(
createGraphQLQueryAction(
vehicleRentalStationsQuery,
{},
carRentalResponse,
carRentalError,
{
rewritePayload: (payload) =>
payload.data.vehicleRentalStations.filter(
vehicleRentalStationFilter('CAR')
)
}
)
)
}
}

const rentalVehiclesQuery = `
query RentalVehicles {
rentalVehicles {
allowPickupNow
id
lat
lon
name
operative
rentalNetwork {
networkId
}
vehicleType {
formFactor
}
}
}`

const vehicleRentalResponse = createAction('VEHICLE_RENTAL_RESPONSE')
const vehicleRentalError = createAction('VEHICLE_RENTAL_ERROR')

export function findRentalVehicles() {
return function (dispatch) {
dispatch(
createGraphQLQueryAction(
rentalVehiclesQuery,
{},
vehicleRentalResponse,
vehicleRentalError,
{}
)
)
}
}

export const findRoute = (params) =>
function (dispatch, getState) {
const { routeId } = params
Expand Down Expand Up @@ -1355,15 +1422,17 @@ const retrieveServiceTimeRangeIfNeeded = () =>

export default {
fetchNearby,
findBikeRentalStations,
findCarRentalStations,
findFeeds,
findPatternsForRoute,
findRentalVehicles,
findRoute,
findRoutes,
findStopsWithinBBox,
findStopTimesForStop,
findTrip,
getVehiclePositionsForRoute,
retrieveServiceTimeRangeIfNeeded,
routingQuery,
vehicleRentalQuery
routingQuery
}
Loading
Loading