From 57fefd85e65154789517b634f8137df4740be9f9 Mon Sep 17 00:00:00 2001 From: miles-grant-ibigroup Date: Mon, 9 Dec 2024 13:00:19 -0500 Subject: [PATCH 1/5] feat(nearby view): add location field --- i18n/en-US.yml | 1 + lib/components/viewers/nearby/nearby-view.tsx | 52 ++++++++++++++++++- lib/components/viewers/viewers.css | 21 ++++++++ 3 files changed, 72 insertions(+), 2 deletions(-) diff --git a/i18n/en-US.yml b/i18n/en-US.yml index 9bb360c76..efa1b74c8 100644 --- a/i18n/en-US.yml +++ b/i18n/en-US.yml @@ -379,6 +379,7 @@ components: headsign: "{destination}" nearbyListIntro: List of {count} nearby entities. nothingNearby: There are no places nearby. + searchNearby: Search nearby... spacesAvailable: "{spacesAvailable} empty spaces available" NewAccountWizard: createNewAccount: Create a new account diff --git a/lib/components/viewers/nearby/nearby-view.tsx b/lib/components/viewers/nearby/nearby-view.tsx index 1405f9eae..23294de6d 100644 --- a/lib/components/viewers/nearby/nearby-view.tsx +++ b/lib/components/viewers/nearby/nearby-view.tsx @@ -2,12 +2,17 @@ import { connect } from 'react-redux' import { FormattedMessage, useIntl } from 'react-intl' import { Location } from '@opentripplanner/types' import { MapRef, useMap } from 'react-map-gl' +import { Search } from '@styled-icons/fa-solid' +import getGeocoder from '@opentripplanner/geocoder' +import LocationField from '@opentripplanner/location-field' import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react' import * as apiActions from '../../../actions/api' +import * as locationActions from '../../../actions/location' import * as mapActions from '../../../actions/map' import * as uiActions from '../../../actions/ui' import { AppReduxState } from '../../../util/state-types' +import { GeocoderConfig } from '../../../util/config-types' import { getCurrentServiceWeek } from '../../../util/current-service-week' import { SetLocationHandler, ZoomToPlaceHandler } from '../../util/types' import Loading from '../../narrative/loading' @@ -45,6 +50,8 @@ type Props = { radius?: number, currentServiceWeek?: ServiceWeek ) => void + geocoderConfig: GeocoderConfig + getCurrentPosition: TODO hideBackButton?: boolean location: string mobile?: boolean @@ -114,6 +121,8 @@ function NearbyView({ displayedCoords, entityId, fetchNearby, + geocoderConfig, + getCurrentPosition, location, mobile, nearby, @@ -127,6 +136,7 @@ function NearbyView({ const map = useMap().default const intl = useIntl() const [loading, setLoading] = useState(true) + const [reversedPoint, setReversedPoint] = useState('') const firstItemRef = useRef(null) const finalNearbyCoords = useMemo( () => @@ -139,6 +149,12 @@ function NearbyView({ [nearbyViewCoords, currentPosition, map] ) + const reverseCoords = (coords) => { + getGeocoder(geocoderConfig) + .reverse({ point: coords }) + .then((result) => setReversedPoint(result.name)) + } + // Make sure the highlighted location is cleaned up when leaving nearby useEffect(() => { return function cleanup() { @@ -149,10 +165,12 @@ function NearbyView({ useEffect(() => { const moveListener = (e: mapboxgl.EventData) => { if (e.geolocateSource) { - setViewedNearbyCoords({ + const coords = { lat: e.viewState.latitude, lon: e.viewState.longitude - }) + } + setViewedNearbyCoords(coords) + reverseCoords(coords) } } @@ -162,9 +180,11 @@ function NearbyView({ lon: e.viewState.longitude } setViewedNearbyCoords(coords) + reverseCoords(coords) // Briefly flash the highlight to alert the user that we've moved setHighlightedLocation(coords) + setTimeout(() => { setHighlightedLocation(null) }, 500) @@ -286,6 +306,32 @@ function NearbyView({ > {/* This is used to scroll to top */}
+ ( + + )} + locationType="to" + onLocationSelected={(selection) => { + const { location } = selection + setViewedNearbyCoords(location) + map && zoomToPlace(map, location) + setReversedPoint(location.name || '') + }} + sortByDistance + /> {loading && ( @@ -327,6 +373,7 @@ const mapStateToProps = (state: AppReduxState) => { defaultLatLon, displayedCoords: nearby?.coords, entityId: entityId && decodeURIComponent(entityId), + geocoderConfig: config.geocoder, homeTimezone: config.homeTimezone, location: state.router.location.hash, nearby: nearby?.data, @@ -337,6 +384,7 @@ const mapStateToProps = (state: AppReduxState) => { const mapDispatchToProps = { fetchNearby: apiActions.fetchNearby, + getCurrentPosition: locationActions.getCurrentPosition, setHighlightedLocation: uiActions.setHighlightedLocation, setLocation: mapActions.setLocation, setMainPanelContent: uiActions.setMainPanelContent, diff --git a/lib/components/viewers/viewers.css b/lib/components/viewers/viewers.css index 1ea4637a9..c06fb1df2 100644 --- a/lib/components/viewers/viewers.css +++ b/lib/components/viewers/viewers.css @@ -249,3 +249,24 @@ justify-content: center; padding-top: 10px; } + +/* Nearby View Location Field Styles */ +.nearby-view-location-field { + background-color: rgba(255, 255, 255, 0.85); + transition: background-color 0.1s ease-out; + border-radius: 10px; + height: 50px; + color: #111; + display: flex !important; + border: none !important; + box-shadow: 0px 0px 5px 1px inset rgb(0 0 0 / 0.05); +} +.nearby-view-location-field:hover, +.nearby-view-location-field:active { + background-color: rgba(255, 255, 255, 0.95); + box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1); +} +.nearby-view-location-field input { + width: 100% !important; + background: transparent !important; +} From 72d0d6c2fcbd54f2cd99a34bbabe2d294eca9275 Mon Sep 17 00:00:00 2001 From: miles-grant-ibigroup Date: Fri, 20 Dec 2024 12:25:47 -0500 Subject: [PATCH 2/5] address pr feedback --- lib/components/viewers/nearby/nearby-view.tsx | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/lib/components/viewers/nearby/nearby-view.tsx b/lib/components/viewers/nearby/nearby-view.tsx index 23294de6d..87a70345f 100644 --- a/lib/components/viewers/nearby/nearby-view.tsx +++ b/lib/components/viewers/nearby/nearby-view.tsx @@ -308,6 +308,7 @@ function NearbyView({
- {loading && ( - - - - )} + {loading && } {nearby && !staleData && (nearby.error ? ( From 7fb5f6f3c40dd16055879bf418ce828986269ce3 Mon Sep 17 00:00:00 2001 From: miles-grant-ibigroup Date: Fri, 20 Dec 2024 12:30:11 -0500 Subject: [PATCH 3/5] correct icon imports --- lib/components/app/app-menu.tsx | 4 +++- lib/components/app/popup.tsx | 2 +- lib/components/form/advanced-settings-button.tsx | 2 +- lib/components/form/connected-location-field.tsx | 2 +- lib/components/user/monitored-trip/saved-trip-list.tsx | 3 ++- lib/components/user/monitored-trip/trip-summary-pane.tsx | 5 ++++- lib/components/util/externalLink.tsx | 2 +- lib/components/util/transit-operator-icons.tsx | 2 +- lib/components/viewers/nearby/nearby-view.tsx | 8 ++------ lib/components/viewers/nearby/stop.tsx | 2 +- lib/components/viewers/nearby/vehicle-parking.tsx | 2 +- lib/components/viewers/pattern-row.tsx | 2 +- lib/components/viewers/route-row.tsx | 2 +- 13 files changed, 20 insertions(+), 18 deletions(-) diff --git a/lib/components/app/app-menu.tsx b/lib/components/app/app-menu.tsx index fe3870e5c..71b144192 100644 --- a/lib/components/app/app-menu.tsx +++ b/lib/components/app/app-menu.tsx @@ -3,9 +3,11 @@ import { connect } from 'react-redux' import { Envelope } from '@styled-icons/fa-regular/Envelope' import { ExternalLinkSquareAlt } from '@styled-icons/fa-solid/ExternalLinkSquareAlt' import { FormattedMessage, injectIntl } from 'react-intl' -import { GlobeAmericas, MapMarked, MapPin } from '@styled-icons/fa-solid' +import { GlobeAmericas } from '@styled-icons/fa-solid/GlobeAmericas' import { GraduationCap } from '@styled-icons/fa-solid/GraduationCap' import { History } from '@styled-icons/fa-solid/History' +import { MapMarked } from '@styled-icons/fa-solid/MapMarked' +import { MapPin } from '@styled-icons/fa-solid/MapPin' import { Undo } from '@styled-icons/fa-solid/Undo' import React, { Component, Fragment, useContext } from 'react' import SlidingPane from 'react-sliding-pane' diff --git a/lib/components/app/popup.tsx b/lib/components/app/popup.tsx index 8a67961cd..a569b9c5d 100644 --- a/lib/components/app/popup.tsx +++ b/lib/components/app/popup.tsx @@ -1,5 +1,5 @@ import { Modal } from 'react-bootstrap' -import { Times } from '@styled-icons/fa-solid' +import { Times } from '@styled-icons/fa-solid/Times' import { useIntl } from 'react-intl' import coreUtils from '@opentripplanner/core-utils' import React, { useCallback, useEffect } from 'react' diff --git a/lib/components/form/advanced-settings-button.tsx b/lib/components/form/advanced-settings-button.tsx index 0449dc85d..2453ba13b 100644 --- a/lib/components/form/advanced-settings-button.tsx +++ b/lib/components/form/advanced-settings-button.tsx @@ -1,4 +1,4 @@ -import { ArrowRight } from '@styled-icons/fa-solid' +import { ArrowRight } from '@styled-icons/fa-solid/ArrowRight' import { FormattedMessage } from 'react-intl' import { grey } from '../util/colors' diff --git a/lib/components/form/connected-location-field.tsx b/lib/components/form/connected-location-field.tsx index 7b715333e..1f7ae03dd 100644 --- a/lib/components/form/connected-location-field.tsx +++ b/lib/components/form/connected-location-field.tsx @@ -3,7 +3,7 @@ import { LocationFieldProps, LocationSelectedEvent } from '@opentripplanner/location-field/lib/types' -import { MapPin } from '@styled-icons/fa-solid' +import { MapPin } from '@styled-icons/fa-solid/MapPin' import React, { useCallback, useContext, useState } from 'react' import * as formActions from '../../actions/form' diff --git a/lib/components/user/monitored-trip/saved-trip-list.tsx b/lib/components/user/monitored-trip/saved-trip-list.tsx index 03e33f80f..a02855f52 100644 --- a/lib/components/user/monitored-trip/saved-trip-list.tsx +++ b/lib/components/user/monitored-trip/saved-trip-list.tsx @@ -1,6 +1,7 @@ import { connect } from 'react-redux' -import { Edit, Map } from '@styled-icons/fa-solid' +import { Edit } from '@styled-icons/fa-solid/Edit' import { FormattedMessage, injectIntl, IntlShape, useIntl } from 'react-intl' +import { Map } from '@styled-icons/fa-solid/Map' import { Panel } from 'react-bootstrap' import { TriangleExclamation } from '@styled-icons/fa-solid/TriangleExclamation' import { withAuthenticationRequired } from '@auth0/auth0-react' diff --git a/lib/components/user/monitored-trip/trip-summary-pane.tsx b/lib/components/user/monitored-trip/trip-summary-pane.tsx index 3e1ccef51..6bf8a4465 100644 --- a/lib/components/user/monitored-trip/trip-summary-pane.tsx +++ b/lib/components/user/monitored-trip/trip-summary-pane.tsx @@ -1,4 +1,7 @@ -import { Bell, BellSlash, Calendar, Clock } from '@styled-icons/fa-regular' +import { Bell } from '@styled-icons/fa-regular/Bell' +import { BellSlash } from '@styled-icons/fa-regular/BellSlash' +import { Calendar } from '@styled-icons/fa-regular/Calendar' +import { Clock } from '@styled-icons/fa-regular/Clock' import { FormattedDate, FormattedMessage, useIntl } from 'react-intl' import LocationIcon from '@opentripplanner/location-icon' import React from 'react' diff --git a/lib/components/util/externalLink.tsx b/lib/components/util/externalLink.tsx index ce7a8d422..78ee20a84 100644 --- a/lib/components/util/externalLink.tsx +++ b/lib/components/util/externalLink.tsx @@ -1,4 +1,4 @@ -import { ExternalLinkAlt } from '@styled-icons/fa-solid' +import { ExternalLinkAlt } from '@styled-icons/fa-solid/ExternalLinkAlt' import { useIntl } from 'react-intl' import React, { HTMLAttributes } from 'react' diff --git a/lib/components/util/transit-operator-icons.tsx b/lib/components/util/transit-operator-icons.tsx index 7f40fe11c..d92aaf6f9 100644 --- a/lib/components/util/transit-operator-icons.tsx +++ b/lib/components/util/transit-operator-icons.tsx @@ -1,4 +1,4 @@ -import { MapPin } from '@styled-icons/fa-solid' +import { MapPin } from '@styled-icons/fa-solid/MapPin' import { useIntl } from 'react-intl' import React from 'react' import Skeleton from 'react-loading-skeleton' diff --git a/lib/components/viewers/nearby/nearby-view.tsx b/lib/components/viewers/nearby/nearby-view.tsx index 87a70345f..927a15f6c 100644 --- a/lib/components/viewers/nearby/nearby-view.tsx +++ b/lib/components/viewers/nearby/nearby-view.tsx @@ -2,7 +2,7 @@ import { connect } from 'react-redux' import { FormattedMessage, useIntl } from 'react-intl' import { Location } from '@opentripplanner/types' import { MapRef, useMap } from 'react-map-gl' -import { Search } from '@styled-icons/fa-solid' +import { Search } from '@styled-icons/fa-solid/Search' import getGeocoder from '@opentripplanner/geocoder' import LocationField from '@opentripplanner/location-field' import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react' @@ -21,11 +21,7 @@ import MobileNavigationBar from '../../mobile/navigation-bar' import PageTitle from '../../util/page-title' import VehiclePositionRetriever from '../vehicle-position-retriever' -import { - FloatingLoadingIndicator, - NearbySidebarContainer, - Scrollable -} from './styled' +import { NearbySidebarContainer, Scrollable } from './styled' import FromToPicker from './from-to-picker' import RentalStation from './rental-station' import Stop from './stop' diff --git a/lib/components/viewers/nearby/stop.tsx b/lib/components/viewers/nearby/stop.tsx index c98d288c1..6e02fa0dc 100644 --- a/lib/components/viewers/nearby/stop.tsx +++ b/lib/components/viewers/nearby/stop.tsx @@ -1,4 +1,4 @@ -import { Calendar } from '@styled-icons/fa-solid' +import { Calendar } from '@styled-icons/fa-solid/Calendar' import { connect } from 'react-redux' import { FormattedMessage } from 'react-intl' import coreUtils from '@opentripplanner/core-utils' diff --git a/lib/components/viewers/nearby/vehicle-parking.tsx b/lib/components/viewers/nearby/vehicle-parking.tsx index e9bf9771f..d8b26d41f 100644 --- a/lib/components/viewers/nearby/vehicle-parking.tsx +++ b/lib/components/viewers/nearby/vehicle-parking.tsx @@ -1,4 +1,4 @@ -import { Parking } from '@styled-icons/fa-solid' +import { Parking } from '@styled-icons/fa-solid/Parking' import { Place } from '@opentripplanner/types' import React from 'react' diff --git a/lib/components/viewers/pattern-row.tsx b/lib/components/viewers/pattern-row.tsx index e4bbef83c..794e8472b 100644 --- a/lib/components/viewers/pattern-row.tsx +++ b/lib/components/viewers/pattern-row.tsx @@ -1,4 +1,4 @@ -import { Calendar } from '@styled-icons/fa-regular' +import { Calendar } from '@styled-icons/fa-regular/Calendar' import { format, utcToZonedTime } from 'date-fns-tz' import { FormattedMessage } from 'react-intl' import { getMostReadableTextColor } from '@opentripplanner/core-utils/lib/route' diff --git a/lib/components/viewers/route-row.tsx b/lib/components/viewers/route-row.tsx index 6e1aebe98..094693e91 100644 --- a/lib/components/viewers/route-row.tsx +++ b/lib/components/viewers/route-row.tsx @@ -1,4 +1,4 @@ -import { ArrowRight } from '@styled-icons/fa-solid' +import { ArrowRight } from '@styled-icons/fa-solid/ArrowRight' import { IntlShape } from 'react-intl' import React, { PureComponent } from 'react' import styled from 'styled-components' From bc00c76c8ef2aecd482a32aef685cb6a164bee1e Mon Sep 17 00:00:00 2001 From: miles-grant-ibigroup Date: Fri, 20 Dec 2024 12:38:53 -0500 Subject: [PATCH 4/5] clean up --- lib/components/viewers/nearby/nearby-view.tsx | 13 +++++++------ lib/components/viewers/viewers.css | 9 +++++---- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/lib/components/viewers/nearby/nearby-view.tsx b/lib/components/viewers/nearby/nearby-view.tsx index e020971e5..e1764ef06 100644 --- a/lib/components/viewers/nearby/nearby-view.tsx +++ b/lib/components/viewers/nearby/nearby-view.tsx @@ -13,7 +13,7 @@ import * as locationActions from '../../../actions/location' import * as mapActions from '../../../actions/map' import * as uiActions from '../../../actions/ui' import { AppReduxState } from '../../../util/state-types' -import { GeocoderConfig, NearbyViewConfig } from '../../../util/config-types' +import { GeocoderConfig } from '../../../util/config-types' import { getCurrentServiceWeek } from '../../../util/current-service-week' import { PatternStopTime, @@ -53,13 +53,13 @@ type Props = { currentServiceWeek?: ServiceWeek ) => void geocoderConfig: GeocoderConfig - getCurrentPosition: TODO + getCurrentPosition: any // TODO hideBackButton?: boolean + hideEmptyStops?: boolean location: string mobile?: boolean // Todo: type nearby results nearby: any - nearbyViewConfig?: NearbyViewConfig nearbyViewCoords?: LatLonObj radius?: number routeSortComparator: (a: PatternStopTime, b: PatternStopTime) => number @@ -128,10 +128,10 @@ function NearbyView({ fetchNearby, geocoderConfig, getCurrentPosition, + hideEmptyStops, location, mobile, nearby, - nearbyViewConfig, nearbyViewCoords, radius, routeSortComparator, @@ -254,7 +254,7 @@ function NearbyView({ // If configured, filter out stops that don't have any patterns const filteredNearby = nearby?.filter((n: any) => { - if (n.place.__typename === 'Stop' && nearbyViewConfig?.hideEmptyStops) { + if (n.place.__typename === 'Stop' && hideEmptyStops) { const patternArray = patternArrayforStops(n.place, routeSortComparator) return !(patternArray?.length === 0) } @@ -332,6 +332,7 @@ function NearbyView({
{ displayedCoords: nearby?.coords, entityId: entityId && decodeURIComponent(entityId), geocoderConfig: config.geocoder, + hideEmptyStops: config.nearbyView?.hideEmptyStops, homeTimezone: config.homeTimezone, location: state.router.location.hash, nearby: nearby?.data, - nearbyViewConfig, nearbyViewCoords, radius: config.nearbyView?.radius, routeSortComparator diff --git a/lib/components/viewers/viewers.css b/lib/components/viewers/viewers.css index c06fb1df2..2f715e1df 100644 --- a/lib/components/viewers/viewers.css +++ b/lib/components/viewers/viewers.css @@ -253,13 +253,14 @@ /* Nearby View Location Field Styles */ .nearby-view-location-field { background-color: rgba(255, 255, 255, 0.85); - transition: background-color 0.1s ease-out; border-radius: 10px; - height: 50px; - color: #111; - display: flex !important; border: none !important; box-shadow: 0px 0px 5px 1px inset rgb(0 0 0 / 0.05); + color: #111; + display: flex !important; + height: 50px; + margin-bottom: -5px !important; + transition: background-color 0.1s ease-out; } .nearby-view-location-field:hover, .nearby-view-location-field:active { From ad4eb9f219da8b01add3976f3b93f2d322b7abcd Mon Sep 17 00:00:00 2001 From: miles-grant-ibigroup Date: Fri, 20 Dec 2024 12:48:36 -0500 Subject: [PATCH 5/5] pass ci --- .../viewers/__snapshots__/nearby-view.js.snap | 474 ++++++++++++++++++ i18n/fr.yml | 1 + lib/components/viewers/nearby/nearby-view.tsx | 5 +- 3 files changed, 478 insertions(+), 2 deletions(-) diff --git a/__tests__/components/viewers/__snapshots__/nearby-view.js.snap b/__tests__/components/viewers/__snapshots__/nearby-view.js.snap index 629be1f50..c968a306d 100644 --- a/__tests__/components/viewers/__snapshots__/nearby-view.js.snap +++ b/__tests__/components/viewers/__snapshots__/nearby-view.js.snap @@ -33,6 +33,7 @@ exports[`components > viewers > nearby view renders nothing on a blank page 1`] } defaultLatLon={null} fetchNearby={[Function]} + getCurrentPosition={[Function]} homeTimezone="America/Los_Angeles" nearby={Array []} routeSortComparator={[Function]} @@ -102,6 +103,242 @@ exports[`components > viewers > nearby view renders nothing on a blank page 1`] } } > +
+ + +
+ + + + + + + + + + + + + +
    + +
+
+
@@ -156,6 +393,7 @@ exports[`components > viewers > nearby view renders proper scooter dates 1`] = ` } defaultLatLon={null} fetchNearby={[Function]} + getCurrentPosition={[Function]} homeTimezone="America/Los_Angeles" nearby={ Array [ @@ -4143,6 +4381,242 @@ exports[`components > viewers > nearby view renders proper scooter dates 1`] = ` } } > +
+ + +
+ + + + + + + + + + + + + +
    + +
+
+
  • { + const reverseCoords = (coords: LonLatInput) => { getGeocoder(geocoderConfig) .reverse({ point: coords }) - .then((result) => setReversedPoint(result.name)) + .then((result: Location) => setReversedPoint(result?.name || '')) } // Make sure the highlighted location is cleaned up when leaving nearby