-
Notifications
You must be signed in to change notification settings - Fork 58
Improve trip settings #323
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
5a25d9c
c6cf7dc
41084cd
0acd10d
a990abc
337bb96
f7efc70
6c40335
77affe0
42a08c1
8dc5971
4801a00
b30a2ef
b2baccf
af09bb5
2dd1821
79f1545
814d9df
2487512
ec90a40
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,32 +1,107 @@ | ||
| import { Field } from 'formik' | ||
| import React, { Component } from 'react' | ||
| import { Alert, Checkbox, ControlLabel, FormControl, FormGroup, Glyphicon, HelpBlock, Radio } from 'react-bootstrap' | ||
| import { Alert, FormControl, Glyphicon } from 'react-bootstrap' | ||
| import styled from 'styled-components' | ||
|
|
||
| import Icon from '../../narrative/icon' | ||
|
|
||
| const notificationChannelLabels = { | ||
| email: 'email', | ||
| sms: 'SMS' | ||
| } | ||
|
|
||
| // Element styles | ||
| const SettingsList = styled.ul` | ||
| border-spacing: 0 10px; | ||
| display: table; | ||
| padding-left: 0; | ||
| width: 100%; | ||
| label { | ||
| font-weight: inherit; | ||
| } | ||
| & > li { | ||
| align-items: center; | ||
| display: block; | ||
| } | ||
| ` | ||
|
|
||
| // Using table display for this element, so that all dropdowns occupy the same width. | ||
| // (Bootstrap already sets them to occupy 100% of the width of the parent, i.e. the logical cell.) | ||
| const SettingsListWithAlign = styled(SettingsList)` | ||
| & > li { | ||
| display: table-row; | ||
| & > * { | ||
| display: table-cell; | ||
| } | ||
| & > label { | ||
| padding-right: 10px; | ||
| } | ||
| } | ||
| ` | ||
|
|
||
| const InlineFormControl = styled(FormControl)` | ||
| display: inline-block; | ||
| margin: 0 0.5em; | ||
| width: auto; | ||
| ` | ||
|
|
||
| const SettingsToggle = styled.button` | ||
| background: none; | ||
| border: none; | ||
| padding: 0; | ||
| & span.fa { | ||
| line-height: 150%; | ||
| } | ||
| ` | ||
|
|
||
| /** | ||
| * A label followed by a dropdown control. | ||
| */ | ||
| const Select = ({ children, Control = FormControl, label, name }) => ( | ||
| // <Field> is kept outside of <label> to accommodate layout in table/grid cells. | ||
| <> | ||
| <label htmlFor={name}>{label}</label> | ||
| <Field | ||
| as={Control} | ||
| componentClass='select' | ||
| id={name} | ||
| name={name} | ||
| > | ||
| {children} | ||
| </Field> | ||
| </> | ||
| ) | ||
|
|
||
| /** | ||
| * This component wraps the elements to edit trip notification settings. | ||
| */ | ||
| class TripNotificationsPane extends Component { | ||
| /** | ||
| * Handles the conversion of 'true'/'false' strings in event data into boolean | ||
| * to update the Formik state. | ||
| */ | ||
| _handleIsActiveChange = e => { | ||
| const { handleChange } = this.props | ||
| handleChange({ target: { | ||
| name: 'isActive', | ||
| value: e.target.value === 'true' | ||
| }}) | ||
| state = { | ||
| showAdvancedSettings: false | ||
| } | ||
|
|
||
| render () { | ||
| const { notificationChannel, values: monitoredTrip } = this.props | ||
| _handleToggleAdvancedSettings = () => { | ||
| this.setState({ showAdvancedSettings: !this.state.showAdvancedSettings }) | ||
| } | ||
|
|
||
| _handleDelayThresholdChange = e => { | ||
| // To spare users the complexity of the departure/arrival delay thresholds, | ||
| // set both the arrival and departure variance delays to the selected value. | ||
| const { setFieldValue } = this.props | ||
| const threshold = e.target.value | ||
| setFieldValue('arrivalVarianceMinutesThreshold', threshold) | ||
| setFieldValue('departureVarianceMinutesThreshold', threshold) | ||
| } | ||
|
|
||
| // Set text and visuals based on user's notificationChannel. | ||
| render () { | ||
| const { notificationChannel, values } = this.props | ||
| const areNotificationsDisabled = notificationChannel === 'none' | ||
| const notificationChannelText = !areNotificationsDisabled && | ||
| notificationChannelLabels[notificationChannel] | ||
| // Define a common trip delay field for simplicity, set to the smallest between the | ||
| // retrieved departure/arrival delay attributes. | ||
| const commonDelayThreshold = Math.min( | ||
| values.arrivalVarianceMinutesThreshold, | ||
| values.departureVarianceMinutesThreshold | ||
| ) | ||
|
|
||
| let notificationSettingsContent | ||
| if (areNotificationsDisabled) { | ||
|
|
@@ -42,66 +117,72 @@ class TripNotificationsPane extends Component { | |
| </Alert> | ||
| ) | ||
| } else { | ||
| const { showAdvancedSettings } = this.state | ||
| notificationSettingsContent = ( | ||
| <> | ||
| <FormGroup> | ||
| <ControlLabel id='is-active-label'>Would you like to receive notifications about this trip?</ControlLabel> | ||
| <div role='group' aria-labelledby='is-active-label'> | ||
| <Radio | ||
| checked={monitoredTrip.isActive} | ||
| name='isActive' | ||
| onChange={this._handleIsActiveChange} | ||
| value | ||
| <h4>Notify me via {notificationChannelLabels[notificationChannel]} when:</h4> | ||
| <SettingsListWithAlign> | ||
| <li> | ||
| <Select | ||
| label='There is a realtime alert flagged on my journey' | ||
| name='notifyOnAlert' | ||
| > | ||
| Yes | ||
| </Radio> | ||
| <Radio | ||
| checked={!monitoredTrip.isActive} | ||
| name='isActive' | ||
| onChange={this._handleIsActiveChange} | ||
| value={false} | ||
| <option value>Yes (default)</option> | ||
| <option value={false}>No</option> | ||
| </Select> | ||
| </li> | ||
| <li> | ||
| <Select | ||
| label='An alternative route or transfer point is recommended' | ||
| name='notifyOnItineraryChange' | ||
| > | ||
| No | ||
| </Radio> | ||
| </div> | ||
| <HelpBlock> | ||
| Note: you will be notified by {notificationChannelText}. This can be changed in | ||
| your account settings once the trip has been saved. | ||
| </HelpBlock> | ||
| </FormGroup> | ||
|
|
||
| <FormGroup> | ||
| <ControlLabel>When would you like to receive notifications about delays or disruptions to your trip?</ControlLabel> | ||
|
|
||
| <FormGroup> | ||
| <ControlLabel>Check for delays or disruptions:</ControlLabel> | ||
| <Field | ||
| as={FormControl} | ||
| <option value>Yes (default)</option> | ||
| <option value={false}>No</option> | ||
| </Select> | ||
| </li> | ||
| <li> | ||
| <label htmlFor='commonDelayThreshold'>There are delays or disruptions of more than</label> | ||
| <FormControl | ||
| componentClass='select' | ||
| name='leadTimeInMinutes' | ||
| id='commonDelayThreshold' | ||
| onChange={this._handleDelayThresholdChange} | ||
| value={commonDelayThreshold} | ||
| > | ||
| <option value={15}>15 min. prior</option> | ||
| <option value={30}>30 min. prior (default)</option> | ||
| <option value={45}>45 min. prior</option> | ||
| <option value={60}>60 min. prior</option> | ||
| </Field> | ||
| </FormGroup> | ||
| <Alert bsStyle='warning'> | ||
| Under construction! | ||
| <FormGroup> | ||
| <ControlLabel>Notify me if:</ControlLabel> | ||
| <Checkbox>A different route or transfer point is recommended</Checkbox> | ||
| <Checkbox>There is an alert for a route or stop that is part of my journey</Checkbox> | ||
| <option value={5}>5 min (default)</option> | ||
| <option value={10}>10 min</option> | ||
| <option value={15}>15 min</option> | ||
| </FormControl> | ||
| </li> | ||
| </SettingsListWithAlign> | ||
|
|
||
| Your arrival or departure time changes by more than: | ||
| <FormControl componentClass='select' defaultValue={5} placeholder='select'> | ||
| <option value={5}>5 min. (default)</option> | ||
| <option value={10}>10 min.</option> | ||
| <option value={15}>15 min.</option> | ||
| </FormControl> | ||
| </FormGroup> | ||
| </Alert> | ||
| </FormGroup> | ||
| <h4> | ||
| <SettingsToggle | ||
| aria-expanded={showAdvancedSettings} | ||
| aria-label='Toggle advanced settings' | ||
| onClick={this._handleToggleAdvancedSettings} | ||
| type='button' | ||
| > | ||
| <Icon type={showAdvancedSettings ? 'caret-down' : 'caret-right'} /> | ||
| Advanced settings | ||
| </SettingsToggle> | ||
| </h4> | ||
| {showAdvancedSettings && ( | ||
| <SettingsList> | ||
| <li> | ||
| <Select | ||
| Control={InlineFormControl} | ||
| label='Monitor this trip' | ||
| name='leadTimeInMinutes' | ||
| > | ||
| <option value={15}>15 min</option> | ||
| <option value={30}>30 min (default)</option> | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Because it's not the first option, 30 minutes is not selected by default. For this select and the others, we may want to add a selected prop? I'm not too familiar with how Formik handles
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Forgot about that, glad you pointed it out.
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That was trickier. The default value was already populated correctly in the trip object, but the I passed the wrong component for styling, so it's fixed now in 4801a00. |
||
| <option value={45}>45 min</option> | ||
| <option value={60}>1 hour</option> | ||
| </Select> | ||
| before it begins until it ends. | ||
| </li> | ||
| </SettingsList> | ||
| )} | ||
| </> | ||
| ) | ||
| } | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After seeing this in action, let's make all these settings flush with the left edge (i.e., no indentation). Same goes for the below item in Advanced Settings.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated in 4801a00.