Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Monitored Trips - Middleware GraphQL support #1178

Open
wants to merge 28 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
fe85d07
fix(SavedTripScreen): Pass GraphQL plan vars to middleware for existe…
binh-dam-ibigroup Mar 25, 2024
7daa690
refactor(apiV2): Drop irrelevant params from GraphQL plan variables.
binh-dam-ibigroup Mar 25, 2024
9ff8d13
refactor(SavedTripScreen): Pass query.variables from apiV2 directly t…
binh-dam-ibigroup Mar 25, 2024
7e18f4e
refactor(SavedTripScreen): Remove unused prop.
binh-dam-ibigroup Mar 25, 2024
0c5b16b
Merge branch 'dev' into middleware-graphql
binh-dam-ibigroup Jul 16, 2024
458933d
Merge branch 'dev' into middleware-graphql
binh-dam-ibigroup Jul 19, 2024
b92f82f
refactor(apiV2): Use OTP2 route response more intentionally.
binh-dam-ibigroup Jul 22, 2024
6f48705
Merge branch 'dev' into middleware-graphql
binh-dam-ibigroup Jul 23, 2024
8b074de
refactor(actions/user): Parse OTP2 query params
binh-dam-ibigroup Jul 24, 2024
337685b
fix(actions/users): Better filter duplicate entries
binh-dam-ibigroup Jul 25, 2024
5bf5fa9
refactor(user-settings-i18n): Combine modes for displaying
binh-dam-ibigroup Jul 25, 2024
308363e
Merge branch 'dev' into middleware-graphql
binh-dam-ibigroup Jul 26, 2024
4594839
fix: Fix parsing errors
binh-dam-ibigroup Jul 26, 2024
7c361c1
chore(deps): Update core-utils version for bug fix
binh-dam-ibigroup Aug 2, 2024
9053e97
refactor(actions/users): Remove obsolete location parsing code.
binh-dam-ibigroup Aug 2, 2024
ad5a491
chore(i18n): Revert formatting changes
binh-dam-ibigroup Aug 5, 2024
d839208
Merge branch 'dev' into middleware-graphql
binh-dam-ibigroup Sep 4, 2024
4d1792a
fix: Add new originalMode field to legs.
binh-dam-ibigroup Sep 6, 2024
5428f46
refactor(itinerary): Fix comment
binh-dam-ibigroup Sep 6, 2024
8bfd731
fix(SavedTripScreen): Remove route mode overrides when saving trip.
binh-dam-ibigroup Sep 6, 2024
cf68453
fix(DefaultRouteRenderer): Prefer OTP2 leg route data.
binh-dam-ibigroup Sep 6, 2024
d4ea7d2
refactor(itinerary): Fix types
binh-dam-ibigroup Sep 6, 2024
54c7207
refactor(DefaultRouteRenderer): Fix types
binh-dam-ibigroup Sep 6, 2024
7817c5b
refactor(actions/user): Rename function and tweak comments
binh-dam-ibigroup Sep 13, 2024
ed5f0ad
refactor(actions/user): Use lodash.isEqual for comparison.
binh-dam-ibigroup Sep 13, 2024
1940361
Merge branch 'dev' into middleware-graphql
binh-dam-ibigroup Sep 13, 2024
6793c3c
Merge branch 'dev' into middleware-graphql
binh-dam-ibigroup Sep 26, 2024
560d1cc
Merge branch 'dev' into middleware-graphql
binh-dam-ibigroup Sep 26, 2024
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
6 changes: 5 additions & 1 deletion lib/actions/apiV2.js
Original file line number Diff line number Diff line change
Expand Up @@ -1109,7 +1109,11 @@ export function routingQuery(searchId = null, updateSearchInReducer) {
}
}
})
?.map(convertGraphQLResponseToLegacy)
?.map((leg) => ({
...convertGraphQLResponseToLegacy(leg),
route: leg.transitLeg ? leg.route : undefined
})),
otp2QueryParams: query.variables
})
)

Expand Down
27 changes: 26 additions & 1 deletion lib/actions/user.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import isEqual from 'lodash.isequal'
import qs from 'qs'
import toast from 'react-hot-toast'

import { applyRouteModeOverrides } from '../util/itinerary'
import {
convertToPlace,
getPersistenceMode,
Expand Down Expand Up @@ -129,6 +130,11 @@ export function fetchMonitoredTrips() {
'GET'
)
if (status === 'success') {
const { routeModeOverrides } = getState().otp.config
trips.data.forEach((trip) => {
applyRouteModeOverrides(trip.itinerary, routeModeOverrides)
})

dispatch(setCurrentUserMonitoredTrips(trips.data))
}
}
Expand Down Expand Up @@ -169,14 +175,33 @@ function convertRequestToSearch(config) {
}
}

/**
* Determines whether two GraphQL sets of variables are for the same trip request/search.
*
* Modes are excluded from the comparison because the UI triggers multiple queries
* with the same GraphQL variables but with different combinations of modes.
* Modes exclusion also means that if someone makes the same search with different mode settings
* (e.g. excludes/adds transit modes), that search will also be combined with the previous ones.
*/
function areRequestsSameExceptModes(qp1, qp2) {
const { modes: modes1, ...otherParams1 } = qp1
const { modes: modes2, ...otherParams2 } = qp2
return isEqual(otherParams1, otherParams2)
}

/**
* Removes duplicate requests so that only one request is displayed per "batch".
*/
function removeDuplicateRequests(filtered, tripRequest) {
// Compare one trip request to the next one.
if (filtered.length === 0) {
filtered.push(tripRequest)
} else if (!isEqual(filtered[filtered.length - 1].query, tripRequest.query)) {
} else if (
!areRequestsSameExceptModes(
filtered[filtered.length - 1].query,
tripRequest.query
)
) {
filtered.push(tripRequest)
} else {
filtered[filtered.length - 1].query.modes.push(...tripRequest.query.modes)
Expand Down
10 changes: 8 additions & 2 deletions lib/components/narrative/metro/default-route-renderer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,16 @@ const DefaultRouteRenderer = ({
leg,
style
}: RouteRendererProps): JSX.Element => {
const routeTitle = leg.routeShortName || leg.routeLongName
const routeTitle =
typeof leg.route === 'object'
? leg.route.shortName || leg.route.longName
: leg.routeShortName || leg.routeLongName
return (
<Block
color={leg.routeColor || '333333'}
color={
(typeof leg.route === 'object' ? leg.route.color : leg.routeColor) ||
'333333'
}
isOnColoredBackground={leg.onColoredBackground}
style={style}
title={routeTitle}
Expand Down
17 changes: 13 additions & 4 deletions lib/components/user/monitored-trip/saved-trip-screen.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,11 @@ import * as formActions from '../../../actions/form'
import * as uiActions from '../../../actions/ui'
import * as userActions from '../../../actions/user'
import { arrayToDayFields } from '../../../util/monitored-trip'
import {
copyAndRemoveRouteModeOverrides,
getItineraryDefaultMonitoredDays
} from '../../../util/itinerary'
import { getActiveItineraries, getActiveSearch } from '../../../util/state'
import { getItineraryDefaultMonitoredDays } from '../../../util/itinerary'
import { RETURN_TO_CURRENT_ROUTE } from '../../../util/ui'
import { TRIPS_PATH } from '../../../util/constants'
import AccountPage from '../account-page'
Expand Down Expand Up @@ -60,14 +63,16 @@ class SavedTripScreen extends Component {
itinerary,
homeTimezone
)
const { otp2QueryParams, ...otherItineraryProps } = itinerary
return {
...arrayToDayFields(monitoredDays),
arrivalVarianceMinutesThreshold: 5,
departureVarianceMinutesThreshold: 5,
excludeFederalHolidays: true,
isActive: true,
itinerary,
itinerary: copyAndRemoveRouteModeOverrides(otherItineraryProps),
leadTimeInMinutes: 30,
otp2QueryParams,
// when creating a monitored trip, the query params will be changed on the
// backend so that the modes parameter will reflect the modes seen in the
// itinerary
Expand All @@ -87,8 +92,13 @@ class SavedTripScreen extends Component {
*/
_updateMonitoredTrip = (monitoredTrip) => {
const { createOrUpdateUserMonitoredTrip, intl, isCreating } = this.props
const tripToSave = {
...monitoredTrip,
itinerary: copyAndRemoveRouteModeOverrides(monitoredTrip.itinerary)
}

createOrUpdateUserMonitoredTrip(
monitoredTrip,
tripToSave,
isCreating,
undefined,
undefined,
Expand Down Expand Up @@ -237,7 +247,6 @@ const mapStateToProps = (state, ownProps) => {
const itineraries = getActiveItineraries(state) || []
const tripId = ownProps.match.params.id
return {
activeSearchId: state.otp.activeSearchId,
homeTimezone: state.otp.config.homeTimezone,
isCreating: tripId === 'new',
itinerary: itineraries[activeItinerary],
Expand Down
3 changes: 2 additions & 1 deletion lib/components/user/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,8 @@ export type MonitoredTrip = Record<DaysOfWeek, boolean> & {
itinerary: Itinerary
itineraryExistence?: ItineraryExistence
leadTimeInMinutes: number
queryParams: string
otp2QueryParams: Record<string, unknown>
queryParams: Record<string, unknown>
tripName: string
userId: string
}
Expand Down
15 changes: 2 additions & 13 deletions lib/reducers/create-otp-reducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import deepmerge from 'deepmerge'
import objectPath from 'object-path'
import update from 'immutability-helper'

import { checkForRouteModeOverride } from '../util/config'
import { applyRouteModeOverrides } from '../util/itinerary'
import {
FETCH_STATUS,
PERSIST_TO_LOCAL_STORAGE,
Expand Down Expand Up @@ -311,18 +311,7 @@ function createOtpReducer(config) {
response.requestId = requestId
response.plan.itineraries = response.plan?.itineraries?.map(
(itinerary) => {
itinerary.legs = itinerary.legs.map((leg) => {
if (leg.routeId) {
leg.mode = checkForRouteModeOverride(
{
id: leg.routeId,
mode: leg.mode
},
state.config?.routeModeOverrides
)
}
return leg
})
applyRouteModeOverrides(itinerary, state.config.routeModeOverrides)
return itinerary
}
)
Expand Down
39 changes: 39 additions & 0 deletions lib/util/itinerary.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import hash from 'object-hash'
import memoize from 'lodash.memoize'

import { AppConfig, CO2Config } from './config-types'
import { checkForRouteModeOverride } from './config'
import { WEEKDAYS, WEEKEND_DAYS } from './monitored-trip'

export interface ItineraryStartTime {
Expand Down Expand Up @@ -449,3 +450,41 @@ export function addSortingCosts<T extends Itinerary>(
totalFare
}
}

interface LegWithOriginalMode extends Leg {
originalMode?: string
}

/** Applies route mode overrides to an itinerary. */
export function applyRouteModeOverrides(
itinerary: Itinerary,
routeModeOverrides: Record<string, string>
): void {
itinerary.legs.forEach((leg: LegWithOriginalMode) => {
// Use OTP2 leg route first, fallback on legacy leg routeId.
const routeId = typeof leg.route === 'object' ? leg.route.id : leg.routeId
if (routeId) {
leg.originalMode = leg.mode
leg.mode = checkForRouteModeOverride(
{
id: routeId,
mode: leg.mode
},
routeModeOverrides
)
}
})
}

/** Remove mode overrides from an itinerary */
export function copyAndRemoveRouteModeOverrides(
itinerary: Itinerary
): Itinerary {
return {
...itinerary,
legs: itinerary.legs.map((leg: LegWithOriginalMode) => ({
...leg,
mode: leg.originalMode || leg.mode
}))
}
}
Loading