Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ Object {
"filter": "ALL",
"sort": Object {
"direction": "ASC",
"type": "BEST",
"type": null,
},
},
"location": Object {
Expand Down
5 changes: 2 additions & 3 deletions lib/components/form/error-message.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import PropTypes from 'prop-types'
import { connect } from 'react-redux'
import TripTools from '../narrative/trip-tools'

import { getActiveSearch } from '../../util/state'
import { getActiveErrors } from '../../util/state'

class ErrorMessage extends Component {
static propTypes = {
Expand Down Expand Up @@ -45,9 +45,8 @@ class ErrorMessage extends Component {
// connect to the redux store

const mapStateToProps = (state, ownProps) => {
const activeSearch = getActiveSearch(state.otp)
return {
error: activeSearch && activeSearch.response && activeSearch.response.error,
error: getActiveErrors(state.otp)[0],
currentQuery: state.otp.currentQuery,
errorMessages: state.otp.config.errorMessages
}
Expand Down
9 changes: 7 additions & 2 deletions lib/components/mobile/results-screen.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,12 @@ import MobileNavigationBar from './navigation-bar'
import { MobileScreens, setMobileScreen } from '../../actions/ui'
import { setUseRealtimeResponse } from '../../actions/narrative'
import { clearActiveSearch } from '../../actions/form'
import { getActiveItineraries, getActiveSearch, getRealtimeEffects } from '../../util/state'
import {
getActiveErrors,
getActiveItineraries,
getActiveSearch,
getRealtimeEffects
} from '../../util/state'

const LocationContainer = styled.div`
font-weight: 300;
Expand Down Expand Up @@ -239,7 +244,7 @@ const mapStateToProps = (state, ownProps) => {
return {
query: state.otp.currentQuery,
realtimeEffects,
error: response && response.error,
error: getActiveErrors(state.otp)[0],
resultCount:
response
? activeSearch.query.routingType === 'ITINERARY'
Expand Down
8 changes: 6 additions & 2 deletions lib/components/narrative/narrative-routing-results.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,11 @@ import Loading from './loading'
import TabbedItineraries from './tabbed-itineraries'
import ErrorMessage from '../form/error-message'

import { getActiveSearch, getActiveItineraries } from '../../util/state'
import {
getActiveErrors,
getActiveItineraries,
getActiveSearch
} from '../../util/state'
import { setMainPanelContent } from '../../actions/ui'

class NarrativeRoutingResults extends Component {
Expand Down Expand Up @@ -47,7 +51,7 @@ const mapStateToProps = (state, ownProps) => {
const pending = activeSearch ? Boolean(activeSearch.pending) : false
return {
mainPanelContent: state.otp.ui.mainPanelContent,
error: activeSearch && activeSearch.response && activeSearch.response.error,
error: getActiveErrors(state.otp)[0],
itineraries: getActiveItineraries(state.otp),
pending,
routingType: activeSearch && activeSearch.query.routingType
Expand Down
4 changes: 3 additions & 1 deletion lib/reducers/create-otp-reducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import coreUtils from '@opentripplanner/core-utils'

import { MainPanelContent, MobileScreens } from '../actions/ui'
import {getTimestamp} from '../util/state'
import {isBatchRoutingEnabled} from '../util/itinerary'

const { isTransit, getTransitModes } = coreUtils.itinerary
const { matchLatLon } = coreUtils.map
Expand Down Expand Up @@ -161,7 +162,8 @@ export function getInitialState (userDefinedConfig, initialQuery) {
filter: 'ALL',
sort: {
direction: 'ASC',
type: 'BEST'
// Only apply custom sort if batch routing is enabled.
type: isBatchRoutingEnabled(config) ? 'BEST' : null
}
},
location: {
Expand Down
4 changes: 4 additions & 0 deletions lib/util/itinerary.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,7 @@ export function getLeafletItineraryBounds (itinerary) {
export function getLeafletLegBounds (leg) {
return latLngBounds(coreUtils.itinerary.getLegBounds(leg))
}

export function isBatchRoutingEnabled (otpConfig) {
return Boolean(otpConfig.routingTypes.find(t => t.key === 'BATCH'))
}
68 changes: 39 additions & 29 deletions lib/util/state.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ export function getActiveItineraries (otpState) {
}
const {filter, sort} = otpState.filter
const {direction, type} = sort
return itineraries
const filteredItineraries = itineraries
.filter(itinerary => {
switch (filter) {
case 'ALL':
Expand All @@ -91,34 +91,44 @@ export function getActiveItineraries (otpState) {
return true
}
})
.sort((a, b) => {
switch (type) {
case 'WALKTIME':
if (direction === 'ASC') return a.walkTime - b.walkTime
else return b.walkTime - a.walkTime
case 'ARRIVALTIME':
if (direction === 'ASC') return a.endTime - b.endTime
else return b.endTime - a.endTime
case 'DEPARTURETIME':
if (direction === 'ASC') return a.startTime - b.startTime
else return b.startTime - a.startTime
case 'DURATION':
if (direction === 'ASC') return a.duration - b.duration
else return b.duration - a.duration
case 'COST':
const aTotal = getTotalFare(a, config)
const bTotal = getTotalFare(b, config)
if (direction === 'ASC') return aTotal - bTotal
else return bTotal - aTotal
default:
if (type !== 'BEST') console.warn(`Sort (${type}) not supported. Defaulting to BEST.`)
// FIXME: Fully implement default sort algorithm.
const aCost = calculateItineraryCost(a, config)
const bCost = calculateItineraryCost(b, config)
if (direction === 'ASC') return aCost - bCost
else return bCost - aCost
}
})
// If no sort type is provided (e.g., because batch routing is not enabled),
// do not sort itineraries (default sort from API response is used).
return !type
? filteredItineraries
: filteredItineraries.sort((a, b) => sortItineraries(type, direction, a, b, config))
}

/**
* Array sort function for itineraries (in batch routing context) that attempts
* to sort based on the type/direction specified.
*/
function sortItineraries (type, direction, a, b, config) {
switch (type) {
case 'WALKTIME':
if (direction === 'ASC') return a.walkTime - b.walkTime
else return b.walkTime - a.walkTime
case 'ARRIVALTIME':
if (direction === 'ASC') return a.endTime - b.endTime
else return b.endTime - a.endTime
case 'DEPARTURETIME':
if (direction === 'ASC') return a.startTime - b.startTime
else return b.startTime - a.startTime
case 'DURATION':
if (direction === 'ASC') return a.duration - b.duration
else return b.duration - a.duration
case 'COST':
const aTotal = getTotalFare(a, config)
const bTotal = getTotalFare(b, config)
if (direction === 'ASC') return aTotal - bTotal
else return bTotal - aTotal
default:
if (type !== 'BEST') console.warn(`Sort (${type}) not supported. Defaulting to BEST.`)
// FIXME: Fully implement default sort algorithm.
const aCost = calculateItineraryCost(a, config)
const bCost = calculateItineraryCost(b, config)
if (direction === 'ASC') return aCost - bCost
else return bCost - aCost
}
}

/**
Expand Down