Skip to content

Commit 24cf3d0

Browse files
authored
Merge pull request #359 from opentripplanner/rental-errors
Consolidate batch-routing errors into errors section
2 parents 29d455d + 9cba448 commit 24cf3d0

File tree

5 files changed

+376
-177
lines changed

5 files changed

+376
-177
lines changed

Diff for: lib/components/form/error-message.js

+16-39
Original file line numberDiff line numberDiff line change
@@ -1,54 +1,31 @@
1-
import React, { Component } from 'react'
2-
import PropTypes from 'prop-types'
1+
import React from 'react'
32
import { connect } from 'react-redux'
43
import TripTools from '../narrative/trip-tools'
54

6-
import { getActiveError } from '../../util/state'
5+
import { getActiveError, getErrorMessage } from '../../util/state'
76

8-
class ErrorMessage extends Component {
9-
static propTypes = {
10-
error: PropTypes.object
11-
}
12-
13-
render () {
14-
const { error, errorMessages, currentQuery } = this.props
15-
if (!error) return null
16-
17-
let message = error.msg
18-
// check for configuration-defined message override
19-
if (errorMessages) {
20-
const msgConfig = errorMessages.find(m => m.id === error.id)
21-
if (msgConfig) {
22-
if (msgConfig.modes) {
23-
for (const mode of msgConfig.modes) {
24-
if (currentQuery.mode.includes(mode)) {
25-
message = msgConfig.msg
26-
break
27-
}
28-
}
29-
} else message = msgConfig.msg
30-
}
31-
}
7+
const ErrorMessage = ({ message }) => {
8+
if (!message) return null
329

33-
return (
34-
<div className='error-message'>
35-
<div className='header'>
36-
<i className='fa fa-exclamation-circle' /> Could Not Plan Trip
37-
</div>
38-
<div className='message'>{message}</div>
39-
<TripTools buttonTypes={['START_OVER', 'REPORT_ISSUE']} />
10+
return (
11+
<div className='error-message'>
12+
<div className='header'>
13+
<i className='fa fa-exclamation-circle' /> Could Not Plan Trip
4014
</div>
41-
)
42-
}
15+
<div className='message'>{message}</div>
16+
<TripTools buttonTypes={['START_OVER', 'REPORT_ISSUE']} />
17+
</div>
18+
)
4319
}
4420

4521
// connect to the redux store
4622

4723
const mapStateToProps = (state, ownProps) => {
4824
return {
49-
error: getActiveError(state.otp),
50-
currentQuery: state.otp.currentQuery,
51-
errorMessages: state.otp.config.errorMessages
25+
message: getErrorMessage(
26+
getActiveError(state.otp),
27+
state.otp.config.errorMessages
28+
)
5229
}
5330
}
5431

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import { getCompanyIcon } from '@opentripplanner/icons/lib/companies'
2+
import styled from 'styled-components'
3+
4+
import Icon from '../narrative/icon'
5+
import { getErrorMessage } from '../../util/state'
6+
7+
const IssueContainer = styled.div`
8+
border-top: 1px solid grey;
9+
display: flex;
10+
padding: 10px;
11+
`
12+
13+
const IssueIconContainer = styled.div`
14+
font-size: 18px;
15+
height: 24px;
16+
width: 24px;
17+
`
18+
19+
const IssueContents = styled.div`
20+
font-size: 14px;
21+
margin-left: 10px;
22+
text-align: left;
23+
`
24+
25+
export default function NarrativeItinerariesErrors ({ errorMessages, errors }) {
26+
return errors.map((error, idx) => {
27+
let icon
28+
if (error.network) {
29+
const CompanyIcon = getCompanyIcon(error.network)
30+
icon = <CompanyIcon />
31+
} else {
32+
icon = <Icon className='text-warning' type='exclamation-triangle' />
33+
}
34+
return (
35+
<IssueContainer key={idx}>
36+
<IssueIconContainer>
37+
{icon}
38+
</IssueIconContainer>
39+
<IssueContents>
40+
{getErrorMessage(error, errorMessages)}
41+
</IssueContents>
42+
</IssueContainer>
43+
)
44+
})
45+
}
+112
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
import styled from 'styled-components'
2+
3+
import Icon from '../narrative/icon'
4+
import SaveTripButton from './save-trip-button'
5+
6+
const IssueButton = styled.button`
7+
background-color: #ECBE03;
8+
border: none;
9+
border-radius: 5px;
10+
display: inline-block;
11+
font-size: 12px;
12+
padding: 2px 4px;
13+
`
14+
15+
export default function NarrativeItinerariesHeader ({
16+
errors,
17+
itineraries,
18+
itineraryIsExpanded,
19+
onSortChange,
20+
onSortDirChange,
21+
onToggleShowErrors,
22+
onViewAllOptions,
23+
pending,
24+
showingErrors,
25+
sort
26+
}) {
27+
let resultText, titleText
28+
if (pending) {
29+
resultText = 'Finding your options...'
30+
titleText = 'Finding your options...'
31+
} else {
32+
const itineraryPlural = itineraries.length === 1
33+
? 'itinerary'
34+
: 'itineraries'
35+
const issuePlural = errors.length === 1
36+
? 'issue'
37+
: 'issues'
38+
resultText = `${itineraries.length} ${itineraryPlural} found.`
39+
titleText = errors.length > 0
40+
? `${itineraries.length} ${itineraryPlural} (and ${errors.length} ${issuePlural}) found`
41+
: resultText
42+
}
43+
44+
return (
45+
<div
46+
className='options header'
47+
style={{
48+
alignItems: 'end',
49+
display: 'flex'
50+
}}
51+
>
52+
{(itineraryIsExpanded || showingErrors)
53+
? <>
54+
<button
55+
className='clear-button-formatting'
56+
onClick={onViewAllOptions}
57+
>
58+
<Icon type='arrow-left' /> View all options
59+
</button>
60+
61+
{itineraryIsExpanded && (
62+
// marginLeft: auto is a way of making something "float right"
63+
// within a flex container
64+
// see https://stackoverflow.com/a/36182782/269834
65+
<div style={{marginLeft: 'auto'}}>
66+
<SaveTripButton />
67+
</div>
68+
)}
69+
</>
70+
: <>
71+
<div
72+
style={{flexGrow: 1}}
73+
title={titleText}
74+
>
75+
<span style={{
76+
marginRight: '10px'
77+
}}>
78+
{resultText}
79+
</span>
80+
{errors.length > 0 && (
81+
<IssueButton onClick={onToggleShowErrors}>
82+
<Icon style={{fontSize: 11, marginRight: 2}} type='warning' />
83+
<span>{errors.length} issues</span>
84+
</IssueButton>
85+
)}
86+
</div>
87+
<div style={{display: 'flex', float: 'right'}}>
88+
<button
89+
className='clear-button-formatting'
90+
onClick={onSortDirChange}
91+
style={{marginRight: '5px'}}
92+
>
93+
<Icon type={`sort-amount-${sort.direction.toLowerCase()}`} />
94+
</button>
95+
<select
96+
onBlur={onSortChange}
97+
onChange={onSortChange}
98+
value={sort.value}
99+
>
100+
<option value='BEST'>Best option</option>
101+
<option value='DURATION'>Duration</option>
102+
<option value='ARRIVALTIME'>Arrival time</option>
103+
<option value='DEPARTURETIME'>Departure time</option>
104+
<option value='WALKTIME'>Walk time</option>
105+
<option value='COST'>Cost</option>
106+
</select>
107+
</div>
108+
</>
109+
}
110+
</div>
111+
)
112+
}

0 commit comments

Comments
 (0)