Skip to content

Commit

Permalink
Merge branch 'dev' into mobility-profile-routing-2
Browse files Browse the repository at this point in the history
  • Loading branch information
binh-dam-ibigroup authored Nov 6, 2024
2 parents e60f694 + 17eee37 commit f5074c8
Show file tree
Hide file tree
Showing 16 changed files with 202 additions and 110 deletions.
6 changes: 5 additions & 1 deletion example-config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,11 @@ modes:
iconName: wheelchair
type: CHECKBOX # Possible options: CHECKBOX, SUBMODE, SLIDER, DROPDOWN
transitModes:
- mode: BUS
# Mode can be a string or an array of strings.
- mode: ["TROLLEYBUS", "BUS"]
# When mode is an array an overrideMode must be provided.
# This specifies the displayed mode used for icon and URL param.
overrideMode: BUS
label: Bus
# A mode color can be added, used throughout the application,
# most notably in the enhanced stop viewer bubble
Expand Down
27 changes: 19 additions & 8 deletions lib/actions/apiV2.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import {
import {
getRouteColorBasedOnSettings,
getRouteIdForPattern,
getRouteTextColorBasedOnSettings,
routeIsValid
} from '../util/viewer'
import { isLastStop } from '../util/stop-times'
Expand Down Expand Up @@ -1135,20 +1136,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
2 changes: 1 addition & 1 deletion lib/actions/form.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export function resetForm(full = false) {
const options = getTripOptionsFromQuery(defaultQuery)
// Default mode is currently WALK,TRANSIT. We need to update this value
// here to match the list of modes, otherwise the form will break.
options.mode = ['WALK', ...transitModes.map((m) => m.mode)].join(',')
options.mode = ['WALK', ...transitModes.flatMap((m) => m.mode)].join(',')
dispatch(settingQueryParam(options))
}
if (full) {
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))
42 changes: 34 additions & 8 deletions lib/components/form/advanced-settings-panel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ import {
onSettingsUpdate,
pipe,
populateSettingWithIcon,
setModeButton
setModeButton,
tripPlannerValidationErrors
} from './util'
import { setModeButtonEnabled } from './batch-settings'
import { styledCheckboxCss } from './styled'
Expand Down Expand Up @@ -111,8 +112,11 @@ const DtSelectorContainer = styled.div`
`

const AdvancedSettingsPanel = ({
autoPlan,
closeAdvancedSettings,
currentQuery,
enabledModeButtons,
handlePlanTrip,
innerRef,
modeButtonOptions,
modeSettingDefinitions,
Expand All @@ -121,8 +125,11 @@ const AdvancedSettingsPanel = ({
setCloseAdvancedSettingsWithDelay,
setQueryParam
}: {
autoPlan: boolean
closeAdvancedSettings: () => void
currentQuery: any
enabledModeButtons: string[]
handlePlanTrip: () => void
innerRef: RefObject<HTMLDivElement>
modeButtonOptions: ModeButtonDefinition[]
modeSettingDefinitions: ModeSetting[]
Expand Down Expand Up @@ -177,11 +184,29 @@ const AdvancedSettingsPanel = ({
)
)


const tripFormErrors = tripPlannerValidationErrors(currentQuery, intl)

const closePanel = useCallback(() => {
// Only autoplan if there are no validation errors
tripFormErrors.length === 0 && autoPlan && handlePlanTrip()
closeAdvancedSettings()
}, [autoPlan, closeAdvancedSettings, handlePlanTrip, tripFormErrors.length])

const handleModeButtonToggle = setModeButton(
enabledModeButtons,
onSettingsUpdate(setQueryParam)
)

const handleAllSubmodesDisabled = (modeButton: ModeButtonDefinition) => {
handleModeButtonToggle(modeButton.key, false)
}

const onSaveAndReturnClick = useCallback(async () => {
await setCloseAdvancedSettingsWithDelay()
setClosingBySave(true)
closeAdvancedSettings()
}, [closeAdvancedSettings, setCloseAdvancedSettingsWithDelay])
closePanel()
}, [closePanel, setCloseAdvancedSettingsWithDelay])

return (
<PanelOverlay className="advanced-settings" ref={innerRef}>
Expand All @@ -190,7 +215,7 @@ const AdvancedSettingsPanel = ({
aria-label={closeButtonText}
id="close-advanced-settings-button"
onClick={() => {
closeAdvancedSettings()
closePanel()
}}
title={closeButtonText}
>
Expand Down Expand Up @@ -221,11 +246,9 @@ const AdvancedSettingsPanel = ({
id: 'components.BatchSearchScreen.submodeSelectorLabel'
})}
modeButtons={processedModeButtons}
onAllSubmodesDisabled={handleAllSubmodesDisabled}
onSettingsUpdate={onSettingsUpdate(setQueryParam)}
onToggleModeButton={setModeButton(
enabledModeButtons,
onSettingsUpdate(setQueryParam)
)}
onToggleModeButton={handleModeButtonToggle}
/>
{saveAndReturnButton && (
<ReturnToTripPlanButton
Expand Down Expand Up @@ -256,9 +279,12 @@ const mapStateToProps = (state: AppReduxState) => {
state.otp.modeSettingDefinitions || [],
modes?.initialState?.modeSettingValues || {}
)

const { autoPlan } = state.otp.config
const saveAndReturnButton =
state.otp.config?.advancedSettingsPanel?.saveAndReturnButton
return {
autoPlan: autoPlan !== false,
currentQuery: state.otp.currentQuery,
// TODO: Duplicated in apiv2.js
enabledModeButtons:
Expand Down
13 changes: 2 additions & 11 deletions lib/components/form/batch-settings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,8 @@ import { ModeButtonDefinition } from '@opentripplanner/types'
import { Search } from '@styled-icons/fa-solid/Search'
import { SyncAlt } from '@styled-icons/fa-solid/SyncAlt'
import { useIntl } from 'react-intl'
import React, { useCallback, useContext, useState } from 'react'
import React, { useContext, useState } from 'react'

import * as apiActions from '../../actions/api'
import * as formActions from '../../actions/form'
import { ComponentContext } from '../../util/contexts'
import { getActiveSearch, hasValidLocation } from '../../util/state'
Expand All @@ -16,7 +15,6 @@ import { StyledIconWrapper } from '../util/styledIcon'

import {
addModeButtonIcon,
alertUserTripPlan,
modesQueryParamConfig,
onSettingsUpdate,
pipe,
Expand All @@ -39,7 +37,6 @@ type Props = {
modeButtonOptions: ModeButtonDefinition[]
onPlanTripClick: () => void
openAdvancedSettings: () => void
routingQuery: any
setQueryParam: (evt: any) => void
spacedOutModeSelector?: boolean
}
Expand All @@ -64,7 +61,6 @@ function BatchSettings({
modeButtonOptions,
onPlanTripClick,
openAdvancedSettings,
routingQuery,
setQueryParam,
spacedOutModeSelector
}: Props) {
Expand All @@ -80,10 +76,6 @@ function BatchSettings({
pipe(addModeButtonIcon(ModeIcon), setModeButtonEnabled(enabledModeButtons))
)

const _planTrip = useCallback(() => {
alertUserTripPlan(intl, currentQuery, onPlanTripClick, routingQuery)
}, [currentQuery, intl, onPlanTripClick, routingQuery])

const baseColor = getBaseColor()

const accentColor = getDarkenedBaseColor()
Expand All @@ -109,7 +101,7 @@ function BatchSettings({
/>
<PlanTripButton
id="plan-trip"
onClick={_planTrip}
onClick={onPlanTripClick}
title={intl.formatMessage({
id: 'components.BatchSettings.planTripTooltip'
})}
Expand Down Expand Up @@ -151,7 +143,6 @@ const mapStateToProps = (state: any) => {
}

const mapDispatchToProps = {
routingQuery: apiActions.routingQuery,
setQueryParam: formActions.setQueryParam
}

Expand Down
20 changes: 14 additions & 6 deletions lib/components/form/util.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -72,13 +72,10 @@ export const setModeButton =
)
}

export const alertUserTripPlan = (
intl: IntlShape,
export const tripPlannerValidationErrors = (
currentQuery: any,
onPlanTripClick: () => void,
routingQuery: () => any
): void => {
// Check for any validation issues in query.
intl: IntlShape
): string[] => {
const issues: string[] = []
if (!hasValidLocation(currentQuery, 'from')) {
issues.push(intl.formatMessage({ id: 'components.BatchSettings.origin' }))
Expand All @@ -88,6 +85,17 @@ export const alertUserTripPlan = (
intl.formatMessage({ id: 'components.BatchSettings.destination' })
)
}
return issues
}

export const alertUserTripPlan = (
intl: IntlShape,
currentQuery: any,
onPlanTripClick: () => void,
routingQuery: () => any
): void => {
// Check for any validation issues in query and alert user.
const issues = tripPlannerValidationErrors(currentQuery, intl)
onPlanTripClick()
if (issues.length > 0) {
// TODO: replace with less obtrusive validation.
Expand Down
7 changes: 6 additions & 1 deletion lib/components/map/default-map.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,12 @@ class DefaultMap extends Component {

// Generate operator logos to pass through OTP tile layer to map-popup
getEntityPrefix = (entity) => {
const stopId = entity.gtfsId
// In the case that we are dealing with a station, use the first stop of the station
const firstStopOfStationId = entity.stops
? JSON.parse(entity.stops)[0]
: false

const stopId = firstStopOfStationId || entity.gtfsId
this.props.findStopTimesForStop({
date: getCurrentDate(),
onlyRequestForOperators: true,
Expand Down
Loading

0 comments on commit f5074c8

Please sign in to comment.