Skip to content

Commit

Permalink
Merge branch 'dev' into route-vehicles-overlay-name-override
Browse files Browse the repository at this point in the history
  • Loading branch information
miles-grant-ibigroup committed Nov 13, 2024
2 parents 2128ad7 + 2f6a865 commit 1928b3e
Show file tree
Hide file tree
Showing 26 changed files with 2,863 additions and 5,014 deletions.
543 changes: 543 additions & 0 deletions __tests__/components/viewers/__snapshots__/nearby-view.js.snap

Large diffs are not rendered by default.

28 changes: 27 additions & 1 deletion craco.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ module.exports = {
findBackwardsCompatibleEnvVar('JS_CONFIG')
backwardsCompatibleEnv.HTML_FILE =
findBackwardsCompatibleEnvVar('HTML_FILE')
backwardsCompatibleEnv.PLAN_QUERY_RESOURCE_URI =
findBackwardsCompatibleEnvVar('PLAN_QUERY_RESOURCE_URI')
backwardsCompatibleEnv.CUSTOM_CSS =
findBackwardsCompatibleEnvVar('CUSTOM_CSS')

Expand All @@ -65,6 +67,13 @@ module.exports = {
}
addBeforeLoader(webpackConfig, loaderByName('file-loader'), yamlLoader)

// Support import of raw GraphQL files
const graphqlLoader = {
loader: ['raw-loader'],
test: /\.graphql$/
}
addBeforeLoader(webpackConfig, loaderByName('file-loader'), graphqlLoader)

// Support webfonts (for font awesome)
const webfontLoader = {
loader: ['url-loader'],
Expand All @@ -82,7 +91,7 @@ module.exports = {
loader.exclude = /node_modules/
})

// Gather the CSS, HTML, YAML, and JS override files.
// Gather the CSS, HTML, YAML, GraphQL, and JS override files.
const CUSTOM_CSS =
(process.env && process.env.CUSTOM_CSS) ||
backwardsCompatibleEnv.CUSTOM_CSS ||
Expand All @@ -91,6 +100,22 @@ module.exports = {
(process.env && process.env.HTML_FILE) ||
backwardsCompatibleEnv.HTML_FILE ||
'lib/index.tpl.html'
// resolve the custom GraphQL file. If it is present, copy the file to a
// temporary folder within this project so that it can be bundled and loaded at runtime.
let customPlanGraphQLFile = './planQuery.graphql'
const PLAN_QUERY_RESOURCE_URI =
(process.env && process.env.PLAN_QUERY_RESOURCE_URI) ||
backwardsCompatibleEnv.PLAN_QUERY_RESOURCE_URI ||
'node_modules/@opentripplanner/core-utils/src/planQuery.graphql'
if (PLAN_QUERY_RESOURCE_URI) {
const splitPath = PLAN_QUERY_RESOURCE_URI.split(path.sep)
customPlanGraphQLFile = `../tmp/${splitPath[splitPath.length - 1]}`
// copy location is relative to root, while js file for app is relative to lib
fs.copySync(
PLAN_QUERY_RESOURCE_URI,
`./tmp/${splitPath[splitPath.length - 1]}`
)
}
const YAML_CONFIG =
(process.env && process.env.YAML_CONFIG) ||
backwardsCompatibleEnv.YAML_CONFIG ||
Expand Down Expand Up @@ -143,6 +168,7 @@ module.exports = {
new webpack.DefinePlugin({
CSS: JSON.stringify(CUSTOM_CSS),
JS_CONFIG: JSON.stringify(customJsFile),
PLAN_QUERY_RESOURCE: JSON.stringify(customPlanGraphQLFile),
// Optionally override the default config files with some other
// files.
YAML_CONFIG: JSON.stringify(YAML_CONFIG)
Expand Down
2 changes: 2 additions & 0 deletions example-config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -677,6 +677,8 @@ disableSingleItineraryDays: false
# maxRealtimeVehicleAge: 60
# # Interval for refreshing vehicle positions
# vehiclePositionRefreshSeconds: 30 # defaults to 30 seconds.
# # Enable this to restrict listing to routes active within the last to next Sunday
# onlyShowCurrentServiceWeek: true

# API key to make Mapillary API calls. These are used to show street imagery.
# Mapillary calls these "Client Tokens". They can be created at https://www.mapillary.com/dashboard/developers
Expand Down
4 changes: 2 additions & 2 deletions lib/actions/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -370,8 +370,8 @@ export function vehicleRentalQuery(
export const fetchNearbyResponse = createAction('FETCH_NEARBY_RESPONSE')
export const fetchNearbyError = createAction('FETCH_NEARBY_ERROR')

export function fetchNearby(coords, map) {
return executeOTPAction('fetchNearby', coords, map)
export function fetchNearby(coords, map, currentServiceWeek) {
return executeOTPAction('fetchNearby', coords, map, currentServiceWeek)
}

// Single trip lookup query
Expand Down
58 changes: 44 additions & 14 deletions lib/actions/apiV2.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,11 @@ import {
isValidSubsequence,
queryIsValid
} from '../util/state'
import { getCurrentServiceWeek } from '../util/current-service-week'
import {
getRouteColorBasedOnSettings,
getRouteIdForPattern,
getRouteTextColorBasedOnSettings,
routeIsValid
} from '../util/viewer'
import { isLastStop } from '../util/stop-times'
Expand Down Expand Up @@ -379,14 +381,15 @@ export const fetchNearbyFromStopId = (stopId) => {
)
}

export const fetchNearby = (position, radius) => {
export const fetchNearby = (position, radius, currentServiceWeek) => {
const { lat, lon } = position

return createGraphQLQueryAction(
`query Nearby(
$lat: Float!
$lon: Float!
$radius: Int
$currentServiceWeek: LocalDateRangeInput
) {
nearest(lat:$lat, lon:$lon, maxDistance: $radius, first: 100, filterByPlaceTypes: [STOP, VEHICLE_RENT, BIKE_PARK, CAR_PARK]) {
edges {
Expand Down Expand Up @@ -436,11 +439,15 @@ export const fetchNearby = (position, radius) => {
lon
code
gtfsId
stopRoutes: routes (serviceDates: $currentServiceWeek) {
gtfsId
}
stoptimesForPatterns {
pattern {
headsign
desc: name
route {
gtfsId
agency {
name
gtfsId
Expand Down Expand Up @@ -474,7 +481,7 @@ export const fetchNearby = (position, radius) => {
}
}
}`,
{ lat, lon, radius },
{ currentServiceWeek, lat, lon, radius },
fetchNearbyResponse,
fetchNearbyError,
{
Expand Down Expand Up @@ -857,10 +864,18 @@ export const findRoute = (params) =>

export function findRoutes() {
return function (dispatch, getState) {
// Only calculate current service week if the setting for it is enabled
const currentServiceWeek =
getState().otp?.config?.routeViewer?.onlyShowCurrentServiceWeek === true
? getCurrentServiceWeek()
: undefined

dispatch(
createGraphQLQueryAction(
`{
routes {
`query Routes(
$currentServiceWeek: LocalDateRangeInput
) {
routes (serviceDates: $currentServiceWeek) {
id: gtfsId
agency {
id: gtfsId
Expand All @@ -875,7 +890,7 @@ export function findRoutes() {
}
}
`,
{},
{ currentServiceWeek },
findRoutesResponse,
findRoutesError,
{
Expand Down Expand Up @@ -963,6 +978,8 @@ export function routingQuery(searchId = null, updateSearchInReducer) {
return function (dispatch, getState) {
const state = getState()
const { config, currentQuery, modeSettingDefinitions } = state.otp
const { planQuery } = config.api
const { loggedInUser } = state.user
const persistenceMode = getPersistenceMode(config.persistence)
const activeItinerary =
getActiveItinerary(state) ||
Expand Down Expand Up @@ -1046,6 +1063,9 @@ export function routingQuery(searchId = null, updateSearchInReducer) {
...currentQuery,
numItineraries: numItineraries || getDefaultNumItineraries(config)
}
if (config.mobilityProfile) {
baseQuery.mobilityProfile = loggedInUser?.mobilityProfile?.mobilityMode
}
// Generate combinations if the modes for query are not specified in the query
// FIXME: BICYCLE_RENT does not appear in this list unless TRANSIT is also enabled.
// This is likely due to the fact that BICYCLE_RENT is treated as a transit submode.
Expand All @@ -1069,7 +1089,7 @@ export function routingQuery(searchId = null, updateSearchInReducer) {
const query = generateOtp2Query(combo)
dispatch(
createGraphQLQueryAction(
query.query,
planQuery || query.query,
query.variables,
(response) => {
const dispatchedRoutingResponse = routingResponse(response)
Expand Down Expand Up @@ -1130,20 +1150,30 @@ export function routingQuery(searchId = null, updateSearchInReducer) {
...itin,
legs: itin.legs
?.map((leg) => {
const routeOperator = getRouteOperator(
{
agencyId: leg?.agency?.id,
id: leg?.route?.id
},
config.transitOperators
)
const routeProperties = {
color: leg?.route?.color,
mode: leg.mode
}

return {
...leg,
origColor: leg?.route?.color,
route: {
...leg.route,
color: getRouteColorBasedOnSettings(
getRouteOperator(
{
agencyId: leg?.agency?.id,
id: leg?.route?.id
},
config.transitOperators
),
{ color: leg?.route?.color, mode: leg.mode }
routeOperator,
routeProperties
).split('#')?.[1],
textColor: getRouteTextColorBasedOnSettings(
routeOperator,
routeProperties
).split('#')?.[1]
}
}
Expand Down
20 changes: 19 additions & 1 deletion lib/actions/user.js
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,8 @@ function setUser(user, fetchTrips) {
return function (dispatch, getState) {
positionHomeAndWorkFirst(user)
// If mobility profile is enabled, set a default selection for "no mobility devices".
if (getState().otp.config.mobilityProfile) {
const hasMobilityProfile = !!getState().otp.config.mobilityProfile
if (hasMobilityProfile) {
setAtLeastNoMobilityDevice(user)
}
dispatch(setCurrentUser(user))
Expand All @@ -287,6 +288,23 @@ function setUser(user, fetchTrips) {
if (!isBlank(preferredLocale)) {
dispatch(setLocale(preferredLocale))
}

// Also replan itinerary search for the current user profile.
if (
hasMobilityProfile &&
!getState().router.location.pathname.startsWith('/account')
) {
// TODO: Refactor below.
// This prevents some kind of race condition whose origin I can't figure
// out. Unless this is called after redux catches up with routing to the '/'
// path, then the old path will be used and the screen won't change.
// Therefore, this timeout occurs so that the view of the homepage has time
// to render itself.
// FIXME: remove hack
setTimeout(() => {
dispatch(routingQuery())
}, 300)
}
}
}

Expand Down
24 changes: 22 additions & 2 deletions lib/components/app/batch-routing-panel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@ import { CSSTransition, TransitionGroup } from 'react-transition-group'
import { FormattedMessage, injectIntl, IntlShape } from 'react-intl'
import React, { Component, FormEvent } from 'react'

import * as apiActions from '../../actions/api'
import {
advancedPanelClassName,
mainPanelClassName,
transitionDuration,
TransitionStyles
} from '../form/styled'
import { alertUserTripPlan } from '../form/util'
import { getActiveSearch, getShowUserSettings } from '../../util/state'
import { getPersistenceMode } from '../../util/user'
import AdvancedSettingsPanel from '../form/advanced-settings-panel'
Expand All @@ -22,9 +24,11 @@ import ViewerContainer from '../viewers/viewer-container'

interface Props {
activeSearch: any
currentQuery: any
intl: IntlShape
mainPanelContent: number
mobile?: boolean
routingQuery: () => void
showUserSettings: boolean
}

Expand Down Expand Up @@ -75,7 +79,13 @@ class BatchRoutingPanel extends Component<Props> {
handleSubmit = (e: FormEvent) => e.preventDefault()

handlePlanTripClick = () => {
this.setState({ planTripClicked: true })
const { currentQuery, intl, routingQuery } = this.props
alertUserTripPlan(
intl,
currentQuery,
() => this.setState({ planTripClicked: true }),
routingQuery
)
}

render() {
Expand Down Expand Up @@ -128,6 +138,7 @@ class BatchRoutingPanel extends Component<Props> {
>
<AdvancedSettingsPanel
closeAdvancedSettings={this.closeAdvancedSettings}
handlePlanTrip={this.handlePlanTripClick}
innerRef={this._advancedSettingRef}
setCloseAdvancedSettingsWithDelay={
this.setCloseAdvancedSettingsWithDelay
Expand Down Expand Up @@ -223,12 +234,21 @@ const mapStateToProps = (state: any) => {
(state.user.loggedInUser?.hasConsentedToTerms ||
getPersistenceMode(state.otp.config.persistence).isLocalStorage)
const { mainPanelContent } = state.otp.ui
const currentQuery = state.otp.currentQuery

return {
activeSearch: getActiveSearch(state),
currentQuery,
mainPanelContent,
showUserSettings
}
}

export default connect(mapStateToProps)(injectIntl(BatchRoutingPanel))
const mapDispatchToProps = {
routingQuery: apiActions.routingQuery
}

export default connect(
mapStateToProps,
mapDispatchToProps
)(injectIntl(BatchRoutingPanel))
7 changes: 6 additions & 1 deletion lib/components/app/responsive-webapp.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ class ResponsiveWebapp extends Component {
/* eslint-disable-next-line complexity */
componentDidUpdate(prevProps) {
const {
activeItinerary,
activeSearchId,
autoFly,
currentPosition,
Expand Down Expand Up @@ -101,7 +102,11 @@ class ResponsiveWebapp extends Component {
setLocationToCurrent({ locationType: 'from' }, intl)
setMapCenter(map, pt)
}
} else if (mainPanelContent === null && autoFly !== false) {
} else if (
mainPanelContent === null &&
autoFly !== false &&
activeItinerary === null
) {
if (query.from && query.to) {
map?.fitBounds([query.from, query.to], {
duration: 600,
Expand Down
Loading

0 comments on commit 1928b3e

Please sign in to comment.