Skip to content

Commit 7525efa

Browse files
authored
Merge pull request #183 from opentripplanner/form-fixes
Add SettingsPreview and TripDetails messages
2 parents c66177f + 0db732d commit 7525efa

File tree

4 files changed

+74
-10
lines changed

4 files changed

+74
-10
lines changed

Diff for: lib/components/form/form.css

+8
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,14 @@
126126
font-size: 14px;
127127
line-height: 1.4;
128128
margin-top: -1px;
129+
white-space: pre-wrap;
130+
}
131+
132+
.otp .settings-preview .summary.tall {
133+
line-height: 2.6;
134+
}
135+
136+
.otp:not(.mobile) .settings-preview .summary {
129137
/* Prevent overflow from being multi-line. 36px is edit button width. */
130138
width: calc(100% - 36px);
131139
}

Diff for: lib/components/form/settings-preview.js

+14-4
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import PropTypes from 'prop-types'
33
import { Button } from 'react-bootstrap'
44
import { connect } from 'react-redux'
55

6+
import { mergeMessages } from '../../util/messages'
67
import { isNotDefaultQuery } from '../../util/query'
78

89
class SettingsPreview extends Component {
@@ -22,11 +23,15 @@ class SettingsPreview extends Component {
2223
}
2324

2425
static defaultProps = {
25-
editButtonText: <i className='fa fa-pencil' />
26+
editButtonText: <i className='fa fa-pencil' />,
27+
messages: {
28+
label: 'Transit Options\n& Preferences'
29+
}
2630
}
2731

2832
render () {
29-
const { config, query, caret, editButtonText } = this.props
33+
const { caret, config, query, editButtonText } = this.props
34+
const messages = mergeMessages(SettingsPreview.defaultProps, this.props)
3035
// Show dot indicator if the current query differs from the default query.
3136
let showDot = isNotDefaultQuery(query, config)
3237
const button = (
@@ -37,10 +42,14 @@ class SettingsPreview extends Component {
3742
{showDot && <div className='dot' />}
3843
</div>
3944
)
40-
45+
// Add tall class to account for vertical centering if there is only
46+
// one line in the label (default is 2).
47+
const addClass = messages.label.match(/\n/) ? '' : ' tall'
4148
return (
4249
<div className='settings-preview' onClick={this.props.onClick}>
43-
<div className='summary'>Transit Options<br />&amp; Preferences</div>
50+
<div className={`summary${addClass}`}>
51+
{messages.label}
52+
</div>
4453
{button}
4554
<div style={{ clear: 'both' }} />
4655
</div>
@@ -51,6 +60,7 @@ class SettingsPreview extends Component {
5160
const mapStateToProps = (state, ownProps) => {
5261
return {
5362
config: state.otp.config,
63+
messages: state.otp.config.language.settingsPreview,
5464
query: state.otp.currentQuery
5565
}
5666
}

Diff for: lib/components/narrative/trip-details.js

+37-6
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,31 @@ import { VelocityTransitionGroup } from 'velocity-react'
55
import moment from 'moment'
66

77
import { calculateFares, calculatePhysicalActivity, getTimeZoneOffset } from '../../util/itinerary'
8+
import { mergeMessages } from '../../util/messages'
89
import { formatTime, getTimeFormat, getLongDateFormat } from '../../util/time'
910

1011
class TripDetails extends Component {
12+
static defaultProps = {
13+
// Note: messages with default null values included here for visibility.
14+
// Overriding with a truthy string value will cause the expandable help
15+
// message to appear in trip details.
16+
messages: {
17+
at: 'at',
18+
caloriesBurned: 'Calories Burned',
19+
// FIXME: Add templated string description.
20+
caloriesBurnedDescription: null,
21+
depart: 'Depart',
22+
departDescription: null,
23+
title: 'Trip Details',
24+
fare: 'Fare',
25+
transitFare: 'Transit Fare',
26+
transitFareDescription: null
27+
}
28+
}
29+
1130
render () {
1231
const { itinerary, timeFormat, longDateFormat } = this.props
32+
const messages = mergeMessages(TripDetails.defaultProps, this.props)
1333
const date = moment(itinerary.startTime)
1434

1535
// process the transit fare
@@ -25,15 +45,16 @@ class TripDetails extends Component {
2545
fare = (
2646
<span>
2747
{transitFare && (
28-
<span>Transit Fare: <b>{centsToString(transitFare)}</b></span>
48+
<span>{messages.transitFare}: <b>{centsToString(transitFare)}</b></span>
2949
)}
3050
{minTNCFare !== 0 && (
3151
<span>
3252
<br />
3353
<span style={{ textTransform: 'capitalize' }}>
3454
{companies.toLowerCase()}
3555
</span>{' '}
36-
Fare: <b>{dollarsToString(minTNCFare)} - {dollarsToString(maxTNCFare)}</b>
56+
{messages.fare}:{' '}
57+
<b>{dollarsToString(minTNCFare)} - {dollarsToString(maxTNCFare)}</b>
3758
</span>
3859
)}
3960
</span>
@@ -50,27 +71,36 @@ class TripDetails extends Component {
5071

5172
return (
5273
<div className='trip-details'>
53-
<div className='trip-details-header'>Trip Details</div>
74+
<div className='trip-details-header'>{messages.title}</div>
5475
<div className='trip-details-body'>
5576
<TripDetail
77+
description={messages.departDescription}
5678
icon={<i className='fa fa-calendar' />}
5779
summary={
5880
<span>
59-
<span>Depart <b>{date.format(longDateFormat)}</b></span>
60-
{this.props.routingType === 'ITINERARY' && <span> at <b>{formatTime(itinerary.startTime, timeOptions)}</b></span>}
81+
<span>{messages.depart} <b>{date.format(longDateFormat)}</b></span>
82+
{this.props.routingType === 'ITINERARY' &&
83+
<span>
84+
{' '}{messages.at}{' '}
85+
<b>{formatTime(itinerary.startTime, timeOptions)}</b>
86+
</span>
87+
}
6188
</span>
6289
}
6390
/>
6491
{fare && (
6592
<TripDetail
93+
description={messages.transitFareDescription}
6694
icon={<i className='fa fa-money' />}
6795
summary={fare}
6896
/>
6997
)}
7098
{caloriesBurned > 0 && (
7199
<TripDetail
72100
icon={<i className='fa fa-heartbeat' />}
73-
summary={<span>Calories Burned: <b>{Math.round(caloriesBurned)}</b></span>}
101+
summary={<span>{messages.caloriesBurned}: <b>{Math.round(caloriesBurned)}</b></span>}
102+
// FIXME: Come up with a way to replace the caloriesBurnedDescription text with
103+
// templated strings.
74104
description={
75105
<span>
76106
Calories burned is based on <b>{Math.round(walkDuration / 60)} minute(s)</b>{' '}
@@ -147,6 +177,7 @@ class TripDetail extends Component {
147177

148178
const mapStateToProps = (state, ownProps) => {
149179
return {
180+
messages: state.otp.config.language.tripDetails,
150181
routingType: state.otp.currentQuery.routingType,
151182
tnc: state.otp.tnc,
152183
timeFormat: getTimeFormat(state.otp.config),

Diff for: lib/util/messages.js

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
/**
2+
* Takes component's default props and its instance props and returns the
3+
* merged messages props. The returned object will ensure that the default
4+
* messages are substituted for any translation strings that were missing in the
5+
* props. Note: this does not account for messages in nested objects (e.g.,
6+
* messages.header.description).
7+
*/
8+
export function mergeMessages (defaultProps, props) {
9+
const defaultMessages = defaultProps.messages || {}
10+
const propsMessages = props.messages || {}
11+
return {
12+
...defaultMessages,
13+
...propsMessages
14+
}
15+
}

0 commit comments

Comments
 (0)