From 4c68565ca8936e551fd1af938a1daffaed168fab Mon Sep 17 00:00:00 2001 From: binh-dam-ibigroup <56846598+binh-dam-ibigroup@users.noreply.github.com> Date: Tue, 10 Sep 2024 16:54:29 -0400 Subject: [PATCH 01/18] feat(TripPreviewLayout): Add trip preview path+UI by duplicating print layout --- lib/components/app/responsive-webapp.js | 3 +- lib/components/app/trip-preview-layout.tsx | 175 +++++++++++++++++++++ lib/util/webapp-trip-preview-routes.js | 18 +++ 3 files changed, 195 insertions(+), 1 deletion(-) create mode 100644 lib/components/app/trip-preview-layout.tsx create mode 100644 lib/util/webapp-trip-preview-routes.js diff --git a/lib/components/app/responsive-webapp.js b/lib/components/app/responsive-webapp.js index dc7d26f72..537e13bc3 100644 --- a/lib/components/app/responsive-webapp.js +++ b/lib/components/app/responsive-webapp.js @@ -33,6 +33,7 @@ import BeforeSignInScreen from '../user/before-signin-screen' import Map from '../map/map' import MobileMain from '../mobile/main' import printRoutes from '../../util/webapp-print-routes' +import tripPreviewRoutes from '../../util/webapp-trip-preview-routes' import webAppRoutes from '../../util/webapp-routes' import withLoggedInUserSupport from '../user/with-logged-in-user-support' import withMap from '../map/with-map' @@ -43,7 +44,7 @@ import SessionTimeout from './session-timeout' const { isMobile } = coreUtils.ui -const routes = [...webAppRoutes, ...printRoutes] +const routes = [...webAppRoutes, ...printRoutes, ...tripPreviewRoutes] class ResponsiveWebapp extends Component { static propTypes = { diff --git a/lib/components/app/trip-preview-layout.tsx b/lib/components/app/trip-preview-layout.tsx new file mode 100644 index 000000000..4b4142e11 --- /dev/null +++ b/lib/components/app/trip-preview-layout.tsx @@ -0,0 +1,175 @@ +import { Button } from 'react-bootstrap' +import { connect } from 'react-redux' +import { FormattedMessage, injectIntl, IntlShape } from 'react-intl' +import { Itinerary } from '@opentripplanner/types' +import { Map } from '@styled-icons/fa-solid/Map' +import { Print } from '@styled-icons/fa-solid/Print' +import { Times } from '@styled-icons/fa-solid/Times' +// @ts-expect-error not typescripted yet +import PrintableItinerary from '@opentripplanner/printable-itinerary' +import React, { Component } from 'react' + +import * as apiActions from '../../actions/api' +import * as formActions from '../../actions/form' +import { + addPrintViewClassToRootHtml, + clearClassFromRootHtml +} from '../../util/print' +import { ComponentContext } from '../../util/contexts' +import { getActiveItinerary, getActiveSearch } from '../../util/state' +import { IconWithText } from '../util/styledIcon' +import { summarizeQuery } from '../form/user-settings-i18n' +import DefaultMap from '../map/default-map' +import PageTitle from '../util/page-title' +import SpanWithSpace from '../util/span-with-space' +import TripDetails from '../narrative/connected-trip-details' + +type Props = { + // TODO: Typescript activeSearch type + activeSearch: any + // TODO: Typescript config type + config: any + currentQuery: any + intl: IntlShape + itinerary: Itinerary + location?: { search?: string } + parseUrlQueryString: (params?: any, source?: string) => any + // TODO: Typescript user type + user: any +} + +type State = { + mapVisible?: boolean +} + +class TripPreviewLayout extends Component { + static contextType = ComponentContext + + constructor(props: Props) { + super(props) + this.state = { + mapVisible: true + } + } + + _toggleMap = () => { + this.setState({ mapVisible: !this.state.mapVisible }) + } + + _print = () => { + window.print() + } + + _close = () => { + window.location.replace(String(window.location).replace('print/', '')) + } + + componentDidMount() { + const { itinerary, location, parseUrlQueryString } = this.props + + // Add print-view class to html tag to ensure that iOS scroll fix only applies + // to non-print views. + addPrintViewClassToRootHtml() + // Parse the URL query parameters, if present + if (!itinerary && location && location.search) { + parseUrlQueryString() + } + + // TODO: use currentQuery to pan/zoom to the correct part of the map + } + + componentWillUnmount() { + clearClassFromRootHtml() + } + + render() { + const { activeSearch, config, intl, itinerary, user } = this.props + const { LegIcon } = this.context + const printVerb = intl.formatMessage({ id: 'common.forms.print' }) + + return ( +
+ + {/* The header bar, including the Toggle Map and Print buttons */} +
+
+ + + + + + + +
+ +
+ + {/* The map, if visible */} + {this.state.mapVisible && ( +
+ {/* FIXME: Improve reframing/setting map bounds when itinerary is received. */} + +
+ )} + + {/* The main itinerary body */} + {itinerary && ( + <> + + + + )} +
+ ) + } +} + +// connect to the redux store + +// TODO: Typescript state +const mapStateToProps = (state: any) => { + const activeSearch = getActiveSearch(state) + const { localUser, loggedInUser } = state.user + const user = loggedInUser || localUser + return { + activeSearch, + config: state.otp.config, + currentQuery: state.otp.currentQuery, + itinerary: getActiveItinerary(state) as Itinerary, + user + } +} + +const mapDispatchToProps = { + parseUrlQueryString: formActions.parseUrlQueryString, + routingQuery: apiActions.routingQuery +} + +export default connect( + mapStateToProps, + mapDispatchToProps +)(injectIntl(TripPreviewLayout)) diff --git a/lib/util/webapp-trip-preview-routes.js b/lib/util/webapp-trip-preview-routes.js new file mode 100644 index 000000000..70f35b506 --- /dev/null +++ b/lib/util/webapp-trip-preview-routes.js @@ -0,0 +1,18 @@ +import TripPreviewLayout from '../components/app/trip-preview-layout' + +/** + * Contains mapping of the component(s) to display for each URL printing route. + * + * Note: This file is separate from webapp-routes to isolate the import of printing components + * (YML file from @opentripplanner/trip-details). + * that cause build errors during the a11y test. + */ +const routes = [ + { + a11yIgnore: true, + component: TripPreviewLayout, + path: '/previewtrip/:id' + } +] + +export default routes From 36f166e5c354be7d169892aa348ebe778786c47a Mon Sep 17 00:00:00 2001 From: binh-dam-ibigroup <56846598+binh-dam-ibigroup@users.noreply.github.com> Date: Tue, 10 Sep 2024 17:37:29 -0400 Subject: [PATCH 02/18] refactor(TripPreviewLayout): Display trip from tripId and redux state --- lib/components/app/trip-preview-layout.tsx | 83 +++++++++++----------- 1 file changed, 42 insertions(+), 41 deletions(-) diff --git a/lib/components/app/trip-preview-layout.tsx b/lib/components/app/trip-preview-layout.tsx index 4b4142e11..ef2b3f23a 100644 --- a/lib/components/app/trip-preview-layout.tsx +++ b/lib/components/app/trip-preview-layout.tsx @@ -1,41 +1,35 @@ import { Button } from 'react-bootstrap' import { connect } from 'react-redux' import { FormattedMessage, injectIntl, IntlShape } from 'react-intl' -import { Itinerary } from '@opentripplanner/types' import { Map } from '@styled-icons/fa-solid/Map' import { Print } from '@styled-icons/fa-solid/Print' import { Times } from '@styled-icons/fa-solid/Times' +import { withAuthenticationRequired } from '@auth0/auth0-react' // @ts-expect-error not typescripted yet import PrintableItinerary from '@opentripplanner/printable-itinerary' import React, { Component } from 'react' -import * as apiActions from '../../actions/api' -import * as formActions from '../../actions/form' import { addPrintViewClassToRootHtml, clearClassFromRootHtml } from '../../util/print' +import { AppConfig } from '../../util/config-types' +import { AppReduxState } from '../../util/state-types' import { ComponentContext } from '../../util/contexts' -import { getActiveItinerary, getActiveSearch } from '../../util/state' import { IconWithText } from '../util/styledIcon' -import { summarizeQuery } from '../form/user-settings-i18n' +import { MonitoredTrip } from '../user/types' +import { RETURN_TO_CURRENT_ROUTE } from '../../util/ui' +import AwaitingScreen from '../user/awaiting-screen' import DefaultMap from '../map/default-map' import PageTitle from '../util/page-title' import SpanWithSpace from '../util/span-with-space' import TripDetails from '../narrative/connected-trip-details' +import withLoggedInUserSupport from '../user/with-logged-in-user-support' type Props = { - // TODO: Typescript activeSearch type - activeSearch: any - // TODO: Typescript config type - config: any - currentQuery: any + config: AppConfig intl: IntlShape - itinerary: Itinerary - location?: { search?: string } - parseUrlQueryString: (params?: any, source?: string) => any - // TODO: Typescript user type - user: any + tripId: string } type State = { @@ -52,6 +46,14 @@ class TripPreviewLayout extends Component { } } + /** + * Gets the trip to view from the props. + */ + _getTripToEdit = (): MonitoredTrip => { + const { monitoredTrips, tripId } = this.props + return monitoredTrips.find((trip) => trip.id === tripId) + } + _toggleMap = () => { this.setState({ mapVisible: !this.state.mapVisible }) } @@ -64,7 +66,7 @@ class TripPreviewLayout extends Component { window.location.replace(String(window.location).replace('print/', '')) } - componentDidMount() { + componentDidUpdate() { const { itinerary, location, parseUrlQueryString } = this.props // Add print-view class to html tag to ensure that iOS scroll fix only applies @@ -83,19 +85,22 @@ class TripPreviewLayout extends Component { } render() { - const { activeSearch, config, intl, itinerary, user } = this.props + const { config, intl, monitoredTrips } = this.props const { LegIcon } = this.context const printVerb = intl.formatMessage({ id: 'common.forms.print' }) + const isAwaiting = !monitoredTrips + if (isAwaiting) { + // Flash an indication while the selected and saved user trips are being loaded. + return + } + + const monitoredTrip = this._getTripToEdit() + const itinerary = + monitoredTrip.journeyState?.matchingItinerary || monitoredTrip.itinerary return (
- + {/* The header bar, including the Toggle Map and Print buttons */}
@@ -151,25 +156,21 @@ class TripPreviewLayout extends Component { // connect to the redux store // TODO: Typescript state -const mapStateToProps = (state: any) => { - const activeSearch = getActiveSearch(state) - const { localUser, loggedInUser } = state.user - const user = loggedInUser || localUser +const mapStateToProps = (state: AppReduxState, ownProps: Props) => { + const { loggedInUserMonitoredTrips: monitoredTrips } = state.user + const tripId = ownProps.match.params.id + return { - activeSearch, config: state.otp.config, - currentQuery: state.otp.currentQuery, - itinerary: getActiveItinerary(state) as Itinerary, - user + monitoredTrips, + tripId } } -const mapDispatchToProps = { - parseUrlQueryString: formActions.parseUrlQueryString, - routingQuery: apiActions.routingQuery -} - -export default connect( - mapStateToProps, - mapDispatchToProps -)(injectIntl(TripPreviewLayout)) +export default withLoggedInUserSupport( + withAuthenticationRequired( + connect(mapStateToProps)(injectIntl(TripPreviewLayout)), + RETURN_TO_CURRENT_ROUTE + ), + true +) From 9a6cd8c8c9ede5542a10d124dc6e169f8d3728f4 Mon Sep 17 00:00:00 2001 From: binh-dam-ibigroup <56846598+binh-dam-ibigroup@users.noreply.github.com> Date: Wed, 11 Sep 2024 10:37:20 -0400 Subject: [PATCH 03/18] feat(SavedTripList): Add link to preview trips --- .../user/monitored-trip/saved-trip-list.tsx | 31 ++++++++++++------- lib/components/user/styled.ts | 6 +++- lib/util/constants.js | 1 + 3 files changed, 26 insertions(+), 12 deletions(-) diff --git a/lib/components/user/monitored-trip/saved-trip-list.tsx b/lib/components/user/monitored-trip/saved-trip-list.tsx index 0df5ff909..abb591300 100644 --- a/lib/components/user/monitored-trip/saved-trip-list.tsx +++ b/lib/components/user/monitored-trip/saved-trip-list.tsx @@ -1,13 +1,15 @@ import { connect } from 'react-redux' +import { Edit, Map } from '@styled-icons/fa-solid' import { FormattedMessage, injectIntl, IntlShape, useIntl } from 'react-intl' import { Panel } from 'react-bootstrap' import { TriangleExclamation } from '@styled-icons/fa-solid/TriangleExclamation' import { withAuthenticationRequired } from '@auth0/auth0-react' import React, { Component } from 'react' +import styled from 'styled-components' import * as userActions from '../../../actions/user' import { AppReduxState } from '../../../util/state-types' -import { Edit } from '@styled-icons/fa-solid' +import { ComponentContext } from '../../../util/contexts' import { IconWithText } from '../../util/styledIcon' import { MonitoredTrip } from '../types' import { @@ -19,23 +21,17 @@ import { TripPanelTitle } from '../styled' import { RETURN_TO_CURRENT_ROUTE } from '../../../util/ui' -import { TRIPS_PATH } from '../../../util/constants' +import { TRIP_PREVIEW_PATH, TRIPS_PATH } from '../../../util/constants' import AccountPage from '../account-page' import AwaitingScreen from '../awaiting-screen' import BackToTripPlanner from '../back-to-trip-planner' -import PageTitle from '../../util/page-title' - -import styled from 'styled-components' - -import withLoggedInUserSupport from '../with-logged-in-user-support' - -import getRenderData from './trip-status-rendering-strategies' import InvisibleA11yLabel from '../../util/invisible-a11y-label' - -import { ComponentContext } from '../../../util/contexts' import Link from '../../util/link' import MetroItineraryRoutes from '../../narrative/metro/metro-itinerary-routes' +import PageTitle from '../../util/page-title' +import withLoggedInUserSupport from '../with-logged-in-user-support' +import getRenderData from './trip-status-rendering-strategies' import TripSummaryPane from './trip-summary-pane' interface ItemOwnProps { @@ -111,6 +107,7 @@ class TripListItem extends Component { const from = legs[0].from const to = legs[legs.length - 1].to const editTripPath = `${TRIPS_PATH}/${trip.id}` + const previewPath = `${TRIP_PREVIEW_PATH}/${trip.id}` const { LegIcon } = this.context return ( @@ -119,6 +116,18 @@ class TripListItem extends Component { {trip.tripName} + + + + Preview Trip + {/* + div:first-child { + flex-grow: 1; + } ` export const TripPanelHeading = styled(Panel.Heading)` diff --git a/lib/util/constants.js b/lib/util/constants.js index 07f0abf3e..0c4303772 100644 --- a/lib/util/constants.js +++ b/lib/util/constants.js @@ -23,6 +23,7 @@ export const CREATE_ACCOUNT_PLACES_PATH = `${CREATE_ACCOUNT_PATH}/places` export const CREATE_TRIP_PATH = `${TRIPS_PATH}/new` export const TERMS_OF_SERVICE_PATH = '/terms-of-service' export const TERMS_OF_STORAGE_PATH = '/terms-of-storage' +export const TRIP_PREVIEW_PATH = '/previewtrip' // Contains ignored actions when determining timeout, // such as actions triggered by a timer. From dd64366e9484bccabede8185d52d0819678f5356 Mon Sep 17 00:00:00 2001 From: binh-dam-ibigroup <56846598+binh-dam-ibigroup@users.noreply.github.com> Date: Wed, 11 Sep 2024 10:54:51 -0400 Subject: [PATCH 04/18] refactor(SavedTripList): Add trip preview i18n, combine strings --- i18n/en-US.yml | 2 ++ i18n/fr.yml | 2 ++ .../user/monitored-trip/saved-trip-list.tsx | 29 +++++++------------ 3 files changed, 15 insertions(+), 18 deletions(-) diff --git a/i18n/en-US.yml b/i18n/en-US.yml index f03fa5bce..4a1ae407b 100644 --- a/i18n/en-US.yml +++ b/i18n/en-US.yml @@ -623,6 +623,8 @@ components: oneHour: 1 hour realtimeAlertFlagged: There is a realtime alert flagged on my journey timeBefore: "{time} before" + TripPreviewLayout: + previewTrip: Preview Trip TripStatus: alerts: "{alerts, plural, one {# alert!} other {# alerts!}}" deleteTrip: Delete Trip diff --git a/i18n/fr.yml b/i18n/fr.yml index 082b0e96a..bf90f8469 100644 --- a/i18n/fr.yml +++ b/i18n/fr.yml @@ -658,6 +658,8 @@ components: oneHour: 1 heure realtimeAlertFlagged: Une alerte en temps réel affecte mon trajet timeBefore: "{time} avant" + TripPreviewLayout: + previewTrip: Aperçu du trajet TripStatus: alerts: "{alerts, plural, =0 {# alerte !} one {# alerte !} other {# alertes !}}" deleteTrip: Supprimer le trajet diff --git a/lib/components/user/monitored-trip/saved-trip-list.tsx b/lib/components/user/monitored-trip/saved-trip-list.tsx index abb591300..03e33f80f 100644 --- a/lib/components/user/monitored-trip/saved-trip-list.tsx +++ b/lib/components/user/monitored-trip/saved-trip-list.tsx @@ -107,7 +107,12 @@ class TripListItem extends Component { const from = legs[0].from const to = legs[legs.length - 1].to const editTripPath = `${TRIPS_PATH}/${trip.id}` - const previewPath = `${TRIP_PREVIEW_PATH}/${trip.id}` + const editTripText = intl.formatMessage({ + id: 'components.SavedTripEditor.editSavedTrip' + }) + const previewTripText = intl.formatMessage({ + id: 'components.TripPreviewLayout.previewTrip' + }) const { LegIcon } = this.context return ( @@ -117,27 +122,15 @@ class TripListItem extends Component { {trip.tripName} - - Preview Trip - {/* + {previewTripText} - + - - - + {editTripText} From 51546dc1f07144b466e1ecac94bedc23a4cec645 Mon Sep 17 00:00:00 2001 From: binh-dam-ibigroup <56846598+binh-dam-ibigroup@users.noreply.github.com> Date: Wed, 11 Sep 2024 11:47:46 -0400 Subject: [PATCH 05/18] refactor(TripPreviewLayout): Remove unneeded code --- lib/components/app/trip-preview-layout.tsx | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/lib/components/app/trip-preview-layout.tsx b/lib/components/app/trip-preview-layout.tsx index ef2b3f23a..7a0ab3aba 100644 --- a/lib/components/app/trip-preview-layout.tsx +++ b/lib/components/app/trip-preview-layout.tsx @@ -3,7 +3,6 @@ import { connect } from 'react-redux' import { FormattedMessage, injectIntl, IntlShape } from 'react-intl' import { Map } from '@styled-icons/fa-solid/Map' import { Print } from '@styled-icons/fa-solid/Print' -import { Times } from '@styled-icons/fa-solid/Times' import { withAuthenticationRequired } from '@auth0/auth0-react' // @ts-expect-error not typescripted yet import PrintableItinerary from '@opentripplanner/printable-itinerary' @@ -62,20 +61,10 @@ class TripPreviewLayout extends Component { window.print() } - _close = () => { - window.location.replace(String(window.location).replace('print/', '')) - } - componentDidUpdate() { - const { itinerary, location, parseUrlQueryString } = this.props - // Add print-view class to html tag to ensure that iOS scroll fix only applies // to non-print views. addPrintViewClassToRootHtml() - // Parse the URL query parameters, if present - if (!itinerary && location && location.search) { - parseUrlQueryString() - } // TODO: use currentQuery to pan/zoom to the correct part of the map } @@ -120,13 +109,8 @@ class TripPreviewLayout extends Component { {printVerb} -
- +
{/* The map, if visible */} @@ -155,7 +139,6 @@ class TripPreviewLayout extends Component { // connect to the redux store -// TODO: Typescript state const mapStateToProps = (state: AppReduxState, ownProps: Props) => { const { loggedInUserMonitoredTrips: monitoredTrips } = state.user const tripId = ownProps.match.params.id From 662651f9dc424189065d205b6f6fb5f7dfcd2e3b Mon Sep 17 00:00:00 2001 From: binh-dam-ibigroup <56846598+binh-dam-ibigroup@users.noreply.github.com> Date: Wed, 11 Sep 2024 12:37:12 -0400 Subject: [PATCH 06/18] refactor(TripPreviewLayout): Update title --- lib/components/app/trip-preview-layout.tsx | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/components/app/trip-preview-layout.tsx b/lib/components/app/trip-preview-layout.tsx index 7a0ab3aba..dee0d787e 100644 --- a/lib/components/app/trip-preview-layout.tsx +++ b/lib/components/app/trip-preview-layout.tsx @@ -77,6 +77,9 @@ class TripPreviewLayout extends Component { const { config, intl, monitoredTrips } = this.props const { LegIcon } = this.context const printVerb = intl.formatMessage({ id: 'common.forms.print' }) + const previewTripText = intl.formatMessage({ + id: 'components.TripPreviewLayout.previewTrip' + }) const isAwaiting = !monitoredTrips if (isAwaiting) { // Flash an indication while the selected and saved user trips are being loaded. @@ -89,7 +92,7 @@ class TripPreviewLayout extends Component { return (
- + {/* The header bar, including the Toggle Map and Print buttons */}
@@ -110,7 +113,7 @@ class TripPreviewLayout extends Component {
- + {previewTripText}
{/* The map, if visible */} From f2057efa2d202999eea922169413fe62706f36f5 Mon Sep 17 00:00:00 2001 From: binh-dam-ibigroup <56846598+binh-dam-ibigroup@users.noreply.github.com> Date: Wed, 11 Sep 2024 16:08:47 -0400 Subject: [PATCH 07/18] refactor(SimpleMap): Introduce component, use with TripPreviewLayout. --- lib/components/app/trip-preview-layout.tsx | 5 +- lib/components/map/simple-map.tsx | 95 ++++++++++++++++++++++ 2 files changed, 97 insertions(+), 3 deletions(-) create mode 100644 lib/components/map/simple-map.tsx diff --git a/lib/components/app/trip-preview-layout.tsx b/lib/components/app/trip-preview-layout.tsx index dee0d787e..30f3df206 100644 --- a/lib/components/app/trip-preview-layout.tsx +++ b/lib/components/app/trip-preview-layout.tsx @@ -19,8 +19,8 @@ import { IconWithText } from '../util/styledIcon' import { MonitoredTrip } from '../user/types' import { RETURN_TO_CURRENT_ROUTE } from '../../util/ui' import AwaitingScreen from '../user/awaiting-screen' -import DefaultMap from '../map/default-map' import PageTitle from '../util/page-title' +import SimpleMap from '../map/simple-map' import SpanWithSpace from '../util/span-with-space' import TripDetails from '../narrative/connected-trip-details' import withLoggedInUserSupport from '../user/with-logged-in-user-support' @@ -119,8 +119,7 @@ class TripPreviewLayout extends Component { {/* The map, if visible */} {this.state.mapVisible && (
- {/* FIXME: Improve reframing/setting map bounds when itinerary is received. */} - +
)} diff --git a/lib/components/map/simple-map.tsx b/lib/components/map/simple-map.tsx new file mode 100644 index 000000000..b7937163b --- /dev/null +++ b/lib/components/map/simple-map.tsx @@ -0,0 +1,95 @@ +import { connect } from 'react-redux' +import { GeolocateControl, NavigationControl } from 'react-map-gl' +import { Itinerary } from '@opentripplanner/types' +import { useIntl } from 'react-intl' +import BaseMap from '@opentripplanner/base-map' +import EndpointsOverlay from '@opentripplanner/endpoints-overlay' +import React, { useContext } from 'react' +import styled from 'styled-components' +import TransitiveOverlay, { + itineraryToTransitive +} from '@opentripplanner/transitive-overlay' + +import { AppConfig } from '../../util/config-types' +import { AppReduxState } from '../../util/state-types' +import { ComponentContext } from '../../util/contexts' + +interface Props { + config: AppConfig + itinerary: Itinerary +} + +const MapContainer = styled.div` + height: 100%; + width: 100%; + + .map { + height: 100%; + width: 100%; + } +` + +function noop() { + return null +} + +const DefaultMap = ({ config, itinerary }: Props): JSX.Element => { + const intl = useIntl() + const { getTransitiveRouteLabel } = useContext(ComponentContext) + const { + baseLayers, + initLat, + initLon, + initZoom, + maxZoom, + navigationControlPosition, + transitive + } = config.map || {} + const baseLayerUrls = baseLayers?.map((bl) => bl.url) + const { disableFlexArc, labeledModes, styles } = transitive || {} + const { legs } = itinerary + + return ( + + 1 ? baseLayerUrls : baseLayerUrls?.[0] + } + center={[initLat, initLon]} + mapLibreProps={{ reuseMaps: true }} + maxZoom={maxZoom} + zoom={initZoom} + > + + + + + + + + ) +} + +// connect to the redux store + +const mapStateToProps = (state: AppReduxState) => ({ + config: state.otp.config +}) + +export default connect(mapStateToProps)(DefaultMap) From ae22791ee21b8207eaccba56e587b3c7ce76f1b5 Mon Sep 17 00:00:00 2001 From: binh-dam-ibigroup <56846598+binh-dam-ibigroup@users.noreply.github.com> Date: Wed, 11 Sep 2024 17:29:06 -0400 Subject: [PATCH 08/18] refactor: Improve types --- lib/components/app/trip-preview-layout.tsx | 17 +++++++++++------ .../map/connected-transitive-overlay.tsx | 13 ++++--------- lib/components/map/simple-map.tsx | 12 +++++------- lib/components/user/types.ts | 5 +++++ lib/util/config-types.ts | 13 ++++++++++++- 5 files changed, 37 insertions(+), 23 deletions(-) diff --git a/lib/components/app/trip-preview-layout.tsx b/lib/components/app/trip-preview-layout.tsx index 30f3df206..aae4bb2bf 100644 --- a/lib/components/app/trip-preview-layout.tsx +++ b/lib/components/app/trip-preview-layout.tsx @@ -3,6 +3,7 @@ import { connect } from 'react-redux' import { FormattedMessage, injectIntl, IntlShape } from 'react-intl' import { Map } from '@styled-icons/fa-solid/Map' import { Print } from '@styled-icons/fa-solid/Print' +import { RouteComponentProps } from 'react-router' import { withAuthenticationRequired } from '@auth0/auth0-react' // @ts-expect-error not typescripted yet import PrintableItinerary from '@opentripplanner/printable-itinerary' @@ -28,6 +29,7 @@ import withLoggedInUserSupport from '../user/with-logged-in-user-support' type Props = { config: AppConfig intl: IntlShape + monitoredTrips?: MonitoredTrip[] | null tripId: string } @@ -48,9 +50,9 @@ class TripPreviewLayout extends Component { /** * Gets the trip to view from the props. */ - _getTripToEdit = (): MonitoredTrip => { + _getTripToEdit = (): MonitoredTrip | undefined => { const { monitoredTrips, tripId } = this.props - return monitoredTrips.find((trip) => trip.id === tripId) + return monitoredTrips?.find((trip) => trip.id === tripId) } _toggleMap = () => { @@ -74,19 +76,19 @@ class TripPreviewLayout extends Component { } render() { - const { config, intl, monitoredTrips } = this.props + const { config, intl } = this.props const { LegIcon } = this.context const printVerb = intl.formatMessage({ id: 'common.forms.print' }) const previewTripText = intl.formatMessage({ id: 'components.TripPreviewLayout.previewTrip' }) - const isAwaiting = !monitoredTrips + const monitoredTrip = this._getTripToEdit() + const isAwaiting = !monitoredTrip if (isAwaiting) { // Flash an indication while the selected and saved user trips are being loaded. return } - const monitoredTrip = this._getTripToEdit() const itinerary = monitoredTrip.journeyState?.matchingItinerary || monitoredTrip.itinerary @@ -141,7 +143,10 @@ class TripPreviewLayout extends Component { // connect to the redux store -const mapStateToProps = (state: AppReduxState, ownProps: Props) => { +const mapStateToProps = ( + state: AppReduxState, + ownProps: Props & RouteComponentProps<{ id: string }> +) => { const { loggedInUserMonitoredTrips: monitoredTrips } = state.user const tripId = ownProps.match.params.id diff --git a/lib/components/map/connected-transitive-overlay.tsx b/lib/components/map/connected-transitive-overlay.tsx index 71af754b8..7ed9d628c 100644 --- a/lib/components/map/connected-transitive-overlay.tsx +++ b/lib/components/map/connected-transitive-overlay.tsx @@ -2,19 +2,14 @@ import { connect } from 'react-redux' import { injectIntl, IntlShape } from 'react-intl' import TransitiveCanvasOverlay from '@opentripplanner/transitive-overlay' +import { AppReduxState } from '../../util/state-types' import { getActiveLeg, getTransitiveData } from '../../util/state' +import { TransitiveConfig } from '../../util/config-types' -type Props = { - intl?: IntlShape - labeledModes?: string[] - styles?: { - labels: Record - segmentLabels: Record - } -} +type Props = TransitiveConfig & IntlShape // connect to the redux store -const mapStateToProps = (state: Record, ownProps: Props) => { +const mapStateToProps = (state: AppReduxState, ownProps: Props) => { const { labeledModes, styles } = state.otp.config.map.transitive || {} const { viewedRoute } = state.otp.ui diff --git a/lib/components/map/simple-map.tsx b/lib/components/map/simple-map.tsx index b7937163b..de7079e6a 100644 --- a/lib/components/map/simple-map.tsx +++ b/lib/components/map/simple-map.tsx @@ -35,25 +35,26 @@ function noop() { const DefaultMap = ({ config, itinerary }: Props): JSX.Element => { const intl = useIntl() + // @ts-expect-error ComponentContext not typed yet. const { getTransitiveRouteLabel } = useContext(ComponentContext) const { baseLayers, - initLat, - initLon, + initLat = 0, + initLon = 0, initZoom, maxZoom, navigationControlPosition, transitive } = config.map || {} const baseLayerUrls = baseLayers?.map((bl) => bl.url) - const { disableFlexArc, labeledModes, styles } = transitive || {} + const { disableFlexArc } = transitive || {} const { legs } = itinerary return ( 1 ? baseLayerUrls : baseLayerUrls?.[0] + (baseLayerUrls?.length || 0) > 1 ? baseLayerUrls : baseLayerUrls?.[0] } center={[initLat, initLon]} mapLibreProps={{ reuseMaps: true }} @@ -67,9 +68,6 @@ const DefaultMap = ({ config, itinerary }: Props): JSX.Element => { /> +export interface JourneyState { + matchingItinerary?: Itinerary +} + export type MonitoredTrip = Record & { arrivalVarianceMinutesThreshold: number departureVarianceMinutesThreshold: number @@ -65,6 +69,7 @@ export type MonitoredTrip = Record & { isActive: boolean itinerary: Itinerary itineraryExistence?: ItineraryExistence + journeyState?: JourneyState leadTimeInMinutes: number queryParams: string tripName: string diff --git a/lib/util/config-types.ts b/lib/util/config-types.ts index 18e27ca37..f0bce5320 100644 --- a/lib/util/config-types.ts +++ b/lib/util/config-types.ts @@ -15,6 +15,7 @@ import { TransitOperator, VehicleRentalMapOverlaySymbol } from '@opentripplanner/types' +import { ControlPosition } from 'react-map-gl' import { GeocoderConfig as GeocoderConfigOtpUI } from '@opentripplanner/geocoder' /** Accessibility threshold settings */ @@ -221,6 +222,15 @@ export type SupportedOverlays = | Otp1StopsOverlayConfig | MapTileLayerConfig +export interface TransitiveConfig { + disableFlexArc?: boolean + labeledModes?: string[] + styles?: { + labels: Record + segmentLabels: Record + } +} + export interface MapConfig { autoFlyOnTripFormUpdate?: boolean baseLayers?: BaseLayerConfig[] @@ -228,8 +238,9 @@ export interface MapConfig { initLon?: number initZoom?: number maxZoom?: number - navigationControlPosition?: string + navigationControlPosition?: ControlPosition overlays?: SupportedOverlays[] + transitive?: TransitiveConfig views?: MapViewConfig[] } From 8d1da2424555da34d0f14f94fa61094cafaf1240 Mon Sep 17 00:00:00 2001 From: binh-dam-ibigroup <56846598+binh-dam-ibigroup@users.noreply.github.com> Date: Wed, 11 Sep 2024 17:49:41 -0400 Subject: [PATCH 09/18] refactor(webapp-trip-preview-routes): Tweak comments --- lib/util/webapp-trip-preview-routes.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/util/webapp-trip-preview-routes.js b/lib/util/webapp-trip-preview-routes.js index 70f35b506..004fd1767 100644 --- a/lib/util/webapp-trip-preview-routes.js +++ b/lib/util/webapp-trip-preview-routes.js @@ -1,9 +1,9 @@ import TripPreviewLayout from '../components/app/trip-preview-layout' /** - * Contains mapping of the component(s) to display for each URL printing route. + * Contains mapping of the component(s) to display for the trip preview URL. * - * Note: This file is separate from webapp-routes to isolate the import of printing components + * Note: This file is separate from webapp-routes to isolate the import of trip preview components * (YML file from @opentripplanner/trip-details). * that cause build errors during the a11y test. */ From af5f569ca5b8d1615c92df9817c5cf36c7c1ccd0 Mon Sep 17 00:00:00 2001 From: binh-dam-ibigroup <56846598+binh-dam-ibigroup@users.noreply.github.com> Date: Wed, 11 Sep 2024 17:55:43 -0400 Subject: [PATCH 10/18] refactor(SimpleMap): Move container out of component --- lib/components/app/trip-preview-layout.tsx | 15 ++++- lib/components/map/simple-map.tsx | 71 +++++++++------------- 2 files changed, 42 insertions(+), 44 deletions(-) diff --git a/lib/components/app/trip-preview-layout.tsx b/lib/components/app/trip-preview-layout.tsx index aae4bb2bf..7b0e92d4d 100644 --- a/lib/components/app/trip-preview-layout.tsx +++ b/lib/components/app/trip-preview-layout.tsx @@ -8,6 +8,7 @@ import { withAuthenticationRequired } from '@auth0/auth0-react' // @ts-expect-error not typescripted yet import PrintableItinerary from '@opentripplanner/printable-itinerary' import React, { Component } from 'react' +import styled from 'styled-components' import { addPrintViewClassToRootHtml, @@ -37,6 +38,16 @@ type State = { mapVisible?: boolean } +const MapContainer = styled.div` + height: 100%; + width: 100%; + + .map { + height: 100%; + width: 100%; + } +` + class TripPreviewLayout extends Component { static contextType = ComponentContext @@ -120,9 +131,9 @@ class TripPreviewLayout extends Component { {/* The map, if visible */} {this.state.mapVisible && ( -
+ -
+
)} {/* The main itinerary body */} diff --git a/lib/components/map/simple-map.tsx b/lib/components/map/simple-map.tsx index de7079e6a..a62aca608 100644 --- a/lib/components/map/simple-map.tsx +++ b/lib/components/map/simple-map.tsx @@ -5,7 +5,6 @@ import { useIntl } from 'react-intl' import BaseMap from '@opentripplanner/base-map' import EndpointsOverlay from '@opentripplanner/endpoints-overlay' import React, { useContext } from 'react' -import styled from 'styled-components' import TransitiveOverlay, { itineraryToTransitive } from '@opentripplanner/transitive-overlay' @@ -19,21 +18,11 @@ interface Props { itinerary: Itinerary } -const MapContainer = styled.div` - height: 100%; - width: 100%; - - .map { - height: 100%; - width: 100%; - } -` - function noop() { return null } -const DefaultMap = ({ config, itinerary }: Props): JSX.Element => { +const SimpleMap = ({ config, itinerary }: Props): JSX.Element => { const intl = useIntl() // @ts-expect-error ComponentContext not typed yet. const { getTransitiveRouteLabel } = useContext(ComponentContext) @@ -51,36 +40,34 @@ const DefaultMap = ({ config, itinerary }: Props): JSX.Element => { const { legs } = itinerary return ( - - 1 ? baseLayerUrls : baseLayerUrls?.[0] - } - center={[initLat, initLon]} - mapLibreProps={{ reuseMaps: true }} - maxZoom={maxZoom} - zoom={initZoom} - > - - - + 1 ? baseLayerUrls : baseLayerUrls?.[0] + } + center={[initLat, initLon]} + mapLibreProps={{ reuseMaps: true }} + maxZoom={maxZoom} + zoom={initZoom} + > + + + - - - + + ) } @@ -90,4 +77,4 @@ const mapStateToProps = (state: AppReduxState) => ({ config: state.otp.config }) -export default connect(mapStateToProps)(DefaultMap) +export default connect(mapStateToProps)(SimpleMap) From 650f390cae06ac0f521de63638ee6a8570585b02 Mon Sep 17 00:00:00 2001 From: binh-dam-ibigroup <56846598+binh-dam-ibigroup@users.noreply.github.com> Date: Tue, 1 Oct 2024 16:46:54 -0400 Subject: [PATCH 11/18] refactor(TripPreviewLayoutBase): Extract common component between print and preview layouts --- lib/components/app/print-layout.tsx | 126 +++----------- .../app/trip-preview-layout-base.tsx | 131 +++++++++++++++ lib/components/app/trip-preview-layout.tsx | 158 ++++-------------- 3 files changed, 181 insertions(+), 234 deletions(-) create mode 100644 lib/components/app/trip-preview-layout-base.tsx diff --git a/lib/components/app/print-layout.tsx b/lib/components/app/print-layout.tsx index d0365f015..2610eac90 100644 --- a/lib/components/app/print-layout.tsx +++ b/lib/components/app/print-layout.tsx @@ -1,65 +1,30 @@ -import { Button } from 'react-bootstrap' import { connect } from 'react-redux' import { FormattedMessage, injectIntl, IntlShape } from 'react-intl' import { Itinerary } from '@opentripplanner/types' -import { Map } from '@styled-icons/fa-solid/Map' -import { Print } from '@styled-icons/fa-solid/Print' -import { Times } from '@styled-icons/fa-solid/Times' -// @ts-expect-error not typescripted yet -import PrintableItinerary from '@opentripplanner/printable-itinerary' import React, { Component } from 'react' import * as apiActions from '../../actions/api' import * as formActions from '../../actions/form' -import { - addPrintViewClassToRootHtml, - clearClassFromRootHtml -} from '../../util/print' -import { ComponentContext } from '../../util/contexts' +import { AppReduxState } from '../../util/state-types' import { getActiveItinerary, getActiveSearch } from '../../util/state' -import { IconWithText } from '../util/styledIcon' import { summarizeQuery } from '../form/user-settings-i18n' +import { User } from '../user/types' import DefaultMap from '../map/default-map' -import PageTitle from '../util/page-title' -import SpanWithSpace from '../util/span-with-space' -import TripDetails from '../narrative/connected-trip-details' + +import TripPreviewLayoutBase from './trip-preview-layout-base' type Props = { // TODO: Typescript activeSearch type activeSearch: any - // TODO: Typescript config type - config: any currentQuery: any intl: IntlShape itinerary: Itinerary location?: { search?: string } parseUrlQueryString: (params?: any, source?: string) => any - // TODO: Typescript user type - user: any -} - -type State = { - mapVisible?: boolean + user: User } -class PrintLayout extends Component { - static contextType = ComponentContext - - constructor(props: Props) { - super(props) - this.state = { - mapVisible: true - } - } - - _toggleMap = () => { - this.setState({ mapVisible: !this.state.mapVisible }) - } - - _print = () => { - window.print() - } - +class PrintLayout extends Component { _close = () => { window.location.replace(String(window.location).replace('print/', '')) } @@ -67,9 +32,8 @@ class PrintLayout extends Component { componentDidMount() { const { itinerary, location, parseUrlQueryString } = this.props - // Add print-view class to html tag to ensure that iOS scroll fix only applies - // to non-print views. - addPrintViewClassToRootHtml() + console.log(itinerary, location) + // Parse the URL query parameters, if present if (!itinerary && location && location.search) { parseUrlQueryString() @@ -78,72 +42,27 @@ class PrintLayout extends Component { // TODO: use currentQuery to pan/zoom to the correct part of the map } - componentWillUnmount() { - clearClassFromRootHtml() - } - render() { - const { activeSearch, config, intl, itinerary, user } = this.props - const { LegIcon } = this.context + const { activeSearch, intl, itinerary, user } = this.props const printVerb = intl.formatMessage({ id: 'common.forms.print' }) return ( -
- - {/* The header bar, including the Toggle Map and Print buttons */} -
-
- - - - - - - -
- -
- - {/* The map, if visible */} - {this.state.mapVisible && ( + } + itinerary={itinerary} + mapElement={
{/* FIXME: Improve reframing/setting map bounds when itinerary is received. */}
- )} - - {/* The main itinerary body */} - {itinerary && ( - <> - - - - )} -
+ } + onClose={this._close} + subTitle={ + activeSearch && + summarizeQuery(activeSearch.query, intl, user.savedLocations) + } + title={printVerb} + /> ) } } @@ -151,13 +70,12 @@ class PrintLayout extends Component { // connect to the redux store // TODO: Typescript state -const mapStateToProps = (state: any) => { +const mapStateToProps = (state: AppReduxState) => { const activeSearch = getActiveSearch(state) const { localUser, loggedInUser } = state.user const user = loggedInUser || localUser return { activeSearch, - config: state.otp.config, currentQuery: state.otp.currentQuery, itinerary: getActiveItinerary(state) as Itinerary, user diff --git a/lib/components/app/trip-preview-layout-base.tsx b/lib/components/app/trip-preview-layout-base.tsx new file mode 100644 index 000000000..d7738f80f --- /dev/null +++ b/lib/components/app/trip-preview-layout-base.tsx @@ -0,0 +1,131 @@ +import { Button } from 'react-bootstrap' +import { connect } from 'react-redux' +import { FormattedMessage } from 'react-intl' +import { Itinerary } from '@opentripplanner/types' +import { Map } from '@styled-icons/fa-solid/Map' +import { Print } from '@styled-icons/fa-solid/Print' +import { Times } from '@styled-icons/fa-solid/Times' +// @ts-expect-error not typescripted yet +import PrintableItinerary from '@opentripplanner/printable-itinerary' +import React, { Component, ReactNode } from 'react' + +import { + addPrintViewClassToRootHtml, + clearClassFromRootHtml +} from '../../util/print' +import { AppConfig } from '../../util/config-types' +import { AppReduxState } from '../../util/state-types' +import { ComponentContext } from '../../util/contexts' +import { IconWithText } from '../util/styledIcon' +import PageTitle from '../util/page-title' +import SpanWithSpace from '../util/span-with-space' +import TripDetails from '../narrative/connected-trip-details' + +type Props = { + config: AppConfig + header?: ReactNode + itinerary?: Itinerary + mapElement?: ReactNode + onClose?: () => void + subTitle: string + title: string +} + +type State = { + mapVisible?: boolean +} + +class TripPreviewLayoutBase extends Component { + static contextType = ComponentContext + + constructor(props: Props) { + super(props) + this.state = { + mapVisible: true + } + } + + _toggleMap = () => { + this.setState({ mapVisible: !this.state.mapVisible }) + } + + _print = () => { + window.print() + } + + componentDidUpdate() { + // Add print-view class to html tag to ensure that iOS scroll fix only applies + // to non-print views. + addPrintViewClassToRootHtml() + } + + componentWillUnmount() { + clearClassFromRootHtml() + } + + render() { + const { config, itinerary, mapElement, onClose, subTitle, title } = + this.props + const { LegIcon } = this.context + + return ( +
+ + {/* The header bar, including the Toggle Map and Print buttons */} +
+
+ + + + + + + {onClose && ( + + )} +
+ {title} +
+ + {/* The map, if visible */} + {this.state.mapVisible && mapElement} + + {/* The main itinerary body */} + {itinerary && ( + <> + + + + )} +
+ ) + } +} + +// connect to the redux store + +const mapStateToProps = (state: AppReduxState) => ({ + config: state.otp.config +}) + +export default connect(mapStateToProps)(TripPreviewLayoutBase) diff --git a/lib/components/app/trip-preview-layout.tsx b/lib/components/app/trip-preview-layout.tsx index 7b0e92d4d..c3c9ffa31 100644 --- a/lib/components/app/trip-preview-layout.tsx +++ b/lib/components/app/trip-preview-layout.tsx @@ -1,41 +1,20 @@ -import { Button } from 'react-bootstrap' import { connect } from 'react-redux' -import { FormattedMessage, injectIntl, IntlShape } from 'react-intl' -import { Map } from '@styled-icons/fa-solid/Map' -import { Print } from '@styled-icons/fa-solid/Print' import { RouteComponentProps } from 'react-router' +import { useIntl } from 'react-intl' import { withAuthenticationRequired } from '@auth0/auth0-react' -// @ts-expect-error not typescripted yet -import PrintableItinerary from '@opentripplanner/printable-itinerary' -import React, { Component } from 'react' +import React from 'react' import styled from 'styled-components' -import { - addPrintViewClassToRootHtml, - clearClassFromRootHtml -} from '../../util/print' -import { AppConfig } from '../../util/config-types' import { AppReduxState } from '../../util/state-types' -import { ComponentContext } from '../../util/contexts' -import { IconWithText } from '../util/styledIcon' import { MonitoredTrip } from '../user/types' import { RETURN_TO_CURRENT_ROUTE } from '../../util/ui' -import AwaitingScreen from '../user/awaiting-screen' -import PageTitle from '../util/page-title' import SimpleMap from '../map/simple-map' -import SpanWithSpace from '../util/span-with-space' -import TripDetails from '../narrative/connected-trip-details' import withLoggedInUserSupport from '../user/with-logged-in-user-support' -type Props = { - config: AppConfig - intl: IntlShape - monitoredTrips?: MonitoredTrip[] | null - tripId: string -} +import TripPreviewLayoutBase from './trip-preview-layout-base' -type State = { - mapVisible?: boolean +type Props = { + monitoredTrip?: MonitoredTrip } const MapContainer = styled.div` @@ -48,108 +27,29 @@ const MapContainer = styled.div` } ` -class TripPreviewLayout extends Component { - static contextType = ComponentContext - - constructor(props: Props) { - super(props) - this.state = { - mapVisible: true - } - } - - /** - * Gets the trip to view from the props. - */ - _getTripToEdit = (): MonitoredTrip | undefined => { - const { monitoredTrips, tripId } = this.props - return monitoredTrips?.find((trip) => trip.id === tripId) - } - - _toggleMap = () => { - this.setState({ mapVisible: !this.state.mapVisible }) - } - - _print = () => { - window.print() - } - - componentDidUpdate() { - // Add print-view class to html tag to ensure that iOS scroll fix only applies - // to non-print views. - addPrintViewClassToRootHtml() - - // TODO: use currentQuery to pan/zoom to the correct part of the map - } - - componentWillUnmount() { - clearClassFromRootHtml() - } - - render() { - const { config, intl } = this.props - const { LegIcon } = this.context - const printVerb = intl.formatMessage({ id: 'common.forms.print' }) - const previewTripText = intl.formatMessage({ - id: 'components.TripPreviewLayout.previewTrip' - }) - const monitoredTrip = this._getTripToEdit() - const isAwaiting = !monitoredTrip - if (isAwaiting) { - // Flash an indication while the selected and saved user trips are being loaded. - return - } - - const itinerary = - monitoredTrip.journeyState?.matchingItinerary || monitoredTrip.itinerary - - return ( -
- - {/* The header bar, including the Toggle Map and Print buttons */} -
-
- - - - - - -
- {previewTripText} -
- - {/* The map, if visible */} - {this.state.mapVisible && ( +const TripPreviewLayout = ({ monitoredTrip }: Props) => { + const intl = useIntl() + const previewTripText = intl.formatMessage({ + id: 'components.TripPreviewLayout.previewTrip' + }) + const itinerary = + monitoredTrip?.journeyState?.matchingItinerary || monitoredTrip?.itinerary + + return ( + - )} - - {/* The main itinerary body */} - {itinerary && ( - <> - - - - )} -
- ) - } + ) + } + subTitle={monitoredTrip?.tripName} + title={previewTripText} + /> + ) } // connect to the redux store @@ -158,19 +58,17 @@ const mapStateToProps = ( state: AppReduxState, ownProps: Props & RouteComponentProps<{ id: string }> ) => { - const { loggedInUserMonitoredTrips: monitoredTrips } = state.user + const { loggedInUserMonitoredTrips: trips } = state.user const tripId = ownProps.match.params.id return { - config: state.otp.config, - monitoredTrips, - tripId + monitoredTrip: trips?.find((trip) => trip.id === tripId) } } export default withLoggedInUserSupport( withAuthenticationRequired( - connect(mapStateToProps)(injectIntl(TripPreviewLayout)), + connect(mapStateToProps)(TripPreviewLayout), RETURN_TO_CURRENT_ROUTE ), true From c5b622ef562b191ab11bddc4bec66d4570bcc9b4 Mon Sep 17 00:00:00 2001 From: binh-dam-ibigroup <56846598+binh-dam-ibigroup@users.noreply.github.com> Date: Tue, 1 Oct 2024 17:52:23 -0400 Subject: [PATCH 12/18] refactor(SimpleMap): Add checks for null itinerary --- lib/components/app/trip-preview-layout.tsx | 8 +++----- lib/components/map/simple-map.tsx | 22 ++++++++++++---------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/lib/components/app/trip-preview-layout.tsx b/lib/components/app/trip-preview-layout.tsx index c3c9ffa31..f00ff4d4c 100644 --- a/lib/components/app/trip-preview-layout.tsx +++ b/lib/components/app/trip-preview-layout.tsx @@ -40,11 +40,9 @@ const TripPreviewLayout = ({ monitoredTrip }: Props) => { header={previewTripText} itinerary={itinerary} mapElement={ - itinerary && ( - - - - ) + + + } subTitle={monitoredTrip?.tripName} title={previewTripText} diff --git a/lib/components/map/simple-map.tsx b/lib/components/map/simple-map.tsx index a62aca608..c0eebb708 100644 --- a/lib/components/map/simple-map.tsx +++ b/lib/components/map/simple-map.tsx @@ -15,7 +15,7 @@ import { ComponentContext } from '../../util/contexts' interface Props { config: AppConfig - itinerary: Itinerary + itinerary?: Itinerary } function noop() { @@ -37,7 +37,7 @@ const SimpleMap = ({ config, itinerary }: Props): JSX.Element => { } = config.map || {} const baseLayerUrls = baseLayers?.map((bl) => bl.url) const { disableFlexArc } = transitive || {} - const { legs } = itinerary + const { legs = [] } = itinerary || {} return ( { toLocation={legs[legs.length - 1]?.to} /> - + {itinerary && ( + + )} Date: Tue, 1 Oct 2024 18:43:43 -0400 Subject: [PATCH 13/18] refactor(TripPreviewLayoutBase): Fix types --- lib/components/app/trip-preview-layout-base.tsx | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/lib/components/app/trip-preview-layout-base.tsx b/lib/components/app/trip-preview-layout-base.tsx index d7738f80f..7fbe12bca 100644 --- a/lib/components/app/trip-preview-layout-base.tsx +++ b/lib/components/app/trip-preview-layout-base.tsx @@ -27,7 +27,7 @@ type Props = { itinerary?: Itinerary mapElement?: ReactNode onClose?: () => void - subTitle: string + subTitle?: string title: string } @@ -64,8 +64,14 @@ class TripPreviewLayoutBase extends Component { } render() { - const { config, itinerary, mapElement, onClose, subTitle, title } = - this.props + const { + config, + itinerary, + mapElement, + onClose, + subTitle = '', + title + } = this.props const { LegIcon } = this.context return ( From 2db92844849bf2a7ef4ea8b80f640572258b3208 Mon Sep 17 00:00:00 2001 From: binh-dam-ibigroup <56846598+binh-dam-ibigroup@users.noreply.github.com> Date: Tue, 1 Oct 2024 18:59:47 -0400 Subject: [PATCH 14/18] refactor: Remove unused code and tweak comments --- lib/components/app/print-layout.tsx | 7 ------- lib/components/map/simple-map.tsx | 1 + 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/lib/components/app/print-layout.tsx b/lib/components/app/print-layout.tsx index 2610eac90..7d8b2fd4e 100644 --- a/lib/components/app/print-layout.tsx +++ b/lib/components/app/print-layout.tsx @@ -16,7 +16,6 @@ import TripPreviewLayoutBase from './trip-preview-layout-base' type Props = { // TODO: Typescript activeSearch type activeSearch: any - currentQuery: any intl: IntlShape itinerary: Itinerary location?: { search?: string } @@ -32,14 +31,10 @@ class PrintLayout extends Component { componentDidMount() { const { itinerary, location, parseUrlQueryString } = this.props - console.log(itinerary, location) - // Parse the URL query parameters, if present if (!itinerary && location && location.search) { parseUrlQueryString() } - - // TODO: use currentQuery to pan/zoom to the correct part of the map } render() { @@ -69,14 +64,12 @@ class PrintLayout extends Component { // connect to the redux store -// TODO: Typescript state const mapStateToProps = (state: AppReduxState) => { const activeSearch = getActiveSearch(state) const { localUser, loggedInUser } = state.user const user = loggedInUser || localUser return { activeSearch, - currentQuery: state.otp.currentQuery, itinerary: getActiveItinerary(state) as Itinerary, user } diff --git a/lib/components/map/simple-map.tsx b/lib/components/map/simple-map.tsx index c0eebb708..446a11fbb 100644 --- a/lib/components/map/simple-map.tsx +++ b/lib/components/map/simple-map.tsx @@ -22,6 +22,7 @@ function noop() { return null } +/** Renders an optional itinerary with a given config. */ const SimpleMap = ({ config, itinerary }: Props): JSX.Element => { const intl = useIntl() // @ts-expect-error ComponentContext not typed yet. From 57234328e7b0f443cb28d40d7968d9da49e2e295 Mon Sep 17 00:00:00 2001 From: binh-dam-ibigroup <56846598+binh-dam-ibigroup@users.noreply.github.com> Date: Tue, 1 Oct 2024 19:11:38 -0400 Subject: [PATCH 15/18] refactor(TripPreviewLayoutBase): Actually render header prop --- lib/components/app/trip-preview-layout-base.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/components/app/trip-preview-layout-base.tsx b/lib/components/app/trip-preview-layout-base.tsx index 7fbe12bca..14fbf080b 100644 --- a/lib/components/app/trip-preview-layout-base.tsx +++ b/lib/components/app/trip-preview-layout-base.tsx @@ -66,6 +66,7 @@ class TripPreviewLayoutBase extends Component { render() { const { config, + header, itinerary, mapElement, onClose, @@ -106,7 +107,7 @@ class TripPreviewLayoutBase extends Component { )}
- {title} + {header}
{/* The map, if visible */} From d82715415e51b06d6ef623ccba6bd129bb3032aa Mon Sep 17 00:00:00 2001 From: binh-dam-ibigroup <56846598+binh-dam-ibigroup@users.noreply.github.com> Date: Thu, 10 Oct 2024 12:46:12 -0400 Subject: [PATCH 16/18] style(SimpleMap): Apply code style feedback. --- lib/components/map/simple-map.tsx | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/lib/components/map/simple-map.tsx b/lib/components/map/simple-map.tsx index 446a11fbb..960e6b532 100644 --- a/lib/components/map/simple-map.tsx +++ b/lib/components/map/simple-map.tsx @@ -33,7 +33,7 @@ const SimpleMap = ({ config, itinerary }: Props): JSX.Element => { initLon = 0, initZoom, maxZoom, - navigationControlPosition, + navigationControlPosition = 'bottom-right', transitive } = config.map || {} const baseLayerUrls = baseLayers?.map((bl) => bl.url) @@ -42,9 +42,7 @@ const SimpleMap = ({ config, itinerary }: Props): JSX.Element => { return ( 1 ? baseLayerUrls : baseLayerUrls?.[0] - } + baseLayer={baseLayerUrls?.length > 1 ? baseLayerUrls : baseLayerUrls?.[0]} center={[initLat, initLon]} mapLibreProps={{ reuseMaps: true }} maxZoom={maxZoom} @@ -52,6 +50,7 @@ const SimpleMap = ({ config, itinerary }: Props): JSX.Element => { > @@ -67,9 +66,7 @@ const SimpleMap = ({ config, itinerary }: Props): JSX.Element => { /> )} - + ) } From 6b97adfe7801db2275fc6358dd7248bdc9e64def Mon Sep 17 00:00:00 2001 From: binh-dam-ibigroup <56846598+binh-dam-ibigroup@users.noreply.github.com> Date: Thu, 10 Oct 2024 12:54:25 -0400 Subject: [PATCH 17/18] refactor(SimpleMap): Fix types --- lib/components/map/simple-map.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/components/map/simple-map.tsx b/lib/components/map/simple-map.tsx index 960e6b532..25040c268 100644 --- a/lib/components/map/simple-map.tsx +++ b/lib/components/map/simple-map.tsx @@ -42,7 +42,9 @@ const SimpleMap = ({ config, itinerary }: Props): JSX.Element => { return ( 1 ? baseLayerUrls : baseLayerUrls?.[0]} + baseLayer={ + (baseLayerUrls?.length || 0) > 1 ? baseLayerUrls : baseLayerUrls?.[0] + } center={[initLat, initLon]} mapLibreProps={{ reuseMaps: true }} maxZoom={maxZoom} From 83cadc9952112d9040f39768c5e7cd45577ba0cf Mon Sep 17 00:00:00 2001 From: binh-dam-ibigroup <56846598+binh-dam-ibigroup@users.noreply.github.com> Date: Fri, 11 Oct 2024 11:38:38 -0400 Subject: [PATCH 18/18] refactor(SimpleMap): Remove EndpointOverlay handler after updating OTP-UI pkg. --- lib/components/map/simple-map.tsx | 6 ------ package.json | 2 +- yarn.lock | 20 ++++++++++---------- 3 files changed, 11 insertions(+), 17 deletions(-) diff --git a/lib/components/map/simple-map.tsx b/lib/components/map/simple-map.tsx index 25040c268..f9312a9a4 100644 --- a/lib/components/map/simple-map.tsx +++ b/lib/components/map/simple-map.tsx @@ -18,10 +18,6 @@ interface Props { itinerary?: Itinerary } -function noop() { - return null -} - /** Renders an optional itinerary with a given config. */ const SimpleMap = ({ config, itinerary }: Props): JSX.Element => { const intl = useIntl() @@ -52,8 +48,6 @@ const SimpleMap = ({ config, itinerary }: Props): JSX.Element => { > diff --git a/package.json b/package.json index 34e1e7c8f..63a43c1fa 100644 --- a/package.json +++ b/package.json @@ -45,7 +45,7 @@ "@opentripplanner/base-map": "4.0.0", "@opentripplanner/building-blocks": "2.0.0", "@opentripplanner/core-utils": "12.0.0", - "@opentripplanner/endpoints-overlay": "3.0.0", + "@opentripplanner/endpoints-overlay": "3.0.1", "@opentripplanner/from-to-location-picker": "3.0.0", "@opentripplanner/geocoder": "^3.0.2", "@opentripplanner/humanize-distance": "^1.2.0", diff --git a/yarn.lock b/yarn.lock index 599332b3e..c96260c70 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2383,7 +2383,7 @@ dependencies: "@octokit/openapi-types" "^10.0.0" -"@opentripplanner/base-map@4.0.0": +"@opentripplanner/base-map@4.0.0", "@opentripplanner/base-map@^4.0.0": version "4.0.0" resolved "https://registry.yarnpkg.com/@opentripplanner/base-map/-/base-map-4.0.0.tgz#56ffa1d833673282cc3a0b7a17f388fc5dbd31e3" integrity sha512-pWTKXxnzUQk43woPMc40uYfGIcGqHV8GoCvRwrIu2pqNw7QAV4rxjZfca0pm5hnbbJ+G83sRzYboILEbEUwMcw== @@ -2403,7 +2403,7 @@ maplibre-gl "^2.1.9" react-map-gl "^7.0.15" -"@opentripplanner/building-blocks@2.0.0": +"@opentripplanner/building-blocks@2.0.0", "@opentripplanner/building-blocks@^2.0.0": version "2.0.0" resolved "https://registry.yarnpkg.com/@opentripplanner/building-blocks/-/building-blocks-2.0.0.tgz#8282c01dff7db5c7e809f6ea91cb52df559a2f9d" integrity sha512-N07rDaZL8fp552eI9/0j1udKjc0uOpvO0Wv1P19Ge0a4roques463MJgWJ026fbopRCi3uwbc/gYTlh4/ske9A== @@ -2413,7 +2413,7 @@ resolved "https://registry.yarnpkg.com/@opentripplanner/building-blocks/-/building-blocks-1.2.3.tgz#404e8f9038867d66d55f51adf8855b1326c51ed5" integrity sha512-I0AxiZrTZu+e7+av4u0tHW2ijqpxH0AkLHrhf75BHf1Ep2FOGxaul/v+8UT18mNYiM5eHNstOX3XiXaDjtCUaw== -"@opentripplanner/core-utils@12.0.0": +"@opentripplanner/core-utils@12.0.0", "@opentripplanner/core-utils@^12.0.0": version "12.0.0" resolved "https://registry.yarnpkg.com/@opentripplanner/core-utils/-/core-utils-12.0.0.tgz#cc40af92620b207f4dce817d08f99def0cdaea7a" integrity sha512-udLF8XU+k7gxZ+yyyw7ASz6/4D540zYIv8a9GbUL61TF8HmgGhcMk3XOgBnm5jdOukuaNNpOFE4J3oJc5QsSBQ== @@ -2449,14 +2449,14 @@ lodash.isequal "^4.5.0" qs "^6.9.1" -"@opentripplanner/endpoints-overlay@3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@opentripplanner/endpoints-overlay/-/endpoints-overlay-3.0.0.tgz#17bb943f5bf2b8571cb808b12b5a2185fd18196a" - integrity sha512-st6vfLRCBzVollYS4nIXghbjApDq73lcExo7hZh60DCVSGESSZA9jsNE6ff0HmvhYHdag9QV9zbZOFuNxPIrng== +"@opentripplanner/endpoints-overlay@3.0.1": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@opentripplanner/endpoints-overlay/-/endpoints-overlay-3.0.1.tgz#b6b8e2f08ae41fbaad475fc0f0fe3e72d7d36463" + integrity sha512-X3T0GM8U+VU/mOOSNUgj6fVcjAKMeciKFYnQNbKiNgNeDHa5JltwvtXsM4x3wCLP2xAF6jH/HTWJmYmsfLPlAw== dependencies: - "@opentripplanner/base-map" "^3.2.2" - "@opentripplanner/building-blocks" "^1.2.2" - "@opentripplanner/core-utils" "^11.4.4" + "@opentripplanner/base-map" "^4.0.0" + "@opentripplanner/building-blocks" "^2.0.0" + "@opentripplanner/core-utils" "^12.0.0" "@opentripplanner/location-icon" "^1.4.1" "@styled-icons/fa-solid" "^10.34.0" flat "^5.0.2"