diff --git a/app/component/AlertBanner.js b/app/component/AlertBanner.js index 222f73c02a..7629dcb5c9 100644 --- a/app/component/AlertBanner.js +++ b/app/component/AlertBanner.js @@ -17,7 +17,8 @@ const AlertBanner = ({ alerts, linkAddress }, { config }) => { alert.alertSeverityLevel !== 'INFO' ? 'icon_caution_white_exclamation' : 'icon_info'; - const iconColor = alert.alertSeverityLevel !== 'INFO' ? '#DC0451' : '#888'; + const iconColor = + alert.alertSeverityLevel !== 'INFO' ? config.colors.caution : '#888'; return ( { const alerts = [...getAlertsForObject(route)]; @@ -51,7 +51,7 @@ export default function DepartureRow( let backgroundClass; let sr; if ( - route?.alerts?.filter(alert => isAlertValid(alert, props.currentTime)) + route.alerts?.filter(alert => isAlertValid(alert, props.currentTime)) ?.length > 0 ) { const alert = getMostSevereAlert(route); @@ -65,17 +65,17 @@ export default function DepartureRow( if (alert.alertSeverityLevel === 'INFO') { icon = 'icon_info'; iconColor = '#888'; - background = ; + background = ; backgroundClass = 'circle'; } else { icon = 'icon_caution-white-excl-stroke'; - iconColor = '#DC0451'; + iconColor = config.colors.caution; } } const headsign = departure.headsign || trip.tripHeadsign || - getHeadsignFromRouteLongName(trip.route); + getHeadsignFromRouteLongName(route); let shownTime; if (timeDiffInMinutes <= 0) { shownTime = intl.formatMessage({ @@ -93,7 +93,7 @@ export default function DepartureRow( { minutes: timeDiffInMinutes }, ); } - const { shortName } = trip.route; + const { shortName } = route; const lowerCaseShortName = shortName?.toLowerCase(); const nameOrIcon = shortName?.length > 6 || !shortName?.length ? ( @@ -166,7 +166,7 @@ export default function DepartureRow( className={cx('route-number-container', { long: shortName && shortName.length <= 6 && shortName.length >= 5, })} - style={{ backgroundColor: `#${trip.route.color}` }} + style={{ backgroundColor: `#${route.color}` }} > -
-

- {intl.formatMessage({ id: `${prePostFix}-disclaimer-header` })} -

-
- {intl.formatMessage({ id: `${prePostFix}-disclaimer` })} + {showInfo && ( +
+

+ {intl.formatMessage({ id: `${prePostFix}-disclaimer-header` })} +

+
+ {intl.formatMessage({ id: `${prePostFix}-disclaimer` })} +
+ {/* eslint-disable-next-line jsx-a11y/anchor-is-valid */} + {config.parkAndRide.url && ( + { + e.stopPropagation(); + }} + className="external-link" + href={config.parkAndRide.url[lang]} + target="_blank" + rel="noreferrer" + > + {intl.formatMessage({ id: `${prePostFix}-disclaimer-link` })}{' '} + › + + )}
- {/* eslint-disable-next-line jsx-a11y/anchor-is-valid */} - {config.parkAndRide.url && ( - { - e.stopPropagation(); - }} - className="external-link" - href={config.parkAndRide.url[lang]} - target="_blank" - rel="noreferrer" - > - {intl.formatMessage({ id: `${prePostFix}-disclaimer-link` })}{' '} - › - - )} -
+ )}
); } @@ -236,11 +241,17 @@ ParkAndRideContent.propTypes = { vehicleParking: parkShape, error: errorShape, currentLanguage: PropTypes.string.isRequired, + mode: PropTypes.oneOf(['CARPARK', 'BIKEPARK']), + showInfo: PropTypes.bool, + backButton: PropTypes.bool, }; ParkAndRideContent.defaultProps = { vehicleParking: undefined, error: undefined, + mode: undefined, + showInfo: true, + backButton: true, }; ParkAndRideContent.contextTypes = { diff --git a/app/component/ParkContainer.js b/app/component/ParkContainer.js index 1da8696a5e..3fb359e087 100644 --- a/app/component/ParkContainer.js +++ b/app/component/ParkContainer.js @@ -8,7 +8,7 @@ const containerComponent = createFragmentContainer(ParkAndRideContent, { bicycleSpaces carSpaces } - capacity { + parkCapacity: capacity { carSpaces } name diff --git a/app/component/ParkOrStationHeader.js b/app/component/ParkOrStationHeader.js index 01cb60afb4..4f8009ae96 100644 --- a/app/component/ParkOrStationHeader.js +++ b/app/component/ParkOrStationHeader.js @@ -3,17 +3,17 @@ import React, { useEffect, useState } from 'react'; import { FormattedMessage } from 'react-intl'; import { configShape } from '../util/shapes'; import StopCode from './StopCode'; +import withBreakpoint from '../util/withBreakpoint'; import BackButton from './BackButton'; import { getJson } from '../util/xhrPromise'; import getZoneId from '../util/zoneIconUtils'; import ZoneIcon from './ZoneIcon'; -import withBreakpoint from '../util/withBreakpoint'; import { hasVehicleRentalCode } from '../util/vehicleRentalUtils'; import { getIdWithoutFeed } from '../util/feedScopedIdUtils'; import FavouriteVehicleRentalStationContainer from './FavouriteVehicleRentalStationContainer'; const ParkOrBikeStationHeader = ( - { parkOrStation, breakpoint, parkType }, + { parkOrStation, breakpoint, parkType, backButton }, { config }, ) => { const [zoneId, setZoneId] = useState(undefined); @@ -48,7 +48,7 @@ const ParkOrBikeStationHeader = ( return (
- {breakpoint === 'large' && ( + {breakpoint === 'large' && backButton && ( { } }, [query]); - const color = colors.primary; - const hoverColor = colors.hover; const appElement = 'embedded-root'; let titleText; if (bikeOnly) { @@ -220,8 +218,6 @@ const EmbeddedSearch = (props, context) => { lang, sources, targets: getLocationSearchTargets(config, false), - color, - hoverColor, refPoint, searchPanelText: titleText, originPlaceHolder: 'search-origin-index', @@ -229,7 +225,7 @@ const EmbeddedSearch = (props, context) => { selectHandler: onSelectLocation, onGeolocationStart: onSelectLocation, fontWeights, - modeIconColors: config.colors.iconColors, + colors, modeSet: config.iconModeSet, isMobile: true, showScroll: true, diff --git a/app/component/embedded/EmbeddedSearchGenerator.js b/app/component/embedded/EmbeddedSearchGenerator.js index d1d42c856a..6415522739 100644 --- a/app/component/embedded/EmbeddedSearchGenerator.js +++ b/app/component/embedded/EmbeddedSearchGenerator.js @@ -78,11 +78,9 @@ const EmbeddedSearchGenerator = (props, context) => { sources, targets: getLocationSearchTargets(config, false), isMobile: breakpoint !== 'large', - color: colors.primary, - hoverColor: colors.hover, fontWeights, modeSet: config.iconModeSet, - modeIconColors: config.colors.modeIconColors, + colors, selectHandler: onSelectLocation, getAutoSuggestIcons: context.config.getAutoSuggestIcons, }; diff --git a/app/component/icon/IconBackground.js b/app/component/icon/IconBackground.js index 4486ee5207..70c91d0671 100644 --- a/app/component/icon/IconBackground.js +++ b/app/component/icon/IconBackground.js @@ -4,35 +4,41 @@ import PropTypes from 'prop-types'; const STOP_SIGN_POLE_WIDTH = 4; const STOP_SIGN_POLE_X = 20 - STOP_SIGN_POLE_WIDTH / 2; -const IconBackground = ({ backgroundShape, backgroundColor }) => ( - <> - - {backgroundShape === 'stopsign' && ( - { + if (shape === undefined) { + return null; + } + return ( + <> + - )} - -); + {shape === 'stopsign' && ( + + )} + + ); +}; IconBackground.propTypes = { - backgroundShape: PropTypes.oneOf(['circle', 'stopsign']).isRequired, - backgroundColor: PropTypes.string, + shape: PropTypes.oneOf(['circle', 'stopsign']), + color: PropTypes.string, }; IconBackground.defaultProps = { - backgroundColor: 'white', + shape: undefined, + color: 'white', }; export default IconBackground; diff --git a/app/component/itinerary/ItineraryPageControls.js b/app/component/itinerary/ItineraryPageControls.js index c67c4961df..f6a0882731 100644 --- a/app/component/itinerary/ItineraryPageControls.js +++ b/app/component/itinerary/ItineraryPageControls.js @@ -1,4 +1,3 @@ -import cx from 'classnames'; import PropTypes from 'prop-types'; import React from 'react'; import { matchShape, routerShape } from 'found'; @@ -59,7 +58,6 @@ class ItineraryPageControls extends React.Component { } render() { - const className = cx({ 'bp-large': this.props.breakpoint === 'large' }); const { params } = this.props; return (
@@ -89,11 +87,9 @@ class ItineraryPageControls extends React.Component { />
diff --git a/app/component/itinerary/OriginDestinationBar.js b/app/component/itinerary/OriginDestinationBar.js index b11a1c80fc..f38f537aaf 100644 --- a/app/component/itinerary/OriginDestinationBar.js +++ b/app/component/itinerary/OriginDestinationBar.js @@ -22,7 +22,6 @@ import { } from '../../util/queryUtils'; import { getIntermediatePlaces, locationToOTP } from '../../util/otpStrings'; import { setViaPoints } from '../../action/ViaPointActions'; -import { LightenDarkenColor } from '../../util/colorUtils'; import { getRefPoint } from '../../util/apiUtils'; const DTAutosuggestPanelWithSearchContext = @@ -30,7 +29,6 @@ const DTAutosuggestPanelWithSearchContext = class OriginDestinationBar extends React.Component { static propTypes = { - className: PropTypes.string, origin: locationShape.isRequired, destination: locationShape.isRequired, language: PropTypes.string, @@ -38,7 +36,6 @@ class OriginDestinationBar extends React.Component { showFavourites: PropTypes.bool.isRequired, viaPoints: PropTypes.arrayOf(locationShape), locationState: locationStateShape.isRequired, - modeSet: PropTypes.string, }; static contextTypes = { @@ -51,11 +48,9 @@ class OriginDestinationBar extends React.Component { }; static defaultProps = { - className: undefined, language: 'fi', isMobile: false, viaPoints: [], - modeSet: undefined, }; constructor(props) { @@ -137,11 +132,9 @@ class OriginDestinationBar extends React.Component { : undefined; return (
{}} showSwapControl showViapointControl={config.viaPointsEnabled} @@ -186,7 +175,7 @@ const connectedComponent = connectToStores( ['PreferencesStore', 'FavouriteStore', 'ViaPointStore', 'PositionStore'], ({ getStore }) => ({ language: getStore('PreferencesStore').getLanguage(), - showFavourites: getStore('FavouriteStore').getStatus() === 'has-data', + showFavourites: getStore('FavouriteStore').getLocationCount() > 0, viaPoints: getStore('ViaPointStore').getViaPoints(), locationState: getStore('PositionStore').getLocationState(), }), diff --git a/app/component/itinerary/StartNavi.js b/app/component/itinerary/StartNavi.js index c691cdffd0..676ac95c3e 100644 --- a/app/component/itinerary/StartNavi.js +++ b/app/component/itinerary/StartNavi.js @@ -7,16 +7,13 @@ import Icon from '../Icon'; const StartNavi = ({ startNavigation }, context) => { const { config, intl } = context; - const color = - config.colors?.accessiblePrimary || config.colors?.primary || 'black'; - return (
+
+ )} + {showInfo && ( +
+ +
+ )} +
+ + ); +} + +LocationModal.propTypes = { + handleClose: PropTypes.func.isRequired, + startGeolocation: PropTypes.func.isRequired, + showGeolocationButton: PropTypes.bool.isRequired, + showInfo: PropTypes.bool.isRequired, + children: PropTypes.node, +}; + +LocationModal.defaultProps = { children: null }; + +LocationModal.contextTypes = { + intl: intlShape.isRequired, +}; diff --git a/app/component/nearyou/MapWrapper.js b/app/component/nearyou/MapWrapper.js new file mode 100644 index 0000000000..5387bde0b8 --- /dev/null +++ b/app/component/nearyou/MapWrapper.js @@ -0,0 +1,179 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import { graphql, QueryRenderer } from 'react-relay'; +import { matchShape } from 'found'; +import { + relayShape, + configShape, + mapLayerOptionsShape, +} from '../../util/shapes'; +import NearYouMapContainer from './NearYouMapContainer'; +import NearYouFavouritesMapContainer from './NearYouFavouritesMapContainer'; +import { mapLayerShape } from '../../store/MapLayerStore'; + +const TransitStopModes = ['BUS', 'FERRY', 'RAIL', 'SUBWAY', 'TRAM']; + +export default function MapWrapper( + { + match, + relayEnvironment, + favouriteStopIds, + favouriteStationIds, + favouriteVehicleStationIds, + setCenterOfMap, + mapLayers, + mapLayerOptions, + variables, + ...rest + }, + { config }, +) { + const commonProps = { + match, + onEndNavigation: setCenterOfMap, + onMapTracking: setCenterOfMap, + }; + const { mode } = match.params; + + if (mode === 'FAVORITE') { + return ( + { + const mapProps = props || { + stops: null, + stations: null, + vehicleStations: null, + }; + return ( + + ); + }} + /> + ); + } + + const filteredMapLayers = { + ...mapLayers, + parkAndRide: mode === 'CARPARK', + parkAndRideForBikes: mode === 'BIKEPARK', + citybike: mode === 'CITYBIKE', + citybikeOverrideMinZoom: mode === 'CITYBIKE', + }; + if (!config.map.showLayerSelector) { + filteredMapLayers.stop = {}; + if (TransitStopModes.includes(mode)) { + filteredMapLayers.stop[mode.toLowerCase()] = true; + } + } + let favouriteIds; + switch (mode) { + case 'CITYBIKE': + favouriteIds = new Set(favouriteVehicleStationIds); + break; + case 'BIKEPARK': + case 'CARPARK': + favouriteIds = new Set(); + break; + default: + favouriteIds = new Set([...favouriteStopIds, ...favouriteStationIds]); + break; + } + + return ( + { + const mapProps = props || { stops: null, prioritizedStops: null }; + return ( + + ); + }} + /> + ); +} + +MapWrapper.propTypes = { + relayEnvironment: relayShape.isRequired, + match: matchShape.isRequired, + favouriteStopIds: PropTypes.arrayOf(PropTypes.string).isRequired, + favouriteStationIds: PropTypes.arrayOf(PropTypes.string).isRequired, + favouriteVehicleStationIds: PropTypes.arrayOf(PropTypes.string).isRequired, + setCenterOfMap: PropTypes.func.isRequired, + mapLayers: mapLayerShape.isRequired, + mapLayerOptions: mapLayerOptionsShape.isRequired, + // eslint-disable-next-line + variables: PropTypes.object.isRequired, +}; + +MapWrapper.contextTypes = { config: configShape.isRequired }; diff --git a/app/component/nearyou/NearYouContainer.js b/app/component/nearyou/NearYouContainer.js new file mode 100644 index 0000000000..242630ae91 --- /dev/null +++ b/app/component/nearyou/NearYouContainer.js @@ -0,0 +1,402 @@ +import PropTypes from 'prop-types'; +import React, { useEffect, useState, useRef } from 'react'; +import { createPaginationContainer, graphql } from 'react-relay'; +import { intlShape, FormattedMessage } from 'react-intl'; +import { configShape, relayShape } from '../../util/shapes'; +import StopNearYouContainer from './StopNearYouContainer'; +import withBreakpoint from '../../util/withBreakpoint'; +import { + sortNearYouRentalStations, + sortNearYouStops, +} from '../../util/sortUtils'; +import VehicleRentalStationNearYou from './VehicleRentalStationNearYou'; +import ParkNearYou from './ParkNearYou'; +import Loading from '../Loading'; +import Icon from '../Icon'; +import { getDefaultNetworks } from '../../util/vehicleRentalUtils'; +import DisruptionBanner from '../DisruptionBanner'; + +function NearYouContainer( + { + places, + loadingDone, + currentTime, + relay, + position, + withSeparator, + prioritizedStops, + mode, + isParentTabActive, + favouriteIds, + }, + { config, intl }, +) { + const ariaRef = useRef('stop-near-you'); + const searchPos = useRef(position); // position used for fetching nearest places + const refetches = useRef(0); + const stopCount = useRef(5); + const [loading, setLoading] = useState(0); + + const updatePosition = () => { + const variables = { + ...position, + startTime: currentTime, + }; + setLoading(1); + relay.refetchConnection( + stopCount.current, + () => { + setLoading(0); + searchPos.current = position; + }, + variables, + ); + }; + + const showMore = automatic => { + if (!relay.hasMore() || loading) { + return; + } + setLoading(2); + if (!automatic) { + ariaRef.current = 'loading'; + } + relay.loadMore(5, () => { + if (automatic) { + refetches.current += 1; + } + stopCount.current += 5; + ariaRef.current = 'stop-near-you-update-alert'; + setLoading(0); + }); + }; + + useEffect(() => { + const { edges } = places.nearest; + const fetchMore = + edges.filter( + stop => !(stop.node.place.stoptimesWithoutPatterns?.length === 0), + ).length < 5 && refetches.current < config.maxNearYouRefetches; + if (fetchMore) { + showMore(true); + } + }, [places]); + + useEffect(() => { + if ( + position.lat !== searchPos.current.lat || + position.lon !== searchPos.current.lon + ) { + updatePosition(); + } + }, [position.lat, position.lon]); + + useEffect(() => { + loadingDone(); + }, []); + + const createNearYouPlaces = () => { + if (!places?.nearest) { + return []; + } + const walkRoutingThreshold = + mode === 'RAIL' || mode === 'SUBWAY' || mode === 'FERRY' ? 3000 : 1500; + const { edges } = places.nearest; + let sorted; + if (mode === 'CITYBIKE') { + const withNetworks = edges.filter(edge => { + return !!edge.node.place.rentalNetwork?.networkId; + }); + const filteredCityBikeStopEdges = withNetworks.filter(edge => { + return getDefaultNetworks(config).includes( + edge.node.place.rentalNetwork?.networkId, + ); + }); + sorted = filteredCityBikeStopEdges + .slice(0, 5) + .sort(sortNearYouRentalStations(favouriteIds)); + sorted.push(...filteredCityBikeStopEdges.slice(5)); + } else if (mode === 'BIKEPARK' || mode === 'CARPARK') { + sorted = edges; + } else { + sorted = edges + .slice(0, 5) + .sort(sortNearYouStops(favouriteIds, walkRoutingThreshold)); + sorted.push(...edges.slice(5)); + } + + const stops = sorted.map(({ node }) => { + const { place } = node; + /* eslint-disable-next-line no-underscore-dangle */ + switch (place.__typename) { + case 'Stop': + if (place.stoptimesWithoutPatterns.length > 0) { + if (!prioritizedStops.includes(place.gtfsId)) { + return ( + + ); + } + } + break; + case 'VehicleRentalStation': + return ( + + ); + case 'VehicleParking': + return ( + + ); + default: + return null; + } + return null; + }); + return stops; + }; + + const items = createNearYouPlaces(); + const alerts = items + .flatMap(stop => stop?.props?.stop?.routes || []) + .flatMap(route => route?.alerts || []) + .filter(alert => alert.alertSeverityLevel === 'SEVERE'); + const noStopsFound = + !items.length && refetches >= config.maxNearYouRefetches && !loading; + return ( + <> + {alerts?.length ? : null} + {((!relay.hasMore() && !items.length && !prioritizedStops.length) || + (noStopsFound && !prioritizedStops.length)) && ( + <> + {withSeparator &&
} +
+ + +
+ + )} +
+ +
+ {loading === 1 && ( +
+ +
+ )} +
+ {items} +
+ {loading === 2 && ( +
+ +
+ )} + {relay.hasMore() && !noStopsFound && ( + + )} + + ); +} + +NearYouContainer.propTypes = { + // eslint-disable-next-line + places: PropTypes.object, + loadingDone: PropTypes.func.isRequired, + currentTime: PropTypes.number.isRequired, + relay: relayShape.isRequired, + position: PropTypes.shape({ + lat: PropTypes.number, + lon: PropTypes.number, + }).isRequired, + withSeparator: PropTypes.bool, + prioritizedStops: PropTypes.arrayOf(PropTypes.string).isRequired, + mode: PropTypes.string.isRequired, + isParentTabActive: PropTypes.bool, + // eslint-disable-next-line + favouriteIds: PropTypes.object, +}; + +NearYouContainer.defaultProps = { + places: undefined, + withSeparator: false, + isParentTabActive: false, +}; + +NearYouContainer.contextTypes = { + config: configShape, + intl: intlShape.isRequired, + executeAction: PropTypes.func.isRequired, + getStore: PropTypes.func, +}; + +const NearYouContainerWithBreakpoint = withBreakpoint(NearYouContainer); + +const refetchContainer = createPaginationContainer( + NearYouContainerWithBreakpoint, + { + places: graphql` + fragment NearYouContainer_places on QueryType + @argumentDefinitions( + startTime: { type: "Long!", defaultValue: 0 } + omitNonPickups: { type: "Boolean!", defaultValue: false } + lat: { type: "Float!" } + lon: { type: "Float!", defaultValue: 0 } + filterByPlaceTypes: { type: "[FilterPlaceType]", defaultValue: null } + filterByModes: { type: "[Mode]", defaultValue: null } + first: { type: "Int!", defaultValue: 5 } + after: { type: "String" } + maxResults: { type: "Int" } + maxDistance: { type: "Int" } + filterByNetwork: { type: "[String!]", defaultValue: null } + ) { + nearest( + lat: $lat + lon: $lon + filterByPlaceTypes: $filterByPlaceTypes + filterByModes: $filterByModes + first: $first + after: $after + maxResults: $maxResults + maxDistance: $maxDistance + filterByNetwork: $filterByNetwork + ) @connection(key: "NearYouContainer_nearest") { + edges { + node { + distance + place { + __typename + ... on VehicleRentalStation { + ...VehicleRentalStationNearYou_station + stationId + rentalNetwork { + networkId + } + } + ... on VehicleParking { + ...ParkNearYou_park + vehicleParkingId + } + ... on Stop { + ...StopNearYouContainer_stop + @arguments( + startTime: $startTime + omitNonPickups: $omitNonPickups + ) + id + name + gtfsId + stoptimesWithoutPatterns( + startTime: $startTime + omitNonPickups: $omitNonPickups + ) { + scheduledArrival + } + routes { + ... on Route { + alerts { + feed + id + alertSeverityLevel + alertHeaderText + alertEffect + alertCause + alertDescriptionText + effectiveStartDate + effectiveEndDate + entities { + __typename + ... on Route { + mode + shortName + } + } + } + } + } + } + } + } + } + } + } + `, + }, + { + direction: 'forward', + getConnectionFromProps(props) { + return props.places?.nearest; + }, + getFragmentVariables(prevVars, totalCount) { + return { + ...prevVars, + first: totalCount, + }; + }, + getVariables(props, pagevars, fragmentVariables) { + return { + ...fragmentVariables, + first: pagevars.count, + after: pagevars.cursor, + }; + }, + query: graphql` + query NearYouContainerRefetchQuery( + $lat: Float! + $lon: Float! + $filterByPlaceTypes: [FilterPlaceType] + $filterByModes: [Mode] + $first: Int! + $after: String + $maxResults: Int! + $maxDistance: Int! + $startTime: Long! + $omitNonPickups: Boolean! + $filterByNetwork: [String!] + ) { + viewer { + ...NearYouContainer_places + @arguments( + startTime: $startTime + omitNonPickups: $omitNonPickups + lat: $lat + lon: $lon + filterByPlaceTypes: $filterByPlaceTypes + filterByModes: $filterByModes + first: $first + after: $after + maxResults: $maxResults + maxDistance: $maxDistance + filterByNetwork: $filterByNetwork + ) + } + } + `, + }, +); + +export { refetchContainer as default, NearYouContainer as Component }; diff --git a/app/component/nearyou/NearYouFavourites.js b/app/component/nearyou/NearYouFavourites.js new file mode 100644 index 0000000000..157d93aa84 --- /dev/null +++ b/app/component/nearyou/NearYouFavourites.js @@ -0,0 +1,112 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import { graphql, QueryRenderer, ReactRelayContext } from 'react-relay'; +import { FormattedMessage } from 'react-intl'; +import { locationShape, relayShape } from '../../util/shapes'; +import NearYouFavouritesContainer from './NearYouFavouritesContainer'; +import withBreakpoint from '../../util/withBreakpoint'; +import Loading from '../Loading'; + +function NearYouFavourites({ + stopIds, + stationIds, + vehicleRentalStationIds, + relayEnvironment, + searchPosition, + breakpoint, + noFavourites, + isParentTabActive, + currentTime, +}) { + if (noFavourites) { + return ( +
+ {breakpoint !== 'large' && ( +
+ +
+ )} +
+ +
+ Käyttöohje + +
+ ); + } + return ( + { + if (props) { + return ( + + ); + } + return ; + }} + /> + ); +} +NearYouFavourites.propTypes = { + stopIds: PropTypes.arrayOf(PropTypes.string).isRequired, + stationIds: PropTypes.arrayOf(PropTypes.string).isRequired, + vehicleRentalStationIds: PropTypes.arrayOf(PropTypes.string).isRequired, + relayEnvironment: relayShape.isRequired, + searchPosition: locationShape.isRequired, + breakpoint: PropTypes.string, + noFavourites: PropTypes.bool, + isParentTabActive: PropTypes.bool, + currentTime: PropTypes.number.isRequired, +}; + +NearYouFavourites.defaultProps = { + breakpoint: undefined, + noFavourites: false, + isParentTabActive: false, +}; + +const NearYouFavouritesWithBreakpoint = withBreakpoint(props => ( + + {({ environment }) => ( + + )} + +)); + +export default NearYouFavouritesWithBreakpoint; diff --git a/app/component/nearyou/StopsNearYouFavouritesContainer.js b/app/component/nearyou/NearYouFavouritesContainer.js similarity index 56% rename from app/component/nearyou/StopsNearYouFavouritesContainer.js rename to app/component/nearyou/NearYouFavouritesContainer.js index 23bd3ee191..84ddbef473 100644 --- a/app/component/nearyou/StopsNearYouFavouritesContainer.js +++ b/app/component/nearyou/NearYouFavouritesContainer.js @@ -9,14 +9,15 @@ import { locationShape, } from '../../util/shapes'; import StopNearYouContainer from './StopNearYouContainer'; -import CityBikeStopNearYou from './VehicleRentalStationNearYou'; +import VehicleRentalStationNearYou from './VehicleRentalStationNearYou'; -function StopsNearYouFavouritesContainer({ +function NearYouFavouritesContainer({ stops, stations, vehicleStations, searchPosition, isParentTabActive, + currentTime, }) { const stopList = []; stopList.push( @@ -61,12 +62,19 @@ function StopsNearYouFavouritesContainer({ ); case 'vehicleRentalStation': - return ; + return ( + + ); default: return null; } @@ -74,63 +82,57 @@ function StopsNearYouFavouritesContainer({ return stopElements; } -StopsNearYouFavouritesContainer.propTypes = { +NearYouFavouritesContainer.propTypes = { stops: PropTypes.arrayOf(stopShape), stations: PropTypes.arrayOf(stationShape), vehicleStations: PropTypes.arrayOf(vehicleRentalStationShape), searchPosition: locationShape, isParentTabActive: PropTypes.bool, + currentTime: PropTypes.number.isRequired, }; -const refetchContainer = createFragmentContainer( - StopsNearYouFavouritesContainer, - { - stops: graphql` - fragment StopsNearYouFavouritesContainer_stops on Stop - @relay(plural: true) { - ...StopNearYouContainer_stop +const refetchContainer = createFragmentContainer(NearYouFavouritesContainer, { + stops: graphql` + fragment NearYouFavouritesContainer_stops on Stop @relay(plural: true) { + ...StopNearYouContainer_stop + gtfsId + lat + lon + } + `, + stations: graphql` + fragment NearYouFavouritesContainer_stations on Stop @relay(plural: true) { + ...StopNearYouContainer_stop + gtfsId + lat + lon + stops { gtfsId - lat - lon + desc } - `, - stations: graphql` - fragment StopsNearYouFavouritesContainer_stations on Stop - @relay(plural: true) { - ...StopNearYouContainer_stop - gtfsId - lat - lon - stops { - gtfsId - desc - } + } + `, + vehicleStations: graphql` + fragment NearYouFavouritesContainer_vehicleStations on VehicleRentalStation + @relay(plural: true) { + ...VehicleRentalStationNearYou_station + stationId + name + availableVehicles { + total + } + availableSpaces { + total } - `, - vehicleStations: graphql` - fragment StopsNearYouFavouritesContainer_vehicleStations on VehicleRentalStation - @relay(plural: true) { - stationId - name - availableVehicles { - total - } - availableSpaces { - total - } - capacity - rentalNetwork { - networkId - } - lat - lon - operative + capacity + rentalNetwork { + networkId } - `, - }, -); + lat + lon + operative + } + `, +}); -export { - refetchContainer as default, - StopsNearYouFavouritesContainer as Component, -}; +export { refetchContainer as default, NearYouFavouritesContainer as Component }; diff --git a/app/component/nearyou/NearYouFavouritesMapContainer.js b/app/component/nearyou/NearYouFavouritesMapContainer.js new file mode 100644 index 0000000000..4cad933774 --- /dev/null +++ b/app/component/nearyou/NearYouFavouritesMapContainer.js @@ -0,0 +1,108 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import { graphql, createFragmentContainer } from 'react-relay'; +import distance from '@digitransit-search-util/digitransit-search-util-distance'; +import NearYouMap from '../map/NearYouMap'; +import { + vehicleRentalStationShape, + stopShape, + stationShape, + locationShape, +} from '../../util/shapes'; + +function NearYouFavouritesMapContainer(props) { + const { stops, stations, vehicleStations, position } = props; + const favs = [ + ...(stops || []), + ...(stations || []), + ...(vehicleStations || []), + ]; + const edges = favs + .filter(s => s) + .map(stop => { + return { + node: { + distance: distance(position, stop), + place: { ...stop }, + }, + }; + }) + .sort((a, b) => a.node.distance - b.node.distance); + + return ; +} + +NearYouFavouritesMapContainer.propTypes = { + stops: PropTypes.arrayOf(stopShape), + stations: PropTypes.arrayOf(stationShape), + vehicleStations: PropTypes.arrayOf(vehicleRentalStationShape), + position: locationShape.isRequired, +}; + +NearYouFavouritesMapContainer.defaultProps = { + stops: [], + stations: [], + vehicleStations: [], +}; + +const containerComponent = createFragmentContainer( + NearYouFavouritesMapContainer, + { + stops: graphql` + fragment NearYouFavouritesMapContainer_stops on Stop + @relay(plural: true) { + gtfsId + lat + lon + patterns { + route { + gtfsId + shortName + mode + type + } + code + patternGeometry { + points + } + } + } + `, + stations: graphql` + fragment NearYouFavouritesMapContainer_stations on Stop + @relay(plural: true) { + gtfsId + lat + lon + stops { + patterns { + route { + gtfsId + shortName + mode + type + } + code + patternGeometry { + points + } + } + } + } + `, + vehicleStations: graphql` + fragment NearYouFavouritesMapContainer_vehicleStations on VehicleRentalStation + @relay(plural: true) { + name + lat + lon + stationId + } + `, + }, +); + +export { + containerComponent as default, + NearYouFavouritesMapContainer as Component, +}; diff --git a/app/component/nearyou/StopNearYouHeader.js b/app/component/nearyou/NearYouHeader.js similarity index 88% rename from app/component/nearyou/StopNearYouHeader.js rename to app/component/nearyou/NearYouHeader.js index 54b8d2ca29..f27eeca622 100644 --- a/app/component/nearyou/StopNearYouHeader.js +++ b/app/component/nearyou/NearYouHeader.js @@ -8,10 +8,7 @@ import PlatformNumber from '../PlatformNumber'; import FavouriteStopContainer from '../FavouriteStopContainer'; import { getZoneLabel } from '../../util/legUtils'; -const StopNearYouHeader = ( - { stop, desc, isStation, linkAddress }, - { config }, -) => { +const NearYouHeader = ({ stop, desc, isStation, linkAddress }, { config }) => { const zoneId = isStation && stop.stops.length ? stop.stops[0].zoneId : stop.zoneId; return ( @@ -52,20 +49,20 @@ const StopNearYouHeader = ( ); }; -StopNearYouHeader.propTypes = { +NearYouHeader.propTypes = { stop: stopShape.isRequired, linkAddress: PropTypes.string.isRequired, desc: PropTypes.string, isStation: PropTypes.bool, }; -StopNearYouHeader.defaultProps = { +NearYouHeader.defaultProps = { isStation: false, desc: undefined, }; -StopNearYouHeader.contextTypes = { +NearYouHeader.contextTypes = { config: configShape.isRequired, }; -export default StopNearYouHeader; +export default NearYouHeader; diff --git a/app/component/nearyou/StopsNearYouMapContainer.js b/app/component/nearyou/NearYouMapContainer.js similarity index 64% rename from app/component/nearyou/StopsNearYouMapContainer.js rename to app/component/nearyou/NearYouMapContainer.js index c0f38314c7..d4a378b313 100644 --- a/app/component/nearyou/StopsNearYouMapContainer.js +++ b/app/component/nearyou/NearYouMapContainer.js @@ -1,42 +1,12 @@ -import connectToStores from 'fluxible-addons-react/connectToStores'; import { graphql, createPaginationContainer } from 'react-relay'; import NearYouMap from '../map/NearYouMap'; -import FavouriteStore from '../../store/FavouriteStore'; -import PreferencesStore from '../../store/PreferencesStore'; - -const StopsNearYouMapWithStores = connectToStores( - NearYouMap, - [PreferencesStore, FavouriteStore], - ({ getStore }, { match }) => { - const language = getStore(PreferencesStore).getLanguage(); - const favouriteIds = - match.params.mode === 'CITYBIKE' - ? new Set( - getStore('FavouriteStore') - .getVehicleRentalStations() - .map(station => station.stationId), - ) - : new Set( - getStore('FavouriteStore') - .getStopsAndStations() - .map(stop => stop.gtfsId), - ); - return { - language, - favouriteIds, - }; - }, -); - const containerComponent = createPaginationContainer( - StopsNearYouMapWithStores, + NearYouMap, { - stopsNearYou: graphql` - fragment StopsNearYouMapContainer_stopsNearYou on QueryType + stops: graphql` + fragment NearYouMapContainer_stops on QueryType @argumentDefinitions( - startTime: { type: "Long!", defaultValue: 0 } - omitNonPickups: { type: "Boolean!", defaultValue: false } lat: { type: "Float!" } lon: { type: "Float!", defaultValue: 0 } filterByPlaceTypes: { type: "[FilterPlaceType]", defaultValue: null } @@ -57,26 +27,26 @@ const containerComponent = createPaginationContainer( maxResults: $maxResults maxDistance: $maxDistance filterByNetwork: $filterByNetwork - ) @connection(key: "StopsNearYouMapContainer_nearest") { + ) @connection(key: "NearYouMapContainer_nearest") { edges { node { distance place { __typename ... on VehicleRentalStation { - name lat lon stationId - rentalNetwork { - networkId - } + } + ... on VehicleParking { + lat + lon + vehicleParkingId } ... on Stop { gtfsId lat lon - name patterns { route { gtfsId @@ -85,7 +55,6 @@ const containerComponent = createPaginationContainer( type } code - directionId patternGeometry { points } @@ -99,18 +68,11 @@ const containerComponent = createPaginationContainer( type } code - directionId patternGeometry { points } } } - stoptimesWithoutPatterns( - startTime: $startTime - omitNonPickups: $omitNonPickups - ) { - scheduledArrival - } } } } @@ -118,13 +80,12 @@ const containerComponent = createPaginationContainer( } } `, - prioritizedStopsNearYou: graphql` - fragment StopsNearYouMapContainer_prioritizedStopsNearYou on Stop + prioritizedStops: graphql` + fragment NearYouMapContainer_prioritizedStops on Stop @relay(plural: true) { gtfsId lat lon - name stops { patterns { route { @@ -134,7 +95,6 @@ const containerComponent = createPaginationContainer( type } code - directionId patternGeometry { points } @@ -145,23 +105,20 @@ const containerComponent = createPaginationContainer( gtfsId shortName mode + type } code - directionId patternGeometry { points } } - stoptimesWithoutPatterns { - scheduledArrival - } } `, }, { direction: 'forward', getConnectionFromProps(props) { - return props.stopsNearYou && props.stopsNearYou.nearest; + return props.stops?.nearest; }, getFragmentVariables(prevVars, totalCount) { return { @@ -177,7 +134,7 @@ const containerComponent = createPaginationContainer( }; }, query: graphql` - query StopsNearYouMapContainerRefetchQuery( + query NearYouMapContainerRefetchQuery( $lat: Float! $lon: Float! $filterByPlaceTypes: [FilterPlaceType] @@ -186,15 +143,11 @@ const containerComponent = createPaginationContainer( $after: String $maxResults: Int! $maxDistance: Int! - $startTime: Long! - $omitNonPickups: Boolean! $filterByNetwork: [String!] ) { viewer { - ...StopsNearYouMapContainer_stopsNearYou + ...NearYouMapContainer_stops @arguments( - startTime: $startTime - omitNonPickups: $omitNonPickups lat: $lat lon: $lon filterByPlaceTypes: $filterByPlaceTypes diff --git a/app/component/nearyou/NearYouPage.js b/app/component/nearyou/NearYouPage.js index 371c58693b..1a2be9dba8 100644 --- a/app/component/nearyou/NearYouPage.js +++ b/app/component/nearyou/NearYouPage.js @@ -1,49 +1,35 @@ /* eslint-disable react/no-unstable-nested-components */ import PropTypes from 'prop-types'; -import React from 'react'; +import React, { useEffect, useState, useRef } from 'react'; import { FormattedMessage, intlShape } from 'react-intl'; import { graphql, ReactRelayContext, QueryRenderer } from 'react-relay'; import { matchShape, routerShape } from 'found'; import connectToStores from 'fluxible-addons-react/connectToStores'; -import Modal from '@hsl-fi/modal'; -import DTAutoSuggest from '@digitransit-component/digitransit-component-autosuggest'; -import DTIcon from '@digitransit-component/digitransit-component-icon'; import distance from '@digitransit-search-util/digitransit-search-util-distance'; import { relayShape, configShape, locationShape } from '../../util/shapes'; -import Icon from '../Icon'; import DesktopView from '../DesktopView'; import MobileView from '../MobileView'; import withBreakpoint, { DesktopOrMobile } from '../../util/withBreakpoint'; import { otpToLocation, locationToUri } from '../../util/otpStrings'; -import { isKeyboardSelectionEvent } from '../../util/browser'; import Loading from '../Loading'; import StopNearYouContainer from './StopNearYouContainer'; +import UpdateLocationButton from './UpdateLocationButton'; +import MapWrapper from './MapWrapper'; +import LocationModal from './LocationModal'; +import CityBikeInfo from './CityBikeInfo'; import { checkPositioningPermission, startLocationWatch, } from '../../action/PositionActions'; -import StopsNearYouSearch from './StopsNearYouSearch'; -import { - getGeolocationState, - getReadMessageIds, - setReadMessageIds, -} from '../../store/localStorage'; -import { - withSearchContext, - getLocationSearchTargets, -} from '../WithSearchContext'; +import Search from './Search'; +import StopRouteSearch from './StopRouteSearch'; +import { getGeolocationState } from '../../store/localStorage'; import { PREFIX_NEARYOU } from '../../util/path'; -import StopsNearYouContainer from './StopsNearYouContainer'; +import NearYouContainer from './NearYouContainer'; import SwipeableTabs from '../SwipeableTabs'; -import StopsNearYouFavorites from './StopsNearYouFavorites'; -import StopsNearYouMapContainer from './StopsNearYouMapContainer'; -import StopsNearYouFavoritesMapContainer from './StopsNearYouFavoritesMapContainer'; +import NearYouFavourites from './NearYouFavourites'; import { mapLayerShape } from '../../store/MapLayerStore'; -import { - getRentalNetworkConfig, - getRentalNetworkId, - getDefaultNetworks, -} from '../../util/vehicleRentalUtils'; +import { getDefaultNetworks } from '../../util/vehicleRentalUtils'; import { getMapLayerOptions } from '../../util/mapLayerUtils'; import { getTransportModes, @@ -64,8 +50,6 @@ const PH_USEMAPCENTER = 'usemapcenter'; const PH_SHOWSEARCH = [PH_SEARCH, PH_SEARCH_GEOLOCATION]; // show modal const PH_READY = [PH_USEDEFAULTPOS, PH_USEGEOLOCATION, PH_USEMAPCENTER]; // render the actual page -const DTAutoSuggestWithSearchContext = withSearchContext(DTAutoSuggest); - function getModes(config) { const transportModes = getTransportModes(config); const nearYouModes = getNearYouModes(config); @@ -77,83 +61,65 @@ function getModes(config) { return modes.map(nearYouMode => nearYouMode.toUpperCase()); } -class NearYouPage extends React.Component { - static contextTypes = { - config: configShape.isRequired, - executeAction: PropTypes.func.isRequired, - getStore: PropTypes.func, - intl: intlShape.isRequired, - router: routerShape.isRequired, - }; - - static propTypes = { - breakpoint: PropTypes.string.isRequired, - relayEnvironment: relayShape.isRequired, - position: locationShape.isRequired, - lang: PropTypes.string.isRequired, - match: matchShape.isRequired, - favouriteStopIds: PropTypes.arrayOf(PropTypes.string), - favouriteStationIds: PropTypes.arrayOf(PropTypes.string), - favouriteVehicleStationIds: PropTypes.arrayOf(PropTypes.string), - mapLayers: mapLayerShape.isRequired, - favouritesFetched: PropTypes.bool, - }; - - static defaultProps = { - favouriteStopIds: [], - favouriteStationIds: [], - favouriteVehicleStationIds: [], - favouritesFetched: false, - }; - - constructor(props) { - super(props); - this.state = { - phase: PH_START, - centerOfMapChanged: false, - showCityBikeTeaser: true, - searchPosition: {}, - mapLayerOptions: null, - // eslint-disable-next-line react/no-unused-state - resultsLoaded: false, - }; - } - - componentDidMount() { - this.modes = getModes(this.context.config); - const readMessageIds = getReadMessageIds(); - const showCityBikeTeaser = !readMessageIds.includes('citybike_teaser'); - if (this.context.config.map.showLayerSelector) { - const { mode } = this.props.match.params; - const mapLayerOptions = getMapLayerOptions({ +function NearYouPage( + { + breakpoint, + relayEnvironment, + position, + lang, + match, + favouriteStopIds, + favouriteStationIds, + favouriteVehicleStationIds, + mapLayers, + favouritesFetched, + currentTime, + }, + { config, executeAction, router }, +) { + const MWTRef = useRef(); + const modes = useRef(getModes(config)); + const centerOfMap = useRef({}); + const [phase, setPhase] = useState(PH_START); + const [centerOfMapChanged, setCenterOfMapChanged] = useState(false); + const [searchPosition, setSearchPosition] = useState({}); + const [mapLayerOptions, setMapLayerOptions] = useState({}); + // eslint-disable-next-line + const [resultsLoaded, setResultsLoaded] = useState(false); + + const { mode } = match.params; + const allModes = modes.current; + + const updateMapLayerOptions = () => { + if (config.map.showLayerSelector) { + const options = getMapLayerOptions({ lockedMapLayers: ['vehicles', 'citybike', 'stop'], selectedMapLayers: ['vehicles', mode.toLowerCase()], }); - this.setState({ showCityBikeTeaser, mapLayerOptions }); - } else { - this.setState({ showCityBikeTeaser }); + setMapLayerOptions(options); } + }; + + useEffect(() => { + updateMapLayerOptions(); checkPositioningPermission().then(permission => { - const { origin: matchParamsOrigin, place } = this.props.match.params; + const { origin: matchParamsOrigin, place } = match.params; const savedPermission = getGeolocationState(); const { state } = permission; - const newState = {}; - - if (matchParamsOrigin) { - newState.searchPosition = otpToLocation(matchParamsOrigin); - } else { - newState.searchPosition = this.context.config.defaultEndpoint; - } + let newSearchPosition = matchParamsOrigin + ? otpToLocation(matchParamsOrigin) + : config.defaultEndpoint; + let newPhase; if (savedPermission === 'unknown') { if (!matchParamsOrigin) { // state = 'error' means no permission api, so we assume geolocation will work if (state === 'prompt' || state === 'granted' || state === 'error') { - newState.phase = PH_SEARCH_GEOLOCATION; + newPhase = PH_SEARCH_GEOLOCATION; } else { - newState.phase = PH_SEARCH; + newPhase = PH_SEARCH; } } else { - newState.phase = PH_USEDEFAULTPOS; + newPhase = PH_USEDEFAULTPOS; } } else if ( state === 'prompt' || @@ -161,103 +127,101 @@ class NearYouPage extends React.Component { (state === 'error' && savedPermission !== 'denied') ) { // reason to expect that geolocation will work - newState.phase = PH_GEOLOCATIONING; - this.context.executeAction(startLocationWatch); + newPhase = PH_GEOLOCATIONING; + executeAction(startLocationWatch); } else if (matchParamsOrigin) { - newState.phase = PH_USEDEFAULTPOS; + newPhase = PH_USEDEFAULTPOS; } else if (state === 'error') { // No permission api. // Suggest geolocation, user may have changed permissions from browser settings - newState.phase = PH_SEARCH_GEOLOCATION; + newPhase = PH_SEARCH_GEOLOCATION; } else { // Geolocationing is known to be denied. Provide search modal - newState.phase = PH_SEARCH; + newPhase = PH_SEARCH; } if (place !== 'POS') { - newState.searchPosition = otpToLocation(place); - newState.phase = PH_USEDEFAULTPOS; + newSearchPosition = otpToLocation(place); + newPhase = PH_USEDEFAULTPOS; } - this.setState(newState); + setSearchPosition(newSearchPosition); + setPhase(newPhase); }); - } - - componentDidUpdate(prevProps) { - if (this.context.config.map.showLayerSelector) { - const { mode } = this.props.match.params; - const { mode: prevMode } = prevProps.match.params; - if (mode !== prevMode) { - this.setMapLayerOptions(); + }, []); + + useEffect(() => { + updateMapLayerOptions(); + }, [mode]); + + useEffect(() => { + if (phase === PH_GEOLOCATIONING) { + if (position.locationingFailed) { + setPhase(PH_USEDEFAULTPOS); + } else if (position.hasLocation) { + setPhase(PH_USEGEOLOCATION); + setSearchPosition(position); } } - } + }, [phase, position.locationingFailed, position.hasLocation]); - static getDerivedStateFromProps(nextProps, prevState) { - let newState = null; - if (prevState.phase === PH_GEOLOCATIONING) { - if (nextProps.position.locationingFailed) { - newState = { phase: PH_USEDEFAULTPOS }; - } else if (nextProps.position.hasLocation) { - newState = { - phase: PH_USEGEOLOCATION, - searchPosition: nextProps.position, - }; - } - return newState; - } - return newState; - } - - setLoadState = () => { + const loadingDone = () => { // trigger a state update in this component to force a rerender when stop data is received for the first time. // this fixes a bug where swipeable tabs were not keeping focusable elements up to date after receving stop data // and keyboard focus could be lost to hidden elements. // eslint-disable-next-line react/no-unused-state - this.setState({ resultsLoaded: true }); - }; - - setMapLayerOptions = () => { - const { mode } = this.props.match.params; - const mapLayerOptions = getMapLayerOptions({ - lockedMapLayers: ['vehicles', 'citybike', 'stop'], - selectedMapLayers: ['vehicles', mode.toLowerCase()], - }); - this.setState({ mapLayerOptions }); + setResultsLoaded(true); }; - getQueryVariables = mode => { - const { searchPosition } = this.state; - let placeTypes = ['STOP', 'STATION']; - let modes = [mode]; + const getQueryVariables = queryMode => { + if (queryMode === 'FAVORITE') { + return { + stopIds: favouriteStopIds, + stationIds: favouriteStationIds, + vehicleRentalStationIds: favouriteVehicleStationIds, + }; + } + let placeTypes = []; + let qModes = []; let allowedNetworks = []; - if (mode === 'CITYBIKE') { - placeTypes = 'VEHICLE_RENT'; - modes = ['BICYCLE']; - allowedNetworks = getDefaultNetworks(this.context.config); + switch (queryMode) { + case 'CITYBIKE': + placeTypes = 'VEHICLE_RENT'; + qModes = ['BICYCLE']; + allowedNetworks = getDefaultNetworks(config); + break; + case 'BIKEPARK': + placeTypes = 'BIKE_PARK'; + break; + case 'CARPARK': + placeTypes = 'CAR_PARK'; + break; + default: + placeTypes = ['STOP', 'STATION']; + qModes = [queryMode]; + break; } const prioritizedStops = - this.context.config.prioritizedStopsNearYou[mode.toLowerCase()] || []; + config.prioritizedStopsNearYou[queryMode.toLowerCase()] || []; return { lat: searchPosition.lat, lon: searchPosition.lon, maxResults: 10, - first: this.context.config.maxNearbyStopAmount, - maxDistance: - this.context.config.maxNearbyStopDistance[mode.toLowerCase()], - filterByModes: modes, + first: config.maxNearYouCount, + maxDistance: config.maxNearYouDistance[queryMode.toLowerCase()], + filterByModes: qModes, filterByPlaceTypes: placeTypes, - omitNonPickups: this.context.config.omitNonPickups, + omitNonPickups: config.omitNonPickups, prioritizedStopIds: prioritizedStops, filterByNetwork: allowedNetworks, }; }; - setCenterOfMap = mapElement => { + const setCenterOfMap = mapElement => { let location; if (!mapElement) { - location = this.props.position; - } else if (this.props.breakpoint === 'large') { - const centerOfMap = mapElement.leafletElement.getCenter(); - location = { lat: centerOfMap.lat, lon: centerOfMap.lng }; + location = position; + } else if (breakpoint === 'large') { + const center = mapElement.leafletElement.getCenter(); + location = { lat: center.lat, lon: center.lng }; } else { // find center pixel coordinates of the visible part of the map // and convert to lat, lon @@ -273,150 +237,95 @@ class NearYouPage extends React.Component { const point = mapElement.leafletElement.containerPointToLatLng([x, y]); location = { lat: point.lat, lon: point.lng }; } - this.centerOfMap = location; - const changed = distance(location, this.state.searchPosition) > 200; - if (changed !== this.state.centerOfMapChanged) { - this.setState({ centerOfMapChanged: changed }); + centerOfMap.current = location; + const changed = distance(location, searchPosition) > 200; + if (changed !== centerOfMapChanged) { + setCenterOfMapChanged(changed); } }; // store ref to map - setMWTRef = ref => { - this.MWTRef = ref; + const setMWTRef = ref => { + MWTRef.current = ref; }; - updateLocation = () => { - const { centerOfMap } = this; - const { mode } = this.props.match.params; - if (centerOfMap?.lat && centerOfMap?.lon) { - let phase = PH_USEMAPCENTER; + const updateLocation = () => { + const center = centerOfMap.current; + if (center?.lat && center?.lon) { + let newPhase = PH_USEMAPCENTER; let type = 'CenterOfMap'; - if (centerOfMap.type === 'CurrentLocation') { - phase = PH_USEGEOLOCATION; - type = centerOfMap.type; + if (center.type === 'CurrentLocation') { + newPhase = PH_USEGEOLOCATION; + type = center.type; const path = `/${PREFIX_NEARYOU}/${mode}/POS`; - this.context.router.replace({ - ...this.props.match.location, + router.replace({ + ...match.location, pathname: path, }); } else { - const path = `/${PREFIX_NEARYOU}/${mode}/${locationToUri(centerOfMap)}`; - this.context.router.replace({ - ...this.props.match.location, + const path = `/${PREFIX_NEARYOU}/${mode}/${locationToUri(center)}`; + router.replace({ + ...match.location, pathname: path, }); } - return this.setState({ - searchPosition: { ...centerOfMap, type }, - centerOfMapChanged: false, - phase, - }); + setSearchPosition({ ...center, type }); + setCenterOfMapChanged(false); + setPhase(newPhase); + } else { + setSearchPosition(phase === PH_USEDEFAULTPOS ? searchPosition : position); } - return this.setState({ searchPosition: this.getPosition() }); - }; - - getPosition = () => { - return this.state.phase === PH_USEDEFAULTPOS - ? this.state.searchPosition - : this.props.position; }; - onSwipe = e => { - const { mode } = this.props.match.params; - const newMode = this.modes[e]; - const paramArray = this.props.match.location.pathname.split(mode); + const onSwipe = e => { + const newMode = allModes[e]; + const paramArray = match.location.pathname.split(mode); const pathParams = paramArray.length > 1 ? paramArray[1] : '/POS'; const path = `/${PREFIX_NEARYOU}/${newMode}${pathParams}`; - this.context.router.replace({ - ...this.props.match.location, + router.replace({ + ...match.location, pathname: path, }); - this.setState({ centerOfMapChanged: false }); + setCenterOfMapChanged(false); }; - refetchButton = nearByMode => { - const { mode } = this.props.match.params; - const modeClass = nearByMode || mode; - return ( -
- - -
- ); - }; - - noFavorites = () => { - return ( - !this.props.favouriteStopIds.length && - !this.props.favouriteStationIds.length && - !this.props.favouriteVehicleStationIds.length - ); - }; - - handleCityBikeTeaserClose = () => { - const readMessageIds = getReadMessageIds() || []; - readMessageIds.push('citybike_teaser'); - setReadMessageIds(readMessageIds); - this.setState({ showCityBikeTeaser: false }); - }; - - renderContent = () => { - const { centerOfMapChanged } = this.state; - const { mode } = this.props.match.params; - const noFavorites = mode === 'FAVORITE' && this.noFavorites(); - const renderRefetchButton = centerOfMapChanged && !noFavorites; - const nearByStopModes = this.modes; - const index = nearByStopModes.indexOf(mode); - const { config } = this.context; - const tabs = nearByStopModes.map(nearByStopMode => { - const renderSearch = - nearByStopMode !== 'FERRY' && nearByStopMode !== 'FAVORITE'; - const renderDisruptionBanner = nearByStopMode !== 'CITYBIKE'; - const isActive = nearByStopMode === mode; - if (nearByStopMode === 'FAVORITE') { - const noFavs = this.noFavorites(); + const noFavourites = () => + !favouriteStopIds.length && + !favouriteStationIds.length && + !favouriteVehicleStationIds.length; + + const renderContent = () => { + const index = allModes.indexOf(mode); + const tabs = allModes.map(tabMode => { + const renderStopRouteSearch = + tabMode !== 'FERRY' && tabMode !== 'FAVORITE'; + const isActive = tabMode === mode; + if (tabMode === 'FAVORITE') { + const noFavs = noFavourites(); return (
- {renderRefetchButton && this.refetchButton()} - + {centerOfMapChanged && !noFavs && ( + + )} + {favouritesFetched ? ( + + ) : ( + + )}
); } @@ -424,7 +333,7 @@ class NearYouPage extends React.Component { return (
{ - const { vehicleRental } = config; - // Use buy instructions if available - const cityBikeBuyUrl = vehicleRental.buyUrl; - const buyInstructions = cityBikeBuyUrl - ? vehicleRental.buyInstructions?.[this.props.lang] - : undefined; - - let cityBikeNetworkUrl; - // Use general information about using city bike, if one network config is available - if (Object.keys(vehicleRental.networks).length === 1) { - cityBikeNetworkUrl = getRentalNetworkConfig( - getRentalNetworkId(Object.keys(vehicleRental.networks)), - config, - ).url; - } const prioritizedStops = - config.prioritizedStopsNearYou[nearByStopMode.toLowerCase()]; + config.prioritizedStopsNearYou[tabMode.toLowerCase()] || []; + let favIds; + switch (mode) { + case 'CITYBIKE': + favIds = new Set(favouriteVehicleStationIds); + break; + case 'BIKEPARK': + case 'CARPARK': + favIds = new Set(); + break; + default: + favIds = new Set([ + ...favouriteStopIds, + ...favouriteStationIds, + ]); + break; + } return (
- {renderSearch && ( - )} - {this.state.showCityBikeTeaser && - nearByStopMode === 'CITYBIKE' && - (cityBikeBuyUrl || cityBikeNetworkUrl) && ( -
-
- -
{ - if ( - isKeyboardSelectionEvent(e) && - (e.keyCode === 13 || e.keyCode === 32) - ) { - this.handleCityBikeTeaserClose(); - } - }} - onClick={this.handleCityBikeTeaserClose} - role="button" - > - -
-
- -
- )} - - {renderRefetchButton && this.refetchButton(nearByStopMode)} - {prioritizedStops?.length && ( + {tabMode === 'CITYBIKE' && } + {centerOfMapChanged && ( + + )} + {prioritizedStops.length ? ( { - if (res.props) { - return ( - <> - {res.props.stops.map(stop => { - return ( - - ); - })} - - ); - } - return null; - }} + environment={relayEnvironment} + render={res => + res.props?.stops.map(stop => ( + + )) + } /> - )} - {!props && ( -
- -
- )} - {props && ( - + ) : ( +
+ +
)}
); @@ -630,11 +470,9 @@ class NearYouPage extends React.Component { return ( ); @@ -642,314 +480,143 @@ class NearYouPage extends React.Component { return tabs[0]; }; - renderMap = () => { - const { mode } = this.props.match.params; - if (mode === 'FAVORITE') { - return ( - { - if (props) { - return ( - - ); - } - return undefined; - }} - /> - ); - } - const filteredMapLayers = { - ...this.props.mapLayers, - citybike: mode === 'CITYBIKE', - citybikeOverrideMinZoom: mode === 'CITYBIKE', - }; - if (!this.context.config.map.showLayerSelector) { - filteredMapLayers.stop = {}; - if (mode !== 'CITYBIKE') { - filteredMapLayers.stop[mode.toLowerCase()] = true; - } - } - return ( - { - return ( - - ); - }} - /> - ); - }; - - handleClose = () => { - this.setState({ phase: PH_USEDEFAULTPOS }); - }; - - handleStartGeolocation = () => { - this.context.executeAction(startLocationWatch); - this.setState({ phase: PH_GEOLOCATIONING }); + const renderMap = () => ( + + ); + + const handleClose = () => setPhase(PH_USEDEFAULTPOS); + + const handleStartGeolocation = () => { + executeAction(startLocationWatch); + setPhase(PH_GEOLOCATIONING); }; - selectHandler = item => { - const { mode } = this.props.match.params; + const selectHandler = item => { const path = `/${PREFIX_NEARYOU}/${mode}/${locationToUri(item)}`; - this.context.router.replace({ - ...this.props.match.location, + router.replace({ + ...match.location, pathname: path, }); - this.centerOfMap = null; - this.setState({ - phase: PH_USEDEFAULTPOS, - searchPosition: item, - centerOfMapChanged: false, - }); + centerOfMap.current = {}; + setPhase(PH_USEDEFAULTPOS); + setSearchPosition(item); + setCenterOfMapChanged(false); }; - renderSearchBox = () => { - return ( -
- {this.renderAutoSuggestField(true)} -
- ); + const search = onMap => ( + + ); + + const mapSearch = () => { + return
{search(true)}
; }; - renderAutoSuggestField = onMap => { - const isMobile = this.props.breakpoint !== 'large'; - const searchProps = { - id: 'origin-stop-near-you', - placeholder: 'origin', - translatedPlaceholder: onMap - ? this.context.intl.formatMessage({ id: 'move-on-map' }) - : undefined, - mobileLabel: onMap - ? this.context.intl.formatMessage({ id: 'position' }) - : undefined, - inputClassName: onMap ? 'origin-stop-near-you-selector' : undefined, - modeIconColors: this.context.config.colors.iconColors, - modeSet: this.context.config.iconModeSet, - getAutoSuggestIcons: this.context.config.getAutoSuggestIcons, - }; - const targets = getLocationSearchTargets(this.context.config, false); + if (PH_SHOWSEARCH.includes(phase)) { return ( - + + {search(false)} + ); - }; - - renderDialogModal = () => { + } + if (PH_READY.includes(phase)) { return ( - -
-
-
- -
-
-
- -
-
- -
-
-
- {this.renderAutoSuggestField()} -
-
-
- -
- {this.state.phase === PH_SEARCH_GEOLOCATION && ( -
- -
- )} - {this.state.phase === PH_SEARCH && ( -
- -
- )} -
-
+ ( + + ) : ( + + ), + }} + /> + ) + } + bckBtnFallback="back" + content={renderContent()} + scrollable={allModes.length === 1} + map={ + <> + {mapSearch()} + {renderMap()} + + } + /> + )} + mobile={() => ( + + )} + /> ); - }; - - render() { - const { mode } = this.props.match.params; - const { phase } = this.state; - const nearByStopModes = this.modes; - - if (PH_SHOWSEARCH.includes(phase)) { - return
{this.renderDialogModal()}
; - } - if (PH_READY.includes(phase)) { - return ( - ( - - ) : ( - - ), - }} - /> - ) - } - bckBtnFallback="back" - content={this.renderContent()} - scrollable={nearByStopModes.length === 1} - map={ - <> - {this.renderSearchBox()} - {this.renderMap()} - - } - /> - )} - mobile={() => ( - - )} - /> - ); - } - return ; } + return ; } +NearYouPage.contextTypes = { + config: configShape.isRequired, + executeAction: PropTypes.func.isRequired, + getStore: PropTypes.func, + intl: intlShape.isRequired, + router: routerShape.isRequired, +}; + +NearYouPage.propTypes = { + breakpoint: PropTypes.string.isRequired, + relayEnvironment: relayShape.isRequired, + position: locationShape.isRequired, + lang: PropTypes.string.isRequired, + match: matchShape.isRequired, + favouriteStopIds: PropTypes.arrayOf(PropTypes.string).isRequired, + favouriteStationIds: PropTypes.arrayOf(PropTypes.string).isRequired, + favouriteVehicleStationIds: PropTypes.arrayOf(PropTypes.string).isRequired, + mapLayers: mapLayerShape.isRequired, + favouritesFetched: PropTypes.bool, + currentTime: PropTypes.number.isRequired, +}; + +NearYouPage.defaultProps = { + favouritesFetched: false, +}; + const NearYouPageWithBreakpoint = withBreakpoint(props => ( {({ environment }) => ( @@ -960,28 +627,33 @@ const NearYouPageWithBreakpoint = withBreakpoint(props => ( const PositioningWrapper = connectToStores( NearYouPageWithBreakpoint, - ['PositionStore', 'PreferencesStore', 'FavouriteStore', 'MapLayerStore'], + [ + 'PositionStore', + 'PreferencesStore', + 'FavouriteStore', + 'MapLayerStore', + 'TimeStore', + ], (context, props) => { - const favouriteStopIds = context - .getStore('FavouriteStore') + const favStore = context.getStore('FavouriteStore'); + const favouriteStopIds = favStore .getStopsAndStations() .filter(stop => stop.type === 'stop') .map(stop => stop.gtfsId); - const favouriteStationIds = context - .getStore('FavouriteStore') + const favouriteStationIds = favStore .getStopsAndStations() .filter(stop => stop.type === 'station') .map(stop => stop.gtfsId); - let favouriteVehicleStationIds = []; - if (useCitybikes(context.config.vehicleRental?.networks, context.config)) { - favouriteVehicleStationIds = context - .getStore('FavouriteStore') - .getVehicleRentalStations() - .map(station => station.stationId); - } - const status = context.getStore('FavouriteStore').getStatus(); + const favouriteVehicleStationIds = useCitybikes( + context.config.vehicleRental?.networks, + context.config, + ) + ? favStore.getVehicleRentalStations().map(station => station.stationId) + : []; + return { ...props, + currentTime: context.getStore('TimeStore').getCurrentTime(), position: context.getStore('PositionStore').getLocationState(), lang: context.getStore('PreferencesStore').getLanguage(), mapLayers: context @@ -990,7 +662,8 @@ const PositioningWrapper = connectToStores( favouriteStopIds, favouriteVehicleStationIds, favouriteStationIds, - favouritesFetched: status !== FavouriteStore.STATUS_FETCHING_OR_UPDATING, + favouritesFetched: + favStore.getStatus() !== FavouriteStore.STATUS_FETCHING_OR_UPDATING, }; }, ); diff --git a/app/component/nearyou/ParkNearYou.js b/app/component/nearyou/ParkNearYou.js new file mode 100644 index 0000000000..db1261133b --- /dev/null +++ b/app/component/nearyou/ParkNearYou.js @@ -0,0 +1,103 @@ +import React, { useEffect, useRef } from 'react'; +import PropTypes from 'prop-types'; +import { Link } from 'found'; +import { graphql, createRefetchContainer } from 'react-relay'; +import { PREFIX_BIKEPARK, PREFIX_CARPARK } from '../../util/path'; +import { isKeyboardSelectionEvent } from '../../util/browser'; +import { parkShape, relayShape } from '../../util/shapes'; +import ParkAndRideContent from '../ParkAndRideContent'; + +const ParkNearYou = ({ park, relay, currentTime, isParentTabActive, mode }) => { + const timeRef = useRef(currentTime); + + useEffect(() => { + const { vehicleParkingId } = park; + if (isParentTabActive && currentTime - timeRef.current > 30) { + relay.refetch( + oldVariables => { + return { ...oldVariables, vehicleParkingId }; + }, + null, + null, + { force: true }, // query variables stay the same between refetches + ); + timeRef.current = currentTime; + } + }, [currentTime, isParentTabActive]); + + const prefix = mode === 'BIKEPARK' ? PREFIX_BIKEPARK : PREFIX_CARPARK; + return ( + +
+
+
+ { + e.stopPropagation(); + }} + onKeyPress={e => { + if (isKeyboardSelectionEvent(e)) { + e.stopPropagation(); + } + }} + to={`/${prefix}/${park.vehicleParkingId}`} + > + + +
+
+
+
+ ); +}; + +ParkNearYou.propTypes = { + park: parkShape.isRequired, + currentTime: PropTypes.number, + isParentTabActive: PropTypes.bool, + relay: relayShape.isRequired, + mode: PropTypes.string.isRequired, +}; + +ParkNearYou.defaultProps = { + currentTime: undefined, + isParentTabActive: false, +}; + +const containerComponent = createRefetchContainer( + ParkNearYou, + { + park: graphql` + fragment ParkNearYou_park on VehicleParking { + ...ParkContainer_vehicleParking + vehicleParkingId + name + lat + lon + availability { + bicycleSpaces + carSpaces + } + parkCapacity: capacity { + carSpaces + } + tags + realtime + } + `, + }, + graphql` + query ParkNearYouRefetchQuery($vehicleParkingId: String!) { + vehicleParking(id: $vehicleParkingId) { + ...ParkNearYou_park + } + } + `, +); + +export { containerComponent as default, ParkNearYou as Component }; diff --git a/app/component/nearyou/Search.js b/app/component/nearyou/Search.js new file mode 100644 index 0000000000..fc6f29da17 --- /dev/null +++ b/app/component/nearyou/Search.js @@ -0,0 +1,57 @@ +import PropTypes from 'prop-types'; +import React, { memo } from 'react'; +import DTAutoSuggest from '@digitransit-component/digitransit-component-autosuggest'; +import { intlShape } from 'react-intl'; +import { configShape } from '../../util/shapes'; +import { + withSearchContext, + getLocationSearchTargets, +} from '../WithSearchContext'; + +const DTAutoSuggestWithSearchContext = withSearchContext(DTAutoSuggest); + +function Search({ onMap, ...rest }, { config, intl, getStore }) { + const searchProps = { + id: 'origin-stop-near-you', + placeholder: 'origin', + translatedPlaceholder: onMap + ? intl.formatMessage({ id: 'move-on-map' }) + : undefined, + mobileLabel: onMap ? intl.formatMessage({ id: 'position' }) : undefined, + inputClassName: onMap ? 'origin-stop-near-you-selector' : undefined, + colors: config.colors, + modeSet: config.iconModeSet, + getAutoSuggestIcons: config.getAutoSuggestIcons, + }; + const sources = ['History', 'Datasource']; + if (getStore('FavouriteStore').getLocationCount()) { + sources.push('Favourite'); + } + return ( + + ); +} + +Search.propTypes = { + onMap: PropTypes.bool, +}; + +Search.defaultProps = { + onMap: false, +}; + +Search.contextTypes = { + config: configShape.isRequired, + intl: intlShape.isRequired, + getStore: PropTypes.func.isRequired, +}; + +export default memo(Search); diff --git a/app/component/nearyou/StopNearYou.js b/app/component/nearyou/StopNearYou.js index 097fdd0765..5d5f0db6cb 100644 --- a/app/component/nearyou/StopNearYou.js +++ b/app/component/nearyou/StopNearYou.js @@ -1,57 +1,53 @@ -import React, { useEffect, useState } from 'react'; +import React, { useEffect, useState, useRef } from 'react'; import PropTypes from 'prop-types'; import { FormattedMessage, intlShape } from 'react-intl'; import { Link } from 'found'; -import connectToStores from 'fluxible-addons-react/connectToStores'; import Modal from '@hsl-fi/modal'; import { stopShape, configShape, relayShape } from '../../util/shapes'; import { hasEntitiesOfType } from '../../util/alertUtils'; import { stopPagePath } from '../../util/path'; import { AlertEntityType } from '../../constants'; -import StopNearYouHeader from './StopNearYouHeader'; +import NearYouHeader from './NearYouHeader'; import AlertBanner from '../AlertBanner'; import StopNearYouDepartureRowContainer from './StopNearYouDepartureRowContainer'; import CapacityModal from '../CapacityModal'; const StopNearYou = ( - { stop, desc, stopId, currentTime, currentMode, relay, isParentTabActive }, + { stop, currentTime, relay, isParentTabActive }, { config, intl }, ) => { if (!stop.stoptimesWithoutPatterns) { return null; } + const timeRef = useRef(currentTime); const [capacityModalOpen, setCapacityModalOpen] = useState(false); const stopMode = stop.stoptimesWithoutPatterns[0]?.trip.route.mode; const { gtfsId } = stop; useEffect(() => { - let id = gtfsId; - if (stopId) { - id = stopId; - } - if (currentMode === stopMode || !currentMode) { - relay?.refetch(oldVariables => { - return { ...oldVariables, stopId: id, startTime: currentTime }; + if (isParentTabActive && currentTime - timeRef.current > 30) { + relay.refetch(oldVariables => { + return { ...oldVariables, stopId: gtfsId, startTime: currentTime }; }, null); + timeRef.current = currentTime; } - }, [currentTime, currentMode]); + }, [currentTime, isParentTabActive]); - const description = desc || stop.desc; const isStation = stop.locationType === 'STATION'; const linkAddress = stopPagePath(isStation, gtfsId); - const { constantOperationStops } = config; const { locale } = intl; const isConstantOperation = constantOperationStops[gtfsId]; const filteredAlerts = stop.alerts.filter(alert => hasEntitiesOfType(alert, AlertEntityType.Stop), ); + return (
- @@ -86,7 +82,7 @@ const StopNearYou = ( mode={stopMode} stopTimes={stop.stoptimesWithoutPatterns} isStation={isStation && stopMode !== 'SUBWAY'} - setCapacityModalOpen={() => setCapacityModalOpen(true)} + openCapacityModal={() => setCapacityModalOpen(true)} isParentTabActive={isParentTabActive} /> { - return { - ...props, - currentTime: context.getStore('TimeStore').getCurrentTime(), - }; - }, -); - StopNearYou.propTypes = { stop: stopShape.isRequired, - stopId: PropTypes.string, currentTime: PropTypes.number.isRequired, - currentMode: PropTypes.string.isRequired, - desc: PropTypes.string, - relay: relayShape, - isParentTabActive: PropTypes.bool, -}; - -StopNearYou.defaultProps = { - stopId: undefined, - desc: undefined, - relay: undefined, - isParentTabActive: false, + relay: relayShape.isRequired, + isParentTabActive: PropTypes.bool.isRequired, }; StopNearYou.contextTypes = { @@ -152,4 +127,4 @@ StopNearYou.contextTypes = { intl: intlShape.isRequired, }; -export default connectedComponent; +export default StopNearYou; diff --git a/app/component/nearyou/StopNearYouDepartureRowContainer.js b/app/component/nearyou/StopNearYouDepartureRowContainer.js index 0928f154ca..05508a83d0 100644 --- a/app/component/nearyou/StopNearYouDepartureRowContainer.js +++ b/app/component/nearyou/StopNearYouDepartureRowContainer.js @@ -6,7 +6,7 @@ import DepartureRow from '../DepartureRow'; export default function StopNearYouDepartureRowContainer({ stopTimes, mode, - setCapacityModalOpen, + openCapacityModal, isParentTabActive, ...props }) { @@ -29,7 +29,7 @@ export default function StopNearYouDepartureRowContainer({ currentTime={props.currentTime} showPlatformCode={props.isStation} showLink - onCapacityClick={() => setCapacityModalOpen(true)} + onCapacityClick={openCapacityModal} isParentTabActive={isParentTabActive} /> ); @@ -69,7 +69,7 @@ StopNearYouDepartureRowContainer.propTypes = { mode: PropTypes.string.isRequired, isStation: PropTypes.bool.isRequired, currentTime: PropTypes.number.isRequired, - setCapacityModalOpen: PropTypes.func.isRequired, + openCapacityModal: PropTypes.func.isRequired, isParentTabActive: PropTypes.bool, }; diff --git a/app/component/nearyou/StopRouteSearch.js b/app/component/nearyou/StopRouteSearch.js new file mode 100644 index 0000000000..633dd25b5d --- /dev/null +++ b/app/component/nearyou/StopRouteSearch.js @@ -0,0 +1,68 @@ +import PropTypes from 'prop-types'; +import React, { memo } from 'react'; +import { routerShape } from 'found'; +import DTAutoSuggest from '@digitransit-component/digitransit-component-autosuggest'; +import { filterSearchResultsByMode } from '@digitransit-search-util/digitransit-search-util-query-utils'; +import { configShape } from '../../util/shapes'; +import { withSearchContext } from '../WithSearchContext'; +import { getStopRoutePath } from '../../util/path'; + +const DTAutoSuggestWithSearchContext = withSearchContext(DTAutoSuggest); +const searchSources = ['Favourite', 'History', 'Datasource']; + +function StopRouteSearch({ mode, ...rest }, { router, config }) { + const transportMode = `route-${mode}`; + + const filter = config.stopSearchFilter + ? (results, transportmode, type) => + filterSearchResultsByMode(results, transportmode, type).filter( + config.stopSearchFilter, + ) + : filterSearchResultsByMode; + const selectHandler = item => { + router.push(getStopRoutePath(item)); + }; + let targets; + switch (mode) { + case 'CITYBIKE': + targets = ['VehicleRentalStations']; + break; + case 'BIKEPARK': + case 'CARPARK': + targets = ['ParkingAreas']; + break; + default: + targets = ['Stops', 'Stations', 'Routes']; + break; + } + return ( +
+ +
+ ); +} + +StopRouteSearch.propTypes = { mode: PropTypes.string.isRequired }; + +StopRouteSearch.contextTypes = { + router: routerShape.isRequired, + config: configShape.isRequired, +}; + +export default memo(StopRouteSearch); diff --git a/app/component/nearyou/StopsNearYouContainer.js b/app/component/nearyou/StopsNearYouContainer.js deleted file mode 100644 index 65aaa31175..0000000000 --- a/app/component/nearyou/StopsNearYouContainer.js +++ /dev/null @@ -1,493 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -import { createPaginationContainer, graphql } from 'react-relay'; -import { intlShape, FormattedMessage } from 'react-intl'; -import connectToStores from 'fluxible-addons-react/connectToStores'; -import { matchShape } from 'found'; -import { configShape, relayShape } from '../../util/shapes'; -import StopNearYouContainer from './StopNearYouContainer'; -import withBreakpoint from '../../util/withBreakpoint'; -import { - sortNearbyRentalStations, - sortNearbyStops, -} from '../../util/sortUtils'; -import CityBikeStopNearYou from './VehicleRentalStationNearYou'; -import Loading from '../Loading'; -import Icon from '../Icon'; -import { getDefaultNetworks } from '../../util/vehicleRentalUtils'; -import DisruptionBanner from '../DisruptionBanner'; - -class StopsNearYouContainer extends React.Component { - static propTypes = { - // eslint-disable-next-line - stopPatterns: PropTypes.object, - setLoadState: PropTypes.func.isRequired, - currentTime: PropTypes.number.isRequired, - relay: relayShape.isRequired, - // eslint-disable-next-line - favouriteIds: PropTypes.objectOf(PropTypes.string).isRequired, - match: matchShape.isRequired, - position: PropTypes.shape({ - address: PropTypes.string, - lat: PropTypes.number, - lon: PropTypes.number, - }).isRequired, - withSeparator: PropTypes.bool, - prioritizedStops: PropTypes.arrayOf(PropTypes.string), - nearByStopMode: PropTypes.string.isRequired, - renderDisruptionBanner: PropTypes.bool, - isParentTabActive: PropTypes.bool, - }; - - static defaultProps = { - stopPatterns: undefined, - withSeparator: false, - prioritizedStops: undefined, - renderDisruptionBanner: false, - isParentTabActive: false, - }; - - static contextTypes = { - config: configShape, - intl: intlShape.isRequired, - executeAction: PropTypes.func.isRequired, - getStore: PropTypes.func, - }; - - constructor(props, context) { - super(props, context); - this.resultsUpdatedAlertRef = React.createRef(); - this.state = { - maxRefetches: context.config.maxNearbyStopRefetches, - refetches: 0, - stopCount: 5, - currentPosition: props.position, - fetchMoreStops: false, - isLoadingmoreStops: false, - isUpdatingPosition: false, - }; - } - - static getDerivedStateFromProps(nextProps, prevState) { - let newState = null; - if ( - !prevState.currentPosition || - (!prevState.currentPosition.address && - nextProps.position && - nextProps.position.address) - ) { - newState = { - ...newState, - currentPosition: nextProps.position, - }; - } - if (nextProps.stopPatterns) { - const stopsForFiltering = [...nextProps.stopPatterns.nearest.edges]; - const newestStops = stopsForFiltering.splice( - stopsForFiltering.length - 5, - ); - if ( - newestStops.every(stop => { - return ( - stop.node.place.stoptimesWithoutPatterns && - stop.node.place.stoptimesWithoutPatterns.length === 0 - ); - }) && - prevState.refetches < prevState.maxRefetches - ) { - newState = { - ...newState, - fetchMoreStops: true, - }; - } else { - newState = { - ...newState, - fetchMoreStops: false, - }; - } - } - return newState; - } - - componentDidUpdate(prevProps, prevState) { - const { position } = prevProps; - if (position && this.state.currentPosition) { - if ( - position.lat !== this.props.position.lat || - position.lon !== this.props.position.lon - ) { - this.updatePosition(); - } - } - if (this.state.fetchMoreStops) { - this.showMore(true); - } - if ( - this.resultsUpdatedAlertRef.current && - prevState.isLoadingmoreStops && - !this.state.isLoadingmoreStops - ) { - this.resultsUpdatedAlertRef.current.innerHTML = - this.context.intl.formatMessage({ - id: 'stop-near-you-update-alert', - defaultMessage: 'Search results updated', - }); - setTimeout(() => { - this.resultsUpdatedAlertRef.current.innerHTML = null; - }, 100); - } - } - - componentDidMount() { - this.props.setLoadState(); - if (this.state.fetchMoreStops) { - this.showMore(true); - } - } - - updatePosition = () => { - const variables = { - lat: this.props.position.lat, - lon: this.props.position.lon, - startTime: this.props.currentTime, - }; - this.setState({ - isUpdatingPosition: true, - }); - this.props.relay.refetchConnection( - this.state.stopCount, - () => { - this.setState({ - isUpdatingPosition: false, - currentPosition: this.props.position, - }); - }, - variables, - ); - }; - - showMore = automatic => { - if (!this.props.relay.hasMore() || this.state.isLoadingmoreStops) { - return; - } - this.setState({ isLoadingmoreStops: true, fetchMoreStops: false }); - this.props.relay.loadMore(5, () => { - this.setState(previousState => ({ - refetches: automatic - ? previousState.refetches + 1 - : previousState.refetches, - stopCount: previousState.stopCount + 5, - fetchMoreStops: false, - isLoadingmoreStops: false, - })); - }); - }; - - createNearbyStops = () => { - if (!this.props.stopPatterns || !this.props.stopPatterns.nearest) { - return null; - } - const { mode } = this.props.match.params; - const walkRoutingThreshold = - mode === 'RAIL' || mode === 'SUBWAY' || mode === 'FERRY' ? 3000 : 1500; - const stopPatterns = this.props.stopPatterns.nearest.edges; - const isCityBikeView = this.props.match.params.mode === 'CITYBIKE'; - let sortedPatterns; - if (isCityBikeView) { - const withNetworks = stopPatterns.filter(pattern => { - return !!pattern.node.place?.rentalNetwork?.networkId; - }); - const filteredCityBikeStopPatterns = withNetworks.filter(pattern => { - return getDefaultNetworks(this.context.config).includes( - pattern.node.place?.rentalNetwork?.networkId, - ); - }); - sortedPatterns = filteredCityBikeStopPatterns - .slice(0, 5) - .sort(sortNearbyRentalStations(this.props.favouriteIds)); - sortedPatterns.push(...filteredCityBikeStopPatterns.slice(5)); - } else { - sortedPatterns = stopPatterns - .slice(0, 5) - .sort(sortNearbyStops(this.props.favouriteIds, walkRoutingThreshold)); - sortedPatterns.push(...stopPatterns.slice(5)); - } - - const stops = sortedPatterns.map(({ node }) => { - const stop = node.place; - /* eslint-disable-next-line no-underscore-dangle */ - switch (stop.__typename) { - case 'Stop': - if ( - stop.stoptimesWithoutPatterns && - stop.stoptimesWithoutPatterns.length > 0 - ) { - if (!this.props.prioritizedStops?.includes(stop.gtfsId)) { - return ( - - ); - } - } - break; - case 'VehicleRentalStation': - return ( - - ); - default: - return null; - } - return null; - }); - return stops; - }; - - render() { - const screenReaderUpdateAlert = ( - - ); - const stops = this.createNearbyStops().filter(e => e); - const alerts = stops - .flatMap(stop => stop.props.stop?.routes || []) - .flatMap(route => route?.alerts || []) - .filter(alert => alert.alertSeverityLevel === 'SEVERE'); - const noStopsFound = - !stops.length && - this.state.refetches >= this.state.maxRefetches && - !this.state.isLoadingmoreStops; - return ( - <> - {this.props.renderDisruptionBanner && ( - - )} - {((!this.props.relay.hasMore() && - !stops.length && - !this.props.prioritizedStops?.length) || - (noStopsFound && !this.props.prioritizedStops?.length)) && ( - <> - {this.props.withSeparator &&
} -
- - -
- - )} - {screenReaderUpdateAlert} - {this.state.isUpdatingPosition && ( -
- -
- )} -
- {stops} -
- {this.state.isLoadingmoreStops && ( -
- -
- )} - {this.props.relay.hasMore() && !noStopsFound && ( - - )} - - ); - } -} -const StopsNearYouContainerWithBreakpoint = withBreakpoint( - StopsNearYouContainer, -); - -const connectedContainer = connectToStores( - StopsNearYouContainerWithBreakpoint, - ['TimeStore', 'FavouriteStore'], - ({ getStore }, { match }) => { - const favouriteIds = - match.params.mode === 'CITYBIKE' - ? new Set( - getStore('FavouriteStore') - .getVehicleRentalStations() - .map(station => station.stationId), - ) - : new Set( - getStore('FavouriteStore') - .getStopsAndStations() - .map(stop => stop.gtfsId), - ); - return { - currentTime: getStore('TimeStore').getCurrentTime(), - favouriteIds, - }; - }, -); - -const refetchContainer = createPaginationContainer( - connectedContainer, - { - stopPatterns: graphql` - fragment StopsNearYouContainer_stopPatterns on QueryType - @argumentDefinitions( - startTime: { type: "Long!", defaultValue: 0 } - omitNonPickups: { type: "Boolean!", defaultValue: false } - lat: { type: "Float!" } - lon: { type: "Float!", defaultValue: 0 } - filterByPlaceTypes: { type: "[FilterPlaceType]", defaultValue: null } - filterByModes: { type: "[Mode]", defaultValue: null } - first: { type: "Int!", defaultValue: 5 } - after: { type: "String" } - maxResults: { type: "Int" } - maxDistance: { type: "Int" } - filterByNetwork: { type: "[String!]", defaultValue: null } - ) { - nearest( - lat: $lat - lon: $lon - filterByPlaceTypes: $filterByPlaceTypes - filterByModes: $filterByModes - first: $first - after: $after - maxResults: $maxResults - maxDistance: $maxDistance - filterByNetwork: $filterByNetwork - ) @connection(key: "StopsNearYouContainer_nearest") { - edges { - node { - distance - place { - __typename - ... on VehicleRentalStation { - ...VehicleRentalStationNearYou_stop - stationId - rentalNetwork { - networkId - } - } - ... on Stop { - ...StopNearYouContainer_stop - @arguments( - startTime: $startTime - omitNonPickups: $omitNonPickups - ) - id - name - gtfsId - stoptimesWithoutPatterns( - startTime: $startTime - omitNonPickups: $omitNonPickups - ) { - scheduledArrival - } - routes { - ... on Route { - alerts { - feed - id - alertSeverityLevel - alertHeaderText - alertEffect - alertCause - alertDescriptionText - effectiveStartDate - effectiveEndDate - entities { - __typename - ... on Route { - mode - shortName - } - } - } - } - } - } - } - } - } - } - } - `, - }, - { - direction: 'forward', - getConnectionFromProps(props) { - return props.stopPatterns && props.stopPatterns.nearest; - }, - getFragmentVariables(prevVars, totalCount) { - return { - ...prevVars, - first: totalCount, - }; - }, - getVariables(props, pagevars, fragmentVariables) { - return { - ...fragmentVariables, - first: pagevars.count, - after: pagevars.cursor, - }; - }, - query: graphql` - query StopsNearYouContainerRefetchQuery( - $lat: Float! - $lon: Float! - $filterByPlaceTypes: [FilterPlaceType] - $filterByModes: [Mode] - $first: Int! - $after: String - $maxResults: Int! - $maxDistance: Int! - $startTime: Long! - $omitNonPickups: Boolean! - $filterByNetwork: [String!] - ) { - viewer { - ...StopsNearYouContainer_stopPatterns - @arguments( - startTime: $startTime - omitNonPickups: $omitNonPickups - lat: $lat - lon: $lon - filterByPlaceTypes: $filterByPlaceTypes - filterByModes: $filterByModes - first: $first - after: $after - maxResults: $maxResults - maxDistance: $maxDistance - filterByNetwork: $filterByNetwork - ) - } - } - `, - }, -); - -export { refetchContainer as default, StopsNearYouContainer as Component }; diff --git a/app/component/nearyou/StopsNearYouFavorites.js b/app/component/nearyou/StopsNearYouFavorites.js deleted file mode 100644 index 75fa51d2a9..0000000000 --- a/app/component/nearyou/StopsNearYouFavorites.js +++ /dev/null @@ -1,132 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -import { graphql, QueryRenderer, ReactRelayContext } from 'react-relay'; -import { FormattedMessage } from 'react-intl'; -import { - locationShape, - relayShape, - stopShape, - stationShape, - vehicleRentalStationShape, -} from '../../util/shapes'; -import StopsNearYouFavouritesContainer from './StopsNearYouFavouritesContainer'; -import withBreakpoint from '../../util/withBreakpoint'; -import Loading from '../Loading'; - -function StopsNearYouFavorites({ - favoriteStops, - favoriteStations, - favoriteVehicleRentalStationIds, - relayEnvironment, - searchPosition, - breakpoint, - noFavorites, - favouritesFetched, - isParentTabActive, -}) { - if (!favouritesFetched) { - return ; - } - if (noFavorites) { - return ( -
- {breakpoint !== 'large' && ( -
- -
- )} -
- -
- Käyttöohje - -
- ); - } - return ( - { - if (props) { - return ( - - ); - } - return ; - }} - /> - ); -} -StopsNearYouFavorites.propTypes = { - favoriteStops: PropTypes.arrayOf(PropTypes.string), - favoriteStations: PropTypes.arrayOf(PropTypes.string), - favoriteVehicleRentalStationIds: PropTypes.arrayOf(PropTypes.string), - relayEnvironment: relayShape.isRequired, - searchPosition: locationShape.isRequired, - stops: PropTypes.arrayOf(stopShape), - stations: PropTypes.arrayOf(stationShape), - vehicleStations: PropTypes.arrayOf(vehicleRentalStationShape), - breakpoint: PropTypes.string, - noFavorites: PropTypes.bool, - favouritesFetched: PropTypes.bool, - isParentTabActive: PropTypes.bool, -}; - -StopsNearYouFavorites.defaultProps = { - favoriteStops: undefined, - favoriteStations: undefined, - favoriteVehicleRentalStationIds: undefined, - stops: undefined, - stations: undefined, - vehicleStations: undefined, - breakpoint: undefined, - noFavorites: false, - favouritesFetched: false, - isParentTabActive: false, -}; - -const StopsNearYouFavoritesWithBreakpoint = withBreakpoint(props => ( - - {({ environment }) => ( - - )} - -)); - -export default StopsNearYouFavoritesWithBreakpoint; diff --git a/app/component/nearyou/StopsNearYouFavoritesMapContainer.js b/app/component/nearyou/StopsNearYouFavoritesMapContainer.js deleted file mode 100644 index e6f5ea7652..0000000000 --- a/app/component/nearyou/StopsNearYouFavoritesMapContainer.js +++ /dev/null @@ -1,160 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -import connectToStores from 'fluxible-addons-react/connectToStores'; -import { graphql, createFragmentContainer } from 'react-relay'; -import distance from '@digitransit-search-util/digitransit-search-util-distance'; -import NearYouMap from '../map/NearYouMap'; -import PreferencesStore from '../../store/PreferencesStore'; -import FavouriteStore from '../../store/FavouriteStore'; -import { - vehicleRentalStationShape, - stopShape, - stationShape, - locationShape, -} from '../../util/shapes'; - -function StopsNearYouFavoritesMapContainer(props) { - const { stops, stations, vehicleStations, position } = props; - const stopList = []; - stopList.push( - ...stops - .filter(s => s) - .map(stop => { - return { - type: 'stop', - node: { - distance: distance(position, stop), - place: { - ...stop, - }, - }, - }; - }), - ); - stopList.push( - ...stations - .filter(s => s) - .map(stop => { - return { - type: 'station', - node: { - distance: distance(position, stop), - place: { - ...stop, - }, - }, - }; - }), - ); - if (vehicleStations) { - stopList.push( - ...vehicleStations - .filter(s => s) - .map(stop => { - return { - type: 'vehicleRentalStation', - node: { - distance: distance(position, stop), - place: { - ...stop, - }, - }, - }; - }), - ); - } - stopList.sort((a, b) => a.node.distance - b.node.distance); - - return ; -} - -StopsNearYouFavoritesMapContainer.propTypes = { - stops: PropTypes.arrayOf(stopShape), - stations: PropTypes.arrayOf(stationShape), - vehicleStations: PropTypes.arrayOf(vehicleRentalStationShape), - position: locationShape.isRequired, -}; - -StopsNearYouFavoritesMapContainer.defaultProps = { - stops: undefined, - stations: undefined, - vehicleStations: undefined, -}; - -const StopsNearYouMapWithStores = connectToStores( - StopsNearYouFavoritesMapContainer, - [PreferencesStore, FavouriteStore], - ({ getStore }) => { - const language = getStore(PreferencesStore).getLanguage(); - return { language }; - }, -); - -const containerComponent = createFragmentContainer(StopsNearYouMapWithStores, { - stops: graphql` - fragment StopsNearYouFavoritesMapContainer_stops on Stop - @relay(plural: true) - @argumentDefinitions(startTime: { type: "Long!", defaultValue: 0 }) { - gtfsId - lat - lon - name - patterns { - route { - gtfsId - shortName - mode - } - code - directionId - patternGeometry { - points - } - } - stoptimesWithoutPatterns(startTime: $startTime, omitNonPickups: true) { - scheduledArrival - } - } - `, - stations: graphql` - fragment StopsNearYouFavoritesMapContainer_stations on Stop - @relay(plural: true) - @argumentDefinitions(startTime: { type: "Long!", defaultValue: 0 }) { - gtfsId - lat - lon - name - stops { - patterns { - route { - gtfsId - shortName - mode - } - code - directionId - patternGeometry { - points - } - } - } - stoptimesWithoutPatterns(startTime: $startTime, omitNonPickups: true) { - scheduledArrival - } - } - `, - vehicleStations: graphql` - fragment StopsNearYouFavoritesMapContainer_vehicleStations on VehicleRentalStation - @relay(plural: true) { - name - lat - lon - stationId - } - `, -}); - -export { - containerComponent as default, - StopsNearYouFavoritesMapContainer as Component, -}; diff --git a/app/component/nearyou/StopsNearYouSearch.js b/app/component/nearyou/StopsNearYouSearch.js deleted file mode 100644 index 1132350c56..0000000000 --- a/app/component/nearyou/StopsNearYouSearch.js +++ /dev/null @@ -1,80 +0,0 @@ -import PropTypes from 'prop-types'; -import React, { memo } from 'react'; -import { routerShape } from 'found'; -import DTAutoSuggest from '@digitransit-component/digitransit-component-autosuggest'; -import { filterSearchResultsByMode } from '@digitransit-search-util/digitransit-search-util-query-utils'; -import { configShape } from '../../util/shapes'; -import { withSearchContext } from '../WithSearchContext'; -import { getStopRoutePath } from '../../util/path'; - -const DTAutoSuggestWithSearchContext = withSearchContext(DTAutoSuggest); -const searchSources = ['Favourite', 'History', 'Datasource']; - -function StopsNearYouSearch( - { mode, breakpoint, lang, originLocation }, - { router, config }, -) { - const isMobile = breakpoint !== 'large'; - const transportMode = `route-${mode}`; - - const filter = config.stopSearchFilter - ? (results, transportmode, type) => - filterSearchResultsByMode(results, transportmode, type).filter( - config.stopSearchFilter, - ) - : filterSearchResultsByMode; - const selectHandler = item => { - router.push(getStopRoutePath(item)); - }; - return ( -
-
- -
-
- ); -} - -StopsNearYouSearch.propTypes = { - mode: PropTypes.string.isRequired, - breakpoint: PropTypes.string.isRequired, - lang: PropTypes.string.isRequired, - originLocation: PropTypes.shape({ - address: PropTypes.string, - lat: PropTypes.number, - lon: PropTypes.number, - }), -}; - -StopsNearYouSearch.defaultProps = { - originLocation: {}, -}; - -StopsNearYouSearch.contextTypes = { - router: routerShape.isRequired, - config: configShape.isRequired, -}; - -export default memo(StopsNearYouSearch); diff --git a/app/component/nearyou/UpdateLocationButton.js b/app/component/nearyou/UpdateLocationButton.js new file mode 100644 index 0000000000..1e8f2adb50 --- /dev/null +++ b/app/component/nearyou/UpdateLocationButton.js @@ -0,0 +1,33 @@ +import { FormattedMessage, intlShape } from 'react-intl'; +import React from 'react'; +import PropTypes from 'prop-types'; +import Icon from '../Icon'; + +export default function UpdateLocationButton({ mode, onClick }, { intl }) { + return ( +
+ + +
+ ); +} + +UpdateLocationButton.propTypes = { + mode: PropTypes.string.isRequired, + onClick: PropTypes.func.isRequired, +}; + +UpdateLocationButton.contextTypes = { + intl: intlShape.isRequired, +}; diff --git a/app/component/nearyou/VehicleRentalStationNearYou.js b/app/component/nearyou/VehicleRentalStationNearYou.js index 560c7def59..1c4acdcf67 100644 --- a/app/component/nearyou/VehicleRentalStationNearYou.js +++ b/app/component/nearyou/VehicleRentalStationNearYou.js @@ -1,4 +1,4 @@ -import React, { useEffect } from 'react'; +import React, { useEffect, useRef } from 'react'; import PropTypes from 'prop-types'; import { FormattedMessage } from 'react-intl'; import { Link } from 'found'; @@ -9,27 +9,31 @@ import { PREFIX_BIKESTATIONS } from '../../util/path'; import { isKeyboardSelectionEvent } from '../../util/browser'; import { hasVehicleRentalCode } from '../../util/vehicleRentalUtils'; import { getIdWithoutFeed } from '../../util/feedScopedIdUtils'; -import { relayShape } from '../../util/shapes'; +import { vehicleRentalStationShape, relayShape } from '../../util/shapes'; const VehicleRentalStationNearYou = ({ - stop, + station, relay, currentTime, - currentMode, + isParentTabActive, }) => { + const timeRef = useRef(currentTime); + useEffect(() => { - const { stationId } = stop; - if (currentMode === 'CITYBIKE') { - relay?.refetch( + const { stationId } = station; + if (isParentTabActive && currentTime - timeRef.current > 30) { + relay.refetch( oldVariables => { - return { ...oldVariables, stopId: stationId }; + return { ...oldVariables, stationId }; }, null, null, { force: true }, // query variables stay the same between refetches ); + timeRef.current = currentTime; } - }, [currentTime]); + }, [currentTime, isParentTabActive]); + return (
@@ -44,62 +48,49 @@ const VehicleRentalStationNearYou = ({ e.stopPropagation(); } }} - to={`/${PREFIX_BIKESTATIONS}/${stop.stationId}`} + to={`/${PREFIX_BIKESTATIONS}/${station.stationId}`} > -

{stop.name}

+

{station.name}

- +
); }; + VehicleRentalStationNearYou.propTypes = { - stop: PropTypes.shape({ - capacity: PropTypes.number, - distance: PropTypes.number, - lat: PropTypes.number, - lon: PropTypes.number, - name: PropTypes.string, - rentalNetwork: PropTypes.shape({ - networkId: PropTypes.string, - }), - operative: PropTypes.bool, - stationId: PropTypes.string, - type: PropTypes.string, - availableVehicles: PropTypes.shape({ total: PropTypes.number }), - availableSpaces: PropTypes.shape({ total: PropTypes.number }), - }).isRequired, + station: vehicleRentalStationShape.isRequired, currentTime: PropTypes.number, - currentMode: PropTypes.string, + isParentTabActive: PropTypes.bool, relay: relayShape.isRequired, }; VehicleRentalStationNearYou.defaultProps = { currentTime: undefined, - currentMode: undefined, + isParentTabActive: false, }; const containerComponent = createRefetchContainer( VehicleRentalStationNearYou, { - stop: graphql` - fragment VehicleRentalStationNearYou_stop on VehicleRentalStation { + station: graphql` + fragment VehicleRentalStationNearYou_station on VehicleRentalStation { stationId name availableVehicles { @@ -117,9 +108,9 @@ const containerComponent = createRefetchContainer( `, }, graphql` - query VehicleRentalStationNearYouRefetchQuery($stopId: String!) { - vehicleRentalStation(id: $stopId) { - ...VehicleRentalStationNearYou_stop + query VehicleRentalStationNearYouRefetchQuery($stationId: String!) { + vehicleRentalStation(id: $stationId) { + ...VehicleRentalStationNearYou_station } } `, diff --git a/app/component/nearyou/stops-near-you.scss b/app/component/nearyou/stops-near-you.scss index 838adfd4ac..877a306b9f 100644 --- a/app/component/nearyou/stops-near-you.scss +++ b/app/component/nearyou/stops-near-you.scss @@ -143,19 +143,19 @@ } } - .no-favorites-container { + .no-favourites-container { display: flex; flex-direction: column; text-align: center; padding: 3em 2.5em; border-top: 1px solid #ddd; - .no-favorites-header { + .no-favourites-header { font-size: 0.9375em; margin-bottom: 8px; } - .no-favorites-content { + .no-favourites-content { color: #666; font-size: 0.9375em; padding: 0 2em; @@ -224,8 +224,14 @@ margin: 0 14px 4px; } + .stop-near-you-header-container:has(.bike-station-page-container) { + padding: unset; + } + .stop-near-you-header-container { display: flex; + justify-content: space-between; + padding: 14px 15px 1px 20px; .stop-near-you-name { font-size: 1.125rem; @@ -235,19 +241,30 @@ } .stop-header-content { + width: 100%; + a { text-decoration: none; color: #333; } - .bike-station-code { - font-size: 0.813rem; - font-weight: normal; + .bike-station { + &-code { + font-size: 0.813rem; + font-weight: normal; + } + + &-page-container { + margin: 0; + padding: var(--space-s) var(--space-m); + } + + &-header { + padding-top: 0; + } } } - padding: 14px 15px 1px 20px; - .stop-near-you-info { display: flex; margin-bottom: 5px; @@ -300,12 +317,10 @@ .stop-favourite-container { padding-top: 8px; - margin-left: auto; } .bike-rental-favourite-container { padding-top: 8px; - margin-left: auto; } } @@ -437,7 +452,7 @@ text-decoration: none; font-weight: 100; white-space: pre-wrap; - background-color: #dc0451; + background-color: $disruption-color; color: white; font-size: 0.9375rem; padding: 12px 0 5px 0; @@ -576,12 +591,12 @@ } } - .no-favorites-container { + .no-favourites-container { padding-top: 14px; font-size: 16px; border-top: none; - .no-favorites-content { + .no-favourites-content { padding: 0; } diff --git a/app/component/routepage/RouteControlPanel.js b/app/component/routepage/RouteControlPanel.js index b83e665307..92eb05a2d7 100644 --- a/app/component/routepage/RouteControlPanel.js +++ b/app/component/routepage/RouteControlPanel.js @@ -409,7 +409,10 @@ class RouteControlPanel extends React.Component { let disruptionIcon; if (disruptionClassName === 'active-disruption-alert') { disruptionIcon = ( - + ); } else if (disruptionClassName === 'active-service-alert') { disruptionIcon = ; diff --git a/app/config.js b/app/config.js index 8d8a7d102b..4e232da7d1 100644 --- a/app/config.js +++ b/app/config.js @@ -1,9 +1,9 @@ import fs from 'fs'; import path from 'path'; import cloneDeep from 'lodash/cloneDeep'; - import defaultConfig from './configurations/config.default'; import configMerger from './util/configMerger'; +import { LightenDarkenColor } from './util/colorUtils'; import { boundWithMinimumAreaSimple } from './util/geo-utils'; const configs = {}; // cache merged configs for speed @@ -121,6 +121,12 @@ export function getNamedConfiguration(configName) { config.searchParams = config.searchParams || {}; config.searchParams['boundary.polygon'] = pointsParam; } + if (!config.colors.accessiblePrimary) { + config.colors.accessiblePrimary = config.colors.primary; + } + if (!config.colors.hover) { + config.colors.hover = LightenDarkenColor(config.colors.primary, -20); + } Object.keys(config.modePolygons).forEach(mode => { const boundingBoxes = []; diff --git a/app/configurations/config.default.js b/app/configurations/config.default.js index 5a4ce6130a..df63781f0d 100644 --- a/app/configurations/config.default.js +++ b/app/configurations/config.default.js @@ -163,15 +163,15 @@ export default { minimalRegexp: /.{2,}/, }, - nearbyRoutes: { + nearYouRoutes: { radius: 10000, bucketSize: 1000, }, omitNonPickups: true, - maxNearbyStopAmount: 5, - maxNearbyStopRefetches: 5, - maxNearbyStopDistance: { + maxNearYouCount: 5, + maxNearYouRefetches: 5, + maxNearYouDistance: { favorite: 20000, bus: 50000, tram: 20000, @@ -180,6 +180,8 @@ export default { ferry: 50000, citybike: 20000, airplane: 100000, + bikepark: 10000, + carpark: 50000, }, defaultSettings: { @@ -344,7 +346,7 @@ export default { sv: 'Köp ett abonnemang för en dag, en vecka eller för en hel säsong', en: 'Buy a daily, weekly or season pass', }, - maxNearbyRentalVehicleAmount: 5, + maxNearYouRentalVehicleAmount: 5, maxDistanceToRentalVehiclesInMeters: 100, maxMinutesToRentalJourneyStart: 60, maxMinutesToRentalJourneyEnd: 720, @@ -371,21 +373,22 @@ export default { colors: { primary: '#000F94', + caution: '#dc0451', backgroundInfo: '#ebf6fd', - iconColors: { - 'mode-airplane': '#0046ad', - 'mode-bus': '#007ac9', - 'mode-tram': '#008151', - 'mode-subway': '#CA4000', - 'mode-rail': '#8c4799', - 'mode-ferry': '#007A97', - 'mode-ferry-external': '#666666', - 'mode-citybike': '#f2b62d', - 'mode-citybike-secondary': '#333333', - 'mode-scooter': '#C5CAD2', - 'mode-taxi': '#647693', - 'mode-replacement-bus': '#DC0451', - }, + airplane: '#0046ad', + bus: '#007ac9', + 'replacement-bus': '#dc0451', + tram: '#008151', + subway: '#ca4000', + rail: '#8c4799', + ferry: '#007a97', + 'ferry-external': '#666666', + citybike: '#f2b62d', + 'citybike-secondary': '#333333', + scooter: '#c5cad2', + taxi: '#647693', + bikepark: '#f2b62d', + carpark: '#007ac9', }, iconModeSet: 'digitransit', fontWeights: { @@ -748,12 +751,11 @@ export default { vehicles: false, showVehiclesOnStopPage: false, + showVehiclesOnItineraryPage: false, trafficNowLink: '', timetables: {}, - showVehiclesOnItineraryPage: false, - showWeatherInformation: true, showBikeAndParkItineraries: false, diff --git a/app/configurations/config.hameenlinna.js b/app/configurations/config.hameenlinna.js index b3602f0ed3..cfbb47e44b 100644 --- a/app/configurations/config.hameenlinna.js +++ b/app/configurations/config.hameenlinna.js @@ -15,9 +15,7 @@ export default configMerger(walttiConfig, { colors: { primary: 'rgb(196,40,31)', - iconColors: { - 'mode-bus': 'rgb(196,40,31)', - }, + bus: 'rgb(196,40,31)', }, socialMedia: { @@ -137,9 +135,6 @@ export default configMerger(walttiConfig, { 7: 'G', }, - vehicles: true, - showVehiclesOnStopPage: true, - showVehiclesOnItineraryPage: true, zones: { stops: true, itinerary: true, diff --git a/app/configurations/config.hsl.js b/app/configurations/config.hsl.js index 5d246b2e22..aabf23f21f 100644 --- a/app/configurations/config.hsl.js +++ b/app/configurations/config.hsl.js @@ -108,11 +108,6 @@ export default { loginAnalyticsEventName: 'user-hsl-id', loginAnalyticsKey: 'hsl-id', - nearbyRoutes: { - radius: 500, - bucketSize: 100, - }, - defaultSettings: { walkSpeed: 1.28, showBikeAndParkItineraries: true, @@ -155,11 +150,9 @@ export default { primary: '#0074bf', accessiblePrimary: '#0074be', hover: '#0062a1', - iconColors: { - 'mode-bus-express': '#CA4000', - 'mode-bus-local': '#007ac9', - 'mode-speedtram': '#007E79', - }, + 'bus-express': '#CA4000', + 'bus-local': '#007ac9', + speedtram: '#007E79', }, getAutoSuggestIcons: { citybikes: station => { @@ -169,7 +162,7 @@ export default { return ['citybike-stop-default', '#f2b62d']; }, }, - iconModeSet: 'default', + iconModeSet: 'hsl', fontWeights: { medium: 500, }, @@ -335,20 +328,6 @@ export default { en: 'HSL', }, - maxNearbyStopDistance: { - favorite: 20000, - bus: 20000, - tram: 20000, - subway: 20000, - rail: 20000, - ferry: 20000, - citybike: 20000, - }, - - prioritizedStopsNearYou: { - ferry: ['HSL:1030701'], - }, - showTicketSelector: false, staticMessages: [ @@ -570,6 +549,22 @@ export default { 'citybike', ], narrowNearYouButtons: true, + nearYouRoutes: { + radius: 500, + bucketSize: 100, + }, + maxNearYouDistance: { + favorite: 20000, + bus: 20000, + tram: 20000, + subway: 20000, + rail: 20000, + ferry: 20000, + citybike: 20000, + }, + prioritizedStopsNearYou: { + ferry: ['HSL:1030701'], + }, hostnames: [ // DEV hostnames diff --git a/app/configurations/config.joensuu.js b/app/configurations/config.joensuu.js index f775a9b968..447f0746b4 100644 --- a/app/configurations/config.joensuu.js +++ b/app/configurations/config.joensuu.js @@ -28,10 +28,8 @@ export default configMerger(walttiConfig, { colors: { primary: '#5c4696', - iconColors: { - 'mode-bus': '#009fe3', - 'mode-rail': '#64be14', - }, + bus: '#009fe3', + rail: '#64be14', }, socialMedia: { @@ -88,10 +86,6 @@ export default configMerger(walttiConfig, { lon: 29.7569847, }, - vehicles: true, - showVehiclesOnStopPage: true, - showVehiclesOnItineraryPage: true, - aboutThisService: { fi: [ { diff --git a/app/configurations/config.jyvaskyla.js b/app/configurations/config.jyvaskyla.js index 90d2513441..3d4f0d2881 100644 --- a/app/configurations/config.jyvaskyla.js +++ b/app/configurations/config.jyvaskyla.js @@ -41,9 +41,7 @@ export default configMerger(walttiConfig, { colors: { primary: '#7DC02D', - iconColors: { - 'mode-bus': '#7DC02D', - }, + bus: '#7DC02D', }, socialMedia: { @@ -63,10 +61,6 @@ export default configMerger(walttiConfig, { // Navbar logo logo: 'jyvaskyla/jyvaskyla-favicon.png', - vehicles: true, - showVehiclesOnStopPage: true, - showVehiclesOnItineraryPage: true, - mainMenu: { stopMonitor: { show: true, @@ -180,8 +174,7 @@ export default configMerger(walttiConfig, { stops: true, itinerary: true, }, - // Notice! Turning on this setting forces the search for car routes (for the CO2 comparison only). - showCO2InItinerarySummary: true, + sendAnalyticsCustomEventGoals: true, defaultSettings: { diff --git a/app/configurations/config.kela.js b/app/configurations/config.kela.js index f217b4a0d9..11435af030 100644 --- a/app/configurations/config.kela.js +++ b/app/configurations/config.kela.js @@ -151,12 +151,7 @@ export default { }, staticMessagesUrl: process.env.STATIC_MESSAGE_URL, - showNearYouButtons: false, - showVehiclesOnStopPage: false, - showVehiclesOnItineraryPage: false, includeCarSuggestions: true, - // Notice! Turning on this setting forces the search for car routes (for the CO2 comparison only). - showCO2InItinerarySummary: false, useAssembledGeoJsonZones: 'isOnByDefault', locationSearchTargetsFromOTP: [], // remove stop/station location search }; diff --git a/app/configurations/config.kotka.js b/app/configurations/config.kotka.js index 738face925..5774bc65d2 100644 --- a/app/configurations/config.kotka.js +++ b/app/configurations/config.kotka.js @@ -17,19 +17,12 @@ export default configMerger(walttiConfig, { colors: { primary: '#0001FF', - iconColors: { - 'mode-bus': '#0001FF', - }, + bus: '#0001FF', }, transportModes: { bus: { availableForSelection: true, defaultValue: true, - nearYouLabel: { - fi: 'Lähipysäkit kartalla', - sv: 'Hållplatser på kartan', - en: 'Nearby stops on map', - }, }, citybike: { availableForSelection: true, @@ -160,9 +153,6 @@ export default configMerger(walttiConfig, { 1: 'A', 2: 'B', }, - vehicles: true, - showVehiclesOnStopPage: true, - showVehiclesOnItineraryPage: true, zones: { stops: true, itinerary: true, diff --git a/app/configurations/config.kouvola.js b/app/configurations/config.kouvola.js index 17f810cbe7..8d1dcc53ac 100644 --- a/app/configurations/config.kouvola.js +++ b/app/configurations/config.kouvola.js @@ -21,19 +21,12 @@ export default configMerger(walttiConfig, { colors: { primary: '#000000', - iconColors: { - 'mode-bus': '#000000', - }, + bus: '#000000', }, transportModes: { bus: { availableForSelection: true, defaultValue: true, - nearYouLabel: { - fi: 'Lähipysäkit kartalla', - sv: 'Hållplatser på kartan', - en: 'Nearby stops on map', - }, }, citybike: { availableForSelection: true, @@ -115,10 +108,6 @@ export default configMerger(walttiConfig, { lon: 26.705328946745546, }, - vehicles: true, - showVehiclesOnStopPage: true, - showVehiclesOnItineraryPage: true, - menu: { copyright: { label: `© Kouvola ${walttiConfig.YEAR}` }, content: [ diff --git a/app/configurations/config.kuopio.js b/app/configurations/config.kuopio.js index 38f7469343..dd4605a753 100644 --- a/app/configurations/config.kuopio.js +++ b/app/configurations/config.kuopio.js @@ -13,10 +13,8 @@ export default configMerger(walttiConfig, { colors: { primary: '#0ab1c8', - iconColors: { - 'mode-bus': '#724f9f', - 'mode-rail': '#0E7F3C', - }, + bus: '#724f9f', + rail: '#0E7F3C', }, socialMedia: { @@ -71,10 +69,6 @@ export default configMerger(walttiConfig, { lon: 27.678136, }, - vehicles: true, - showVehiclesOnStopPage: true, - showVehiclesOnItineraryPage: true, - vehicleRental: { networks: { freebike_kuopio: { diff --git a/app/configurations/config.lahti.js b/app/configurations/config.lahti.js index 81e5d0c8d2..5105b875da 100644 --- a/app/configurations/config.lahti.js +++ b/app/configurations/config.lahti.js @@ -17,9 +17,7 @@ export default configMerger(walttiConfig, { appBarLink: { name: 'LSL.fi', href: 'http://www.lsl.fi/' }, colors: { primary: '#0066B3', - iconColors: { - 'mode-bus': '#0066B3', - }, + bus: '#0066B3', }, socialMedia: { @@ -142,10 +140,6 @@ export default configMerger(walttiConfig, { itinerary: true, }, - vehicles: true, - showVehiclesOnStopPage: true, - showVehiclesOnItineraryPage: true, - transportModes: { citybike: { availableForSelection: true, diff --git a/app/configurations/config.lappeenranta.js b/app/configurations/config.lappeenranta.js index 8ca5562106..0a17867804 100644 --- a/app/configurations/config.lappeenranta.js +++ b/app/configurations/config.lappeenranta.js @@ -13,9 +13,7 @@ export default configMerger(walttiConfig, { colors: { primary: '#d4007a', - iconColors: { - 'mode-bus': '#d4007a', - }, + bus: '#d4007a', }, socialMedia: { @@ -153,10 +151,6 @@ export default configMerger(walttiConfig, { lon: 28.18572, }, - vehicles: true, - showVehiclesOnStopPage: true, - showVehiclesOnItineraryPage: true, - menu: { copyright: { label: `© Lappeenranta ${walttiConfig.YEAR}` }, content: [ diff --git a/app/configurations/config.matka.js b/app/configurations/config.matka.js index 9addbeb2d7..d201f2e1ae 100644 --- a/app/configurations/config.matka.js +++ b/app/configurations/config.matka.js @@ -61,11 +61,9 @@ export default { colors: { primary: '#000', - iconColors: { - 'mode-tram': '#5E7921', - 'mode-rail': '#000', - 'mode-ferry': '#247C7B', - }, + tram: '#5E7921', + rail: '#000', + ferry: '#247C7B', }, feedIds: IS_DEV ? ['MATKA'] diff --git a/app/configurations/config.mikkeli.js b/app/configurations/config.mikkeli.js index 1da7685107..b089a0abfb 100644 --- a/app/configurations/config.mikkeli.js +++ b/app/configurations/config.mikkeli.js @@ -20,19 +20,12 @@ export default configMerger(walttiConfig, { colors: { primary: '#167CAC', - iconColors: { - 'mode-bus': '#167CAC', - }, + bus: '#167CAC', }, transportModes: { bus: { availableForSelection: true, defaultValue: true, - nearYouLabel: { - fi: 'Lähipysäkit kartalla', - sv: 'Hållplatser på kartan', - en: 'Nearby stops on map', - }, }, }, socialMedia: { @@ -127,8 +120,4 @@ export default configMerger(walttiConfig, { stops: true, itinerary: true, }, - - vehicles: true, - showVehiclesOnStopPage: true, - showVehiclesOnItineraryPage: true, }); diff --git a/app/configurations/config.oulu.js b/app/configurations/config.oulu.js index b0d2e85649..9884a404c0 100644 --- a/app/configurations/config.oulu.js +++ b/app/configurations/config.oulu.js @@ -25,9 +25,7 @@ export default configMerger(walttiConfig, { colors: { primary: '#e10669', - iconColors: { - 'mode-bus': '#e10669', - }, + bus: '#e10669', }, socialMedia: { @@ -118,10 +116,6 @@ export default configMerger(walttiConfig, { ], }, - vehicles: true, - showVehiclesOnStopPage: true, - showVehiclesOnItineraryPage: true, - aboutThisService: { fi: [ { diff --git a/app/configurations/config.pori.js b/app/configurations/config.pori.js index c6f82b2077..a021c2bbf7 100644 --- a/app/configurations/config.pori.js +++ b/app/configurations/config.pori.js @@ -17,9 +17,7 @@ export default configMerger(walttiConfig, { colors: { primary: '#1f1f66', - iconColors: { - 'mode-bus': '#1f1f66', - }, + bus: '#1f1f66', }, socialMedia: { @@ -91,10 +89,6 @@ export default configMerger(walttiConfig, { ], }, - vehicles: true, - showVehiclesOnStopPage: true, - showVehiclesOnItineraryPage: true, - aboutThisService: { fi: [ { diff --git a/app/configurations/config.raasepori.js b/app/configurations/config.raasepori.js index 04cd04ceb5..049242465f 100644 --- a/app/configurations/config.raasepori.js +++ b/app/configurations/config.raasepori.js @@ -21,9 +21,7 @@ export default configMerger(walttiConfig, { colors: { primary: '#5B7B32', - iconColors: { - 'mode-bus': '#5B7B32', - }, + bus: '#5B7B32', }, socialMedia: { @@ -95,11 +93,6 @@ export default configMerger(walttiConfig, { }, ], }, - - vehicles: true, - showVehiclesOnStopPage: true, - showVehiclesOnItineraryPage: true, - aboutThisService: { fi: [ { diff --git a/app/configurations/config.rovaniemi.js b/app/configurations/config.rovaniemi.js index 8c7df26ebb..cd9f8b784c 100644 --- a/app/configurations/config.rovaniemi.js +++ b/app/configurations/config.rovaniemi.js @@ -17,9 +17,7 @@ export default configMerger(walttiConfig, { colors: { primary: '#34B233', - iconColors: { - 'mode-bus': '#34B233', - }, + bus: '#34B233', }, socialMedia: { title: APP_TITLE, @@ -85,9 +83,6 @@ export default configMerger(walttiConfig, { }, ], }, - vehicles: true, - showVehiclesOnStopPage: true, - showVehiclesOnItineraryPage: true, zoneIdMapping: { 1: 'A', 2: 'B', diff --git a/app/configurations/config.tampere.js b/app/configurations/config.tampere.js index 96a0ac90f7..cd5986d5aa 100644 --- a/app/configurations/config.tampere.js +++ b/app/configurations/config.tampere.js @@ -24,11 +24,9 @@ export default configMerger(walttiConfig, { colors: { primary: '#1c57cf', - iconColors: { - 'mode-bus': '#1A4A8F', - 'mode-rail': '#0E7F3C', - 'mode-tram': '#DA2128', - }, + bus: '#1A4A8F', + rail: '#0E7F3C', + tram: '#DA2128', }, socialMedia: { @@ -246,8 +244,6 @@ export default configMerger(walttiConfig, { ], }, - staticMessages: [], - aboutThisService: { fi: [ { @@ -278,9 +274,6 @@ export default configMerger(walttiConfig, { }, ], }, - vehicles: true, - showVehiclesOnStopPage: true, - showVehiclesOnItineraryPage: true, timetables: { tampere: tampereTimetables, }, diff --git a/app/configurations/config.turku.js b/app/configurations/config.turku.js index 948c54950a..f497e58a6d 100644 --- a/app/configurations/config.turku.js +++ b/app/configurations/config.turku.js @@ -44,12 +44,10 @@ export default configMerger(walttiConfig, { colors: { primary: '#e8aa27', hover: '#a07415', - iconColors: { - 'mode-bus': '#e8aa27', - 'mode-rail': '#8c4799', - 'mode-ferry': '#0064f0', - 'mode-funicular': '#ff00ff', - }, + bus: '#e8aa27', + rail: '#8c4799', + ferry: '#0064f0', + funicular: '#ff00ff', }, appBarLink: { name: 'Föli', href: 'http://www.foli.fi/fi' }, @@ -171,10 +169,6 @@ export default configMerger(walttiConfig, { lon: 22.267633, }, - vehicles: true, - showVehiclesOnStopPage: true, - showVehiclesOnItineraryPage: true, - aboutThisService: { fi: [ { @@ -204,13 +198,10 @@ export default configMerger(walttiConfig, { ], }, - staticMessages: [], geoJson: { layerConfigUrl: 'https://data.foli.fi/geojson/reittiopas', }, - showNearYouButtons: true, - allowLogin: false, constantOperationStops: { 'FUNI:9900': CONSTANT_OPERATION_PARAGRAPHS.fori, 'FUNI:9901': CONSTANT_OPERATION_PARAGRAPHS.fori, diff --git a/app/configurations/config.vaasa.js b/app/configurations/config.vaasa.js index c3f004737c..c90c36da09 100644 --- a/app/configurations/config.vaasa.js +++ b/app/configurations/config.vaasa.js @@ -25,9 +25,7 @@ export default configMerger(walttiConfig, { colors: { primary: '#000a8c', - iconColors: { - 'mode-bus': '#000a8c', - }, + bus: '#000a8c', }, socialMedia: { @@ -132,10 +130,6 @@ export default configMerger(walttiConfig, { ], }, - vehicles: true, - showVehiclesOnStopPage: true, - showVehiclesOnItineraryPage: true, - stopCard: { header: { virtualMonitorBaseUrl, diff --git a/app/configurations/config.varely.js b/app/configurations/config.varely.js index 92c161fb1c..1fb931ede8 100644 --- a/app/configurations/config.varely.js +++ b/app/configurations/config.varely.js @@ -37,10 +37,8 @@ export default configMerger(walttiConfig, { colors: { primary: colorPrimary, hover: '#00BF6F', - iconColors: { - 'mode-bus': colorPrimary, - 'mode-ferry': '#0064f0', - }, + bus: colorPrimary, + ferry: '#0064f0', }, appBarLink: { name: 'Seutu+', href: 'https://seutuplus.fi/' }, @@ -125,8 +123,6 @@ export default configMerger(walttiConfig, { /* Enable real-time map layer for vehicle positions */ vehicles: false, viaPointsEnabled: false, - showVehiclesOnStopPage: true, - showVehiclesOnItineraryPage: true, aboutThisService: { fi: [ @@ -185,10 +181,6 @@ export default configMerger(walttiConfig, { }, }, - staticMessages: [], - showCO2InItinerarySummary: true, - showNearYouButtons: true, - allowLogin: false, routeNotifications: [], analyticsScript: '', GTMid: null, diff --git a/app/configurations/config.waltti.js b/app/configurations/config.waltti.js index 10596fedb8..dc8a8ea2ca 100644 --- a/app/configurations/config.waltti.js +++ b/app/configurations/config.waltti.js @@ -60,77 +60,45 @@ export default { availableLanguages: ['fi', 'sv', 'en'], defaultLanguage: 'fi', + vehicles: true, + showVehiclesOnStopPage: true, + showVehiclesOnItineraryPage: true, showCO2InItinerarySummary: true, transportModes: { bus: { availableForSelection: true, defaultValue: true, - nearYouLabel: { - fi: 'Bussit ja lähipysäkit kartalla', - sv: 'Bussar och hållplatser på kartan', - en: 'Buses and nearby stops on map', - }, }, rail: { availableForSelection: false, defaultValue: false, - nearYouLabel: { - fi: 'Junat ja lähiasemat kartalla', - sv: 'Tåg och stationer på kartan', - en: 'Trains and nearby stations on map', - }, }, tram: { availableForSelection: false, defaultValue: false, - nearYouLabel: { - fi: 'Raitiovaunut ja lähipysäkit kartalla', - sv: 'Spårvagnar och hållplatser på kartan', - en: 'Trams and nearby stops on map', - }, }, subway: { availableForSelection: false, defaultValue: false, - nearYouLabel: { - fi: 'Metrot ja lähiasemat kartalla', - sv: 'Metro och stationer på kartan', - en: 'Metro and nearby stations on map', - }, }, citybike: { availableForSelection: false, defaultValue: false, - nearYouLabel: { - fi: 'Lähimmät kaupunkipyöräasemat', - sv: 'Närmaste cykelstationer', - en: 'The closest city bike stations', - }, }, airplane: { availableForSelection: false, defaultValue: false, - nearYouLabel: { - fi: 'Lähimmät lentoasemat', - sv: 'Närmaste flygplatser', - en: 'The closest airports', - }, }, ferry: { availableForSelection: false, defaultValue: false, - nearYouLabel: { - fi: 'Lähimmät lauttalaiturit', - sv: 'Närmaste färjekajer', - en: 'The closest ferry piers', - }, }, funicular: { @@ -144,10 +112,14 @@ export default { }, }, + showNearYouButtons: true, + nearYouTitle: { + fi: 'Aikataulut ja linjat', + sv: 'Tidtabeller och linjer', + en: 'Timetables and routes', + }, nearYouModes: ['bus'], - nearbyModeSet: 'waltti', - - maxNearbyStopDistance: { + maxNearYouDistance: { bus: 30000, tram: 30000, rail: 50000, @@ -173,19 +145,6 @@ export default { }, }, - showNearYouButtons: true, - nearYouButton: { - borderRadius: '50%', - color: '#000F94', - }, - nearYouTitle: { - fi: 'Aikataulut ja linjat', - sv: 'Tidtabeller och linjer', - en: 'Timetables and routes', - }, - - allowLogin: false, - messageBarAlerts: true, includeCarSuggestions: true, diff --git a/app/configurations/config.walttiOpas.js b/app/configurations/config.walttiOpas.js index a12c2ff177..f0f64f3f37 100644 --- a/app/configurations/config.walttiOpas.js +++ b/app/configurations/config.walttiOpas.js @@ -13,19 +13,12 @@ export default configMerger(walttiConfig, { colors: { primary: '#5959a8', topBarColor: '#17083b', - iconColors: { - 'mode-bus': '#5959a8', - }, + bus: '#5959a8', }, transportModes: { bus: { availableForSelection: true, defaultValue: true, - nearYouLabel: { - fi: 'Bussit ja lähipysäkit kartalla', - sv: 'Bussar och hållplatser på kartan', - en: 'Buses and nearby stops on map', - }, }, }, @@ -102,8 +95,6 @@ export default configMerger(walttiConfig, { }, viaPointsEnabled: false, - showVehiclesOnStopPage: true, - showVehiclesOnItineraryPage: true, sourceForAlertsAndDisruptions: { Kajaani: { diff --git a/app/store/FavouriteStore.js b/app/store/FavouriteStore.js index 3d314323fa..8dd4b98c5b 100644 --- a/app/store/FavouriteStore.js +++ b/app/store/FavouriteStore.js @@ -37,6 +37,8 @@ function mapToStore(favourites) { ); } +const locationTypes = ['station', 'stop', 'place', 'bikeStation']; + export default class FavouriteStore extends Store { static storeName = 'FavouriteStore'; @@ -57,6 +59,7 @@ export default class FavouriteStore extends Store { this.config = dispatcher.getContext().config; if (!this.config.allowLogin) { this.favourites = mapFromStore(getFavouriteStorage()); + this.status = FavouriteStore.STATUS_HAS_DATA; } else { this.status = FavouriteStore.STATUS_FETCHING_OR_UPDATING; } @@ -168,6 +171,16 @@ export default class FavouriteStore extends Store { ); } + getLocationCount() { + let cnt = 0; + this.favourites.forEach(favourite => { + if (locationTypes.includes(favourite.type)) { + cnt += 1; + } + }); + return cnt; + } + /** * Merges array of favourites with favourites from localstorage and returns uniques by favouriteId and gtfsId. * If there are duplicates by favouriteId or gtfsId, newer one is saved (by lastUpdated field) diff --git a/app/translations.js b/app/translations.js index b18094f85f..07603934bf 100644 --- a/app/translations.js +++ b/app/translations.js @@ -519,6 +519,7 @@ const translations = { 'more-settings': 'Erweiterte Einstellungen', 'move-on-map': 'Position auf der Karte hat sich geändert', navigate: 'Navigieren', + 'near-you-search': 'Suche nach Haltestellen oder Linien', nearest: '{ mode } in der Nähe', 'nearest-stops': 'Nächstgelegene Haltestellen', 'nearest-stops-bus': 'Nächstgelegene Bushaltestellen', @@ -713,7 +714,6 @@ const translations = { 'Sie haben die Standortabfrage nicht freigegeben.', 'stop-near-you-modal-info': 'Zur Nutzung der Suche nach Haltestellen in der Nähe wird Zugriff auf die Standortabfrage benötigt.', - 'stop-near-you-title': 'Suche nach Haltestellen oder Linien', 'stop-number': 'Haltestellennummer', 'stop-page.description': 'Haltestelle - {name} {code}, {desc}', 'stop-page.title': 'Haltestelle - {name} {code}', @@ -1370,16 +1370,19 @@ const translations = { 'Departs at {time} from {stopName} {stopOrStation}', 'navileg-start-schedule': '{mode} {route} scheduled departure {time}', 'navileg-walk': 'Walk to', + 'near-you-search': 'Search for stops and routes', nearest: '{ mode } near you', - 'nearest-favorites': 'Stops nearby me', - 'nearest-favorites-browse-stops': 'Browse and select stops', - 'nearest-favorites-no-favorites': + 'nearest-favourites': 'Stops nearby me', + 'nearest-favourites-browse-stops': 'Browse and select stops', + 'nearest-favourites-no-favourites': 'Timetables for the selected stops and vehicles on map', 'nearest-no-stops': 'There are no stops or stations for the selected mode of transport nearby.', 'nearest-stops': 'The closest stops', 'nearest-stops-airplane': 'airports', + 'nearest-stops-bikepark': 'bike parking', 'nearest-stops-bus': 'bus stops', + 'nearest-stops-carpark': 'car parking', 'nearest-stops-citybike': 'bike stations', 'nearest-stops-favorite': 'stops nearby me', 'nearest-stops-ferry': 'ferry piers', @@ -1668,7 +1671,6 @@ const translations = { 'stop-near-you-modal-header': 'You have not enabled location services', 'stop-near-you-modal-info': 'Using the nearby stops function requires location access.', - 'stop-near-you-title': 'Search for stops and routes', 'stop-near-you-update-alert': 'Nearest stops updated', 'stop-number': 'Stop number', 'stop-page.description': 'Stop {name} - {code}', @@ -2695,16 +2697,19 @@ const translations = { 'navileg-start-schedule': '{mode} {route} aikataulun mukainen lähtö klo {time}', 'navileg-walk': 'Kävele', + 'near-you-search': 'Linja- ja pysäkkihaku', nearest: 'Lähimmät {mode}', - 'nearest-favorites': 'Omat lähipysäkit', - 'nearest-favorites-browse-stops': 'Selaa ja valitse pysäkkejä', - 'nearest-favorites-no-favorites': + 'nearest-favourites': 'Omat lähipysäkit', + 'nearest-favourites-browse-stops': 'Selaa ja valitse pysäkkejä', + 'nearest-favourites-no-favourites': 'Valitsemiesi pysäkkien aikataulut ja ajoneuvot kartalla', 'nearest-no-stops': 'Valitun liikennevälineen asemia tai pysäkkejä ei ole lähialueella.', 'nearest-stops': 'Lähimmät pysäkit', 'nearest-stops-airplane': 'lentoasemat', + 'nearest-stops-bikepark': 'pyöräparkit', 'nearest-stops-bus': 'bussipysäkit', + 'nearest-stops-carpark': 'autoparkit', 'nearest-stops-citybike': 'pyöräasemat', 'nearest-stops-favorite': 'omat lähipysäkit', 'nearest-stops-ferry': 'lauttalaiturit', @@ -2990,7 +2995,6 @@ const translations = { 'stop-near-you-modal-header': 'Et ole sallinut paikannusta', 'stop-near-you-modal-info': 'Lähipysäkkien käyttö edellyttää tietoa sijainnista.', - 'stop-near-you-title': 'Linja- ja pysäkkihaku', 'stop-near-you-update-alert': 'Lähimmät pysäkit päivitetty', 'stop-number': 'Pysäkkinumero', 'stop-page.description': 'Pysäkki - {name} {code}, {desc}', @@ -4205,10 +4209,11 @@ const translations = { 'move-on-map': 'Rozglądaj się po mapie', 'move-to-tab': 'Przejdź do karty {number}', navigate: 'Nawiguj', + 'near-you-search': 'Szukaj przystanków i tras', nearest: '{ mode } w Twojej okolicy', - 'nearest-favorites': 'Przystanki w pobliżu', - 'nearest-favorites-browse-stops': 'Przeglądaj i wybieraj przystanki', - 'nearest-favorites-no-favorites': + 'nearest-favourites': 'Przystanki w pobliżu', + 'nearest-favourites-browse-stops': 'Przeglądaj i wybieraj przystanki', + 'nearest-favourites-no-favourites': 'Rozkłady jazdy dla wybranych przystanków i pojazdów na mapie', 'nearest-no-stops': 'Brak przystanków lub stacji dla zaznaczonego rodzaju transportu w pobliżu.', @@ -4475,7 +4480,6 @@ const translations = { 'stop-near-you-modal-header': 'Nie masz włączonych usług lokalizacji', 'stop-near-you-modal-info': 'Korzystanie z funkcji najbliższych przystanków wymaga włączenia dostępu do lokalizacji.', - 'stop-near-you-title': 'Szukaj przystanków i tras', 'stop-near-you-update-alert': 'Zaktualizowano najbliższe przystanki', 'stop-number': 'Numer przystanku', 'stop-page.description': 'Przystanek {name} - {code}', @@ -5649,16 +5653,19 @@ const translations = { 'Avgår klockan {time} från {stopName} {stopOrStation}', 'navileg-start-schedule': '{mode} {route} avgång enligt tidtabell {time}', 'navileg-walk': 'Gå till', + 'near-you-search': 'Sök hållplatser och linjer', nearest: 'Närmaste { mode }', - 'nearest-favorites': 'Hållplatser nära mig', - 'nearest-favorites-browse-stops': 'Bläddra och välj hållplatser', - 'nearest-favorites-no-favorites': + 'nearest-favourites': 'Hållplatser nära mig', + 'nearest-favourites-browse-stops': 'Bläddra och välj hållplatser', + 'nearest-favourites-no-favourites': 'Tidtabeller och fordon vid de valda hållplatserna på kartan', 'nearest-no-stops': 'Inga stationer eller hållplatser för det valda trafikfordont i närheten.', 'nearest-stops': 'Närliggande hållplatser', 'nearest-stops-airplane': 'flygplatser', + 'nearest-stops-bikepark': 'cykelparkering', 'nearest-stops-bus': 'busshållplatser', + 'nearest-stops-carpark': 'anslutningsparkering', 'nearest-stops-citybike': 'cykelstationer', 'nearest-stops-favorite': 'hållplatser nära mig', 'nearest-stops-ferry': 'färjekajer', @@ -5951,7 +5958,6 @@ const translations = { 'stop-near-you-modal-header': 'Du har inte aktiverat positionering', 'stop-near-you-modal-info': 'Användning av funktion ”hållplatserna nära dig” förutsätter information om din position.', - 'stop-near-you-title': 'Sök hållplatser och linjer', 'stop-near-you-update-alert': 'Närliggande hållplatser uppdaterade', 'stop-number': 'Hållplatsnummer', 'stop-page.description': 'Hållplats {name} - {code}', diff --git a/app/util/colorUtils.js b/app/util/colorUtils.js index 8be859ca3d..ef360e3919 100644 --- a/app/util/colorUtils.js +++ b/app/util/colorUtils.js @@ -45,8 +45,5 @@ export function LightenDarkenColor(color, amt) { /* map extended route mode to color */ export function getModeIconColor(config, mode) { - return ( - config.colors.iconColors[`mode-${mode.toLowerCase()}`] || - config.colors.primary - ); + return config.colors[mode.toLowerCase()] || config.colors.primary; } diff --git a/app/util/legUtils.js b/app/util/legUtils.js index 8058a877f4..d46e0a3b7e 100644 --- a/app/util/legUtils.js +++ b/app/util/legUtils.js @@ -555,7 +555,7 @@ export function getVehicleAvailabilityIndicatorColor(available, config) { return ( // eslint-disable-next-line no-nested-ternary available === 0 - ? '#DC0451' + ? config.colors.caution : available > config.vehicleRental.fewAvailableCount ? '#3B7F00' : '#FCBC19' diff --git a/app/util/mapIconUtils.js b/app/util/mapIconUtils.js index 789ad693bd..bc1b31429d 100644 --- a/app/util/mapIconUtils.js +++ b/app/util/mapIconUtils.js @@ -482,7 +482,7 @@ export function drawHybridStopIcon( if (!styles) { return; } - const { iconColors } = config.colors; + const { colors } = config; const { style } = styles; let { width, height } = styles; width *= tile.scaleratio; @@ -500,7 +500,7 @@ export function drawHybridStopIcon( tile.ctx.arc(x, y, radiusOuter * tile.scaleratio, 0, FULL_CIRCLE); tile.ctx.fill(); tile.ctx.beginPath(); - tile.ctx.fillStyle = iconColors['mode-tram']; + tile.ctx.fillStyle = colors.tram; tile.ctx.arc(x, y, (radiusOuter - 1) * tile.scaleratio, 0, FULL_CIRCLE); tile.ctx.fill(); // inner icon @@ -509,8 +509,7 @@ export function drawHybridStopIcon( tile.ctx.arc(x, y, radiusInner * tile.scaleratio, 0, FULL_CIRCLE); tile.ctx.fill(); tile.ctx.beginPath(); - tile.ctx.fillStyle = - iconColors[hasTrunkRoute ? 'mode-bus-express' : 'mode-bus']; + tile.ctx.fillStyle = colors[hasTrunkRoute ? 'bus-express' : 'bus']; tile.ctx.arc(x, y, (radiusInner - 0.5) * tile.scaleratio, 0, FULL_CIRCLE); tile.ctx.fill(); /* eslint-enable no-param-reassign */ diff --git a/app/util/shapes.js b/app/util/shapes.js index b49c7ed20e..82907eb45d 100644 --- a/app/util/shapes.js +++ b/app/util/shapes.js @@ -74,7 +74,6 @@ export const popupColorShape = PropTypes.shape({ accessiblePrimary: PropTypes.string, hover: PropTypes.string, primary: PropTypes.string, - iconColors: PropTypes.objectOf(PropTypes.string), }); export const parkShape = PropTypes.shape({ diff --git a/app/util/sortUtils.js b/app/util/sortUtils.js index 4f439f48bc..75f3f385aa 100644 --- a/app/util/sortUtils.js +++ b/app/util/sortUtils.js @@ -3,7 +3,7 @@ * * @param {Set} favouriteRentalStationsIds stationIds of favourite bike rental stations. */ -export const sortNearbyRentalStations = favouriteRentalStationsIds => { +export const sortNearYouRentalStations = favouriteRentalStationsIds => { return (first, second) => { const firstIsClose = first.node.distance < 1500; const secondIsClose = second.node.distance < 1500; @@ -29,7 +29,7 @@ export const sortNearbyRentalStations = favouriteRentalStationsIds => { * @param {Set} favouriteStopIds gtfsIds of favourite stops and stations. * @param distanceThreshold maximum distance with which the stops are priorized */ -export const sortNearbyStops = (favouriteStopIds, distanceThreshold) => { +export const sortNearYouStops = (favouriteStopIds, distanceThreshold) => { return (first, second) => { const firstStopOrStationId = first.node.place.gtfsId; const firstStopOrStationIsClose = first.node.distance < distanceThreshold; diff --git a/digitransit-component/packages/digitransit-component-autosuggest-panel/package.json b/digitransit-component/packages/digitransit-component-autosuggest-panel/package.json index 92b6a33c79..b8fabd54dc 100644 --- a/digitransit-component/packages/digitransit-component-autosuggest-panel/package.json +++ b/digitransit-component/packages/digitransit-component-autosuggest-panel/package.json @@ -1,6 +1,6 @@ { "name": "@digitransit-component/digitransit-component-autosuggest-panel", - "version": "8.0.0", + "version": "8.1.1", "description": "digitransit-component autosuggest-panel module", "main": "index.js", "files": [ @@ -28,8 +28,8 @@ "author": "Digitransit Authors", "license": "(AGPL-3.0 OR EUPL-1.2)", "peerDependencies": { - "@digitransit-component/digitransit-component-autosuggest": "^7.0.0", - "@digitransit-component/digitransit-component-icon": "^1.2.0", + "@digitransit-component/digitransit-component-autosuggest": "^7.1.0", + "@digitransit-component/digitransit-component-icon": "^2.0.0", "@hsl-fi/sass": "^0.2.0", "classnames": "2.5.1", "downshift": "9.0.10", diff --git a/digitransit-component/packages/digitransit-component-autosuggest-panel/src/index.js b/digitransit-component/packages/digitransit-component-autosuggest-panel/src/index.js index b5814ffe3d..8fed487068 100644 --- a/digitransit-component/packages/digitransit-component-autosuggest-panel/src/index.js +++ b/digitransit-component/packages/digitransit-component-autosuggest-panel/src/index.js @@ -5,7 +5,9 @@ import React from 'react'; import { I18nextProvider, withTranslation } from 'react-i18next'; import { ReactSortable } from 'react-sortablejs'; import DTAutoSuggest from '@digitransit-component/digitransit-component-autosuggest'; -import Icon from '@digitransit-component/digitransit-component-icon'; +import Icon, { + defaultColors, +} from '@digitransit-component/digitransit-component-icon'; import isEmpty from 'lodash/isEmpty'; import Select from './helpers/Select'; import i18n from './helpers/i18n'; @@ -232,13 +234,11 @@ class DTAutosuggestPanel extends React.Component { targets: PropTypes.arrayOf(PropTypes.string), filterResults: PropTypes.func, isMobile: PropTypes.bool, - color: PropTypes.string, - hoverColor: PropTypes.string, originMobileLabel: PropTypes.string, destinationMobileLabel: PropTypes.string, refPoint: locationShape, modeSet: PropTypes.string, - modeIconColors: PropTypes.objectOf(PropTypes.string), + colors: PropTypes.objectOf(PropTypes.string), getAutoSuggestIcons: PropTypes.objectOf(PropTypes.func), fontWeights: PropTypes.shape({ medium: PropTypes.number, @@ -271,12 +271,10 @@ class DTAutosuggestPanel extends React.Component { disableAutoFocus: false, isMobile: false, handleViaPointLocationSelected: undefined, - color: '#007ac9', - hoverColor: '#0062a1', originMobileLabel: null, destinationMobileLabel: null, modeSet: undefined, - modeIconColors: undefined, + colors: defaultColors, fontWeights: { medium: 500, }, @@ -413,6 +411,7 @@ class DTAutosuggestPanel extends React.Component { t, lang: lng, } = this.props; + const { primary } = this.props.colors; const { activeSlackInputs } = this.state; const slackTime = getSlackTimeOptions(t); const defaultSlackTimeValue = 0; @@ -431,7 +430,7 @@ class DTAutosuggestPanel extends React.Component { }, ])} style={{ - '--color': `${this.props.color}`, + '--color': primary, '--font-weight-medium': fontWeights.medium, }} > @@ -469,12 +468,10 @@ class DTAutosuggestPanel extends React.Component { targets={this.props.targets} filterResults={this.props.filterResults} isMobile={this.props.isMobile} - color={this.props.color} - hoverColor={this.props.hoverColor} + colors={this.props.colors} mobileLabel={originMobileLabel} fontWeights={this.props.fontWeights} modeSet={this.props.modeSet} - modeIconColors={this.props.modeIconColors} showScroll={this.props.showScroll} isEmbedded={this.props.isEmbedded} /> @@ -488,7 +485,7 @@ class DTAutosuggestPanel extends React.Component { } aria-label={t('swap-order-button-label', { lng })} > - + )}
@@ -522,11 +519,7 @@ class DTAutosuggestPanel extends React.Component { style={viaPoints.length > 1 ? { cursor: 'move' } : {}} > {viaPoints.length > 1 && ( - + )}
@@ -588,7 +579,7 @@ class DTAutosuggestPanel extends React.Component { )} wide > - + )}
@@ -621,7 +612,7 @@ class DTAutosuggestPanel extends React.Component { - + } onSlackTimeSelected={this.handleViaPointSlackTimeSelected} @@ -642,7 +633,7 @@ class DTAutosuggestPanel extends React.Component { lng, })} > - + ))} @@ -671,12 +662,10 @@ class DTAutosuggestPanel extends React.Component { targets={this.props.targets} filterResults={this.props.filterResults} isMobile={this.props.isMobile} - color={this.props.color} - hoverColor={this.props.hoverColor} mobileLabel={destinationMobileLabel} fontWeights={this.props.fontWeights} modeSet={this.props.modeSet} - modeIconColors={this.props.modeIconColors} + colors={this.props.colors} showScroll={this.props.showScroll} isEmbedded={this.props.isEmbedded} /> @@ -696,7 +685,7 @@ class DTAutosuggestPanel extends React.Component { img="viapoint" width={1.25} height={1.375} - color={this.props.color} + color={primary} /> )} diff --git a/digitransit-component/packages/digitransit-component-autosuggest/package.json b/digitransit-component/packages/digitransit-component-autosuggest/package.json index 0436c09123..60713e06e6 100644 --- a/digitransit-component/packages/digitransit-component-autosuggest/package.json +++ b/digitransit-component/packages/digitransit-component-autosuggest/package.json @@ -1,6 +1,6 @@ { "name": "@digitransit-component/digitransit-component-autosuggest", - "version": "7.0.0", + "version": "7.1.0", "description": "digitransit-component autosuggest module", "main": "index.js", "files": [ @@ -35,9 +35,9 @@ "@hsl-fi/hooks": "^1.2.4" }, "peerDependencies": { - "@digitransit-component/digitransit-component-dialog-modal": "^2.0.0", - "@digitransit-component/digitransit-component-icon": "^1.2.0", - "@digitransit-component/digitransit-component-suggestion-item": "^2.3.1", + "@digitransit-component/digitransit-component-dialog-modal": "^3.0.0", + "@digitransit-component/digitransit-component-icon": "^2.0.0", + "@digitransit-component/digitransit-component-suggestion-item": "^3.0.0", "@hsl-fi/sass": "^0.2.0", "classnames": "2.5.1", "downshift": "9.0.10", diff --git a/digitransit-component/packages/digitransit-component-autosuggest/src/components/MobileSearch.scss b/digitransit-component/packages/digitransit-component-autosuggest/src/components/MobileSearch.scss index b3f460ff07..9ba846b45a 100644 --- a/digitransit-component/packages/digitransit-component-autosuggest/src/components/MobileSearch.scss +++ b/digitransit-component/packages/digitransit-component-autosuggest/src/components/MobileSearch.scss @@ -1,4 +1,3 @@ -$primary-color: #007ac9; $font-weight-medium: 500; $search-result-text-highlight-background-color: #f2f5f7; $zindex: base, map-container, map-gradient, map-fullscreen-toggle, map-buttons, @@ -52,7 +51,6 @@ input[type='text'] { background: none; svg { - fill: $primary-color; width: 14px; height: 21px; transform: rotate(-180deg); diff --git a/digitransit-component/packages/digitransit-component-autosuggest/src/components/MobileView.js b/digitransit-component/packages/digitransit-component-autosuggest/src/components/MobileView.js index 8bcaa10c4b..eb08cc6f5a 100644 --- a/digitransit-component/packages/digitransit-component-autosuggest/src/components/MobileView.js +++ b/digitransit-component/packages/digitransit-component-autosuggest/src/components/MobileView.js @@ -29,13 +29,10 @@ import { * @property {function} onSelectedItemChange * @property {object} fontWeights * @property {function} clearOldSearches - * @property {object} itemProps - * @property {string} color - * @property {string} accessiblePrimaryColor - * @property {string} hoverColor + * @property {object} suggestionProps + * @property {object} colors * @property {string} lng * @property {object} ariaProps - * @property {string} clearButtonColor * @property {string} value * @property {string} inputClassName * @property {boolean} required @@ -55,13 +52,9 @@ const MobileView = ({ onSelectedItemChange, fontWeights, clearOldSearches, - itemProps, - color, - accessiblePrimaryColor, - hoverColor, + suggestionProps, lng, ariaProps, - clearButtonColor, value, inputClassName, required, @@ -69,6 +62,7 @@ const MobileView = ({ showScroll, state, dispatch, + colors, }) => { const [t] = useTranslation(); const { lock, unlock } = hooks.useScrollLock(); @@ -171,9 +165,9 @@ const MobileView = ({
@@ -194,7 +188,7 @@ const MobileView = ({ aria-label={t('cancel', { lng })} tabIndex={0} > - +
@@ -253,8 +247,7 @@ const MobileView = ({ setDialogOpen(false); }} secondaryButtonOnClick={() => setDialogOpen(false)} - color={color} - hoverColor={hoverColor} + colors={colors} fontWeights={fontWeights} lang={lng} /> @@ -270,14 +263,11 @@ MobileView.propTypes = { clearOldSearches: PropTypes.func.isRequired, onSelectedItemChange: PropTypes.func.isRequired, value: PropTypes.string.isRequired, - color: PropTypes.string.isRequired, - accessiblePrimaryColor: PropTypes.string.isRequired, - clearButtonColor: PropTypes.string.isRequired, - hoverColor: PropTypes.string.isRequired, + colors: PropTypes.objectOf(PropTypes.string).isRequired, fontWeights: PropTypes.shape({ medium: PropTypes.number.isRequired, }).isRequired, - itemProps: PropTypes.shape({}).isRequired, + suggestionProps: PropTypes.shape({}).isRequired, ariaProps: PropTypes.shape({ ariaRequiredText: PropTypes.string.isRequired, SearchBarId: PropTypes.string.isRequired, diff --git a/digitransit-component/packages/digitransit-component-autosuggest/src/components/Suggestions.js b/digitransit-component/packages/digitransit-component-autosuggest/src/components/Suggestions.js index fbd095e477..54696a880e 100644 --- a/digitransit-component/packages/digitransit-component-autosuggest/src/components/Suggestions.js +++ b/digitransit-component/packages/digitransit-component-autosuggest/src/components/Suggestions.js @@ -12,10 +12,10 @@ function Suggestion({ item, lng, getItemProps, - suggestionItemProps, highlightedIndex, itemIndex, styles, + ...rest }) { const [t] = useTranslation(); const newItem = @@ -34,12 +34,7 @@ function Suggestion({ )} {...getItemProps({ index: itemIndex })} > - + ); } @@ -73,7 +68,6 @@ Suggestion.propTypes = { item: itemShape.isRequired, lng: PropTypes.string.isRequired, getItemProps: PropTypes.func.isRequired, - suggestionItemProps: PropTypes.shape({}).isRequired, highlightedIndex: PropTypes.number.isRequired, itemIndex: PropTypes.number.isRequired, styles: PropTypes.objectOf(PropTypes.string).isRequired, @@ -83,13 +77,12 @@ export function Suggestions({ suggestions, getMenuProps, getItemProps, - itemProps: suggestionItemProps, - highlightedIndex, lng, styles, hidden, renderClearHistoryButton, handleClearHistory, + ...rest }) { const [t] = useTranslation(); return ( @@ -109,13 +102,12 @@ export function Suggestions({ suggestion.properties.name || suggestion.properties.gtfsId }`} - highlightedIndex={highlightedIndex} - itemIndex={i} - suggestionItemProps={suggestionItemProps} getItemProps={getItemProps} + itemIndex={i} item={suggestion} lng={lng} styles={styles} + {...rest} /> ); })} @@ -139,8 +131,6 @@ Suggestions.propTypes = { suggestions: PropTypes.arrayOf(itemShape).isRequired, getMenuProps: PropTypes.func.isRequired, getItemProps: PropTypes.func.isRequired, - itemProps: PropTypes.shape({}).isRequired, - highlightedIndex: PropTypes.number.isRequired, lng: PropTypes.string.isRequired, styles: PropTypes.objectOf(PropTypes.string).isRequired, hidden: PropTypes.bool.isRequired, diff --git a/digitransit-component/packages/digitransit-component-autosuggest/src/index.js b/digitransit-component/packages/digitransit-component-autosuggest/src/index.js index 2e1076514a..ca918334be 100644 --- a/digitransit-component/packages/digitransit-component-autosuggest/src/index.js +++ b/digitransit-component/packages/digitransit-component-autosuggest/src/index.js @@ -5,7 +5,9 @@ import { I18nextProvider, useTranslation } from 'react-i18next'; import cx from 'classnames'; import { executeSearch } from '@digitransit-search-util/digitransit-search-util-execute-search-immidiate'; import { useCombobox } from 'downshift'; -import Icon from '@digitransit-component/digitransit-component-icon'; +import Icon, { + defaultColors, +} from '@digitransit-component/digitransit-component-icon'; import i18n from './utils/i18n'; import styles from './components/styles.scss'; import { getSuggestionValue, suggestionAsAriaContent } from './utils/utils'; @@ -214,11 +216,8 @@ const getNewTargets = ({ * @property {string} [inputClassName] * @property {string} [translatedPlaceholder] * @property {boolean} [required] - * @property {string} [color] - * @property {string} [hoverColor] - * @property {string} [accessiblePrimaryColor] * @property {Object} [fontWeights] - * @property {Object} [modeIconColors] + * @property {Object} [colors] * @property {string} [modeSet] * @property {boolean} [showScroll] * @property {boolean} [isEmbedded] @@ -252,12 +251,9 @@ function DTAutosuggest({ inputClassName, translatedPlaceholder, required, - color, - hoverColor, ariaLabel, - accessiblePrimaryColor, fontWeights, - modeIconColors, + colors, modeSet, showScroll, isEmbedded, @@ -544,11 +540,9 @@ function DTAutosuggest({ loading: state.loading, isMobile, ariaFavouriteString: t('favourite', { lng }), - color, - accessiblePrimaryColor, fontWeights, getAutoSuggestIcons, - modeIconColors, + colors, modeSet, }; @@ -604,12 +598,9 @@ function DTAutosuggest({ onSelectedItemChange={onSelectedItemChange} value={state.value} clearInput={clearInput} - itemProps={baseItemProps} + suggestionProps={baseItemProps} showScroll={!!showScroll} - color={color} - hoverColor={hoverColor} - clearButtonColor={color} - accessiblePrimaryColor={accessiblePrimaryColor} + colors={colors} inputClassName={inputClassName} required={required} state={state} @@ -624,8 +615,8 @@ function DTAutosuggest({ state.renderMobile && 'hidden', ])} style={{ - '--color': color, - '--hover-color': hoverColor, + '--color': colors.primary, + '--hover-color': colors.hover, }} > {icon && ( @@ -662,7 +653,7 @@ function DTAutosuggest({ clearInput={clearInput} inputRef={inputRef} styles={styles} - clearButtonColor={color} + clearButtonColor={colors.primary} placeholder={translatedPlaceholder || t(placeholder, { lng })} required={required} transportMode={transportMode} @@ -676,9 +667,9 @@ function DTAutosuggest({ getItemProps={getItemProps} getMenuProps={getMenuProps} suggestions={state.suggestions} - itemProps={baseItemProps} lng={lng} styles={styles} + {...baseItemProps} /> @@ -712,9 +703,6 @@ DTAutosuggest.propTypes = { focusChange: PropTypes.func, lang: PropTypes.string, isMobile: PropTypes.bool, - color: PropTypes.string, - hoverColor: PropTypes.string, - accessiblePrimaryColor: PropTypes.string, pathOpts: PropTypes.shape({ routesPrefix: PropTypes.string, stopsPrefix: PropTypes.string, @@ -729,7 +717,7 @@ DTAutosuggest.propTypes = { fontWeights: PropTypes.shape({ medium: PropTypes.number, }), - modeIconColors: PropTypes.objectOf(PropTypes.string), + colors: PropTypes.objectOf(PropTypes.string), getAutoSuggestIcons: PropTypes.objectOf(PropTypes.func), required: PropTypes.bool, modeSet: PropTypes.string, @@ -753,9 +741,6 @@ DTAutosuggest.defaultProps = { isMobile: false, isEmbedded: false, geocodingSize: undefined, - color: '#007ac9', - hoverColor: '#0062a1', - accessiblePrimaryColor: '#0074be', pathOpts: { routesPrefix: 'linjat', stopsPrefix: 'pysakit', @@ -767,7 +752,7 @@ DTAutosuggest.defaultProps = { fontWeights: { medium: 500, }, - modeIconColors: undefined, + colors: defaultColors, required: false, modeSet: undefined, showScroll: false, diff --git a/digitransit-component/packages/digitransit-component-autosuggest/src/utils/translations.js b/digitransit-component/packages/digitransit-component-autosuggest/src/utils/translations.js index 0daf347166..a594a2694d 100644 --- a/digitransit-component/packages/digitransit-component-autosuggest/src/utils/translations.js +++ b/digitransit-component/packages/digitransit-component-autosuggest/src/utils/translations.js @@ -145,7 +145,9 @@ const translations = { stop: 'Stop', 'stop-near-you': 'Search stops and routes', 'stop-near-you-airplane': 'Search flights or airports', + 'stop-near-you-bikepark': 'Search bike parks', 'stop-near-you-bus': 'Search bus routes or stops', + 'stop-near-you-carpark': 'Search car parks', 'stop-near-you-citybike': 'Search city bike stations', 'stop-near-you-rail': 'Search train routes or stations', 'stop-near-you-subway': 'Search metro routes or stations ', @@ -230,7 +232,9 @@ const translations = { stop: 'Pysäkki', 'stop-near-you': 'Linja, pysäkki tai asema', 'stop-near-you-airplane': 'Hae lentoja tai lentoasemaa', + 'stop-near-you-bikepark': 'Hae pyöräparkkia', 'stop-near-you-bus': 'Hae bussilinjaa tai pysäkkiä', + 'stop-near-you-carpark': 'Hae autoparkkia', 'stop-near-you-citybike': 'Hae kaupunkipyöräasemaa', 'stop-near-you-rail': 'Hae lähijunaa tai asemaa', 'stop-near-you-subway': 'Hae metrolinjaa tai asemaa', @@ -401,7 +405,9 @@ const translations = { stop: 'Hållplats', 'stop-near-you': 'Sök hållplatser eller linjer', 'stop-near-you-airplane': 'Sök flyg eller flygplatser', + 'stop-near-you-bikepark': 'Sök cykelparkering', 'stop-near-you-bus': 'Sök busslinjer eller hållplatser', + 'stop-near-you-carpark': 'Sök anslutningsparkering', 'stop-near-you-citybike': 'Sök stadscykelstationer', 'stop-near-you-rail': 'Sök närtåger eller stationer', 'stop-near-you-subway': 'Sök metrolinjer eller stationer', diff --git a/digitransit-component/packages/digitransit-component-control-panel/package.json b/digitransit-component/packages/digitransit-component-control-panel/package.json index 4c8a39abf7..74afcef98e 100644 --- a/digitransit-component/packages/digitransit-component-control-panel/package.json +++ b/digitransit-component/packages/digitransit-component-control-panel/package.json @@ -1,6 +1,6 @@ { "name": "@digitransit-component/digitransit-component-control-panel", - "version": "6.0.2", + "version": "7.0.0", "description": "digitransit-component control-panel module", "main": "index.js", "files": [ @@ -29,7 +29,8 @@ "author": "Digitransit Authors", "license": "(AGPL-3.0 OR EUPL-1.2)", "peerDependencies": { - "@digitransit-component/digitransit-component-icon": "^1.2.0", + "@digitransit-component/digitransit-component-icon": "^2.0.0", + "@hsl-fi/modal": "^0.3.2", "@hsl-fi/sass": "^0.2.0", "classnames": "2.5.1", "i18next": "^22.5.1", diff --git a/digitransit-component/packages/digitransit-component-control-panel/src/helpers/AllModesModal.js b/digitransit-component/packages/digitransit-component-control-panel/src/helpers/AllModesModal.js new file mode 100644 index 0000000000..e8d728d134 --- /dev/null +++ b/digitransit-component/packages/digitransit-component-control-panel/src/helpers/AllModesModal.js @@ -0,0 +1,74 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import { useTranslation } from 'react-i18next'; +import Modal from '@hsl-fi/modal'; +import styles from './styles.scss'; + +export default function AllModesModal({ + appElement, + modalOpen, + closeModal, + isMobile, + language, + fontWeights, + colors, + children, +}) { + const [t] = useTranslation(); + + return ( + +
+

+ {t('title', { lng: language })} +

+ {!isMobile && ( +
+ {t('description', { lng: language })} +
+ )} +
+
+ {children} +
+ {!isMobile && ( +
+ )} +
+ +
+
+ + ); +} + +AllModesModal.propTypes = { + appElement: PropTypes.string.isRequired, + language: PropTypes.string.isRequired, + modalOpen: PropTypes.bool.isRequired, + closeModal: PropTypes.func.isRequired, + isMobile: PropTypes.bool.isRequired, + fontWeights: PropTypes.shape({ medium: PropTypes.number }).isRequired, + colors: PropTypes.objectOf(PropTypes.string).isRequired, + children: PropTypes.arrayOf(PropTypes.node).isRequired, +}; diff --git a/digitransit-component/packages/digitransit-component-control-panel/src/helpers/NearYouButton.js b/digitransit-component/packages/digitransit-component-control-panel/src/helpers/NearYouButton.js new file mode 100644 index 0000000000..9e8062cb1c --- /dev/null +++ b/digitransit-component/packages/digitransit-component-control-panel/src/helpers/NearYouButton.js @@ -0,0 +1,109 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import Icon from '@digitransit-component/digitransit-component-icon'; +import styles from './styles.scss'; + +export default function NearYouButton({ + mode, + modeSet, + colors, + getIconName, + title, + srMsg, + withAlert, + boxed, + withBorder, + withArrow, + margin, + padding, + iconSize, +}) { + let iconProps; + + if (mode === 'favorite') { + iconProps = { img: 'star' }; + } else if (mode === 'more') { + iconProps = { + img: 'arrow', + color: colors.primary, + width: 1.2, + height: 1.2, + }; + } else { + iconProps = { + img: getIconName(mode, modeSet, boxed), + color: colors[mode], + }; + } + + if (!boxed) { + iconProps = { + ...iconProps, + width: 1.4, + height: 1.4, + }; + } + const buttonStyle = { '--margin': margin, '--padding': padding }; + let iconContainerStyle = { '--iconSize': iconSize, '--iconMargin': padding }; + if (!boxed) { + iconContainerStyle = { + ...iconContainerStyle, + '--bckColor': colors[mode], + '--borderRadius': '50%', + '--iconMargin': '17px', + }; + } + + const buttonClass = withBorder + ? 'near-you-button-with-border' + : 'near-you-button'; + return ( + <> + {srMsg && {srMsg}} + + + ); +} + +NearYouButton.propTypes = { + mode: PropTypes.string.isRequired, + modeSet: PropTypes.string.isRequired, + colors: PropTypes.objectOf(PropTypes.string).isRequired, + getIconName: PropTypes.func.isRequired, + title: PropTypes.node, + srMsg: PropTypes.string, + withAlert: PropTypes.bool, + boxed: PropTypes.bool, + withBorder: PropTypes.bool, + withArrow: PropTypes.bool, + margin: PropTypes.string, + padding: PropTypes.string, + iconSize: PropTypes.string, +}; + +NearYouButton.defaultProps = { + title: '', + srMsg: undefined, + withAlert: false, + boxed: false, + withBorder: false, + withArrow: false, + margin: '8px', + padding: '8px', + iconSize: '30px', +}; diff --git a/digitransit-component/packages/digitransit-component-control-panel/src/helpers/styles.js b/digitransit-component/packages/digitransit-component-control-panel/src/helpers/styles.js deleted file mode 100644 index b15437b041..0000000000 --- a/digitransit-component/packages/digitransit-component-control-panel/src/helpers/styles.js +++ /dev/null @@ -1,64 +0,0 @@ -export function getStyleInput() { - return { - width: 200, - }; -} - -export function getStyleMain() { - return { - display: 'flex', - order: 1, - flexDirection: 'column', - alignItems: 'stretch', - backgroundColor: '#ffffff', - height: '100%', - width: 'calc(100% - 2em)', - maxWidth: 400, - zIndex: 20, - margin: '0 auto', - }; -} - -export function getStyleMainBottom() { - return { - backgroundColor: '#ffffff', - width: 'calc(100% - 2em)', - margin: '0 auto', - paddingBottom: 32, - }; -} - -export function getStyleSeparatorDiv() { - return { - position: 'relative', - display: 'block', - width: '100%', - // marginTop: 20, - marginBottom: 19, - paddingBottom: 29, - }; -} - -export function getStyleSeparatorDiv2() { - return { - position: 'relative', - display: 'block', - width: '100%', - // marginTop: 20, - marginBottom: 19, - paddingBottom: 20, - }; -} - -export function getStyleSeparatorLine() { - return { - backgroundColor: '#ccc', - content: '', - display: 'block', - height: 1, - position: 'absolute', - bottom: 0, - right: -5, - left: -5, - }; -} diff --git a/digitransit-component/packages/digitransit-component-control-panel/src/helpers/styles.scss b/digitransit-component/packages/digitransit-component-control-panel/src/helpers/styles.scss index 07ca2afa22..a090f2782a 100644 --- a/digitransit-component/packages/digitransit-component-control-panel/src/helpers/styles.scss +++ b/digitransit-component/packages/digitransit-component-control-panel/src/helpers/styles.scss @@ -68,19 +68,63 @@ } } +.separator { + background-color: #ccc; + width: var(--width); + margin-left: var(--margin); + margin-right: var(--margin); + height: 1px; +} + .near-you-container { font-size: 16px; + .modal-desc { + font-weight: 325; + } + + .close-container { + display: flex; + width: 100%; + height: 42px; + justify-content: right; + } + + .close, + .close-mobile { + display: flex; + height: 40px; + color: var(--color); + font-size: 16px; + border-style: solid; + border-width: 1px; + border-radius: 20px; + background-color: white; + border-color: #888; + align-items: center; + justify-content: center; + margin-top: 20px; + } + + .close { + width: 86px; + + &:hover { + box-shadow: 0 0 5px rgba(0, 0, 0, 0.2); + } + } + + .close-mobile { + width: 100%; + } + .near-you-title { font-family: 'Gotham Rounded A', 'Gotham Rounded B', Roboto, Arial, Georgia, serif; - font-weight: var(--font-weight-medium); - font-stretch: normal; - font-style: normal; + font-weight: var(--font-weight); line-height: normal; letter-spacing: -0.67px; color: #333; - margin: 0 0 15px 0; font-size: 1.125em; @include min-width(tablet) { @@ -130,82 +174,57 @@ white-space: nowrap; width: 1px; } + } - .transport-mode-icon-container { - cursor: pointer; - border-radius: 10px; - border: solid 1px #d9d9d9; - background-color: white; - display: flex; - flex: 1; - width: 100%; - justify-content: center; - max-width: 72px; - height: 100%; - - .transport-mode-icon-with-icon { - display: flex; - position: relative; - } - - span.transport-mode-alert-icon { - position: absolute; - bottom: -4px; - right: -5px; + .near-you-button-with-border { + border: solid 1px #d9d9d9; + border-radius: 5px; + cursor: pointer; + background-color: white; + display: flex; + flex: 1; + width: 100%; + justify-content: center; + max-width: 72px; + height: 100%; - svg { - height: 15px !important; - width: 15px !important; + .icon-container { + display: flex; + } - @include min-width(tablet) { - width: 18px !important; - height: 18px !important; - } - } - } + span.transport-mode-alert-icon { + position: absolute; + bottom: -4px; + right: -5px; svg { - width: 30px; - height: 30px; - margin: auto; + height: 15px !important; + width: 15px !important; @include min-width(tablet) { - width: 34px; - height: 34px; + width: 18px !important; + height: 18px !important; } } - - &:hover { - box-shadow: 0 0 5px rgba(0, 0, 0, 0.2); - } } - } - .near-you-buttons-container-wide { - & > a:not(:last-child), - & > div:not(:last-child) { - margin-right: 9px; + svg { + width: 30px; + height: 30px; + margin: auto; @include min-width(tablet) { - margin-right: 10px; + width: 34px; + height: 34px; } } - & > a:last-child, - & > div:last-child { - margin-bottom: 24px; - } - - & > a, - & > div { - width: 100%; - height: 48px; - - @include min-width(tablet) { - margin-bottom: 8px; - } + &:hover { + box-shadow: 0 0 5px rgba(0, 0, 0, 0.2); } + } + .near-you-buttons-container-wide { .sr-only:not(:focus, :active) { clip: rect(0 0 0 0); clip-path: inset(50%); @@ -216,26 +235,26 @@ width: 1px; } - .transport-mode-icon-container { + .near-you-button, + .near-you-button-with-border { + margin-bottom: var(--margin); + margin-top: var(--margin); + padding-bottom: var(--padding); + padding-top: var(--padding); cursor: pointer; - position: relative; display: flex; - border-radius: 5px; - border: solid 1px #ddd; background-color: white; flex: 1; min-width: 100%; - height: 48px; - .transport-mode-icon-with-icon { + .icon-container { cursor: pointer; display: flex; - position: relative; - left: 17px; + margin-left: var(--iconMargin); border-radius: var(--borderRadius); background-color: var(--bckColor); - height: 30px; - width: 30px; + height: var(--iconSize); + width: var(--iconSize); align-items: center; align-self: center; justify-content: center; @@ -259,141 +278,34 @@ .transport-mode-title { cursor: pointer; - position: relative; font-style: normal; - font-weight: var(--font-weight-medium); + font-weight: var(--font-weight); font-size: 15px; line-height: 18px; + margin-left: 9px; align-self: center; - left: 26px; + text-align: left; width: calc(100% - 58px); overflow: hidden; white-space: nowrap; text-overflow: ellipsis; } - - &:hover { - box-shadow: 0 0 5px rgba(0, 0, 0, 0.2); - } } - } -} -.nearby-stops-bubble-dialog { - position: relative; - width: 100%; - z-index: 23; - margin-bottom: 10px; - - @keyframes appear { - 0% { - opacity: 0; - transform: translateY(-15px); + .near-you-button-caret { + align-self: center; } - 100% { - opacity: 1; - transform: translateY(0); + .near-you-button:hover .near-you-button-caret { + transform: translateX(4px); + transition: transform 0.1s; } - } - - opacity: 0; - - &.visible { - opacity: 1; - animation: appear 0.5s; - } - - @include min-width(tablet) { - position: absolute; - width: 0; - height: 0; - margin: 0; - } - - .nearby-stops-bubble-dialog-container { - display: flex; - position: relative; - border-radius: 5px; - background: #ffefe8; - font-size: 15px; - line-height: 18px; - letter-spacing: -0.03em; - padding: 15px 0 17px 0; - - @include min-width(tablet) { - position: absolute; - padding: 12px 0 11px 0; - min-height: 80px; - width: 300px; - left: 230px; - transform: translateY(-100%); - top: -6px; - } - - .nearby-stops-bubble-dialog-header { - font-weight: var(--font-weight-medium); - padding: 0 49px 4px 20px; - - &.fi { - min-height: 19.2px; - } - - &.sv, - &.en { - min-height: 39.2px; - } - @include min-width(tablet) { - padding: 0 44px 3px 20px; - } - } - - .nearby-stops-bubble-dialog-content { - font-weight: 400; - padding: 0 49px 0 20px; - min-height: 35.2px; - - @include min-width(tablet) { - padding: 0 57px 0 20px; - } - } - - .nearby-stops-bubble-dialog-close { - display: flex; - position: absolute; - right: 15px; - top: 14px; - padding: 0; - margin: 0; - cursor: pointer; - border: none; - background: transparent; - - @include min-width(tablet) { - top: 16px; - } - - svg { - fill: #333; - width: 16px; - height: 16px; - } - } - - .nearby-stops-bubble-dialog-tip-container { - position: absolute; - height: 42px; - overflow: hidden; - width: 42px; - background-color: #ffefe8; - transform: rotate(45deg); - z-index: -1; - bottom: -4px; - left: 52px; + .near-you-button-with-border { + border: solid 1px #d9d9d9; - @include min-width(tablet) { - left: 18px; + &:hover { + box-shadow: 0 0 5px rgba(0, 0, 0, 0.2); } } } diff --git a/digitransit-component/packages/digitransit-component-control-panel/src/helpers/translations.js b/digitransit-component/packages/digitransit-component-control-panel/src/helpers/translations.js index 94900029fe..252054974a 100644 --- a/digitransit-component/packages/digitransit-component-control-panel/src/helpers/translations.js +++ b/digitransit-component/packages/digitransit-component-control-panel/src/helpers/translations.js @@ -1,117 +1,120 @@ const translations = { de: { translation: { - 'close-teaser-modal': 'Schließen', - 'pick-mode': 'Wählen Sie ein Verkehrsmittel', - 'pick-mode-airplane': 'Flug', - 'pick-mode-bus': 'Bus', - 'pick-mode-citybike': 'Leihrad', - 'pick-mode-favorite': 'Favoriten', - 'pick-mode-ferry': 'Fähre', - 'pick-mode-rail': 'Zug', - 'pick-mode-subway': 'U-Bahn', - 'pick-mode-tram': 'Straßenbahn', - 'placeholder-destination': 'Geben Sie Ihren Zielort ein', - 'placeholder-origin': 'Geben Sie Ihren Abfahrtsort ein', - 'placeholder-route-stop-station': 'Enter route, stop or station', - 'title-route-stop-station': 'Haltestellen und Linien in der Nähe', - 'title-origin-to-destination': 'Wohin?', - 'use-own-position': 'Verwende aktuelle Position', + airplane: 'Flug', + bus: 'Bus', + citybike: 'Leihrad', + favorite: 'Favoriten', + ferry: 'Fähre', + rail: 'Zug', + subway: 'U-Bahn', + tram: 'Straßenbahn', + title: 'Haltestellen und Linien in der Nähe', + close: 'Schließen', }, }, en: { translation: { - 'close-teaser-modal': 'Close', - 'pick-mode': 'Select a transport mode', - 'pick-mode-airplane': 'Flight', - 'pick-mode-bus': 'Bus', - 'pick-mode-citybike': 'Citybike', - 'pick-mode-favorite': 'Stops nearby me', - 'pick-mode-ferry': 'Ferry', - 'pick-mode-rail': 'Rail', - 'pick-mode-subway': 'Metro', - 'pick-mode-tram': 'Tram', - 'placeholder-destination': 'Enter destination', - 'placeholder-origin': 'Enter origin', - 'placeholder-route-stop-station': 'Enter route, stop or station', - 'title-route-stop-station': 'Nearby stops and routes', - 'title-origin-to-destination': 'Where to?', - 'use-own-position': 'Use current location', - 'nearby-stops-teaser-header': - 'Try the new map views showing nearby stops', - 'nearby-stops-teaser-content': - 'Real-time timetables for nearby stops and vehicles on map.', + airplane: 'The closest airports', + airplane_short: 'Airport', + bus: 'Buses and nearby stops on map', + bus_short: 'Bus', + citybike: 'The closest city bike stations', + citybike_short: 'City bike', + favorite: 'Favorites near you', + favorite_short: 'Favorites', + ferry: 'The closest ferry piers', + ferry_short: 'Ferry', + rail: 'Trains and nearby stations on map', + rail_short: 'Train', + rail_local: 'Commuter train', + subway: 'Metro and nearby stations on map', + subway_short: 'Metro', + tram: 'Trams and nearby stops on map', + tram_short: 'Tram', + bikepark: 'The closest bike parks', + bikepark_short: 'Bike parking', + carpark: 'The closest car parks', + carpark_short: 'Car parking', + more: 'Show more', + title: 'Near you', + description: + 'The Near You view shows stops and lines near you at a glance', + close: 'Close', }, }, fi: { translation: { - 'close-teaser-modal': 'Sulje', - 'pick-mode': 'Valitse joukkoliikennevälineistä', - 'pick-mode-airplane': 'Lentokone', - 'pick-mode-bus': 'Bussi', - 'pick-mode-citybike': 'Kaupunkipyörä', - 'pick-mode-favorite': 'Omat lähipysäkit', - 'pick-mode-ferry': 'Lautta', - 'pick-mode-rail': 'Juna', - 'pick-mode-subway': 'Metro', - 'pick-mode-tram': 'Raitiovaunu', - 'placeholder-destination': 'Syötä määränpää', - 'placeholder-origin': 'Syötä lähtöpaikka', - 'placeholder-route-stop-station': 'Syötä linja, pysäkki tai asema', - 'title-route-stop-station': 'Lähipysäkit ja linjat', - 'title-origin-to-destination': 'Minne mennään?', - 'use-own-position': 'Käytä nykyistä sijaintia', - 'nearby-stops-teaser-header': 'Kokeile uusia lähipysäkkinäkymiä', - 'nearby-stops-teaser-content': - 'Reaaliaikaiset lähipysäkkiesi aikataulut ja ajoneuvot kartalla.', + airplane: 'Lähimmät lentoasemat', + airplane_short: 'Lentoasema', + bus: 'Bussit ja lähipysäkit kartalla', + bus_short: 'Bussi', + citybike: 'Lähimmät kaupunkipyöräasemat', + citybike_short: 'Kaupunkipyörä', + favorite: 'Lähimmät suosikit', + favorite_short: 'Suosikit', + ferry: 'Lähimmät lauttalaiturit', + ferry_short: 'Lautta', + rail: 'Junat ja lähiasemat kartalla', + rail_short: 'Juna', + rail_local: 'Lähijuna', + subway: 'Metrot ja lähiasemat kartalla', + subway_short: 'Metro', + tram: 'Raitiovaunut ja lähipysäkit kartalla', + tram_short: 'Raitiovaunu', + bikepark: 'Lähimmät liityntäpysäköinnit pyörille', + bikepark_short: 'Liityntäpysäköinti pyörille', + carpark: 'Lähimmät liityntäpysäköinnit autoille', + carpark_short: 'Liityntäpysäköinti autoille', + more: 'Näytä lisää', + title: 'Lähelläsi', + description: + 'Lähelläsi -näkymä näyttää yhdellä kertaa pysäkit ja linjat lähelläsi', + close: 'Sulje', }, }, pl: { translation: { - 'close-teaser-modal': 'Zamknij', - 'pick-mode': 'Wybierz typ transportu', - 'pick-mode-airplane': 'Lot', - 'pick-mode-bus': 'Autobus', - 'pick-mode-citybike': 'Rower miejski', - 'pick-mode-favorite': 'Przystanki w pobliżu', - 'pick-mode-ferry': 'Prom', - 'pick-mode-rail': 'Kolej', - 'pick-mode-subway': 'Metro', - 'pick-mode-tram': 'Tramwaj', - 'placeholder-destination': 'Wprowadź cel', - 'placeholder-origin': 'Wprowadź początek', - 'placeholder-route-stop-station': 'Wprowadź trasę, przystanek lub stację', - 'title-route-stop-station': 'Przystanki i trasy w pobliżu', - 'title-origin-to-destination': 'Dokąd?', - 'use-own-position': 'Użyj obecnej lokalizacji', - 'nearby-stops-teaser-header': - 'Wypróbuj nowy widok mapy pokazujący przystanki w pobliżu', - 'nearby-stops-teaser-content': - 'Rozkłady jazdy w czasie rzeczywistym dla pobliskich przystanków i pojazdów na mapie.', + airplane: 'Lot', + bus: 'Autobus', + citybike: 'Rower miejski', + favorite: 'Przystanki w pobliżu', + ferry: 'Prom', + rail: 'Kolej', + subway: 'Metro', + tram: 'Tramwaj', + title: 'Przystanki i trasy w pobliżu', + sulje: 'Zamknij', }, }, sv: { translation: { - 'close-teaser-modal': 'Stäng', - 'pick-mode': 'Välj ett transportläge', - 'pick-mode-airplane': 'Flyg', - 'pick-mode-bus': 'Buss', - 'pick-mode-citybike': 'Stadscykel', - 'pick-mode-favorite': 'Hållplatser nära mig', - 'pick-mode-ferry': 'Färja', - 'pick-mode-rail': 'Tåg', - 'pick-mode-subway': 'Metro', - 'pick-mode-tram': 'Spårvagn', - 'placeholder-destination': 'Skriv destination', - 'placeholder-origin': 'Skriv avfärdsplats', - 'placeholder-route-stop-station': 'Skriv linje, hållplats eller station', - 'title-route-stop-station': 'Hållplatser och linjer nära dig', - 'title-origin-to-destination': 'Var till?', - 'use-own-position': 'Använd min position', - 'nearby-stops-teaser-header': - 'Prova de nya kartavyerna som visar hållplatserna i närheten', - 'nearby-stops-teaser-content': - 'Fordonen och tidtabellerna i realtid för hållplatserna nära dig på kartan.', + airplane: 'Närmaste flygplatser', + airplane_short: 'Flygplats', + bus: 'Bussar och hållplatser på kartan', + bus_short: 'Bus', + citybike: 'Närmaste cykelstationer', + citybike_short: 'Cykelstation', + favorite: 'Hållplatser nära mig', + favorite_short: 'Favoriter', + ferry: 'Närmaste färjekajer', + ferry_short: 'Färja', + rail: 'Tåg och stationer på kartan', + rail_short: 'Tåg', + rail_local: 'Närtåg', + subway: 'Metro och stationer på kartan', + subway_short: 'Metro', + tram: 'Spårvagnar och hållplatser på kartan', + tram_short: 'Spårvagn', + bikepark: 'Närmaste anslutningsparkering för cyklar', + bikepark_short: 'Anslutningsparkering för cyklar', + carpark: 'Närmaste anslutningsparkering för bilar', + carpark_short: 'Anslutningsparkering för bilar', + more: 'Visa flera', + title: 'Nära dig', + description: + 'Vyn Nära dig visar hållplatser och linjer nära dig i ett ögonkast', + close: 'Stäng', }, }, }; diff --git a/digitransit-component/packages/digitransit-component-control-panel/src/index.js b/digitransit-component/packages/digitransit-component-control-panel/src/index.js index e7265a2801..019342115b 100644 --- a/digitransit-component/packages/digitransit-component-control-panel/src/index.js +++ b/digitransit-component/packages/digitransit-component-control-panel/src/index.js @@ -4,7 +4,9 @@ import PropTypes from 'prop-types'; import React, { useEffect, useState } from 'react'; import { useTranslation, I18nextProvider } from 'react-i18next'; -import Icon from '@digitransit-component/digitransit-component-icon'; +import { defaultColors } from '@digitransit-component/digitransit-component-icon'; +import NearYouButton from './helpers/NearYouButton'; +import AllModesModal from './helpers/AllModesModal'; import styles from './helpers/styles.scss'; import i18n from './helpers/i18n'; @@ -45,15 +47,13 @@ SeparatorLine.defaultProps = { * @param {Object} props * @param {string[]} props.modeArray - Names of transport modes to show buttons for. Should be in lower case. Also defines button order * @param {string} props.language - Language used for accessible labels - * @param {string} props.urlPrefix - URL prefix for links. Must end with /lahellasi - * @param {boolean} props.showTitle - Show title, default is false + * @param {boolean} props.title - Custom titles per language * @param {Object} props.alertsContext * @param {function} props.alertsContext.getModesWithAlerts - Function which should return an array of transport modes that have active alerts (e.g. [BUS, SUBWAY]) * @param {Number} props.alertsContext.currentTime - Time stamp with which the returned alerts are validated with * @param {Number} props.alertsContext.feedIds - feedIds for which the alerts are fetched for - * @param {element} props.LinkComponent - React component for creating a link, default is undefined and normal anchor tags are used - * @param {element} props.modeIconColors - object of mode icon colors used for transport mode icons - * + * @param {element} props.colors - theme color configuration + * @param {string} props.urlPrefix - URL prefix for links * @example * const alertsContext = { * getModesWithAlerts: () => ({}), @@ -63,8 +63,6 @@ SeparatorLine.defaultProps = { * * @@ -79,32 +77,49 @@ const validNearYouModes = [ 'airplane', 'ferry', 'citybike', + 'bikepark', + 'carpark', ]; -function getIconName(mode, modeSet) { - return modeSet === 'default' ? `mode-${mode}` : `mode-${modeSet}-${mode}`; +const noTheme = ['bikepark', 'carpark', 'subway', 'airplane']; // common icon in all themes + +function getIconName(mode, modeSet, boxed) { + const theme = noTheme.includes(mode) ? '' : `-${modeSet}`; + const fill = boxed ? '' : '-fill'; // do not render boxed icon for vertical + return `${mode}${fill}${theme}`; } +const MAX_VISIBLE_MODES = 7; + function NearStopsAndRoutes({ + appElement, + horizontal, modeArray, - urlPrefix, language, - showTitle, + title, alertsContext, - LinkComponent, origin, - omitLanguageUrl, onClick, - buttonStyle, - title, - modes, modeSet, - modeIconColors, + colors, fontWeights, + isMobile, + urlPrefix, + omitLanguageUrl, }) { const [modesWithAlerts, setModesWithAlerts] = useState([]); + const [modalOpen, setModalOpen] = useState(false); const [t] = useTranslation(); + let urlStart; + if (omitLanguageUrl) { + urlStart = urlPrefix; + } else { + const urlParts = urlPrefix.split('/'); + urlParts.splice(urlParts.length - 1, 0, language); + urlStart = urlParts.join('/'); + } + useEffect(() => { if (alertsContext) { alertsContext @@ -115,182 +130,182 @@ function NearStopsAndRoutes({ } }, []); - let urlStart; - if (omitLanguageUrl) { - urlStart = urlPrefix; - } else { - const urlParts = urlPrefix.split('/'); - urlParts.splice(urlParts.length - 1, 0, language); - urlStart = urlParts.join('/'); - } - const buttons = modeArray - .filter(mode => validNearYouModes.includes(mode)) - .map(mode => { - const withAlert = modesWithAlerts.includes(mode.toUpperCase()); - let url = `${urlStart}/${mode.toUpperCase()}/POS`; - if (origin.lat && origin.lon) { - url += `/${encodeURIComponent(origin.address)}::${origin.lat},${ + const urlPostfix = + origin.lat && origin.lon + ? `/POS/${encodeURIComponent(origin.address)}::${origin.lat},${ origin.lon - }`; - } + }` + : '/POS'; + const linkedButtonProps = { role: 'link', tabIndex: '0' }; - const modeButton = !modes ? ( - <> - - {t(`pick-mode-${mode}`, { lng: language })} - - - - - {withAlert && ( - - - - )} - - - - ) : ( - <> - - {t(`pick-mode-${mode}`, { lng: language })} - - - - - {withAlert && ( - - - - )} - - - {modes[mode]['nearYouLabel'][language]} - - - - ); + // line between buttons + const separator = ( +
+ ); + const renderButtons = (modes, forModal) => + modes.map(mode => { + const withAlert = modesWithAlerts.includes(mode.toUpperCase()); + const url = `${urlStart}/${mode.toUpperCase()}${urlPostfix}`; + const boxed = forModal || horizontal; // squared icon or interior only + const buttonProps = { + mode, + modeSet, + colors, + withAlert, + boxed, + getIconName, + }; - if (onClick) { - return ( -
{ - if (isKeyboardSelectionEvent(e)) { - onClick(url, e); - } - }} - onClick={() => onClick(url)} + if (forModal || !horizontal) { + let key = mode; + if (forModal) { + key = + modeSet === 'hsl' && mode === 'rail' + ? 'rail_local' + : `${mode}_short`; + } + buttonProps.title = ( + - {modeButton} -
+ {t(key, { lng: language })} + ); + } else { + buttonProps.srMsg = t(mode, { lng: language }); } - if (LinkComponent) { - return ( - - {modeButton} - - ); + if (!forModal) { + buttonProps.withBorder = true; + } else { + buttonProps.withArrow = true; + buttonProps.margin = '0'; + buttonProps.iconSize = '35px'; + buttonProps.padding = '6px'; } - return ( - - {modeButton} - + const clickProps = + mode === 'more' + ? { + onKeyDown: e => { + if (isKeyboardSelectionEvent(e)) { + setModalOpen(true); + } + }, + onClick: () => setModalOpen(true), + } + : { + onKeyDown: e => { + if (isKeyboardSelectionEvent(e)) { + onClick(url, e); + } + }, + onClick: () => onClick(url), + }; + + const button = ( +
+ +
+ ); + + // add separator line into modal button array + return forModal && mode !== modes[modes.length - 1] ? ( +
+ {button} + {separator} +
+ ) : ( + button ); }); + const modes = modeArray.filter(mode => validNearYouModes.includes(mode)); + const useModal = horizontal && modes.length > MAX_VISIBLE_MODES; + let visibleModes = modes; + + if (useModal) { + visibleModes = modes.slice(0, MAX_VISIBLE_MODES - 1); + visibleModes.push('more'); + } + return (
- {showTitle && ( -

- {!modes - ? t('title-route-stop-station', { lng: language }) - : title[language]} -

+ {useModal && ( + setModalOpen(false)} + colors={colors} + > + {renderButtons(modes, true)} + )} +

+ {title?.[language] || t('title', { lng: language })} +

- {buttons} + {renderButtons(visibleModes, false)}
); } NearStopsAndRoutes.propTypes = { + appElement: PropTypes.string.isRequired, modeArray: PropTypes.arrayOf(PropTypes.string).isRequired, - urlPrefix: PropTypes.string.isRequired, + title: PropTypes.objectOf(PropTypes.string), language: PropTypes.string, - showTitle: PropTypes.bool, + horizontal: PropTypes.bool, alertsContext: PropTypes.shape({ getModesWithAlerts: PropTypes.func, currentTime: PropTypes.number, feedIds: PropTypes.arrayOf(PropTypes.string), }), - LinkComponent: PropTypes.object, origin: PropTypes.shape({ address: PropTypes.string, lat: PropTypes.number, lon: PropTypes.number, }), - omitLanguageUrl: PropTypes.bool, - onClick: PropTypes.func, - buttonStyle: PropTypes.objectOf(PropTypes.string), - title: PropTypes.objectOf(PropTypes.string), - modes: PropTypes.object, - modeIconColors: PropTypes.objectOf(PropTypes.string), + onClick: PropTypes.func.isRequired, + colors: PropTypes.objectOf(PropTypes.string), modeSet: PropTypes.string, fontWeights: PropTypes.shape({ medium: PropTypes.number, }), + isMobile: PropTypes.bool, + urlPrefix: PropTypes.string.isRequired, + omitLanguageUrl: PropTypes.bool, }; NearStopsAndRoutes.defaultProps = { - showTitle: false, + horizontal: true, language: 'fi', - LinkComponent: undefined, origin: undefined, - omitLanguageUrl: undefined, - buttonStyle: undefined, alertsContext: undefined, - onClick: undefined, title: undefined, - modes: undefined, - modeIconColors: { - 'mode-bus': '#007ac9', - 'mode-rail': '#8c4799', - 'mode-tram': '#008151', - 'mode-subway': '#ed8c00', - 'mode-ferry': '#007A97', - 'mode-citybike': '#F2B62D', - }, - modeSet: 'default', - fontWeights: { - medium: 500, - }, + colors: defaultColors, + modeSet: 'hsl', + fontWeights: { medium: 500 }, + isMobile: false, + omitLanguageUrl: false, }; /** @@ -302,8 +317,6 @@ NearStopsAndRoutes.defaultProps = { * * */ @@ -337,7 +350,7 @@ class CtrlPanel extends React.Component {
{this.props.children}
diff --git a/digitransit-component/packages/digitransit-component-datetimepicker/package.json b/digitransit-component/packages/digitransit-component-datetimepicker/package.json index a07bfd3af3..fdc86d1bb6 100644 --- a/digitransit-component/packages/digitransit-component-datetimepicker/package.json +++ b/digitransit-component/packages/digitransit-component-datetimepicker/package.json @@ -1,6 +1,6 @@ { "name": "@digitransit-component/digitransit-component-datetimepicker", - "version": "4.0.2", + "version": "5.0.0", "description": "digitransit-component datetimepicker module", "main": "index.js", "files": [ @@ -29,7 +29,7 @@ "author": "Digitransit Authors", "license": "(AGPL-3.0 OR EUPL-1.2)", "peerDependencies": { - "@digitransit-component/digitransit-component-icon": "^1.2.0", + "@digitransit-component/digitransit-component-icon": "^2.0.0", "classnames": "2.5.1", "i18next": "^22.5.1", "lodash": "4.17.21", diff --git a/digitransit-component/packages/digitransit-component-dialog-modal/package.json b/digitransit-component/packages/digitransit-component-dialog-modal/package.json index fcaa7ce5d7..d673b92d23 100644 --- a/digitransit-component/packages/digitransit-component-dialog-modal/package.json +++ b/digitransit-component/packages/digitransit-component-dialog-modal/package.json @@ -1,6 +1,6 @@ { "name": "@digitransit-component/digitransit-component-dialog-modal", - "version": "2.0.0", + "version": "3.0.0", "description": "digitransit-component dialog-modal module", "main": "index.js", "files": [ @@ -32,6 +32,7 @@ "@hsl-fi/modal": "^0.3.2" }, "peerDependencies": { + "@digitransit-component/digitransit-component-icon": "^2.0.0", "@hsl-fi/sass": "^0.2.0", "classnames": "2.5.1", "i18next": "^22.5.1", diff --git a/digitransit-component/packages/digitransit-component-dialog-modal/src/index.js b/digitransit-component/packages/digitransit-component-dialog-modal/src/index.js index 26297f8cc9..cf13337120 100644 --- a/digitransit-component/packages/digitransit-component-dialog-modal/src/index.js +++ b/digitransit-component/packages/digitransit-component-dialog-modal/src/index.js @@ -5,6 +5,7 @@ import React from 'react'; import cx from 'classnames'; import { I18nextProvider, useTranslation } from 'react-i18next'; import Modal from '@hsl-fi/modal'; +import { defaultColors } from '@digitransit-component/digitransit-component-icon'; import styles from './helpers/styles.scss'; import i18n from './helpers/i18n'; @@ -38,8 +39,7 @@ const DialogModal = ({ appElement, isModalOpen, modalAriaLabel, - color, - hoverColor, + colors, fontWeights, }) => { const [t] = useTranslation(); @@ -55,8 +55,8 @@ const DialogModal = ({ >
@@ -125,8 +125,7 @@ DialogModal.propTypes = { lang: PropTypes.string.isRequired, modalAriaLabel: PropTypes.string, href: PropTypes.string, - color: PropTypes.string, - hoverColor: PropTypes.string, + colors: PropTypes.objectOf(PropTypes.string), fontWeights: PropTypes.shape({ medium: PropTypes.number, }), @@ -139,17 +138,12 @@ DialogModal.defaultProps = { secondaryButtonOnClick: undefined, href: undefined, modalAriaLabel: '', - color: '#007ac9', - hoverColor: '#0062a1', + colors: defaultColors, fontWeights: { medium: 500, }, }; -DialogModal.contextTypes = { - config: PropTypes.object, -}; - export default props => ( diff --git a/digitransit-component/packages/digitransit-component-favourite-bar/package.json b/digitransit-component/packages/digitransit-component-favourite-bar/package.json index c0574f197c..f65c2495ab 100644 --- a/digitransit-component/packages/digitransit-component-favourite-bar/package.json +++ b/digitransit-component/packages/digitransit-component-favourite-bar/package.json @@ -1,6 +1,6 @@ { "name": "@digitransit-component/digitransit-component-favourite-bar", - "version": "4.0.3", + "version": "5.0.0", "description": "digitransit-component favourite-bar module", "main": "index.js", "files": [ @@ -32,8 +32,8 @@ "@digitransit-search-util/digitransit-search-util-uniq-by-label": "^2.1.0" }, "peerDependencies": { - "@digitransit-component/digitransit-component-icon": "^1.2.0", - "@digitransit-component/digitransit-component-suggestion-item": "^2.3.2", + "@digitransit-component/digitransit-component-icon": "^2.0.0", + "@digitransit-component/digitransit-component-suggestion-item": "^3.0.0", "@hsl-fi/sass": "^0.2.0", "@hsl-fi/shimmer": "0.1.2", "classnames": "2.5.1", diff --git a/digitransit-component/packages/digitransit-component-favourite-bar/src/index.js b/digitransit-component/packages/digitransit-component-favourite-bar/src/index.js index bbcd4c9734..1093ac0845 100644 --- a/digitransit-component/packages/digitransit-component-favourite-bar/src/index.js +++ b/digitransit-component/packages/digitransit-component-favourite-bar/src/index.js @@ -11,7 +11,9 @@ import isEqual from 'lodash/isEqual'; import isEmpty from 'lodash/isEmpty'; import Shimmer from '@hsl-fi/shimmer'; import SuggestionItem from '@digitransit-component/digitransit-component-suggestion-item'; -import Icon from '@digitransit-component/digitransit-component-icon'; +import Icon, { + defaultColors, +} from '@digitransit-component/digitransit-component-icon'; import { formatFavouritePlaceLabel } from '@digitransit-search-util/digitransit-search-util-uniq-by-label'; import styles from './helpers/styles.scss'; import i18n from './helpers/i18n'; @@ -139,8 +141,8 @@ class FavouriteBar extends React.Component { lang: PropTypes.string, /** Optional. Whether to show loading animation, true or false. */ isLoading: PropTypes.bool, - /** Optional. Default value is '#007ac9'. */ - color: PropTypes.string, + /** Optional color palette */ + colors: PropTypes.objectOf(PropTypes.string), /** Optional. */ fontWeights: PropTypes.shape({ /** Default value is 500. */ @@ -158,7 +160,7 @@ class FavouriteBar extends React.Component { onAddWork: () => ({}), lang: 'fi', isLoading: false, - color: '#007ac9', + colors: defaultColors, fontWeights: { medium: 500, }, @@ -286,12 +288,7 @@ class FavouriteBar extends React.Component { } }; - renderSuggestion = ( - item, - index, - ariaLabelSuffix = '', - className = undefined, - ) => { + renderSuggestion = (item, index, ariaLabelSuffix = '') => { const id = `favourite-suggestion-list--item-${index}`; return (
  • @@ -312,8 +309,7 @@ class FavouriteBar extends React.Component { >
  • @@ -342,6 +338,7 @@ class FavouriteBar extends React.Component { render() { const { onClickFavourite, isLoading, fontWeights } = this.props; + const { primary } = this.props.colors; const { listOpen, favourites, firstFavourite, secondFavourite } = this.state; const expandIcon = this.props.favourites.length === 0 ? 'plus' : 'arrow'; @@ -368,7 +365,7 @@ class FavouriteBar extends React.Component { : 'home' } isLoading={isLoading} - color={this.props.color} + color={primary} lang={this.props.lang} /> {/* eslint-disable jsx-a11y/role-supports-aria-props */} @@ -404,7 +401,7 @@ class FavouriteBar extends React.Component { aria-label={this.translate('open-favourites')} > - + {/* eslint-enable jsx-a11y/role-supports-aria-props */} @@ -441,7 +438,6 @@ class FavouriteBar extends React.Component { item, favourites.length + index, undefined, - 'favouriteCustom', ), )} diff --git a/digitransit-component/packages/digitransit-component-favourite-editing-modal/package.json b/digitransit-component/packages/digitransit-component-favourite-editing-modal/package.json index d8366dc0a8..d64b7994c4 100644 --- a/digitransit-component/packages/digitransit-component-favourite-editing-modal/package.json +++ b/digitransit-component/packages/digitransit-component-favourite-editing-modal/package.json @@ -1,6 +1,6 @@ { "name": "@digitransit-component/digitransit-component-favourite-editing-modal", - "version": "4.0.1", + "version": "5.0.0", "description": "digitransit-component favourite-editing-modal module", "main": "index.js", "files": [ @@ -32,8 +32,8 @@ "@digitransit-search-util/digitransit-search-util-uniq-by-label": "^2.1.0" }, "peerDependencies": { - "@digitransit-component/digitransit-component-dialog-modal": "^2.0.0", - "@digitransit-component/digitransit-component-icon": "^1.2.0", + "@digitransit-component/digitransit-component-dialog-modal": "^3.0.0", + "@digitransit-component/digitransit-component-icon": "^2.0.0", "@hsl-fi/container-spinner": "0.3.2", "@hsl-fi/modal": "^0.3.2", "@hsl-fi/sass": "^0.2.0", diff --git a/digitransit-component/packages/digitransit-component-favourite-editing-modal/src/helpers/ModalContent.js b/digitransit-component/packages/digitransit-component-favourite-editing-modal/src/helpers/ModalContent.js index 48ed1b7d2f..360a2b80a9 100644 --- a/digitransit-component/packages/digitransit-component-favourite-editing-modal/src/helpers/ModalContent.js +++ b/digitransit-component/packages/digitransit-component-favourite-editing-modal/src/helpers/ModalContent.js @@ -1,4 +1,3 @@ -/* eslint-disable jsx-a11y/click-events-have-key-events */ import React from 'react'; import PropTypes from 'prop-types'; import styles from './modal-content.scss'; diff --git a/digitransit-component/packages/digitransit-component-favourite-editing-modal/src/index.js b/digitransit-component/packages/digitransit-component-favourite-editing-modal/src/index.js index 85d88424bf..39c9e21191 100644 --- a/digitransit-component/packages/digitransit-component-favourite-editing-modal/src/index.js +++ b/digitransit-component/packages/digitransit-component-favourite-editing-modal/src/index.js @@ -10,7 +10,9 @@ import isEmpty from 'lodash/isEmpty'; import omit from 'lodash/omit'; import ContainerSpinner from '@hsl-fi/container-spinner'; import Modal from '@hsl-fi/modal'; -import Icon from '@digitransit-component/digitransit-component-icon'; +import Icon, { + defaultColors, +} from '@digitransit-component/digitransit-component-icon'; import DialogModal from '@digitransit-component/digitransit-component-dialog-modal'; import { formatFavouritePlaceLabel } from '@digitransit-search-util/digitransit-search-util-uniq-by-label'; import ModalContent from './helpers/ModalContent'; @@ -76,8 +78,7 @@ class FavouriteEditingModal extends React.Component { isModalOpen: PropTypes.bool.isRequired, isMobile: PropTypes.bool, isLoading: PropTypes.bool.isRequired, - color: PropTypes.string, - hoverColor: PropTypes.string, + colors: PropTypes.objectOf(PropTypes.string), /** Optional. */ fontWeights: PropTypes.shape({ /** Default value is 500. */ @@ -88,8 +89,7 @@ class FavouriteEditingModal extends React.Component { static defaultProps = { lang: 'fi', isMobile: false, - color: '#007ac9', - hoverColor: '#0062a1', + colors: defaultColors, fontWeights: { medium: 500, }, @@ -194,7 +194,7 @@ class FavouriteEditingModal extends React.Component { styles[iconId], )} > - +
    @@ -302,8 +302,7 @@ class FavouriteEditingModal extends React.Component { showDeletePlaceModal: false, }) } - color={this.props.color} - hoverColor={this.props.hoverColor} + colors={this.props.colors} fontWeights={this.props.fontWeights} lang={this.props.lang} /> @@ -321,19 +320,19 @@ class FavouriteEditingModal extends React.Component { }; renderModalContent = () => { - const { color, hoverColor, fontWeights } = this.props; + const { fontWeights } = this.props; + const { primary, hover } = this.props.colors; const modalProps = { headerText: this.translate('edit-places'), - renderList: () => this.renderFavouriteList(), + renderList: this.renderFavouriteList, + }; + const style = { + '--color': primary, + '--hover-color': hover, + '--font-weight-medium': fontWeights.medium, }; return ( -
    +
    ); @@ -343,34 +342,17 @@ class FavouriteEditingModal extends React.Component { const { isMobile } = this.props; const { showDeletePlaceModal, selectedFavourite } = this.state; return ( -
    - {isMobile && ( - - {this.renderDeleteFavouriteModal(selectedFavourite)} - {this.renderModalContent()} - - )} - {!isMobile && ( - - {this.renderDeleteFavouriteModal(selectedFavourite)} - {!showDeletePlaceModal && this.renderModalContent()} - - )} -
    + + {this.renderDeleteFavouriteModal(selectedFavourite)} + {!showDeletePlaceModal && this.renderModalContent()} + ); } } diff --git a/digitransit-component/packages/digitransit-component-favourite-modal/package.json b/digitransit-component/packages/digitransit-component-favourite-modal/package.json index 5b0f4fa7e6..be0c8240a3 100644 --- a/digitransit-component/packages/digitransit-component-favourite-modal/package.json +++ b/digitransit-component/packages/digitransit-component-favourite-modal/package.json @@ -1,6 +1,6 @@ { "name": "@digitransit-component/digitransit-component-favourite-modal", - "version": "3.0.1", + "version": "4.0.0", "description": "digitransit-component favourite-modal module", "main": "index.js", "files": [ @@ -29,7 +29,7 @@ "author": "Digitransit Authors", "license": "(AGPL-3.0 OR EUPL-1.2)", "peerDependencies": { - "@digitransit-component/digitransit-component-icon": "^1.2.0", + "@digitransit-component/digitransit-component-icon": "^2.0.0", "@hsl-fi/modal": "^0.3.2", "@hsl-fi/sass": "^0.2.0", "classnames": "2.5.1", diff --git a/digitransit-component/packages/digitransit-component-favourite-modal/src/index.js b/digitransit-component/packages/digitransit-component-favourite-modal/src/index.js index 968249fe9a..ec23d58211 100644 --- a/digitransit-component/packages/digitransit-component-favourite-modal/src/index.js +++ b/digitransit-component/packages/digitransit-component-favourite-modal/src/index.js @@ -10,7 +10,9 @@ import { import isEmpty from 'lodash/isEmpty'; import isNumber from 'lodash/isNumber'; import Modal from '@hsl-fi/modal'; -import Icon from '@digitransit-component/digitransit-component-icon'; +import Icon, { + defaultColors, +} from '@digitransit-component/digitransit-component-icon'; import styles from './helpers/styles.scss'; import i18n from './helpers/i18n'; import DesktopModal from './helpers/DesktopModal'; @@ -61,26 +63,21 @@ const FavouriteIconTableButton = ({ FavouriteIconTableButton.propTypes = { handleClick: PropTypes.func.isRequired, value: PropTypes.string.isRequired, - selectedIconId: PropTypes.string.isRequired, + selectedIconId: PropTypes.string, color: PropTypes.string.isRequired, lang: PropTypes.string.isRequired, }; -const FavouriteIconTable = ({ - favouriteIconIds, - selectedIconId, - handleClick, - color, - lang, -}) => { +FavouriteIconTableButton.defaultProps = { + selectedIconId: '', +}; + +const FavouriteIconTable = ({ favouriteIconIds, ...rest }) => { const columns = favouriteIconIds.map(value => ( )); @@ -92,15 +89,7 @@ const FavouriteIconTable = ({ }; FavouriteIconTable.propTypes = { - handleClick: PropTypes.func.isRequired, favouriteIconIds: PropTypes.arrayOf(PropTypes.string).isRequired, - selectedIconId: PropTypes.string, - color: PropTypes.string.isRequired, - lang: PropTypes.string.isRequired, -}; - -FavouriteIconTable.defaultProps = { - selectedIconId: '', }; /** @@ -182,8 +171,7 @@ class FavouriteModal extends React.Component { /** Optional. */ isMobile: PropTypes.bool, appElement: PropTypes.string.isRequired, - color: PropTypes.string, - hoverColor: PropTypes.string, + colors: PropTypes.objectOf(PropTypes.string), /** Optional. */ fontWeights: PropTypes.shape({ /** Default value is 500. */ @@ -198,8 +186,7 @@ class FavouriteModal extends React.Component { favourite: null, autosuggestComponent: undefined, addAnalyticsEvent: undefined, - color: '#007ac9', - hoverColor: '#0062a1', + colors: defaultColors, fontWeights: { medium: 500, }, @@ -331,7 +318,9 @@ class FavouriteModal extends React.Component { render() { const { favourite } = this.state; - const { color, hoverColor, fontWeights, lang, t } = this.props; + const { fontWeights, lang, t } = this.props; + const { primary, hover } = this.props.colors; + const headerText = this.isEdit() ? t('edit-place', { lng: lang }) : t('save-place', { lng: lang }); @@ -339,8 +328,6 @@ class FavouriteModal extends React.Component { headerText, autosuggestComponent: { ...this.props.autosuggestComponent, - color, - hoverColor, }, inputPlaceholder: t('input-placeholder', { lng: lang }), specifyName: this.specifyName, @@ -356,7 +343,7 @@ class FavouriteModal extends React.Component { })()} favouriteIconIds={FavouriteModal.favouriteIconIds} handleClick={this.selectIcon} - color={color} + color={primary} lang={lang} /> ), @@ -366,8 +353,8 @@ class FavouriteModal extends React.Component { isEdit: this.isEdit(), cancelText: t('cancel', { lng: lang }), cancelSelected: () => this.cancelSelected(), - color, - hoverColor, + color: primary, + hoverColor: hover, savePlaceText: t('save-place', { lng: lang }), cantSaveText: t('cannot-save-place', { lng: lang }), requiredText: t('required-text', { lng: lang }), diff --git a/digitransit-component/packages/digitransit-component-icon/package.json b/digitransit-component/packages/digitransit-component-icon/package.json index 7e3287b913..1f3c59aac6 100644 --- a/digitransit-component/packages/digitransit-component-icon/package.json +++ b/digitransit-component/packages/digitransit-component-icon/package.json @@ -1,6 +1,6 @@ { "name": "@digitransit-component/digitransit-component-icon", - "version": "1.2.0", + "version": "2.0.0", "description": "digitransit-component icon module", "main": "index.js", "files": [ diff --git a/digitransit-component/packages/digitransit-component-icon/src/assets/airplane.svg b/digitransit-component/packages/digitransit-component-icon/src/assets/airplane.svg index a7075ad7a6..5e563003bc 100644 --- a/digitransit-component/packages/digitransit-component-icon/src/assets/airplane.svg +++ b/digitransit-component/packages/digitransit-component-icon/src/assets/airplane.svg @@ -1,3 +1,4 @@ - - + + + diff --git a/digitransit-component/packages/digitransit-component-icon/src/assets/arrow.svg b/digitransit-component/packages/digitransit-component-icon/src/assets/arrow.svg index 3df4ef3b39..0f18ea5784 100644 --- a/digitransit-component/packages/digitransit-component-icon/src/assets/arrow.svg +++ b/digitransit-component/packages/digitransit-component-icon/src/assets/arrow.svg @@ -1,6 +1,4 @@ - - diff --git a/digitransit-component/packages/digitransit-component-icon/src/assets/bikepark-fill.svg b/digitransit-component/packages/digitransit-component-icon/src/assets/bikepark-fill.svg new file mode 100644 index 0000000000..728a5474a2 --- /dev/null +++ b/digitransit-component/packages/digitransit-component-icon/src/assets/bikepark-fill.svg @@ -0,0 +1,3 @@ + + + diff --git a/digitransit-component/packages/digitransit-component-icon/src/assets/bike-park.svg b/digitransit-component/packages/digitransit-component-icon/src/assets/bikepark.svg similarity index 100% rename from digitransit-component/packages/digitransit-component-icon/src/assets/bike-park.svg rename to digitransit-component/packages/digitransit-component-icon/src/assets/bikepark.svg diff --git a/digitransit-component/packages/digitransit-component-icon/src/assets/search-bus-station-digitransit.svg b/digitransit-component/packages/digitransit-component-icon/src/assets/bus-digitransit.svg similarity index 77% rename from digitransit-component/packages/digitransit-component-icon/src/assets/search-bus-station-digitransit.svg rename to digitransit-component/packages/digitransit-component-icon/src/assets/bus-digitransit.svg index fe700a1e76..fbdbe4719f 100644 --- a/digitransit-component/packages/digitransit-component-icon/src/assets/search-bus-station-digitransit.svg +++ b/digitransit-component/packages/digitransit-component-icon/src/assets/bus-digitransit.svg @@ -1,5 +1,5 @@ - - + + diff --git a/digitransit-component/packages/digitransit-component-icon/src/assets/bus-express.svg b/digitransit-component/packages/digitransit-component-icon/src/assets/bus-express.svg deleted file mode 100644 index 3bed907e35..0000000000 --- a/digitransit-component/packages/digitransit-component-icon/src/assets/bus-express.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/digitransit-component/packages/digitransit-component-icon/src/assets/bus-waltti.svg b/digitransit-component/packages/digitransit-component-icon/src/assets/bus-fill-digitransit.svg similarity index 91% rename from digitransit-component/packages/digitransit-component-icon/src/assets/bus-waltti.svg rename to digitransit-component/packages/digitransit-component-icon/src/assets/bus-fill-digitransit.svg index a3510999b4..72c5dc60eb 100644 --- a/digitransit-component/packages/digitransit-component-icon/src/assets/bus-waltti.svg +++ b/digitransit-component/packages/digitransit-component-icon/src/assets/bus-fill-digitransit.svg @@ -1,4 +1,4 @@ - + diff --git a/digitransit-component/packages/digitransit-component-icon/src/assets/mode_bus.svg b/digitransit-component/packages/digitransit-component-icon/src/assets/bus-hsl.svg similarity index 100% rename from digitransit-component/packages/digitransit-component-icon/src/assets/mode_bus.svg rename to digitransit-component/packages/digitransit-component-icon/src/assets/bus-hsl.svg diff --git a/digitransit-component/packages/digitransit-component-icon/src/assets/bus-local.svg b/digitransit-component/packages/digitransit-component-icon/src/assets/bus-local-hsl.svg similarity index 90% rename from digitransit-component/packages/digitransit-component-icon/src/assets/bus-local.svg rename to digitransit-component/packages/digitransit-component-icon/src/assets/bus-local-hsl.svg index d8b62a8e00..e7287fb1aa 100644 --- a/digitransit-component/packages/digitransit-component-icon/src/assets/bus-local.svg +++ b/digitransit-component/packages/digitransit-component-icon/src/assets/bus-local-hsl.svg @@ -1,4 +1,4 @@ - + diff --git a/digitransit-component/packages/digitransit-component-icon/src/assets/bus-replacement-hsl.svg b/digitransit-component/packages/digitransit-component-icon/src/assets/bus-replacement-hsl.svg new file mode 100644 index 0000000000..ea4605ac66 --- /dev/null +++ b/digitransit-component/packages/digitransit-component-icon/src/assets/bus-replacement-hsl.svg @@ -0,0 +1,4 @@ + + + + diff --git a/digitransit-component/packages/digitransit-component-icon/src/assets/bus-replacement.svg b/digitransit-component/packages/digitransit-component-icon/src/assets/bus-replacement.svg deleted file mode 100644 index 57db6e0cd3..0000000000 --- a/digitransit-component/packages/digitransit-component-icon/src/assets/bus-replacement.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/digitransit-component/packages/digitransit-component-icon/src/assets/search-bus-stop-digitransit.svg b/digitransit-component/packages/digitransit-component-icon/src/assets/bus-stop-digitransit.svg similarity index 93% rename from digitransit-component/packages/digitransit-component-icon/src/assets/search-bus-stop-digitransit.svg rename to digitransit-component/packages/digitransit-component-icon/src/assets/bus-stop-digitransit.svg index d13a3e04a2..03bfb26007 100644 --- a/digitransit-component/packages/digitransit-component-icon/src/assets/search-bus-stop-digitransit.svg +++ b/digitransit-component/packages/digitransit-component-icon/src/assets/bus-stop-digitransit.svg @@ -1,4 +1,4 @@ - + diff --git a/digitransit-component/packages/digitransit-component-icon/src/assets/search-bus-stop-default.svg b/digitransit-component/packages/digitransit-component-icon/src/assets/bus-stop-hsl.svg similarity index 78% rename from digitransit-component/packages/digitransit-component-icon/src/assets/search-bus-stop-default.svg rename to digitransit-component/packages/digitransit-component-icon/src/assets/bus-stop-hsl.svg index b3d08dd947..0ae648fbf8 100644 --- a/digitransit-component/packages/digitransit-component-icon/src/assets/search-bus-stop-default.svg +++ b/digitransit-component/packages/digitransit-component-icon/src/assets/bus-stop-hsl.svg @@ -1,6 +1,5 @@ - + - - + diff --git a/digitransit-component/packages/digitransit-component-icon/src/assets/bus.svg b/digitransit-component/packages/digitransit-component-icon/src/assets/bus.svg deleted file mode 100644 index 1fd5e8b159..0000000000 --- a/digitransit-component/packages/digitransit-component-icon/src/assets/bus.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/digitransit-component/packages/digitransit-component-icon/src/assets/bus_stop.svg b/digitransit-component/packages/digitransit-component-icon/src/assets/bus_stop.svg deleted file mode 100644 index 14fe00cdfd..0000000000 --- a/digitransit-component/packages/digitransit-component-icon/src/assets/bus_stop.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/digitransit-component/packages/digitransit-component-icon/src/assets/search-bustram-stop-digitransit.svg b/digitransit-component/packages/digitransit-component-icon/src/assets/bustram-stop-digitransit.svg similarity index 96% rename from digitransit-component/packages/digitransit-component-icon/src/assets/search-bustram-stop-digitransit.svg rename to digitransit-component/packages/digitransit-component-icon/src/assets/bustram-stop-digitransit.svg index 49b7ab0a3c..0dcc229fb1 100644 --- a/digitransit-component/packages/digitransit-component-icon/src/assets/search-bustram-stop-digitransit.svg +++ b/digitransit-component/packages/digitransit-component-icon/src/assets/bustram-stop-digitransit.svg @@ -1,4 +1,4 @@ - + diff --git a/digitransit-component/packages/digitransit-component-icon/src/assets/calendar.svg b/digitransit-component/packages/digitransit-component-icon/src/assets/calendar.svg index 2cbcf4a509..e4349c01d0 100644 --- a/digitransit-component/packages/digitransit-component-icon/src/assets/calendar.svg +++ b/digitransit-component/packages/digitransit-component-icon/src/assets/calendar.svg @@ -1,3 +1,3 @@ - - + + diff --git a/digitransit-component/packages/digitransit-component-icon/src/assets/carpark-fill.svg b/digitransit-component/packages/digitransit-component-icon/src/assets/carpark-fill.svg new file mode 100644 index 0000000000..d93666b4e0 --- /dev/null +++ b/digitransit-component/packages/digitransit-component-icon/src/assets/carpark-fill.svg @@ -0,0 +1,3 @@ + + + diff --git a/digitransit-component/packages/digitransit-component-icon/src/assets/car-park.svg b/digitransit-component/packages/digitransit-component-icon/src/assets/carpark.svg similarity index 91% rename from digitransit-component/packages/digitransit-component-icon/src/assets/car-park.svg rename to digitransit-component/packages/digitransit-component-icon/src/assets/carpark.svg index 67a0f01717..3e067992ad 100644 --- a/digitransit-component/packages/digitransit-component-icon/src/assets/car-park.svg +++ b/digitransit-component/packages/digitransit-component-icon/src/assets/carpark.svg @@ -1,4 +1,4 @@ - + diff --git a/digitransit-component/packages/digitransit-component-icon/src/assets/check.svg b/digitransit-component/packages/digitransit-component-icon/src/assets/check.svg index c1c1352aef..06932b8e63 100644 --- a/digitransit-component/packages/digitransit-component-icon/src/assets/check.svg +++ b/digitransit-component/packages/digitransit-component-icon/src/assets/check.svg @@ -1,3 +1,3 @@ - + diff --git a/digitransit-component/packages/digitransit-component-icon/src/assets/citybike-digitransit.svg b/digitransit-component/packages/digitransit-component-icon/src/assets/citybike-digitransit.svg new file mode 100644 index 0000000000..9225ac5140 --- /dev/null +++ b/digitransit-component/packages/digitransit-component-icon/src/assets/citybike-digitransit.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/digitransit-component/packages/digitransit-component-icon/src/assets/citybike-waltti.svg b/digitransit-component/packages/digitransit-component-icon/src/assets/citybike-fill-digitransit.svg similarity index 86% rename from digitransit-component/packages/digitransit-component-icon/src/assets/citybike-waltti.svg rename to digitransit-component/packages/digitransit-component-icon/src/assets/citybike-fill-digitransit.svg index 4adf3990f3..b72990f4b2 100644 --- a/digitransit-component/packages/digitransit-component-icon/src/assets/citybike-waltti.svg +++ b/digitransit-component/packages/digitransit-component-icon/src/assets/citybike-fill-digitransit.svg @@ -1,4 +1,4 @@ - - - + + + diff --git a/digitransit-component/packages/digitransit-component-icon/src/assets/mode_citybike.svg b/digitransit-component/packages/digitransit-component-icon/src/assets/citybike-hsl.svg similarity index 100% rename from digitransit-component/packages/digitransit-component-icon/src/assets/mode_citybike.svg rename to digitransit-component/packages/digitransit-component-icon/src/assets/citybike-hsl.svg diff --git a/digitransit-component/packages/digitransit-component-icon/src/assets/citybike-stop-default-secondary.svg b/digitransit-component/packages/digitransit-component-icon/src/assets/citybike-stop-default-secondary.svg deleted file mode 100644 index f68ec8e9dc..0000000000 --- a/digitransit-component/packages/digitransit-component-icon/src/assets/citybike-stop-default-secondary.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/digitransit-component/packages/digitransit-component-icon/src/assets/citybike-stop-default.svg b/digitransit-component/packages/digitransit-component-icon/src/assets/citybike-stop-default.svg deleted file mode 100644 index 5e8c166b17..0000000000 --- a/digitransit-component/packages/digitransit-component-icon/src/assets/citybike-stop-default.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/digitransit-component/packages/digitransit-component-icon/src/assets/citybike-stop-digitransit-secondary.svg b/digitransit-component/packages/digitransit-component-icon/src/assets/citybike-stop-digitransit-secondary.svg index 199b056d1f..05fe3bf664 100644 --- a/digitransit-component/packages/digitransit-component-icon/src/assets/citybike-stop-digitransit-secondary.svg +++ b/digitransit-component/packages/digitransit-component-icon/src/assets/citybike-stop-digitransit-secondary.svg @@ -1,4 +1,4 @@ - + diff --git a/digitransit-component/packages/digitransit-component-icon/src/assets/citybike-stop-digitransit.svg b/digitransit-component/packages/digitransit-component-icon/src/assets/citybike-stop-digitransit.svg index dfec425e01..2b86336eb9 100644 --- a/digitransit-component/packages/digitransit-component-icon/src/assets/citybike-stop-digitransit.svg +++ b/digitransit-component/packages/digitransit-component-icon/src/assets/citybike-stop-digitransit.svg @@ -1,4 +1,4 @@ - + diff --git a/digitransit-component/packages/digitransit-component-icon/src/assets/citybike-stop-hsl-secondary.svg b/digitransit-component/packages/digitransit-component-icon/src/assets/citybike-stop-hsl-secondary.svg new file mode 100644 index 0000000000..6e44de48cd --- /dev/null +++ b/digitransit-component/packages/digitransit-component-icon/src/assets/citybike-stop-hsl-secondary.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/digitransit-component/packages/digitransit-component-icon/src/assets/citybike-stop-hsl.svg b/digitransit-component/packages/digitransit-component-icon/src/assets/citybike-stop-hsl.svg new file mode 100644 index 0000000000..0c96e58369 --- /dev/null +++ b/digitransit-component/packages/digitransit-component-icon/src/assets/citybike-stop-hsl.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/digitransit-component/packages/digitransit-component-icon/src/assets/citybike.svg b/digitransit-component/packages/digitransit-component-icon/src/assets/citybike.svg deleted file mode 100644 index 86e4c8c9b1..0000000000 --- a/digitransit-component/packages/digitransit-component-icon/src/assets/citybike.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/digitransit-component/packages/digitransit-component-icon/src/assets/search-ferry-digitransit.svg b/digitransit-component/packages/digitransit-component-icon/src/assets/ferry-digitransit.svg similarity index 89% rename from digitransit-component/packages/digitransit-component-icon/src/assets/search-ferry-digitransit.svg rename to digitransit-component/packages/digitransit-component-icon/src/assets/ferry-digitransit.svg index f10c100540..ff01aa4e83 100644 --- a/digitransit-component/packages/digitransit-component-icon/src/assets/search-ferry-digitransit.svg +++ b/digitransit-component/packages/digitransit-component-icon/src/assets/ferry-digitransit.svg @@ -1,6 +1,6 @@ - - - + + + diff --git a/digitransit-component/packages/digitransit-component-icon/src/assets/ferry-waltti.svg b/digitransit-component/packages/digitransit-component-icon/src/assets/ferry-fill-digitransit.svg similarity index 96% rename from digitransit-component/packages/digitransit-component-icon/src/assets/ferry-waltti.svg rename to digitransit-component/packages/digitransit-component-icon/src/assets/ferry-fill-digitransit.svg index 7e38b41aaf..e8079d17e5 100644 --- a/digitransit-component/packages/digitransit-component-icon/src/assets/ferry-waltti.svg +++ b/digitransit-component/packages/digitransit-component-icon/src/assets/ferry-fill-digitransit.svg @@ -1,4 +1,4 @@ - + diff --git a/digitransit-component/packages/digitransit-component-icon/src/assets/search-ferry-default.svg b/digitransit-component/packages/digitransit-component-icon/src/assets/ferry-hsl.svg similarity index 82% rename from digitransit-component/packages/digitransit-component-icon/src/assets/search-ferry-default.svg rename to digitransit-component/packages/digitransit-component-icon/src/assets/ferry-hsl.svg index 872adc64d7..876c35e486 100644 --- a/digitransit-component/packages/digitransit-component-icon/src/assets/search-ferry-default.svg +++ b/digitransit-component/packages/digitransit-component-icon/src/assets/ferry-hsl.svg @@ -1,4 +1,4 @@ - - + + diff --git a/digitransit-component/packages/digitransit-component-icon/src/assets/ferry-stop-digitransit.svg b/digitransit-component/packages/digitransit-component-icon/src/assets/ferry-stop-digitransit.svg new file mode 100644 index 0000000000..9632e03a27 --- /dev/null +++ b/digitransit-component/packages/digitransit-component-icon/src/assets/ferry-stop-digitransit.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/digitransit-component/packages/digitransit-component-icon/src/assets/ferry-stop-hsl.svg b/digitransit-component/packages/digitransit-component-icon/src/assets/ferry-stop-hsl.svg new file mode 100644 index 0000000000..d55212217d --- /dev/null +++ b/digitransit-component/packages/digitransit-component-icon/src/assets/ferry-stop-hsl.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/digitransit-component/packages/digitransit-component-icon/src/assets/ferry.svg b/digitransit-component/packages/digitransit-component-icon/src/assets/ferry.svg deleted file mode 100644 index 51cbd9b836..0000000000 --- a/digitransit-component/packages/digitransit-component-icon/src/assets/ferry.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/digitransit-component/packages/digitransit-component-icon/src/assets/funicular-stop.svg b/digitransit-component/packages/digitransit-component-icon/src/assets/funicular-stop.svg new file mode 100644 index 0000000000..8600f05fec --- /dev/null +++ b/digitransit-component/packages/digitransit-component-icon/src/assets/funicular-stop.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/digitransit-component/packages/digitransit-component-icon/src/assets/funicular.svg b/digitransit-component/packages/digitransit-component-icon/src/assets/funicular.svg index a73ef80f71..18f7949610 100644 --- a/digitransit-component/packages/digitransit-component-icon/src/assets/funicular.svg +++ b/digitransit-component/packages/digitransit-component-icon/src/assets/funicular.svg @@ -1,8 +1,9 @@ - - - - - - - + + + + + + + + diff --git a/digitransit-component/packages/digitransit-component-icon/src/assets/icon-route.svg b/digitransit-component/packages/digitransit-component-icon/src/assets/icon-route.svg index f58cd904fa..df2f7e2a09 100644 --- a/digitransit-component/packages/digitransit-component-icon/src/assets/icon-route.svg +++ b/digitransit-component/packages/digitransit-component-icon/src/assets/icon-route.svg @@ -1,3 +1,3 @@ - + diff --git a/digitransit-component/packages/digitransit-component-icon/src/assets/locate.svg b/digitransit-component/packages/digitransit-component-icon/src/assets/locate.svg deleted file mode 100644 index bb6f6b95cb..0000000000 --- a/digitransit-component/packages/digitransit-component-icon/src/assets/locate.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/digitransit-component/packages/digitransit-component-icon/src/assets/map.svg b/digitransit-component/packages/digitransit-component-icon/src/assets/map.svg index 69892011fc..ae694b4bca 100644 --- a/digitransit-component/packages/digitransit-component-icon/src/assets/map.svg +++ b/digitransit-component/packages/digitransit-component-icon/src/assets/map.svg @@ -1,7 +1,5 @@ - - diff --git a/digitransit-component/packages/digitransit-component-icon/src/assets/mapmarker-via.svg b/digitransit-component/packages/digitransit-component-icon/src/assets/mapmarker-via.svg deleted file mode 100644 index 4df92c509c..0000000000 --- a/digitransit-component/packages/digitransit-component-icon/src/assets/mapmarker-via.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/digitransit-component/packages/digitransit-component-icon/src/assets/mapmarker.svg b/digitransit-component/packages/digitransit-component-icon/src/assets/mapmarker.svg index 389573d8f1..eb5cebd49e 100644 --- a/digitransit-component/packages/digitransit-component-icon/src/assets/mapmarker.svg +++ b/digitransit-component/packages/digitransit-component-icon/src/assets/mapmarker.svg @@ -1,3 +1,3 @@ - + diff --git a/digitransit-component/packages/digitransit-component-icon/src/assets/mode_airplane.svg b/digitransit-component/packages/digitransit-component-icon/src/assets/mode_airplane.svg deleted file mode 100644 index 7efda18b98..0000000000 --- a/digitransit-component/packages/digitransit-component-icon/src/assets/mode_airplane.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/digitransit-component/packages/digitransit-component-icon/src/assets/mode_digi_citybike.svg b/digitransit-component/packages/digitransit-component-icon/src/assets/mode_digi_citybike.svg deleted file mode 100644 index 882890a6e8..0000000000 --- a/digitransit-component/packages/digitransit-component-icon/src/assets/mode_digi_citybike.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/digitransit-component/packages/digitransit-component-icon/src/assets/mode_digi_funicular.svg b/digitransit-component/packages/digitransit-component-icon/src/assets/mode_digi_funicular.svg deleted file mode 100644 index faa4881527..0000000000 --- a/digitransit-component/packages/digitransit-component-icon/src/assets/mode_digi_funicular.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/digitransit-component/packages/digitransit-component-icon/src/assets/mode_ferry.svg b/digitransit-component/packages/digitransit-component-icon/src/assets/mode_ferry.svg deleted file mode 100644 index 8615ee5ce8..0000000000 --- a/digitransit-component/packages/digitransit-component-icon/src/assets/mode_ferry.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/digitransit-component/packages/digitransit-component-icon/src/assets/search-rail-station-digitransit.svg b/digitransit-component/packages/digitransit-component-icon/src/assets/rail-digitransit.svg similarity index 80% rename from digitransit-component/packages/digitransit-component-icon/src/assets/search-rail-station-digitransit.svg rename to digitransit-component/packages/digitransit-component-icon/src/assets/rail-digitransit.svg index 69b29fd1f9..b07afec552 100644 --- a/digitransit-component/packages/digitransit-component-icon/src/assets/search-rail-station-digitransit.svg +++ b/digitransit-component/packages/digitransit-component-icon/src/assets/rail-digitransit.svg @@ -1,4 +1,4 @@ - - + + diff --git a/digitransit-component/packages/digitransit-component-icon/src/assets/rail-waltti.svg b/digitransit-component/packages/digitransit-component-icon/src/assets/rail-fill-digitransit.svg similarity index 93% rename from digitransit-component/packages/digitransit-component-icon/src/assets/rail-waltti.svg rename to digitransit-component/packages/digitransit-component-icon/src/assets/rail-fill-digitransit.svg index c6edb61d44..dffbea0d58 100644 --- a/digitransit-component/packages/digitransit-component-icon/src/assets/rail-waltti.svg +++ b/digitransit-component/packages/digitransit-component-icon/src/assets/rail-fill-digitransit.svg @@ -1,3 +1,3 @@ - + diff --git a/digitransit-component/packages/digitransit-component-icon/src/assets/mode_rail.svg b/digitransit-component/packages/digitransit-component-icon/src/assets/rail-hsl.svg similarity index 100% rename from digitransit-component/packages/digitransit-component-icon/src/assets/mode_rail.svg rename to digitransit-component/packages/digitransit-component-icon/src/assets/rail-hsl.svg diff --git a/digitransit-component/packages/digitransit-component-icon/src/assets/search-rail-stop-digitransit.svg b/digitransit-component/packages/digitransit-component-icon/src/assets/rail-stop-digitransit.svg similarity index 94% rename from digitransit-component/packages/digitransit-component-icon/src/assets/search-rail-stop-digitransit.svg rename to digitransit-component/packages/digitransit-component-icon/src/assets/rail-stop-digitransit.svg index 072d171c27..f36a6903ae 100644 --- a/digitransit-component/packages/digitransit-component-icon/src/assets/search-rail-stop-digitransit.svg +++ b/digitransit-component/packages/digitransit-component-icon/src/assets/rail-stop-digitransit.svg @@ -1,4 +1,4 @@ - + diff --git a/digitransit-component/packages/digitransit-component-icon/src/assets/search-rail-stop-default.svg b/digitransit-component/packages/digitransit-component-icon/src/assets/rail-stop-hsl.svg similarity index 85% rename from digitransit-component/packages/digitransit-component-icon/src/assets/search-rail-stop-default.svg rename to digitransit-component/packages/digitransit-component-icon/src/assets/rail-stop-hsl.svg index 45d54a44cb..7fb00b8502 100644 --- a/digitransit-component/packages/digitransit-component-icon/src/assets/search-rail-stop-default.svg +++ b/digitransit-component/packages/digitransit-component-icon/src/assets/rail-stop-hsl.svg @@ -1,6 +1,5 @@ - + - diff --git a/digitransit-component/packages/digitransit-component-icon/src/assets/rail.svg b/digitransit-component/packages/digitransit-component-icon/src/assets/rail.svg deleted file mode 100644 index 870f5248c2..0000000000 --- a/digitransit-component/packages/digitransit-component-icon/src/assets/rail.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/digitransit-component/packages/digitransit-component-icon/src/assets/search-airplane-digitransit.svg b/digitransit-component/packages/digitransit-component-icon/src/assets/search-airplane-digitransit.svg deleted file mode 100644 index 4d61c5b3be..0000000000 --- a/digitransit-component/packages/digitransit-component-icon/src/assets/search-airplane-digitransit.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/digitransit-component/packages/digitransit-component-icon/src/assets/search-bus-stop-express-default.svg b/digitransit-component/packages/digitransit-component-icon/src/assets/search-bus-stop-express-default.svg deleted file mode 100644 index 9dae65e22b..0000000000 --- a/digitransit-component/packages/digitransit-component-icon/src/assets/search-bus-stop-express-default.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/digitransit-component/packages/digitransit-component-icon/src/assets/search-ferry-stop-default.svg b/digitransit-component/packages/digitransit-component-icon/src/assets/search-ferry-stop-default.svg deleted file mode 100644 index f82193af1d..0000000000 --- a/digitransit-component/packages/digitransit-component-icon/src/assets/search-ferry-stop-default.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/digitransit-component/packages/digitransit-component-icon/src/assets/search-ferry-stop-digitransit.svg b/digitransit-component/packages/digitransit-component-icon/src/assets/search-ferry-stop-digitransit.svg deleted file mode 100644 index 3cd7c27614..0000000000 --- a/digitransit-component/packages/digitransit-component-icon/src/assets/search-ferry-stop-digitransit.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/digitransit-component/packages/digitransit-component-icon/src/assets/search-streetname.svg b/digitransit-component/packages/digitransit-component-icon/src/assets/search-streetname.svg index 2d48c42016..70c22d7d42 100644 --- a/digitransit-component/packages/digitransit-component-icon/src/assets/search-streetname.svg +++ b/digitransit-component/packages/digitransit-component-icon/src/assets/search-streetname.svg @@ -1,3 +1,3 @@ - - + + diff --git a/digitransit-component/packages/digitransit-component-icon/src/assets/select-from-map.svg b/digitransit-component/packages/digitransit-component-icon/src/assets/select-from-map.svg deleted file mode 100644 index 38da9594c3..0000000000 --- a/digitransit-component/packages/digitransit-component-icon/src/assets/select-from-map.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/digitransit-component/packages/digitransit-component-icon/src/assets/speedtram.svg b/digitransit-component/packages/digitransit-component-icon/src/assets/speedtram-hsl.svg similarity index 90% rename from digitransit-component/packages/digitransit-component-icon/src/assets/speedtram.svg rename to digitransit-component/packages/digitransit-component-icon/src/assets/speedtram-hsl.svg index 781c6f22e2..eb377f7299 100644 --- a/digitransit-component/packages/digitransit-component-icon/src/assets/speedtram.svg +++ b/digitransit-component/packages/digitransit-component-icon/src/assets/speedtram-hsl.svg @@ -1,4 +1,4 @@ - + diff --git a/digitransit-component/packages/digitransit-component-icon/src/assets/search-speedtram-stop-default.svg b/digitransit-component/packages/digitransit-component-icon/src/assets/speedtram-stop-hsl.svg similarity index 84% rename from digitransit-component/packages/digitransit-component-icon/src/assets/search-speedtram-stop-default.svg rename to digitransit-component/packages/digitransit-component-icon/src/assets/speedtram-stop-hsl.svg index 0d8f69b541..65aa023bb7 100644 --- a/digitransit-component/packages/digitransit-component-icon/src/assets/search-speedtram-stop-default.svg +++ b/digitransit-component/packages/digitransit-component-icon/src/assets/speedtram-stop-hsl.svg @@ -1,6 +1,6 @@ - + - - + + diff --git a/digitransit-component/packages/digitransit-component-icon/src/assets/star.svg b/digitransit-component/packages/digitransit-component-icon/src/assets/star.svg index 20b08b16a3..5257073d60 100644 --- a/digitransit-component/packages/digitransit-component-icon/src/assets/star.svg +++ b/digitransit-component/packages/digitransit-component-icon/src/assets/star.svg @@ -1,6 +1,4 @@ - - diff --git a/digitransit-component/packages/digitransit-component-icon/src/assets/subway.svg b/digitransit-component/packages/digitransit-component-icon/src/assets/subway.svg index 624c9848ab..0e5f597939 100644 --- a/digitransit-component/packages/digitransit-component-icon/src/assets/subway.svg +++ b/digitransit-component/packages/digitransit-component-icon/src/assets/subway.svg @@ -1,6 +1,4 @@ - - + - diff --git a/digitransit-component/packages/digitransit-component-icon/src/assets/time.svg b/digitransit-component/packages/digitransit-component-icon/src/assets/time.svg index 127b187d51..cf5025cc3c 100644 --- a/digitransit-component/packages/digitransit-component-icon/src/assets/time.svg +++ b/digitransit-component/packages/digitransit-component-icon/src/assets/time.svg @@ -1,6 +1,4 @@ - - diff --git a/digitransit-component/packages/digitransit-component-icon/src/assets/mode_digi_tram.svg b/digitransit-component/packages/digitransit-component-icon/src/assets/tram-digitransit.svg similarity index 100% rename from digitransit-component/packages/digitransit-component-icon/src/assets/mode_digi_tram.svg rename to digitransit-component/packages/digitransit-component-icon/src/assets/tram-digitransit.svg diff --git a/digitransit-component/packages/digitransit-component-icon/src/assets/tram-waltti.svg b/digitransit-component/packages/digitransit-component-icon/src/assets/tram-fill-digitransit.svg similarity index 93% rename from digitransit-component/packages/digitransit-component-icon/src/assets/tram-waltti.svg rename to digitransit-component/packages/digitransit-component-icon/src/assets/tram-fill-digitransit.svg index f1b0d90bc4..5e75adc4d9 100644 --- a/digitransit-component/packages/digitransit-component-icon/src/assets/tram-waltti.svg +++ b/digitransit-component/packages/digitransit-component-icon/src/assets/tram-fill-digitransit.svg @@ -1,3 +1,3 @@ - + diff --git a/digitransit-component/packages/digitransit-component-icon/src/assets/mode_tram.svg b/digitransit-component/packages/digitransit-component-icon/src/assets/tram-hsl.svg similarity index 100% rename from digitransit-component/packages/digitransit-component-icon/src/assets/mode_tram.svg rename to digitransit-component/packages/digitransit-component-icon/src/assets/tram-hsl.svg diff --git a/digitransit-component/packages/digitransit-component-icon/src/assets/search-tram-stop-digitransit.svg b/digitransit-component/packages/digitransit-component-icon/src/assets/tram-stop-digitransit.svg similarity index 94% rename from digitransit-component/packages/digitransit-component-icon/src/assets/search-tram-stop-digitransit.svg rename to digitransit-component/packages/digitransit-component-icon/src/assets/tram-stop-digitransit.svg index e365807bf4..89ea4bd864 100644 --- a/digitransit-component/packages/digitransit-component-icon/src/assets/search-tram-stop-digitransit.svg +++ b/digitransit-component/packages/digitransit-component-icon/src/assets/tram-stop-digitransit.svg @@ -1,4 +1,4 @@ - + diff --git a/digitransit-component/packages/digitransit-component-icon/src/assets/search-tram-stop-default.svg b/digitransit-component/packages/digitransit-component-icon/src/assets/tram-stop-hsl.svg similarity index 80% rename from digitransit-component/packages/digitransit-component-icon/src/assets/search-tram-stop-default.svg rename to digitransit-component/packages/digitransit-component-icon/src/assets/tram-stop-hsl.svg index 3ed9e47f0e..b5d1adc69e 100644 --- a/digitransit-component/packages/digitransit-component-icon/src/assets/search-tram-stop-default.svg +++ b/digitransit-component/packages/digitransit-component-icon/src/assets/tram-stop-hsl.svg @@ -1,6 +1,6 @@ - + - - + + diff --git a/digitransit-component/packages/digitransit-component-icon/src/assets/tram.svg b/digitransit-component/packages/digitransit-component-icon/src/assets/tram.svg deleted file mode 100644 index a839b82280..0000000000 --- a/digitransit-component/packages/digitransit-component-icon/src/assets/tram.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/digitransit-component/packages/digitransit-component-icon/src/assets/trash.svg b/digitransit-component/packages/digitransit-component-icon/src/assets/trash.svg index 411b77cc99..4665fe3bd0 100644 --- a/digitransit-component/packages/digitransit-component-icon/src/assets/trash.svg +++ b/digitransit-component/packages/digitransit-component-icon/src/assets/trash.svg @@ -1,7 +1,5 @@ - - diff --git a/digitransit-component/packages/digitransit-component-icon/src/assets/viapoint.svg b/digitransit-component/packages/digitransit-component-icon/src/assets/viapoint.svg index fddd435b2a..0212ee6eb8 100644 --- a/digitransit-component/packages/digitransit-component-icon/src/assets/viapoint.svg +++ b/digitransit-component/packages/digitransit-component-icon/src/assets/viapoint.svg @@ -1,3 +1,3 @@ - + diff --git a/digitransit-component/packages/digitransit-component-icon/src/index.js b/digitransit-component/packages/digitransit-component-icon/src/index.js index 062945446e..56e4d851d2 100644 --- a/digitransit-component/packages/digitransit-component-icon/src/index.js +++ b/digitransit-component/packages/digitransit-component-icon/src/index.js @@ -1,113 +1,116 @@ import PropTypes from 'prop-types'; import React from 'react'; -import Airplane from './assets/airplane.svg'; import Arrow from './assets/arrow.svg'; -import Bus from './assets/bus.svg'; -import Busstop from './assets/bus_stop.svg'; +import Check from './assets/check.svg'; import City from './assets/city.svg'; import Edit from './assets/edit.svg'; -import Ferry from './assets/ferry.svg'; import Home from './assets/home.svg'; -import Locate from './assets/locate.svg'; import Place from './assets/place.svg'; -import Rail from './assets/rail.svg'; import School from './assets/school.svg'; import Shopping from './assets/shopping.svg'; import Sport from './assets/sport.svg'; import Star from './assets/star.svg'; import Station from './assets/station.svg'; -import Subway from './assets/subway.svg'; -import Tram from './assets/tram.svg'; import Work from './assets/work.svg'; import Map from './assets/map.svg'; import Close from './assets/close.svg'; import Mapmarker from './assets/mapmarker.svg'; -import MapmarkerVia from './assets/mapmarker-via.svg'; import Search from './assets/search.svg'; import Plus from './assets/plus.svg'; import Attention from './assets/attention.svg'; import Dropdown from './assets/dropdown.svg'; -import CarPark from './assets/car-park.svg'; -import BikePark from './assets/bike-park.svg'; +import CarPark from './assets/carpark.svg'; +import BikePark from './assets/bikepark.svg'; import Time from './assets/time.svg'; import Ellipsis from './assets/ellipsis.svg'; import Opposite from './assets/opposite.svg'; import Viapoint from './assets/viapoint.svg'; import Calendar from './assets/calendar.svg'; -import SelectFromMap from './assets/select-from-map.svg'; import CautionWhite from './assets/caution_white_exclamation.svg'; import Trash from './assets/trash.svg'; -import ModeBus from './assets/mode_bus.svg'; -import ModeBusExpress from './assets/bus-express.svg'; -import ModeBusReplacement from './assets/bus-replacement.svg'; -import ModeSpeedTram from './assets/speedtram.svg'; -import ModeBusLocal from './assets/bus-local.svg'; -import ModeRail from './assets/mode_rail.svg'; -import ModeTram from './assets/mode_tram.svg'; -import ModeFerry from './assets/mode_ferry.svg'; -import ModeBikeRentalStation from './assets/mode_citybike.svg'; -import ModeAirplane from './assets/mode_airplane.svg'; -import ModeDigiTram from './assets/mode_digi_tram.svg'; -import ModeDigiBikeRentalStation from './assets/mode_digi_citybike.svg'; -import ModeDigiFunicular from './assets/mode_digi_funicular.svg'; import FutureRoute from './assets/icon-route.svg'; import Position from './assets/position.svg'; import SearchStreetName from './assets/search-streetname.svg'; -import BusWaltti from './assets/bus-waltti.svg'; -import FerryWaltti from './assets/ferry-waltti.svg'; -import BikeRentalStationWaltti from './assets/citybike-waltti.svg'; -import RailWaltti from './assets/rail-waltti.svg'; -import TramWaltti from './assets/tram-waltti.svg'; -import Check from './assets/check.svg'; -import SearchBusStopDefault from './assets/search-bus-stop-default.svg'; -import SearchBusStopExpressDefault from './assets/search-bus-stop-express-default.svg'; -import SearchSpeedTramStopDefault from './assets/search-speedtram-stop-default.svg'; -import SearchRailStopDefault from './assets/search-rail-stop-default.svg'; -import SearchFerryDefault from './assets/search-ferry-default.svg'; -import SearchFerryStopDefault from './assets/search-ferry-stop-default.svg'; -import CityBikeRentalStationDefault from './assets/citybike-stop-default.svg'; -import CityBikeRentalStationDefaultSecondary from './assets/citybike-stop-default-secondary.svg'; -import SearchTramStopDefault from './assets/search-tram-stop-default.svg'; -import CityBikeRentalStationDigitransit from './assets/citybike-stop-digitransit.svg'; -import CityBikeRentalStationDigitransitSecondary from './assets/citybike-stop-digitransit-secondary.svg'; -import SearchAirplaneDigitransit from './assets/search-airplane-digitransit.svg'; -import SearchBusStationDigitransit from './assets/search-bus-station-digitransit.svg'; -import SearchBusStopDigitransit from './assets/search-bus-stop-digitransit.svg'; -import SearchBusTramStopDigitransit from './assets/search-bustram-stop-digitransit.svg'; -import SearchFerryDigitransit from './assets/search-ferry-digitransit.svg'; -import SearchFerryStopDigitransit from './assets/search-ferry-stop-digitransit.svg'; -import SearchRailStopDigitransit from './assets/search-rail-stop-digitransit.svg'; -import SearchRailStationDigitransit from './assets/search-rail-station-digitransit.svg'; -import SearchTramStopDigitransit from './assets/search-tram-stop-digitransit.svg'; +import Airplane from './assets/airplane.svg'; +import Subway from './assets/subway.svg'; import Funicular from './assets/funicular.svg'; +import FunicularStop from './assets/funicular-stop.svg'; +import BusHsl from './assets/bus-hsl.svg'; +import BusReplacementHsl from './assets/bus-replacement-hsl.svg'; +import SpeedTramHsl from './assets/speedtram-hsl.svg'; +import BusLocalHsl from './assets/bus-local-hsl.svg'; +import RailHsl from './assets/rail-hsl.svg'; +import TramHsl from './assets/tram-hsl.svg'; +import CityBikeHsl from './assets/citybike-hsl.svg'; +import FerryHsl from './assets/ferry-hsl.svg'; +import BusStopHsl from './assets/bus-stop-hsl.svg'; +import SpeedTramStopHsl from './assets/speedtram-stop-hsl.svg'; +import RailStopHsl from './assets/rail-stop-hsl.svg'; +import FerryStopHsl from './assets/ferry-stop-hsl.svg'; +import CityBikeStopHsl from './assets/citybike-stop-hsl.svg'; +import CityBikeStopHslSecondary from './assets/citybike-stop-hsl-secondary.svg'; +import TramStopHsl from './assets/tram-stop-hsl.svg'; +import CityBikeDigitransit from './assets/citybike-digitransit.svg'; +import BusDigitransit from './assets/bus-digitransit.svg'; +import FerryDigitransit from './assets/ferry-digitransit.svg'; +import RailDigitransit from './assets/rail-digitransit.svg'; +import TramDigitransit from './assets/tram-digitransit.svg'; +import BusStopDigitransit from './assets/bus-stop-digitransit.svg'; +import CityBikeStopDigitransit from './assets/citybike-stop-digitransit.svg'; +import CityBikeStopDigitransitSecondary from './assets/citybike-stop-digitransit-secondary.svg'; +import FerryStopDigitransit from './assets/ferry-stop-digitransit.svg'; +import RailStopDigitransit from './assets/rail-stop-digitransit.svg'; +import TramStopDigitransit from './assets/tram-stop-digitransit.svg'; +import BusTramStopDigitransit from './assets/bustram-stop-digitransit.svg'; +import BusFillDigitransit from './assets/bus-fill-digitransit.svg'; +import CityBikeFillDigitransit from './assets/citybike-fill-digitransit.svg'; +import FerryFillDigitransit from './assets/ferry-fill-digitransit.svg'; +import RailFillDigitransit from './assets/rail-fill-digitransit.svg'; +import TramFillDigitransit from './assets/tram-fill-digitransit.svg'; +import CarParkFill from './assets/carpark-fill.svg'; +import BikeParkFill from './assets/bikepark-fill.svg'; + +export const defaultColors = { + primary: '#0074bf', + accessiblePrimary: '#0074be', + hover: '#0062a1', + caution: '#dc0451', + airplane: '#0046ad', + bus: '#007ac9', + 'bus-express': '#ca4000', + 'bus-local': '#007ac9', + 'replacement-bus': '#dc0451', + rail: '#8c4799', + tram: '#008151', + speedtram: '#007e79', + subway: '#ed8c00', + ferry: '#007a97', + 'ferry-external': '#666666', + funicular: '#ff00ff', + citybike: '#f2b62d', + 'citybike-secondary': '#333333', + bikepark: '#f2b62d', + carpark: '#007ac9', +}; const iconMap = { - airplane: Airplane, arrow: Arrow, - bus: Bus, - busstop: Busstop, caution: CautionWhite, city: City, - citybike: CityBikeRentalStationDefault, + citybike: CityBikeHsl, edit: Edit, - ferry: Ferry, home: Home, - locate: Locate, map: Map, place: Place, - rail: Rail, school: School, shopping: Shopping, sport: Sport, star: Star, station: Station, - subway: Subway, - tram: Tram, work: Work, close: Close, - 'mapMarker-via': MapmarkerVia, - 'bike-park': BikePark, - 'car-park': CarPark, + bikepark: BikePark, + carpark: CarPark, mapMarker: Mapmarker, search: Search, plus: Plus, @@ -118,59 +121,54 @@ const iconMap = { opposite: Opposite, viapoint: Viapoint, calendar: Calendar, - 'select-from-map': SelectFromMap, 'caution-white': CautionWhite, trash: Trash, - 'mode-bus': ModeBus, - 'mode-bus-express': ModeBusExpress, - 'mode-bus-local': ModeBusLocal, - 'mode-bus-replacement': ModeBusReplacement, - 'mode-speedtram': ModeSpeedTram, - 'mode-rail': ModeRail, - 'mode-tram': ModeTram, - 'mode-subway': Subway, - 'mode-ferry': ModeFerry, - 'mode-citybike': ModeBikeRentalStation, - 'mode-digitransit-bus': SearchBusStationDigitransit, - 'mode-digitransit-rail': SearchRailStationDigitransit, - 'mode-digitransit-ferry': SearchFerryDigitransit, - 'mode-digitransit-tram': ModeDigiTram, - 'mode-digitransit-citybike': ModeDigiBikeRentalStation, - 'mode-digitransit-airplane': ModeAirplane, - 'mode-digitransit-subway': Subway, - 'mode-digitransit-funicular': ModeDigiFunicular, - 'mode-waltti-bus': BusWaltti, - 'mode-waltti-citybike': BikeRentalStationWaltti, - 'mode-waltti-ferry': FerryWaltti, - 'mode-waltti-rail': RailWaltti, - 'mode-waltti-tram': TramWaltti, - 'future-route': FutureRoute, position: Position, 'search-street-name': SearchStreetName, + 'future-route': FutureRoute, check: Check, - 'search-bus-stop-default': SearchBusStopDefault, - 'search-bus-stop-express-default': SearchBusStopExpressDefault, - 'search-speedtram-stop-default': SearchSpeedTramStopDefault, - 'search-rail-stop-default': SearchRailStopDefault, - 'search-ferry-default': SearchFerryDefault, - 'search-ferry-stop-default': SearchFerryStopDefault, - 'search-tram-stop-default': SearchTramStopDefault, - 'citybike-stop-digitransit': CityBikeRentalStationDigitransit, - 'citybike-stop-digitransit-secondary': - CityBikeRentalStationDigitransitSecondary, - 'citybike-stop-default': CityBikeRentalStationDefault, - 'citybike-stop-default-secondary': CityBikeRentalStationDefaultSecondary, - 'search-airplane-digitransit': SearchAirplaneDigitransit, - 'search-bus-station-digitransit': SearchBusStationDigitransit, - 'search-bus-stop-digitransit': SearchBusStopDigitransit, - 'search-bustram-stop-digitransit': SearchBusTramStopDigitransit, - 'search-ferry-digitransit': SearchFerryDigitransit, - 'search-ferry-stop-digitransit': SearchFerryStopDigitransit, - 'search-funicular-stop-digitransit': ModeDigiFunicular, - 'search-rail-stop-digitransit': SearchRailStopDigitransit, - 'search-rail-station-digitransit': SearchRailStationDigitransit, - 'search-tram-stop-digitransit': SearchTramStopDigitransit, + // shared transport modes + airplane: Airplane, + subway: Subway, funicular: Funicular, + 'funicular-stop': FunicularStop, + // HSL + 'bus-hsl': BusHsl, + 'bus-local-hsl': BusLocalHsl, + 'replacement-bus-hsl': BusReplacementHsl, + 'ferry-hsl': FerryHsl, + 'rail-hsl': RailHsl, + 'speedtram-hsl': SpeedTramHsl, + 'tram-hsl': TramHsl, + 'citybike-hsl': CityBikeHsl, + 'bus-stop-hsl': BusStopHsl, + 'speedtram-stop-hsl': SpeedTramStopHsl, + 'rail-stop-hsl': RailStopHsl, + 'ferry-stop-hsl': FerryStopHsl, + 'tram-stop-hsl': TramStopHsl, + 'citybike-stop-hsl': CityBikeStopHsl, + 'citybike-stop-hsl-secondary': CityBikeStopHslSecondary, + // digitransit + 'bus-digitransit': BusDigitransit, + 'ferry-digitransit': FerryDigitransit, + 'rail-digitransit': RailDigitransit, + 'tram-digitransit': TramDigitransit, + 'citybike-digitransit': CityBikeDigitransit, + 'citybike-stop-digitransit': CityBikeStopDigitransit, + 'citybike-stop-digitransit-secondary': CityBikeStopDigitransitSecondary, + 'bus-stop-digitransit': BusStopDigitransit, + 'bustram-stop-digitransit': BusTramStopDigitransit, + 'ferry-stop-digitransit': FerryStopDigitransit, + 'rail-stop-digitransit': RailStopDigitransit, + 'tram-stop-digitransit': TramStopDigitransit, + 'bus-fill-digitransit': BusFillDigitransit, + 'citybike-fill-digitransit': CityBikeFillDigitransit, + 'ferry-fill-digitransit': FerryFillDigitransit, + 'rail-fill-digitransit': RailFillDigitransit, + 'tram-fill-digitransit': TramFillDigitransit, + // no theme binding + 'bikepark-fill': BikeParkFill, + 'carpark-fill': CarParkFill, }; /** @@ -191,29 +189,23 @@ const Icon = ({ color, img, height, width, rotate }) => { width: width ? `${width}em` : null, transform: rotate ? `rotate(${rotate}deg)` : null, }; - - const iconName = - img === 'locate' && color && color.toUpperCase() !== '#007AC9' - ? 'position' - : img; - - const Component = iconMap[iconName] || SearchBusStopDigitransit; + const Component = iconMap[img] || BusStopDigitransit; return ; }; Icon.propTypes = { - color: PropTypes.string, - height: PropTypes.number, img: PropTypes.string.isRequired, + color: PropTypes.string, width: PropTypes.number, + height: PropTypes.number, rotate: PropTypes.string, }; Icon.defaultProps = { color: undefined, - height: undefined, width: undefined, + height: undefined, rotate: undefined, }; diff --git a/digitransit-component/packages/digitransit-component-suggestion-item/package.json b/digitransit-component/packages/digitransit-component-suggestion-item/package.json index 56c42e8032..2cc4493bcd 100644 --- a/digitransit-component/packages/digitransit-component-suggestion-item/package.json +++ b/digitransit-component/packages/digitransit-component-suggestion-item/package.json @@ -1,6 +1,6 @@ { "name": "@digitransit-component/digitransit-component-suggestion-item", - "version": "2.3.2", + "version": "3.0.0", "description": "digitransit-component suggestion-item module", "main": "index.js", "files": [ @@ -29,7 +29,7 @@ "author": "Digitransit Authors", "license": "(AGPL-3.0 OR EUPL-1.2)", "peerDependencies": { - "@digitransit-component/digitransit-component-icon": "^1.2.0", + "@digitransit-component/digitransit-component-icon": "^2.0.0", "@hsl-fi/sass": " ^0.2.0", "classnames": "2.5.1", "prop-types": "^15.8.1", diff --git a/digitransit-component/packages/digitransit-component-suggestion-item/src/helpers/styles.scss b/digitransit-component/packages/digitransit-component-suggestion-item/src/helpers/styles.scss index 6ab0dca496..3a0ef58c2c 100644 --- a/digitransit-component/packages/digitransit-component-suggestion-item/src/helpers/styles.scss +++ b/digitransit-component/packages/digitransit-component-suggestion-item/src/helpers/styles.scss @@ -67,11 +67,6 @@ li:last-child > div.suggestion-item-container.mobile { line-height: 1; } - &.favouriteCustom { - color: #0074be; - font-size: 15px; - } - &.futureroute { line-height: 1.33; position: relative; @@ -145,7 +140,6 @@ li:last-child > div.suggestion-item-container.mobile { right: 0; svg { - fill: var(--accessible-primary-color) !important; width: 17px; height: 17px; } diff --git a/digitransit-component/packages/digitransit-component-suggestion-item/src/index.js b/digitransit-component/packages/digitransit-component-suggestion-item/src/index.js index 076aa66315..0002be8fc9 100644 --- a/digitransit-component/packages/digitransit-component-suggestion-item/src/index.js +++ b/digitransit-component/packages/digitransit-component-suggestion-item/src/index.js @@ -2,35 +2,21 @@ import PropTypes from 'prop-types'; import React, { useState, memo } from 'react'; import cx from 'classnames'; -import Icon from '@digitransit-component/digitransit-component-icon'; +import Icon, { + defaultColors, +} from '@digitransit-component/digitransit-component-icon'; import styles from './helpers/styles.scss'; const extendedModes = { 702: 'bus-express', 704: 'bus-local', - 714: 'bus-replacement', + 714: 'replacement-bus', 900: 'speedtram', }; -const iconColors = { - 'mode-airplane': '#0046AD', - 'mode-bus': '#007ac9', - 'mode-bus-express': '#CA4000', - 'mode-bus-local': '#007ac9', - 'mode-rail': '#8c4799', - 'mode-tram': '#008151', - 'mode-speedtram': '#007E79', - 'mode-subway': '#ed8c00', - 'mode-ferry': '#007A97', - 'mode-ferry-external': '#666666', - 'mode-funicular': '#ff00ff', - 'mode-citybike': '#f2b62d', - 'mode-citybike-secondary': '#333333', -}; - const getRouteMode = (props, set) => { let eMode; - if (set === 'default') { + if (set === 'hsl') { eMode = extendedModes[props.type]; } return eMode || props.mode?.toLowerCase() || 'bus'; @@ -38,8 +24,7 @@ const getRouteMode = (props, set) => { const iconProps = { bikestation: ['citybike'], - currentPosition: ['locate'], - stop: ['busstop'], + currentPosition: ['position'], locality: ['city'], station: ['station'], localadmin: ['city'], @@ -50,46 +35,23 @@ const iconProps = { 'icon-icon_sport': ['sport'], 'icon-icon_school': ['school'], 'icon-icon_shopping': ['shopping'], - selectFromMap: ['select-from-map'], + selectFromMap: ['map'], ownLocations: ['star'], - back: ['arrow'], + back: ['arrow', 'accessiblePrimary'], futureRoute: ['future-route'], - 'BUS-default': ['search-bus-stop-default', 'mode-bus'], - 'BUS-EXPRESS-default': [ - 'search-bus-stop-express-default', - 'mode-bus-express', - ], - 'SPEEDTRAM-default': ['search-speedtram-stop-default', 'mode-speedtram'], - 'BUS-digitransit': ['search-bus-stop-digitransit', 'mode-bus'], - 'BUS-STATION-default': ['mode-bus', 'mode-bus'], - 'BUS-STATION-digitransit': ['search-bus-station-digitransit', 'mode-bus'], - 'FUNICULAR-digitransit': [ - 'search-funicular-stop-digitransit', - 'mode-funicular', - ], - 'RAIL-default': ['search-rail-stop-default', 'mode-rail'], - 'RAIL-digitransit': ['search-rail-stop-digitransit', 'mode-rail'], - 'RAIL-STATION-default': ['mode-rail', 'mode-rail'], - 'RAIL-STATION-digitransit': ['search-rail-station-digitransit', 'mode-rail'], - 'TRAM-default': ['search-tram-stop-default', 'mode-tram'], - 'TRAM-digitransit': ['search-tram-stop-digitransit', 'mode-tram'], - 'SUBWAY-default': ['subway', 'mode-subway'], - 'SUBWAY-digitransit': ['subway', 'mode-subway'], - 'SUBWAY-STATION-default': ['subway', 'mode-subway'], - 'SUBWAY-STATION-digitransit': ['subway', 'mode-subway'], - 'SPEEDTRAM-STATION-default': ['mode-speedtram', 'mode-speedtram'], - 'TRAM-STATION-default': ['mode-tram', 'mode-tram'], - 'TRAM-STATION-digitransit': ['mode-tram', 'mode-tram'], - 'SPEEDTRAM-STATION-digitransit': ['mode-tram', 'mode-tram'], - 'FERRY-STATION-default': ['search-ferry-default', 'mode-ferry'], - 'FERRY-STATION-digitransit': ['search-ferry-digitransit', 'mode-ferry'], - 'FERRY-default': ['search-ferry-stop-default', 'mode-ferry-external'], - 'FERRY-digitransit': ['search-ferry-stop-digitransit', 'mode-ferry-external'], - 'AIRPLANE-digitransit': ['search-airplane-digitransit', 'mode-airplane'], - 'BUS-TRAM-STATION-digitransit': [ - 'search-bustram-stop-digitransit', - 'mode-tram', - ], + + // map unusual transport modes + 'subway-stop': ['subway', 'subway'], + 'airplane-stop': ['airplane', 'airplane'], + 'bus-express-hsl': ['bus-hsl', 'bus-express'], + 'bus-express-stop-hsl': ['bus-stop-hsl', 'bus-express'], + 'bus-express-digitransit': ['bus-digitransit', 'bus'], + 'bus-express-stop-digitransit': ['bus-stop-digitransit', 'bus'], + 'speedtram-digitransit': ['tram', 'tram'], + 'speedtram-stop-digitransit': ['tram-stop-digitransit', 'tram'], + 'ferry-stop-hsl': ['ferry-stop-hsl', 'ferry-external'], + 'ferry-stop-digitransit': ['ferry-stop-digitransit', 'ferry-external'], + 'bus-tram-stop-digitransit': ['bustram-stop-digitransit', 'tram'], }; function isFavourite(item) { @@ -104,6 +66,21 @@ function getAriaDescription(ariaContentArray) { } const stopLayers = ['station', 'stop']; +const parkLayers = ['bikepark', 'carpark']; +const noTheme = ['subway', 'airplane', 'funicular']; // common icon in all themes + +function getIconProps(mode, isStop, modeSet) { + // select stop lollipop or mode/station icon + const stopDesc = isStop ? '-stop' : ''; + // is the icon theme specific + const themePostfix = noTheme.includes(mode) ? '' : `-${modeSet}`; + return ( + iconProps[`${mode}${stopDesc}${themePostfix}`] || [ + `${mode}${stopDesc}${themePostfix}`, + mode, + ] + ); +} function getIconProperties(item, modeSet, stopCode, modes) { let iconId; @@ -118,21 +95,16 @@ function getIconProperties(item, modeSet, stopCode, modes) { (item.type === 'OldSearch' && item.properties?.mode) ) { const mode = getRouteMode(item.properties, modeSet); - return modeSet === 'default' - ? [`mode-${mode}`, `mode-${mode}`] - : [`mode-${modeSet}-${mode}`, `mode-${mode}`]; + return getIconProps(mode, false, modeSet); } if (item.selectedIconId) { iconId = item.selectedIconId; } else if (item.properties) { if (item.properties.layer === 'bikestation') { - return [`citybike-stop-${modeSet}`, 'mode-citybike']; + return [`citybike-stop-${modeSet}`, 'citybike']; } - if (item.properties.layer === 'carpark') { - return [`car-park`]; - } - if (item.properties.layer === 'bikepark') { - return [`bike-park`]; + if (parkLayers.includes(item.properties.layer)) { + return [item.properties.layer, item.properties.layer]; } if ( item.properties.label?.split(',').length === 1 && @@ -145,23 +117,18 @@ function getIconProperties(item, modeSet, stopCode, modes) { } // Use more accurate icons in stop/station search, depending on mode from geocoding if (modes?.length) { - const mode = modes[0]; - if (item.properties.layer === 'station' || (mode === 'FERRY' && stopCode)) { - if (modes.includes('SPEEDTRAM') && modeSet === 'default') { - return iconProps['SPEEDTRAM-STATION-default']; - } - return iconProps[`${mode}-STATION-${modeSet}`]; - } - if (modes.includes('BUS-EXPRESS') && modeSet === 'default') { - return iconProps[`BUS-EXPRESS-${modeSet}`]; - } + let station = item.properties.layer === 'station'; + let mode; // select dominating mode if (modes.includes('SPEEDTRAM')) { - return modeSet === 'default' - ? iconProps['SPEEDTRAM-default'] - : iconProps['TRAM-digitransit']; + mode = 'speedtram'; + } else if (modes.includes('BUS-EXPRESS' && !station)) { + mode = 'bus-express'; + } else { + mode = modes[0].toLowerCase(); } - const props = iconProps[`${mode}-${modeSet}`]; - return props || ['busstop', 'mode-bus']; + station = station || (mode === 'ferry' && stopCode); + + return getIconProps(mode, !station, modeSet); } return iconProps[iconId] || ['place']; } @@ -194,16 +161,13 @@ const SuggestionItem = memo( item, content, loading, - className, isMobile, ariaFavouriteString, - color, - accessiblePrimaryColor, fillInput, fontWeights, - modeIconColors, + colors, getAutoSuggestIcons, - modeSet = 'default', + modeSet, }) => { const [suggestionType, name, label, stopCode, modes, platform] = content || ['', item.name, item.address]; @@ -214,27 +178,27 @@ const SuggestionItem = memo( item.properties?.layer && getAutoSuggestIcons?.[item.properties?.layer] ) { - [iconId, iconColor] = getAutoSuggestIcons[item.properties?.layer](item); + [iconId, iconColor] = getAutoSuggestIcons[item.properties.layer](item); } else { let colorId; [iconId, colorId] = getIconProperties(item, modeSet, stopCode, modes); if (item.properties?.color) { iconColor = `#${item.properties.color}`; - } else if (iconId === 'locate' || isFavourite(item)) { - iconColor = color; + } else if (iconId === 'position' || isFavourite(item)) { + iconColor = colors.primary; } else { - iconColor = modeIconColors?.[colorId] || iconColors[colorId] || '#888'; + iconColor = colors?.[colorId] || defaultColors[colorId] || '#888'; } } + const accessiblePrimary = + colors?.accessiblePrimary || defaultColors.accessiblePrimary; // console.log(item, iconId, iconColor); // Arrow clicked is for street. Instead of selecting item when a user clicks on arrow, // It fills the input field. const [arrowClicked, setArrowClicked] = useState(false); const icon = ( - + ); @@ -292,10 +256,7 @@ const SuggestionItem = memo( item.selectedIconId !== 'favourite' && iconId !== 'edit' && ( -