Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
9e9b7ce
feat(saved trip): Add route and basic structure for saving trips.
binh-dam-ibigroup Jun 2, 2020
e13a9d5
Merge branch 'get-user-by-auth0-token' into add-save-trips
binh-dam-ibigroup Jun 3, 2020
700bed2
feat(SavedTripsWizard): Add content for SavedTripWizard
binh-dam-ibigroup Jun 5, 2020
c644cd7
improvement(SavedTripWizard): Add event handlers, build monitored tri…
binh-dam-ibigroup Jun 5, 2020
3f980cf
improvement(SavedTripWizard): Implement save to middleware.
binh-dam-ibigroup Jun 5, 2020
80c4425
feat(SavedTripEditor): Add very basic saved trip editor.
binh-dam-ibigroup Jun 8, 2020
f4c98cd
fix(SavedTripEditor): Fix deleting trips.
binh-dam-ibigroup Jun 9, 2020
80acefc
Merge branch 'add-trip-rq-history' into add-save-trips
binh-dam-ibigroup Jun 11, 2020
6b1fc36
refactor(TripSummary): Extract trip summary component and related cha…
binh-dam-ibigroup Jun 11, 2020
cafe68c
refactor(query): Reuse getQueryParamsFromQueryObj
binh-dam-ibigroup Jun 11, 2020
27a60ce
improvement(TripNotificationPane): Add style for info text.
binh-dam-ibigroup Jun 11, 2020
ae2331c
fix(monitoredtrip API): Change monitored trip URL to match API.
binh-dam-ibigroup Jun 12, 2020
debc8dc
Merge branch 'dev' into add-save-trips
binh-dam-ibigroup Jul 15, 2020
9ab83bf
refactor(SavedTripScreen): Finish merging changed from dev.
binh-dam-ibigroup Jul 15, 2020
0dde27d
refactor(SavedTripScreen): Rename AppNav -> DesktopNav
binh-dam-ibigroup Jul 16, 2020
4f05fb1
refactor(actions/form): Add unmerged file.
binh-dam-ibigroup Jul 16, 2020
2f0c2ba
refactor(util/query): Make query methods async per OTP-UI
binh-dam-ibigroup Jul 16, 2020
5c8f062
refactor(saved-trip-screen): Convert monitoredTrip.days to fields for…
binh-dam-ibigroup Jul 16, 2020
c3dcf9f
improvement(TripSummaryPane): Tweak text in TripSummaryPane
binh-dam-ibigroup Jul 16, 2020
9ecf017
improvement(SavedTripScreen): Improve button flow for trip editing.
binh-dam-ibigroup Jul 16, 2020
6c57944
chore(deps): Upgrade to @opentripplanner/core-utils 1.2.1
binh-dam-ibigroup Jul 16, 2020
180e1f9
Merge branch 'planparamstoquery-async' into add-save-trips
binh-dam-ibigroup Jul 16, 2020
f0d0346
refactor(util/query): Use planParamsToQueryAsync from OTP-UI/core-uti…
binh-dam-ibigroup Jul 16, 2020
04ee40f
refactor(saved-trip-* components): Refactors and comment tweaks per P…
binh-dam-ibigroup Jul 20, 2020
8541c05
refactor(Responsive): Finish rename prop.
binh-dam-ibigroup Jul 20, 2020
8061254
refactor(TripSummary): Remove unused async.
binh-dam-ibigroup Jul 20, 2020
563000c
style(TripSummaryPane): Fix lint
binh-dam-ibigroup Jul 21, 2020
9592581
refactor(LinkButton): Make BeginSaveTripButton more generic.
binh-dam-ibigroup Jul 21, 2020
0ce31e2
refactor(SavedTripScreen): Cleanup monitored trip state handling.
binh-dam-ibigroup Jul 21, 2020
9749c71
fix(TripSummary): Fix component unmount warning.
binh-dam-ibigroup Jul 21, 2020
fb2ffe2
fix(TripNotificationsPane): Fix uncontrolled component warning.
binh-dam-ibigroup Jul 21, 2020
d45cd8c
refactor(SavedTripScreen): Add links out of the saved trip screens.
binh-dam-ibigroup Jul 21, 2020
1f4ef52
refactor(TripNotificationPane): Add missing blank space.
binh-dam-ibigroup Jul 21, 2020
1dda92a
refactor(LineItinerary): Extend Trip save button to LineItinerary.
binh-dam-ibigroup Jul 21, 2020
0adf002
build(yarn.lock): Deduplicate yarn.lock.
binh-dam-ibigroup Jul 24, 2020
9b10f86
build(yarn.lock): Cleanup yarn.lock after yarn install using deduplic…
binh-dam-ibigroup Jul 24, 2020
b4e99d7
refactor: Light reformatting from PR comments.
binh-dam-ibigroup Jul 24, 2020
ad8e678
refactor(TripSummary): Improve state management.
binh-dam-ibigroup Jul 24, 2020
0048026
refactor(actions/user): Move monitored trip middleware calls to actio…
binh-dam-ibigroup Jul 24, 2020
9f18270
refactor(SavedTripList): Separate SavedTripList, enable savedtrips/:i…
binh-dam-ibigroup Jul 27, 2020
277d868
refactor(FavoriteLocationsPane): Address comment for setting a defaul…
binh-dam-ibigroup Jul 30, 2020
b0395b1
refactor(actions/user): Extract fetchUserMonitoredTrips func, rename …
binh-dam-ibigroup Jul 30, 2020
0281f40
refactor(TripSummary): Obtain from/to names directly from itinerary.
binh-dam-ibigroup Jul 30, 2020
76affb2
Merge branch 'dev' into add-save-trips
binh-dam-ibigroup Jul 30, 2020
7ace866
fix(LineItinerary): Pass timeOptions prop to ItineraryBody.
binh-dam-ibigroup Aug 7, 2020
d04b564
refactor(LineItinerary): Alphabetize
binh-dam-ibigroup Aug 7, 2020
5007601
Merge pull request #206 from opentripplanner/itinerary-timeformat
landonreed Aug 11, 2020
d77e617
refactor(util/monitored-trip): Rename vars. Remove unused file.
binh-dam-ibigroup Aug 11, 2020
982a877
docs(FavoriteLocationsPane): Add FIXMEs for initializing user.savedLo…
binh-dam-ibigroup Aug 11, 2020
ae58931
improvement(a11y): Add markup and props for Lighthouse scorecard.
binh-dam-ibigroup Aug 12, 2020
a6b1710
Merge pull request #174 from opentripplanner/add-save-trips
binh-dam-ibigroup Aug 13, 2020
4cc23b4
fix(a11y): Fix some a11y issues (landing page only, desktop and mobile).
binh-dam-ibigroup Aug 18, 2020
4b258e5
fix(a11y): Fix dependendency.
binh-dam-ibigroup Aug 18, 2020
f61e5b5
Merge pull request #210 from opentripplanner/commtrans-accessibility
binh-dam-ibigroup Aug 20, 2020
72875cb
Merge branch 'dev' into commtrans-accessibility-release
binh-dam-ibigroup Aug 20, 2020
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
20 changes: 13 additions & 7 deletions example.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,10 @@ class OtpRRExample extends Component {
<Grid>
<Row className='main-row'>
<Col sm={6} md={4} className='sidebar'>
<DefaultMainPanel LegIcon={MyLegIcon} ModeIcon={MyModeIcon} />
{/* <main> Needed for accessibility checks. TODO: Find a better place. */}
<main>
<DefaultMainPanel LegIcon={MyLegIcon} ModeIcon={MyModeIcon} />
</main>
</Col>
<Col sm={6} md={8} className='map-container'>
<Map />
Expand All @@ -97,12 +100,15 @@ class OtpRRExample extends Component {

/** mobile view **/
const mobileView = (
<MobileMain
LegIcon={MyLegIcon}
ModeIcon={MyModeIcon}
map={<Map />}
title={<div className='navbar-title'>OpenTripPlanner</div>}
/>
// <main> Needed for accessibility checks. TODO: Find a better place.
<main>
<MobileMain
LegIcon={MyLegIcon}
ModeIcon={MyModeIcon}
map={<Map />}
title={<div className='navbar-title'>OpenTripPlanner</div>}
/>
</main>
)

/** the main webapp **/
Expand Down
114 changes: 96 additions & 18 deletions lib/actions/user.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,21 @@
import { createAction } from 'redux-actions'

import { addUser, fetchUser, updateUser } from '../util/middleware'
import {
addTrip,
addUser,
deleteTrip,
fetchUser,
getTrips,
updateTrip,
updateUser
} from '../util/middleware'
import { isNewUser } from '../util/user'

const setCurrentUser = createAction('SET_CURRENT_USER')
const setCurrentUserMonitoredTrips = createAction('SET_CURRENT_USER_MONITORED_TRIPS')
export const setPathBeforeSignIn = createAction('SET_PATH_BEFORE_SIGNIN')

function getStateForNewUser (auth0User) {
function createNewUser (auth0User) {
return {
auth0UserId: auth0User.sub,
email: auth0User.email,
Expand All @@ -18,19 +27,36 @@ function getStateForNewUser (auth0User) {
}
}

/**
* Fetches the saved/monitored trips for a user.
* We use the accessToken to fetch the data regardless of
* whether the process to populate state.user is completed or not.
*/
export function fetchUserMonitoredTrips (accessToken) {
return async function (dispatch, getState) {
const { otp } = getState()
const { otp_middleware: otpMiddleware = null } = otp.config.persistence

if (otpMiddleware) {
const { data: trips, status: fetchStatus } = await getTrips(otpMiddleware, accessToken)
if (fetchStatus === 'success') {
dispatch(setCurrentUserMonitoredTrips(trips))
}
}
}
}

/**
* Fetches user preferences to state.user, or set initial values under state.user if no user has been loaded.
*/
export function fetchOrInitializeUser (auth) {
return async function (dispatch, getState) {
const { otp } = getState()
const { accessToken, user } = auth
const { otp_middleware: otpMiddleware = null } = otp.config.persistence

try {
const result = await fetchUser(
otp.config.persistence.otp_middleware,
accessToken
)
if (otpMiddleware) {
const { accessToken, user: authUser } = auth
const { data: user, status: fetchUserStatus } = await fetchUser(otpMiddleware, accessToken)

// Beware! On AWS API gateway, if a user is not found in the middleware
// (e.g. they just created their Auth0 password but have not completed the account setup form yet),
Expand All @@ -53,19 +79,15 @@ export function fetchOrInitializeUser (auth) {
// }
// TODO: Improve AWS response.

const resultData = result.data
const isNewAccount = result.status === 'error' || (resultData && resultData.result === 'ERR')

const isNewAccount = fetchUserStatus === 'error' || (user && user.result === 'ERR')
if (!isNewAccount) {
// TODO: Move next line somewhere else.
if (resultData.savedLocations === null) resultData.savedLocations = []
dispatch(setCurrentUser({ accessToken, user: resultData }))
// Load user's monitored trips before setting the user state.
await dispatch(fetchUserMonitoredTrips(accessToken))

dispatch(setCurrentUser({ accessToken, user }))
} else {
dispatch(setCurrentUser({ accessToken, user: getStateForNewUser(user) }))
dispatch(setCurrentUser({ accessToken, user: createNewUser(authUser) }))
}
} catch (error) {
// TODO: improve error handling.
alert(`An error was encountered:\n${error}`)
}
}
}
Expand All @@ -91,15 +113,71 @@ export function createOrUpdateUser (userData) {

// TODO: improve the UI feedback messages for this.
if (result.status === 'success' && result.data) {
alert('Your preferences have been saved.')

// Update application state with the user entry as saved
// (as returned) by the middleware.
const userData = result.data
dispatch(setCurrentUser({ accessToken, user: userData }))
} else {
alert(`An error was encountered:\n${JSON.stringify(result)}`)
}
}
}
}

/**
* Updates a logged-in user's monitored trip,
* then, if that was successful, refreshes the redux monitoredTrips
* with the updated trip.
*/
export function createOrUpdateUserMonitoredTrip (tripData, isNew) {
return async function (dispatch, getState) {
const { otp, user } = getState()
const { otp_middleware: otpMiddleware = null } = otp.config.persistence

if (otpMiddleware) {
const { accessToken } = user

let result
if (isNew) {
result = await addTrip(otpMiddleware, accessToken, tripData)
} else {
result = await updateTrip(otpMiddleware, accessToken, tripData)
}

// TODO: improve the UI feedback messages for this.
if (result.status === 'success' && result.data) {
alert('Your preferences have been saved.')

// Reload user's monitored trips after add/update.
await dispatch(fetchUserMonitoredTrips(accessToken))
} else {
alert(`An error was encountered:\n${JSON.stringify(result)}`)
}
}
}
}

/**
* Deletes a logged-in user's monitored trip,
* then, if that was successful, refreshes the redux monitoredTrips state.
*/
export function deleteUserMonitoredTrip (id) {
return async function (dispatch, getState) {
const { otp, user } = getState()
const { otp_middleware: otpMiddleware = null } = otp.config.persistence

if (otpMiddleware) {
const { accessToken } = user
const deleteResult = await deleteTrip(otpMiddleware, accessToken, id)

if (deleteResult.status === 'success') {
// Reload user's monitored trips after deletion.
await dispatch(fetchUserMonitoredTrips(accessToken))
} else {
alert(`An error was encountered:\n${JSON.stringify(deleteResult)}`)
}
}
}
}
1 change: 1 addition & 0 deletions lib/components/app/app-menu.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ class AppMenu extends Component {
return (
<div className='app-menu'>
<DropdownButton
aria-label='Application Menu'
title={(<Icon type='bars' />)}
noCaret
className='app-menu-button'
Expand Down
20 changes: 20 additions & 0 deletions lib/components/app/responsive-webapp.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ import { AUTH0_AUDIENCE, AUTH0_SCOPE, URL_ROOT } from '../../util/constants'
import { getActiveItinerary, getTitle } from '../../util/state'
import AfterSignInScreen from '../user/after-signin-screen'
import BeforeSignInScreen from '../user/before-signin-screen'
import SavedTripList from '../user/saved-trip-list'
import SavedTripScreen from '../user/saved-trip-screen'
import UserAccountScreen from '../user/user-account-screen'
import withLoggedInUserSupport from '../user/with-logged-in-user-support'

Expand Down Expand Up @@ -233,6 +235,24 @@ class RouterWrapperWithAuth0 extends Component {
return <UserAccountScreen {...props} />
}}
/>
<Route
path={'/savetrip'}
component={(routerProps) => {
const props = this._combineProps(routerProps)
return <SavedTripScreen isCreating {...props} />
}}
/>
<Route
path={'/savedtrips/:id'}
component={(routerProps) => {
const props = this._combineProps(routerProps)
return <SavedTripScreen {...props} />
}}
/>
<Route
path={'/savedtrips'}
component={SavedTripList}
/>
<Route
// This route is called immediately after login by Auth0
// and by the onRedirectCallback function from /lib/util/auth.js.
Expand Down
5 changes: 4 additions & 1 deletion lib/components/form/date-time-preview.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,10 @@ class DateTimePreview extends Component {

const button = (
<div className='button-container'>
<Button onClick={this.props.onClick}>
<Button
aria-label='Edit departure or arrival time'
onClick={this.props.onClick}
>
{editButtonText}{caret && <span> <i className={`fa fa-caret-${caret}`} /></span>}
</Button>
</div>
Expand Down
5 changes: 4 additions & 1 deletion lib/components/form/settings-preview.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,10 @@ class SettingsPreview extends Component {
let showDot = coreUtils.query.isNotDefaultQuery(query, config)
const button = (
<div className='button-container'>
<Button onClick={this.props.onClick}>
<Button
aria-label={messages.label.replace('\n', ' ')}
onClick={this.props.onClick}
>
{editButtonText}{caret && <span> <i className={`fa fa-caret-${caret}`} /></span>}
</Button>
{showDot && <div className='dot' />}
Expand Down
2 changes: 2 additions & 0 deletions lib/components/narrative/default/default-itinerary.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import ItinerarySummary from './itinerary-summary'
import ItineraryDetails from './itinerary-details'
import TripDetails from '../connected-trip-details'
import TripTools from '../trip-tools'
import LinkButton from '../../user/link-button'

const { formatDuration, formatTime } = coreUtils.time

Expand All @@ -31,6 +32,7 @@ export default class DefaultItinerary extends NarrativeItinerary {
<span className='title'>Itinerary {index + 1}</span>{' '}
<span className='duration pull-right'>{formatDuration(itinerary.duration)}</span>{' '}
<span className='arrivalTime'>{formatTime(itinerary.startTime)}—{formatTime(itinerary.endTime)}</span>
<span className='pull-right'><LinkButton to='/savetrip'>Save</LinkButton></span>{' '}
<ItinerarySummary itinerary={itinerary} LegIcon={LegIcon} />
</button>
{(active || expanded) &&
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ class ConnectedItineraryBody extends Component {
LegIcon,
setActiveLeg,
setViewedTrip,
showLegDiagram
showLegDiagram,
timeOptions
} = this.props

return (
Expand All @@ -62,6 +63,7 @@ class ConnectedItineraryBody extends Component {
showLegIcon
showMapButtonColumn={false}
showViewTripButton
timeOptions={timeOptions}
toRouteAbbreviation={noop}
TransitLegSubheader={TransitLegSubheader}
TransitLegSummary={TransitLegSummary}
Expand Down
9 changes: 7 additions & 2 deletions lib/components/narrative/line-itin/line-itinerary.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import ItineraryBody from './connected-itinerary-body'
import ItinerarySummary from './itin-summary'
import NarrativeItinerary from '../narrative-itinerary'
import SimpleRealtimeAnnotation from '../simple-realtime-annotation'
import LinkButton from '../../user/link-button'

const { getLegModeLabel, getTimeZoneOffset, isTransit } = coreUtils.itinerary

Expand Down Expand Up @@ -50,9 +51,9 @@ export default class LineItinerary extends NarrativeItinerary {
itinerary,
itineraryFooter,
LegIcon,
onClick,
setActiveLeg,
showRealtimeAnnotation,
onClick,
timeFormat
} = this.props

Expand All @@ -71,9 +72,12 @@ export default class LineItinerary extends NarrativeItinerary {
companies={companies}
itinerary={itinerary}
LegIcon={LegIcon}
timeOptions={timeOptions}
onClick={onClick}
timeOptions={timeOptions}
/>

<span className='pull-right'><LinkButton to='/savetrip'>Save this option</LinkButton></span>

{showRealtimeAnnotation && <SimpleRealtimeAnnotation />}
{active || expanded
? <ItineraryBody
Expand All @@ -83,6 +87,7 @@ export default class LineItinerary extends NarrativeItinerary {
// (will cause error when clicking on itinerary suymmary).
// Use the one passed by NarrativeItineraries instead.
setActiveLeg={setActiveLeg}
timeOptions={timeOptions}
/>
: null}
{itineraryFooter}
Expand Down
Loading