diff --git a/app/component/StopsNearYouFavoritesMapContainer.js b/app/component/StopsNearYouFavoritesMapContainer.js index 3a36f90f8e..38ffa8d27f 100644 --- a/app/component/StopsNearYouFavoritesMapContainer.js +++ b/app/component/StopsNearYouFavoritesMapContainer.js @@ -4,7 +4,6 @@ import connectToStores from 'fluxible-addons-react/connectToStores'; import { graphql, createFragmentContainer } from 'react-relay'; import distance from '@digitransit-search-util/digitransit-search-util-distance'; import StopsNearYouMap from './map/StopsNearYouMap'; -import TimeStore from '../store/TimeStore'; import PreferencesStore from '../store/PreferencesStore'; import FavouriteStore from '../store/FavouriteStore'; import { @@ -84,16 +83,13 @@ StopsNearYouFavoritesMapContainer.defaultProps = { const StopsNearYouMapWithStores = connectToStores( StopsNearYouFavoritesMapContainer, - [TimeStore, PreferencesStore, FavouriteStore], + [PreferencesStore, FavouriteStore], ({ getStore }) => { - const currentTime = getStore(TimeStore).getCurrentTime(); const language = getStore(PreferencesStore).getLanguage(); - return { - language, - currentTime, - }; + return { language }; }, ); + const containerComponent = createFragmentContainer(StopsNearYouMapWithStores, { stops: graphql` fragment StopsNearYouFavoritesMapContainer_stops on Stop diff --git a/app/component/StopsNearYouMapContainer.js b/app/component/StopsNearYouMapContainer.js index 5990365524..4e508b71b1 100644 --- a/app/component/StopsNearYouMapContainer.js +++ b/app/component/StopsNearYouMapContainer.js @@ -2,15 +2,13 @@ import connectToStores from 'fluxible-addons-react/connectToStores'; import { graphql, createPaginationContainer } from 'react-relay'; import StopsNearYouMap from './map/StopsNearYouMap'; -import TimeStore from '../store/TimeStore'; import FavouriteStore from '../store/FavouriteStore'; import PreferencesStore from '../store/PreferencesStore'; const StopsNearYouMapWithStores = connectToStores( StopsNearYouMap, - [TimeStore, PreferencesStore, FavouriteStore], + [PreferencesStore, FavouriteStore], ({ getStore }, { match }) => { - const currentTime = getStore(TimeStore).getCurrentTime(); const language = getStore(PreferencesStore).getLanguage(); const favouriteIds = match.params.mode === 'CITYBIKE' @@ -26,7 +24,6 @@ const StopsNearYouMapWithStores = connectToStores( ); return { language, - currentTime, favouriteIds, }; }, diff --git a/app/component/itinerary/MobileTicketPurchaseInformation.js b/app/component/itinerary/MobileTicketPurchaseInformation.js index 00e2decd20..5d3aa8e08d 100644 --- a/app/component/itinerary/MobileTicketPurchaseInformation.js +++ b/app/component/itinerary/MobileTicketPurchaseInformation.js @@ -21,7 +21,10 @@ export default function MobileTicketPurchaseInformation( !fare.isUnknown, config.availableTickets, ); - const price = `${fare.price.toFixed(2)} €`.replace('.', ','); + const price = + config.showTicketPrice && fare.price > 0 + ? `${fare.price.toFixed(2)} €`.replace('.', ',') + : ''; const faresInfo = () => { const header = `${intl.formatMessage({ @@ -64,7 +67,7 @@ export default function MobileTicketPurchaseInformation( addAnalyticsEvent({ event: 'journey_planner_open_app' }) } > - + diff --git a/app/component/itinerary/mobile-ticket-purchase-information.scss b/app/component/itinerary/mobile-ticket-purchase-information.scss index 232d555f4e..caa8139824 100644 --- a/app/component/itinerary/mobile-ticket-purchase-information.scss +++ b/app/component/itinerary/mobile-ticket-purchase-information.scss @@ -35,6 +35,7 @@ .external-link-container { border: 0; line-height: 25px; + padding: 0 10px; a.external-link { font-size: 16px; diff --git a/app/component/map/ItineraryLine.js b/app/component/map/ItineraryLine.js index 187ad0c624..ef4666e567 100644 --- a/app/component/map/ItineraryLine.js +++ b/app/component/map/ItineraryLine.js @@ -30,7 +30,7 @@ class ItineraryLine extends React.Component { static propTypes = { legs: PropTypes.arrayOf(legShape).isRequired, passive: PropTypes.bool, - hash: PropTypes.number.isRequired, + hash: PropTypes.number, showTransferLabels: PropTypes.bool, showIntermediateStops: PropTypes.bool, showDurationBubble: PropTypes.bool, @@ -38,6 +38,7 @@ class ItineraryLine extends React.Component { }; static defaultProps = { + hash: 0, passive: false, streetMode: undefined, showTransferLabels: false, diff --git a/app/component/map/StopPageMap.js b/app/component/map/StopPageMap.js index f725f62445..59a1e99112 100644 --- a/app/component/map/StopPageMap.js +++ b/app/component/map/StopPageMap.js @@ -1,10 +1,9 @@ import PropTypes from 'prop-types'; import React, { useEffect, useContext, useState } from 'react'; import { matchShape, routerShape } from 'found'; -import moment from 'moment'; import { connectToStores } from 'fluxible-addons-react'; import distance from '@digitransit-search-util/digitransit-search-util-distance'; -import { graphql, fetchQuery } from 'react-relay'; +import { fetchQuery } from 'react-relay'; import ReactRelayContext from 'react-relay/lib/ReactRelayContext'; import { configShape, @@ -12,7 +11,6 @@ import { mapLayerOptionsShape, } from '../../util/shapes'; import { getSettings } from '../../util/planParamUtil'; -import TimeStore from '../../store/TimeStore'; import PositionStore from '../../store/PositionStore'; import MapLayerStore, { mapLayerShape } from '../../store/MapLayerStore'; import MapWithTracking from './MapWithTracking'; @@ -21,13 +19,13 @@ import SelectedStopPopupContent from '../SelectedStopPopupContent'; import withBreakpoint from '../../util/withBreakpoint'; import VehicleMarkerContainer from './VehicleMarkerContainer'; import BackButton from '../BackButton'; -import { locationToUri } from '../../util/otpStrings'; import ItineraryLine from './ItineraryLine'; import Loading from '../Loading'; import { getMapLayerOptions } from '../../util/mapLayerUtils'; import MapRoutingButton from '../MapRoutingButton'; import CookieSettingsButton from '../CookieSettingsButton'; import { PREFIX_CARPARK, PREFIX_BIKEPARK } from '../../util/path'; +import { walkQuery } from './WalkQuery'; const getModeFromProps = props => { if (props.citybike) { @@ -49,15 +47,7 @@ const getModeFromProps = props => { }; function StopPageMap( - { - stop, - breakpoint, - currentTime, - locationState, - mapLayers, - mapLayerOptions, - stopName, - }, + { stop, breakpoint, locationState, mapLayers, mapLayerOptions, stopName }, { config, match }, ) { if (!stop) { @@ -66,67 +56,48 @@ function StopPageMap( const maxShowRouteDistance = breakpoint === 'large' ? 900 : 470; const { environment } = useContext(ReactRelayContext); - const [plan, setPlan] = useState({ plan: {}, isFetching: false }); + const [walk, setWalk] = useState(null); useEffect(() => { let isMounted = true; - const fetchPlan = async targetStop => { + const fetchWalk = async targetStop => { if (locationState.hasLocation && locationState.address) { if (distance(locationState, stop) < maxShowRouteDistance) { - const toPlace = { - address: targetStop.name ? targetStop.name : 'stop', - lon: targetStop.lon, - lat: targetStop.lat, - }; const settings = getSettings(config); const variables = { - fromPlace: locationToUri(locationState), - toPlace: locationToUri(toPlace), - date: moment(currentTime * 1000).format('YYYY-MM-DD'), - time: moment(currentTime * 1000).format('HH:mm:ss'), + origin: { + location: { + coordinate: { + latitude: locationState.lat, + longitude: locationState.lon, + }, + }, + }, + destination: { + location: { + coordinate: { + latitude: targetStop.lat, + longitude: targetStop.lon, + }, + }, + }, walkSpeed: settings.walkSpeed, wheelchair: !!settings.accessibilityOption, }; - const query = graphql` - query StopPageMapQuery( - $fromPlace: String! - $toPlace: String! - $date: String! - $time: String! - $walkSpeed: Float - $wheelchair: Boolean - ) { - plan: plan( - fromPlace: $fromPlace - toPlace: $toPlace - date: $date - time: $time - transportModes: [{ mode: WALK }] - walkSpeed: $walkSpeed - wheelchair: $wheelchair - ) { - itineraries { - legs { - mode - ...ItineraryLine_legs - } - } - } - } - `; - fetchQuery(environment, query, variables) + fetchQuery(environment, walkQuery, variables) .toPromise() - .then(({ plan: result }) => { + .then(result => { if (isMounted) { - setPlan({ plan: result, isFetching: false }); + setWalk( + result.plan.edges.length ? result.plan.edges?.[0].node : null, + ); } }); } } }; if (stop && locationState.hasLocation) { - setPlan({ plan: plan.plan, isFetching: true }); - fetchPlan(stop); + fetchWalk(stop); } return () => { isMounted = false; @@ -161,18 +132,15 @@ function StopPageMap( ); } - if (plan.plan.itineraries) { + if (walk) { leafletObjs.push( - ...plan.plan.itineraries.map((itinerary, i) => ( - - )), + , ); } const id = match.params.stopId || match.params.terminalId || match.params.id; @@ -229,7 +197,6 @@ StopPageMap.propTypes = { }), breakpoint: PropTypes.string.isRequired, locationState: locationShape.isRequired, - currentTime: PropTypes.number.isRequired, mapLayers: mapLayerShape.isRequired, mapLayerOptions: mapLayerOptionsShape.isRequired, parkType: PropTypes.string, @@ -246,9 +213,8 @@ const componentWithBreakpoint = withBreakpoint(StopPageMap); const StopPageMapWithStores = connectToStores( componentWithBreakpoint, - [TimeStore, PositionStore, MapLayerStore], + [PositionStore, MapLayerStore], ({ config, getStore }, props) => { - const currentTime = getStore(TimeStore).getCurrentTime(); const locationState = getStore(PositionStore).getLocationState(); const ml = config.showVehiclesOnStopPage ? { notThese: ['vehicles'] } : {}; if (props.citybike) { @@ -266,7 +232,6 @@ const StopPageMapWithStores = connectToStores( }); return { locationState, - currentTime, mapLayers, mapLayerOptions, }; diff --git a/app/component/map/StopsNearYouMap.js b/app/component/map/StopsNearYouMap.js index cf6588a70b..1db49e932f 100644 --- a/app/component/map/StopsNearYouMap.js +++ b/app/component/map/StopsNearYouMap.js @@ -1,8 +1,7 @@ import React, { useEffect, useState, useRef } from 'react'; import PropTypes from 'prop-types'; import { matchShape } from 'found'; -import { graphql, fetchQuery } from 'react-relay'; -import moment from 'moment'; +import { fetchQuery } from 'react-relay'; import uniqBy from 'lodash/uniqBy'; import compact from 'lodash/compact'; import isEqual from 'lodash/isEqual'; @@ -18,7 +17,6 @@ import { stopRealTimeClient, changeRealTimeClientTopics, } from '../../action/realTimeClientAction'; -import { locationToUri } from '../../util/otpStrings'; import { sortNearbyRentalStations, sortNearbyStops, @@ -35,6 +33,7 @@ import LazilyLoad, { importLazy } from '../LazilyLoad'; import { getDefaultNetworks } from '../../util/vehicleRentalUtils'; import { getRouteMode } from '../../util/modeUtils'; import CookieSettingsButton from '../CookieSettingsButton'; +import { walkQuery } from './WalkQuery'; const locationMarkerModules = { LocationMarker: () => @@ -146,7 +145,6 @@ const getLocationMarker = location => { function StopsNearYouMap( { breakpoint, - currentTime, stopsNearYou, match, loading, @@ -164,11 +162,7 @@ function StopsNearYouMap( const [routeLines, setRouteLines] = useState([]); const [bounds, setBounds] = useState([]); const [clientOn, setClientOn] = useState(false); - const [firstPlan, setFirstPlan] = useState({ - itinerary: [], - isFetching: false, - stop: null, - }); + const [walk, setWalk] = useState({ itinerary: null, stop: null }); const prevPlace = useRef(); const prevMode = useRef(); const { mode } = match.params; @@ -176,56 +170,36 @@ function StopsNearYouMap( const walkRoutingThreshold = mode === 'RAIL' || mode === 'SUBWAY' || mode === 'FERRY' ? 3000 : 1500; const { environment } = relay; + const fetchPlan = stop => { - const toPlace = { - address: stop.name ? stop.name : 'stop', - lon: stop.lon, - lat: stop.lat, - }; - const settings = getSettings(context.config); - const variables = { - fromPlace: locationToUri(position), - toPlace: locationToUri(toPlace), - date: moment(currentTime * 1000).format('YYYY-MM-DD'), - time: moment(currentTime * 1000).format('HH:mm:ss'), - walkSpeed: settings.walkSpeed, - wheelchair: !!settings.accessibilityOption, - }; - const query = graphql` - query StopsNearYouMapQuery( - $fromPlace: String! - $toPlace: String! - $date: String! - $time: String! - $walkSpeed: Float - $wheelchair: Boolean - ) { - plan: plan( - fromPlace: $fromPlace - toPlace: $toPlace - date: $date - time: $time - transportModes: [{ mode: WALK }] - walkSpeed: $walkSpeed - wheelchair: $wheelchair - ) { - itineraries { - legs { - mode - ...ItineraryLine_legs - } - } - } - } - `; if (stop.distance < walkRoutingThreshold) { - fetchQuery(environment, query, variables) + const settings = getSettings(context.config); + const variables = { + origin: { + location: { + coordinate: { latitude: position.lat, longitude: position.lon }, + }, + }, + destination: { + location: { + coordinate: { latitude: stop.lat, longitude: stop.lon }, + }, + }, + walkSpeed: settings.walkSpeed, + wheelchair: !!settings.accessibilityOption, + }; + fetchQuery(environment, walkQuery, variables) .toPromise() - .then(({ plan: result }) => { - setFirstPlan({ itinerary: result, isFetching: false, stop }); + .then(result => { + setWalk({ + itinerary: result.plan.edges.length + ? result.plan.edges?.[0].node + : null, + stop, + }); }); } else { - setFirstPlan({ itinerary: [], isFetching: false, stop }); + setWalk({ itinerary: null, stop }); } }; @@ -239,27 +213,14 @@ function StopsNearYouMap( favouriteIds.has(firstStop.gtfsId) ); }; - if (!isEqual(firstStop, firstPlan.stop) && shouldFetchWalkRoute()) { - setFirstPlan({ - itinerary: firstPlan.itinerary, - isFetching: true, - stop: firstStop, - }); + if (!isEqual(firstStop, walk.stop) && shouldFetchWalkRoute()) { fetchPlan(firstStop); } else if (!shouldFetchWalkRoute()) { - setFirstPlan({ - itinerary: [], - isFetching: false, - stop: null, - }); + setWalk({ itinerary: null, stop: null }); } } } else { - setFirstPlan({ - itinerary: [], - isFetching: false, - stop: null, - }); + setWalk({ itinerary: null, stop: null }); } }; useEffect(() => { @@ -412,23 +373,15 @@ function StopsNearYouMap( />, ); } - if ( - firstPlan.itinerary.itineraries && - firstPlan.itinerary.itineraries.length > 0 - ) { + if (walk.itinerary) { leafletObjs.push( - firstPlan.itinerary.itineraries.map((itinerary, i) => { - return ( - - ); - }), + , ); } @@ -481,7 +434,6 @@ function StopsNearYouMap( } StopsNearYouMap.propTypes = { - currentTime: PropTypes.number.isRequired, stopsNearYou: PropTypes.shape({ nearest: PropTypes.shape({ // eslint-disable-next-line diff --git a/app/component/map/WalkQuery.js b/app/component/map/WalkQuery.js new file mode 100644 index 0000000000..b091e95252 --- /dev/null +++ b/app/component/map/WalkQuery.js @@ -0,0 +1,31 @@ +import { graphql } from 'react-relay'; + +const walkQuery = graphql` + query WalkQuery( + $origin: PlanLabeledLocationInput! + $destination: PlanLabeledLocationInput! + $walkSpeed: Speed + $wheelchair: Boolean + ) { + plan: planConnection( + first: 1 + origin: $origin + destination: $destination + modes: { directOnly: true, direct: [WALK] } + preferences: { + accessibility: { wheelchair: { enabled: $wheelchair } } + street: { walk: { speed: $walkSpeed } } + } + ) { + edges { + node { + legs { + ...ItineraryLine_legs + } + } + } + } + } +`; + +export { walkQuery }; diff --git a/app/component/navigation.scss b/app/component/navigation.scss index d4070149d3..01d2500aa5 100644 --- a/app/component/navigation.scss +++ b/app/component/navigation.scss @@ -113,6 +113,7 @@ $content-background-color: $background-color; .logo { min-height: 30px; + max-height: 40px; } } diff --git a/app/configurations/config.hsl.js b/app/configurations/config.hsl.js index e5b4689f36..70973fff12 100644 --- a/app/configurations/config.hsl.js +++ b/app/configurations/config.hsl.js @@ -426,6 +426,7 @@ export default { ? fareId.substring(fareId.indexOf(':') + 1) : ''; }, + ticketButtonTextId: 'open-app', trafficNowLink: { fi: 'matkustaminen/liikenne', diff --git a/app/configurations/config.jyvaskyla.js b/app/configurations/config.jyvaskyla.js index 15adf6de01..165b982080 100644 --- a/app/configurations/config.jyvaskyla.js +++ b/app/configurations/config.jyvaskyla.js @@ -174,34 +174,6 @@ export default configMerger(walttiConfig, { }, ticketLinkOperatorCode: 50209, - fareMapping: function mapFareId(fareId) { - const id = fareId?.substring?.(fareId.indexOf(':') + 1); - switch (id) { - case 'A': - return 'Käteismaksu autossa, Vyöhyke A'; - case 'AB': - return 'Käteismaksu autossa, Vyöhykkeet AB'; - case 'ABC': - return 'Käteismaksu autossa, Vyöhykkeet ABC'; - case 'ABCD': - return 'Käteismaksu autossa, Vyöhykkeet ABCD'; - case 'B': - return 'Käteismaksu autossa, Vyöhyke B'; - case 'BC': - return 'Käteismaksu autossa, Vyöhykkeet BC'; - case 'BCD': - return 'Käteismaksu autossa, Vyöhykkeet BCD'; - case 'C': - return 'Käteismaksu autossa, Vyöhyke C'; - case 'CD': - return 'Käteismaksu autossa, Vyöhykkeet CD'; - case 'D': - return 'Käteismaksu autossa, Vyöhyke D'; - default: - return ''; - } - }, - stopCard: { header: { virtualMonitorBaseUrl: 'https://pysakit.jyvaskyla.fi/', @@ -213,5 +185,4 @@ export default configMerger(walttiConfig, { }, // Notice! Turning on this setting forces the search for car routes (for the CO2 comparison only). showCO2InItinerarySummary: true, - devAnalytics: true, }); diff --git a/app/configurations/config.kuopio.js b/app/configurations/config.kuopio.js index 87150f1a4d..baa73725e7 100644 --- a/app/configurations/config.kuopio.js +++ b/app/configurations/config.kuopio.js @@ -199,5 +199,4 @@ export default configMerger(walttiConfig, { }, }, }, - devAnalytics: true, }); diff --git a/app/configurations/config.lahti.js b/app/configurations/config.lahti.js index 28b2726849..44c351d4bb 100644 --- a/app/configurations/config.lahti.js +++ b/app/configurations/config.lahti.js @@ -176,7 +176,7 @@ export default configMerger(walttiConfig, { showTicketInformation: true, useTicketIcons: true, ticketLink: 'https://www.lsl.fi/liput-ja-hinnat/', - showTicketPrice: true, + showTicketPrice: false, showTicketLinkOnlyWhenTesting: true, settingsForFeatureTesting: { @@ -186,33 +186,4 @@ export default configMerger(walttiConfig, { transferPenalty: 1600, }, ticketLinkOperatorCode: 50223, - - fareMapping: function mapFareId(fareId) { - const id = fareId?.substring?.(fareId.indexOf(':') + 1); - switch (id) { - case 'A': - return 'Käteismaksu autossa, Vyöhyke A'; - case 'AB': - return 'Käteismaksu autossa, Vyöhykkeet AB'; - case 'ABC': - return 'Käteismaksu autossa, Vyöhykkeet ABC'; - case 'ABCD': - return 'Käteismaksu autossa, Vyöhykkeet ABCD'; - case 'B': - return 'Käteismaksu autossa, Vyöhyke B'; - case 'BC': - return 'Käteismaksu autossa, Vyöhykkeet BC'; - case 'BCD': - return 'Käteismaksu autossa, Vyöhykkeet BCD'; - case 'C': - return 'Käteismaksu autossa, Vyöhyke C'; - case 'CD': - return 'Käteismaksu autossa, Vyöhykkeet CD'; - case 'D': - return 'Käteismaksu autossa, Vyöhyke D'; - default: - return ''; - } - }, - devAnalytics: true, }); diff --git a/app/configurations/config.waltti.js b/app/configurations/config.waltti.js index 7ce97c693b..758e62a911 100644 --- a/app/configurations/config.waltti.js +++ b/app/configurations/config.waltti.js @@ -278,6 +278,7 @@ export default { } return `https://waltti.fi/walttiapp/busTicket/?operator=${operatorCode}&ticketType=single&customerGroup=adult&zones=${zones}`; }, + ticketButtonTextId: 'buy-in-app', analyticsScript: function createAnalyticsScript(hostname) { // eslint-disable-next-line no-useless-escape diff --git a/app/translations.js b/app/translations.js index 04947c9526..b5a5f64d41 100644 --- a/app/translations.js +++ b/app/translations.js @@ -862,6 +862,7 @@ const translations = { 'as-destination': 'Destination', 'as-origin': 'Origin', 'as-viapoint': 'Viapoint', + 'buy-in-app': 'Buy in App', 'search-autosuggest-label': 'Venue, place and stopsearch.', 'search-autosuggest-label-instructions': 'Navigate list with arrow keys and select with enter key.', @@ -2110,6 +2111,7 @@ const translations = { 'as-destination': 'Määränpääksi', 'as-origin': 'Lähtöpaikaksi', 'as-viapoint': 'Välipisteeksi', + 'buy-in-app': 'Osta sovelluksessa', 'search-autosuggest-label': 'Paikka, linja ja pysäkkihaku.', 'search-autosuggest-label-instructions': 'Navigoi listassa nuolinäppäimillä ja valitse enterillä.', @@ -5025,6 +5027,7 @@ const translations = { 'as-viapoint': 'Via punkt', 'book-a-lift': 'Tilaa kyyti sovelluksella ja jää odottamaan sen saapumista:', + 'buy-in-app': 'Köp i appen', 'search-autosuggest-label': 'Plats, linje och hållplatssökning.', 'search-autosuggest-label-instructions': 'Navigera listan med piltangenterna och välj med Enter-tangeten.',