Skip to content

feat: date time use url storage #1208

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

Open
wants to merge 3 commits into
base: dev
Choose a base branch
from
Open
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
76 changes: 0 additions & 76 deletions lib/components/form/date-time-modal.js

This file was deleted.

107 changes: 107 additions & 0 deletions lib/components/form/date-time-modal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
import { connect } from 'react-redux'
import { decodeQueryParams, StringParam } from 'serialize-query-params'
import coreUtils from '@opentripplanner/core-utils'
import React, { useCallback } from 'react'

import { AppConfig } from '../../util/config-types'
import { AppReduxState } from '../../util/state-types'
import { setQueryParam } from '../../actions/form'

import { StyledDateTimeSelector } from './styled'

export type DepartArriveValue = 'NOW' | 'DEPART' | 'ARRIVE'

type Props = {
config: AppConfig
date: any
dateFormatLegacy: string
departArrive: DepartArriveValue
setQueryParam: (params: any) => void
time: any
timeFormatLegacy: string
}

function DateTimeModal({
config,
date,
dateFormatLegacy,
departArrive,
setQueryParam,
time,
timeFormatLegacy
}: Props) {
/**
* Stores parameters in both the Redux `currentQuery` and URL
* @param params Params to store
*/
const _onSettingsUpdate = useCallback(
(params: any) => {
console.log('setting')
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Whoops!

setQueryParam({ queryParamData: params, ...params })
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are we really inserting everything twice? That's so annoying

},
[setQueryParam]
)

const { homeTimezone, isTouchScreenOnDesktop } = config
const touchClassName = isTouchScreenOnDesktop
? 'with-desktop-touchscreen'
: ''

return (
<div className="date-time-modal">
<div className="main-panel">
<StyledDateTimeSelector
className={`date-time-selector ${touchClassName}`}
date={date}
dateFormatLegacy={dateFormatLegacy}
departArrive={departArrive}
onQueryParamChange={_onSettingsUpdate}
time={time}
// These props below are for Safari on MacOS, and legacy browsers
// that don't support `<input type="time|date">`.
// These props are not relevant in modern browsers,
// where `<input type="time|date">` already
// formats the time|date according to the OS settings.
// eslint-disable-next-line react/jsx-sort-props
timeFormatLegacy={timeFormatLegacy}
timeZone={homeTimezone}
/>
</div>
</div>
)
}

const queryParamConfig = {
date: StringParam,
departArrive: StringParam,
time: StringParam
}

const mapStateToProps = (state: AppReduxState) => {
const config = state.otp.config
const urlSearchParams = new URLSearchParams(state.router.location.search)
const { date, departArrive, time } = decodeQueryParams(queryParamConfig, {
date: urlSearchParams.get('date'),
departArrive: urlSearchParams.get('departArrive'),
time: urlSearchParams.get('time')
})

return {
config,
date: date || coreUtils.time.getCurrentDate(),
// This prop is for legacy browsers (see render method above).
// @ts-expect-error why do we have two config types?
dateFormatLegacy: coreUtils.time.getDateFormat(config),
departArrive: (departArrive as DepartArriveValue) || 'NOW',
time: time || coreUtils.time.getCurrentTime(),
// This prop is for legacy browsers (see render method above).
// @ts-expect-error why do we have two config types?
timeFormatLegacy: coreUtils.time.getTimeFormat(config)
}
}

const mapDispatchToProps = {
setQueryParam
}

export default connect(mapStateToProps, mapDispatchToProps)(DateTimeModal)
23 changes: 19 additions & 4 deletions lib/components/form/date-time-preview.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
import { CalendarAlt } from '@styled-icons/fa-solid/CalendarAlt'
import { Clock } from '@styled-icons/fa-regular/Clock'
import { connect } from 'react-redux'
import { decodeQueryParams, StringParam } from 'serialize-query-params'
import { toDate } from 'date-fns-tz'
import coreUtils from '@opentripplanner/core-utils'
import React from 'react'

import { IconWithText } from '../util/styledIcon'
import FormattedCalendarString from '../util/formatted-calendar-string'
import FormattedDateTimePreview from '../util/formatted-date-time-preview'

import { DepartArriveValue } from './date-time-modal'

interface Props {
date: string
departArrive: string
@@ -38,13 +42,24 @@ const DateTimePreview = ({
)
}

const queryParamConfig = {
date: StringParam,
departArrive: StringParam,
time: StringParam
}

const mapStateToProps = (state: any) => {
const { date, departArrive, time } = state.otp.currentQuery
const { homeTimezone: timeZone } = state.otp.config
const urlSearchParams = new URLSearchParams(state.router.location.search)
const { date, departArrive, time } = decodeQueryParams(queryParamConfig, {
date: urlSearchParams.get('date'),
departArrive: urlSearchParams.get('departArrive'),
time: urlSearchParams.get('time')
Comment on lines +55 to +57
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is simple enough I don't mind the repetition

})
return {
date,
departArrive,
time,
date: date || coreUtils.time.getCurrentDate(),
departArrive: (departArrive as DepartArriveValue) || 'NOW',
time: time || coreUtils.time.getCurrentTime(),
timeZone
}
}
1 change: 1 addition & 0 deletions lib/util/state-types.ts
Original file line number Diff line number Diff line change
@@ -12,6 +12,7 @@ export interface OtpState {
// TODO: Add other OTP states
activeSearchId?: string
config: AppConfig
currentQuery: any // TODO
filter: {
sort: {
type: string
2 changes: 1 addition & 1 deletion percy/percy.test.js
Original file line number Diff line number Diff line change
@@ -105,7 +105,7 @@ async function executeTest(page, isMobile, isCallTaker) {
// Triggers mock.har graphql query #1 and #2 (bike-only query, twice).
// FIXME: Opening a url with non-default mode params triggers the plan query twice.
await page.goto(
`http://localhost:${MOCK_SERVER_PORT}/#/?ui_activeSearch=fg33svlbf&ui_activeItinerary=-1&fromPlace=South%20Prado%20Northeast%2C%20Atlanta%2C%20GA%2C%20USA%3A%3A33.78946214120528%2C-84.37663414886111&toPlace=1%20Copenhill%20Avenue%20NE%2C%20Atlanta%2C%20GA%2C%20USA%3A%3A33.767060728439574%2C-84.35749390533111&date=2023-08-09&time=17%3A56&arriveBy=false&mode=BICYCLE&showIntermediateStops=true&walkSpeed=1.34&ignoreRealtimeUpdates=true&numItineraries=3&otherThanPreferredRoutesPenalty=900&modeButtons=walk_bike`
`http://localhost:${MOCK_SERVER_PORT}/#/?ui_activeSearch=fg33svlbf&ui_activeItinerary=-1&fromPlace=South%20Prado%20Northeast%2C%20Atlanta%2C%20GA%2C%20USA%3A%3A33.78946214120528%2C-84.37663414886111&toPlace=1%20Copenhill%20Avenue%20NE%2C%20Atlanta%2C%20GA%2C%20USA%3A%3A33.767060728439574%2C-84.35749390533111&date=2023-08-09&time=17%3A56&departArrive=DEPART&mode=BICYCLE&showIntermediateStops=true&walkSpeed=1.34&ignoreRealtimeUpdates=true&numItineraries=3&otherThanPreferredRoutesPenalty=900&modeButtons=walk_bike`
)
// FIXME: Network idle condition seems never met after navigating to above link.
// await page.waitForNavigation({ waitUntil: 'networkidle2' })

Unchanged files with check annotations Beta

import { replace, push } from 'connected-react-router'

Check failure on line 1 in lib/actions/auth.js

GitHub Actions / test-build-release

Member 'push' of the import declaration should be sorted alphabetically
import { setPathBeforeSignIn } from '../actions/user'
* @param {Error} err
* @param {AccessTokenRequestOptions} options
*/
export function showAccessTokenError (err, options) {

Check failure on line 11 in lib/actions/auth.js

GitHub Actions / test-build-release

Delete `·`
return function (dispatch, getState) {
// TODO: improve this.
console.error('Failed to retrieve access token: ', err)
* when signing-in fails for some reason.
* @param {Error} err
*/
export function showLoginError (err) {

Check failure on line 23 in lib/actions/auth.js

GitHub Actions / test-build-release

Delete `·`
return function (dispatch, getState) {
// TODO: improve this.
if (err) dispatch(push('/oops'))
* @param {Object} appState The state stored when calling useAuth0().loginWithRedirect
* or when instantiating a component that uses withAuhenticationRequired.
*/
export function processSignIn (appState) {

Check failure on line 36 in lib/actions/auth.js

GitHub Actions / test-build-release

Delete `·`
return function (dispatch, getState) {
if (appState && appState.returnTo) {
// Remove URL parameters that were added by auth0-react
import { createAction } from 'redux-actions'
if (typeof (fetch) === 'undefined') require('isomorphic-fetch')

Check failure on line 2 in lib/actions/zipcar.js

GitHub Actions / test-build-release

Replace `(fetch)` with `fetch`
export const receivedZipcarLocationsError = createAction('ZIPCAR_LOCATIONS_ERROR')

Check failure on line 4 in lib/actions/zipcar.js

GitHub Actions / test-build-release

Replace `'ZIPCAR_LOCATIONS_ERROR'` with `⏎··'ZIPCAR_LOCATIONS_ERROR'⏎`
export const receivedZipcarLocationsResponse = createAction('ZIPCAR_LOCATIONS_RESPONSE')

Check failure on line 5 in lib/actions/zipcar.js

GitHub Actions / test-build-release

Replace `'ZIPCAR_LOCATIONS_RESPONSE'` with `⏎··'ZIPCAR_LOCATIONS_RESPONSE'⏎`
export const requestZipcarLocationsResponse = createAction('ZIPCAR_LOCATIONS_REQUEST')

Check failure on line 6 in lib/actions/zipcar.js

GitHub Actions / test-build-release

Replace `'ZIPCAR_LOCATIONS_REQUEST'` with `⏎··'ZIPCAR_LOCATIONS_REQUEST'⏎`
export function zipcarLocationsQuery (url) {

Check failure on line 8 in lib/actions/zipcar.js

GitHub Actions / test-build-release

Delete `·`
return async function (dispatch, getState) {
dispatch(requestZipcarLocationsResponse())
let json
import { Field, Form, Formik } from 'formik'
import React, {Component} from 'react'

Check failure on line 2 in lib/components/admin/editable-section.js

GitHub Actions / test-build-release

Replace `Component` with `·Component·`
import {
Button,