diff --git a/.env.example b/.env.example
index 2626f6b76..13e838a96 100644
--- a/.env.example
+++ b/.env.example
@@ -52,8 +52,9 @@ REITTIOPAS_URL="https://reittiopas.foli.fi/reitti/"
THEME_PKG=1
MOBILITY_PLATFORM_API="https://palvelukartta-api.turku.fi"
RAILWAYS_API="https://rata.digitraffic.fi/api/v1"
-ROADWORKS_API="https://tie.digitraffic.fi/api/traffic-message/v1/messages"
+ROADWORKS_API="https://palvelukartta-api.turku.fi/exceptional_situations/api/v1"
AIR_MONITORING_API="https://palvelukartta-api.turku.fi/environment_data/api/v1"
+MOBILITY_TEST_API="https://liikkumistesti-api.turku.fi/api/v1/postalcoderesult"
# API URLs to fetch parking spaces data
PARKING_SPACES_URL="https://parkkiopas.turku.fi/public/v1/parking_area/"
diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
index 0ac640741..f7a7e5f91 100644
--- a/.github/workflows/codeql-analysis.yml
+++ b/.github/workflows/codeql-analysis.yml
@@ -18,7 +18,7 @@ on:
# The branches below must be a subset of the branches above
branches: [ develop ]
schedule:
- - cron: '29 10 * * 6'
+ - cron: '39 16 * * 1'
jobs:
analyze:
@@ -38,11 +38,11 @@ jobs:
steps:
- name: Checkout repository
- uses: actions/checkout@v2
+ uses: actions/checkout@v3
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
- uses: github/codeql-action/init@v1
+ uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
@@ -53,7 +53,7 @@ jobs:
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
- uses: github/codeql-action/autobuild@v1
+ uses: github/codeql-action/autobuild@v3
# ℹ️ Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
@@ -67,4 +67,4 @@ jobs:
# make release
- name: Perform CodeQL Analysis
- uses: github/codeql-action/analyze@v1
+ uses: github/codeql-action/analyze@v3
diff --git a/config/default.js b/config/default.js
index d72e82e46..cca511771 100644
--- a/config/default.js
+++ b/config/default.js
@@ -285,4 +285,5 @@ export default {
"airMonitoringAPI": settings.AIR_MONITORING_API,
"roadworksAPI": settings.ROADWORKS_API,
"railwaysAPI": settings.RAILWAYS_API,
+ "mobilityTestAPI": settings.MOBILITY_TEST_API,
}
diff --git a/package-lock.json b/package-lock.json
index 32fda84c2..d6a4f52e9 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -9,6 +9,7 @@
"version": "0.1.0",
"dependencies": {
"@datapunt/matomo-tracker-js": "^0.5.1",
+ "@emotion/css": "^11.11.2",
"@emotion/react": "^11.10.8",
"@emotion/styled": "^11.10.8",
"@formatjs/intl-pluralrules": "^1.5.9",
@@ -2312,6 +2313,18 @@
"stylis": "4.2.0"
}
},
+ "node_modules/@emotion/css": {
+ "version": "11.11.2",
+ "resolved": "https://registry.npmjs.org/@emotion/css/-/css-11.11.2.tgz",
+ "integrity": "sha512-VJxe1ucoMYMS7DkiMdC2T7PWNbrEI0a39YRiyDvK2qq4lXwjRbVP/z4lpG+odCsRzadlR+1ywwrTzhdm5HNdew==",
+ "dependencies": {
+ "@emotion/babel-plugin": "^11.11.0",
+ "@emotion/cache": "^11.11.0",
+ "@emotion/serialize": "^1.1.2",
+ "@emotion/sheet": "^1.2.2",
+ "@emotion/utils": "^1.2.1"
+ }
+ },
"node_modules/@emotion/hash": {
"version": "0.9.1",
"resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.1.tgz",
diff --git a/package.json b/package.json
index 05f703c6c..759e91263 100644
--- a/package.json
+++ b/package.json
@@ -4,6 +4,7 @@
"private": true,
"dependencies": {
"@datapunt/matomo-tracker-js": "^0.5.1",
+ "@emotion/css": "^11.11.2",
"@emotion/react": "^11.10.8",
"@emotion/styled": "^11.10.8",
"@formatjs/intl-pluralrules": "^1.5.9",
diff --git a/server/server.js b/server/server.js
index 20d23b715..1e3d46ae0 100644
--- a/server/server.js
+++ b/server/server.js
@@ -273,6 +273,7 @@ const htmlTemplate = (req, reactDom, preloadedState, css, cssString, emotionCss,
window.nodeEnvSettings.ROADWORKS_API = "${process.env.ROADWORKS_API}";
window.nodeEnvSettings.RAILWAYS_API = "${process.env.RAILWAYS_API}";
window.nodeEnvSettings.AIR_MONITORING_API = "${process.env.AIR_MONITORING_API}";
+ window.nodeEnvSettings.MOBILITY_TEST_API = "${process.env.MOBILITY_TEST_API}";
window.nodeEnvSettings.FEATURE_SERVICEMAP_PAGE_TRACKING = "${process.env.FEATURE_SERVICEMAP_PAGE_TRACKING}";
window.appVersion = {};
diff --git a/src/components/AddressSearchBar/AddressSearchBar.js b/src/components/AddressSearchBar/AddressSearchBar.js
index 0d28510b8..6ba556b73 100644
--- a/src/components/AddressSearchBar/AddressSearchBar.js
+++ b/src/components/AddressSearchBar/AddressSearchBar.js
@@ -14,7 +14,9 @@ import useMobileStatus from '../../utils/isMobile';
import ServiceMapAPI from '../../utils/newFetch/ServiceMapAPI';
import useLocaleText from '../../utils/useLocaleText';
import { getAddressText } from '../../utils/address';
+import { getCitySettings } from '../../redux/selectors/settings';
import { focusToPosition } from '../../views/MapView/utils/mapActions';
+import config from '../../../config';
const AddressSearchBar = ({ title, intl, handleAddressChange }) => {
const getLocaleText = useLocaleText();
@@ -24,6 +26,7 @@ const AddressSearchBar = ({ title, intl, handleAddressChange }) => {
const map = useSelector(state => state.mapRef);
const customPosition = useSelector(state => state.user.customPosition);
const position = useSelector(state => state.user.position);
+ const citySettings = useSelector(getCitySettings);
const defaultAddress = position.addressData || customPosition.addressData;
@@ -36,12 +39,14 @@ const AddressSearchBar = ({ title, intl, handleAddressChange }) => {
const suggestionCount = 5;
const inputRef = useRef();
- const fetchAddressResults = async (text) => {
+ const fetchAddressResults = async text => {
const smAPI = new ServiceMapAPI();
+ const municipalities = citySettings?.length ? citySettings?.join(',') : config.cities;
const fetchOptions = {
page_size: suggestionCount,
type: 'address',
address_limit: suggestionCount,
+ municipality: municipalities,
language: locale,
};
setIsFetching(true);
@@ -50,7 +55,7 @@ const AddressSearchBar = ({ title, intl, handleAddressChange }) => {
return results;
};
- const handleAddressSelect = (address) => {
+ const handleAddressSelect = address => {
if (!addressResults.length) return;
if (inputRef.current) {
inputRef.current.focus();
@@ -64,7 +69,7 @@ const AddressSearchBar = ({ title, intl, handleAddressChange }) => {
focusToPosition(map, address.location?.coordinates);
};
- const handleSearchBarKeyPress = (e) => {
+ const handleSearchBarKeyPress = e => {
if (e.key === 'ArrowDown') {
e.preventDefault();
if (resultIndex === null || resultIndex === addressResults.length - 1) {
@@ -82,14 +87,14 @@ const AddressSearchBar = ({ title, intl, handleAddressChange }) => {
}
};
- const clearSuggestions = (e) => {
+ const clearSuggestions = e => {
e.preventDefault();
setTimeout(() => {
setAddressResults([]);
}, 200);
};
- const handleSubmit = (e) => {
+ const handleSubmit = e => {
if (resultIndex !== null) {
handleAddressSelect(addressResults[resultIndex]);
} else {
@@ -98,7 +103,7 @@ const AddressSearchBar = ({ title, intl, handleAddressChange }) => {
clearSuggestions(e);
};
- const handleInputChange = (text) => {
+ const handleInputChange = text => {
// Reset cleared text
if (cleared) {
setCleared(false);
@@ -108,7 +113,7 @@ const AddressSearchBar = ({ title, intl, handleAddressChange }) => {
if (currentLocation) {
setCurrentLocation(null);
}
- fetchAddressResults(text).then((data) => {
+ fetchAddressResults(text).then(data => {
if (!isFetching) setAddressResults(data);
});
} else if (addressResults.length) setAddressResults([]);
diff --git a/src/components/EcoCounter/CounterMarkers/CounterMarkers.js b/src/components/EcoCounter/CounterMarkers/CounterMarkers.js
index 85ec6cae5..870977f8c 100644
--- a/src/components/EcoCounter/CounterMarkers/CounterMarkers.js
+++ b/src/components/EcoCounter/CounterMarkers/CounterMarkers.js
@@ -1,14 +1,13 @@
import { PropTypes } from 'prop-types';
import React from 'react';
import { useSelector } from 'react-redux';
+import styled from '@emotion/styled';
import ecoCounterIcon from 'servicemap-ui-turku/assets/icons/icons-icon_ecocounter.svg';
import ecoCounterIconBw from 'servicemap-ui-turku/assets/icons/contrast/icons-icon_ecocounter-bw.svg';
import { useAccessibleMap } from '../../../redux/selectors/settings';
import { createIcon } from '../../MobilityPlatform/utils/utils';
-const CounterMarkers = ({
- classes, counterStation, children,
-}) => {
+const CounterMarkers = ({ counterStation, children }) => {
const useContrast = useSelector(useAccessibleMap);
const { Marker, Popup } = global.rL;
@@ -18,22 +17,33 @@ const CounterMarkers = ({
return (
+ Lähestymisalue: +
++ Kulkumuto: Kävely +
++ Arvioitu aika: 10 minuuttia +
++ Lähtevät lennot: +
++ Ei lähteviä lentoja. +
++ Saapuvat lennot: +
++ Ei saapuvia lentoja. +
++ Grillaus- ja tulentekopaikka +
++ Valmistaja: Testi +
++ Malli: Testigrilli +
+({ - title: { - marginBottom: theme.spacing(1), - width: '85%', - borderBottom: '1px solid #000000', - }, - titleText: { - fontSize: '0.9rem', - }, - paragraph: { - marginBottom: theme.spacing(0.5), - }, - padding: { - padding: theme.spacing(1), - }, -}); diff --git a/src/components/MobilityPlatform/BicycleStands/index.js b/src/components/MobilityPlatform/BicycleStands/index.js index 8c9a86d52..3235dfe69 100644 --- a/src/components/MobilityPlatform/BicycleStands/index.js +++ b/src/components/MobilityPlatform/BicycleStands/index.js @@ -1,6 +1,3 @@ -import { withStyles } from '@mui/styles'; -import { injectIntl } from 'react-intl'; import BicycleStands from './BicycleStands'; -import styles from './styles'; -export default withStyles(styles)(injectIntl(BicycleStands)); +export default BicycleStands; diff --git a/src/components/MobilityPlatform/BicycleStands/styles.js b/src/components/MobilityPlatform/BicycleStands/styles.js deleted file mode 100644 index bed7a8e7a..000000000 --- a/src/components/MobilityPlatform/BicycleStands/styles.js +++ /dev/null @@ -1,7 +0,0 @@ -const styles = { - popupInner: { - margin: '0.8rem', - }, -}; - -export default styles; diff --git a/src/components/MobilityPlatform/BikeServiceStations/components/BikeServiceStationContent/BikeServiceStationContent.js b/src/components/MobilityPlatform/BikeServiceStations/components/BikeServiceStationContent/BikeServiceStationContent.js index 7e65bc257..a6e1cb985 100644 --- a/src/components/MobilityPlatform/BikeServiceStations/components/BikeServiceStationContent/BikeServiceStationContent.js +++ b/src/components/MobilityPlatform/BikeServiceStations/components/BikeServiceStationContent/BikeServiceStationContent.js @@ -1,8 +1,9 @@ import PropTypes from 'prop-types'; import React from 'react'; +import { StyledContainer, StyledHeaderContainer, StyledTextContainer } from '../../../styled/styled'; import TextComponent from '../../../TextComponent'; -const BikeServiceStationContent = ({ classes, station }) => { +const BikeServiceStationContent = ({ station }) => { const stationName = { fi: station.name, en: station.name_en, @@ -22,27 +23,35 @@ const BikeServiceStationContent = ({ classes, station }) => { }; const bikeServiceStationInfo = ( -
({
- container: {
- margin: theme.spacing(1),
- },
- headerContainer: {
- width: '85%',
- borderBottom: '1px solid #000',
- paddingBottom: theme.spacing(0.5),
- },
- textContainer: {
- marginTop: theme.spacing(0.5),
- },
- contentInner: {
- marginLeft: theme.spacing(1),
- marginBottom: theme.spacing(1),
- },
- margin: {
- margin: theme.spacing(0.4),
- },
-});
diff --git a/src/components/MobilityPlatform/Boating/Marinas/components/MarinasContent/MarinasContent.js b/src/components/MobilityPlatform/Boating/Marinas/components/MarinasContent/MarinasContent.js
index 963a9a224..3d06a9420 100644
--- a/src/components/MobilityPlatform/Boating/Marinas/components/MarinasContent/MarinasContent.js
+++ b/src/components/MobilityPlatform/Boating/Marinas/components/MarinasContent/MarinasContent.js
@@ -1,14 +1,19 @@
import { Link, Typography } from '@mui/material';
import PropTypes from 'prop-types';
import React from 'react';
+import { useIntl } from 'react-intl';
+import styled from '@emotion/styled';
+import { StyledContainer, StyledHeaderContainer, StyledTextContainer } from '../../../../styled/styled';
+
+const MarinasContent = ({ berthItem }) => {
+ const intl = useIntl();
-const MarinasContent = ({
- classes, intl, berthItem,
-}) => {
const renderText = (translationId, value) => (
-
- Venepaikkojen määrä: 1 -
-+
- Tyyppi: Aisapaikka -
-+ Venepaikkojen määrä: 1 +
++ + Venetyyppi (esimerkki): + +
+Sähkölatausaseman tyyppi: CCS
diff --git a/src/components/MobilityPlatform/ChargerStationMarkers/components/ChargerStationContent/index.js b/src/components/MobilityPlatform/ChargerStationMarkers/components/ChargerStationContent/index.js
index df2828ca2..9f82ac180 100644
--- a/src/components/MobilityPlatform/ChargerStationMarkers/components/ChargerStationContent/index.js
+++ b/src/components/MobilityPlatform/ChargerStationMarkers/components/ChargerStationContent/index.js
@@ -1,6 +1,3 @@
-import { withStyles } from '@mui/styles';
-import { injectIntl } from 'react-intl';
import ChargerStationContent from './ChargerStationContent';
-import styles from './styles';
-export default withStyles(styles)(injectIntl(ChargerStationContent));
+export default ChargerStationContent;
diff --git a/src/components/MobilityPlatform/ChargerStationMarkers/components/ChargerStationContent/styles.js b/src/components/MobilityPlatform/ChargerStationMarkers/components/ChargerStationContent/styles.js
deleted file mode 100644
index 6818cfb53..000000000
--- a/src/components/MobilityPlatform/ChargerStationMarkers/components/ChargerStationContent/styles.js
+++ /dev/null
@@ -1,20 +0,0 @@
-export default theme => ({
- container: {
- margin: theme.spacing(1),
- },
- headerContainer: {
- width: '85%',
- borderBottom: '1px solid #000',
- paddingBottom: theme.spacing(0.5),
- },
- textContainer: {
- marginTop: theme.spacing(0.5),
- },
- contentInner: {
- marginLeft: theme.spacing(1),
- marginBottom: theme.spacing(1),
- },
- margin: {
- margin: theme.spacing(0.4),
- },
-});
diff --git a/src/components/MobilityPlatform/CityBikes/CityBikes.js b/src/components/MobilityPlatform/CityBikes/CityBikes.js
index fd495cdfe..9e4161671 100644
--- a/src/components/MobilityPlatform/CityBikes/CityBikes.js
+++ b/src/components/MobilityPlatform/CityBikes/CityBikes.js
@@ -12,14 +12,13 @@ import cargoBikesIconProvider from 'servicemap-ui-turku/assets/icons/icons-icon_
import cargoBikesIconProviderBw from 'servicemap-ui-turku/assets/icons/contrast/icons-icon_cargo_bikes_provider-bw.svg';
import { useMobilityPlatformContext } from '../../../context/MobilityPlatformContext';
import { useAccessibleMap } from '../../../redux/selectors/settings';
-import { fetchCityBikesData } from '../mobilityPlatformRequests/mobilityPlatformRequests';
+import useIotDataFetch from '../utils/useIotDataFetch';
import { isDataValid, setRender, checkMapType } from '../utils/utils';
import { isEmbed } from '../../../utils/path';
+import { StyledPopupWrapper, StyledPopupInner } from '../styled/styled';
import CityBikesContent from './components/CityBikesContent';
const CityBikes = () => {
- const [cityBikeStationsData, setCityBikeStationsData] = useState([]);
- const [cityBikeStatistics, setCityBikeStatistics] = useState([]);
const [zoomLevel, setZoomLevel] = useState(13);
const { showCityBikes, showCargoBikes } = useMobilityPlatformContext();
@@ -54,22 +53,15 @@ const CityBikes = () => {
iconSize: zoomLevel < 14 ? [45, 45] : [35, 35],
});
- useEffect(() => {
- if (showCityBikes || showCargoBikes || embedded) {
- fetchCityBikesData('CBI', setCityBikeStationsData);
- }
- }, [showCityBikes, showCargoBikes, embedded]);
+ const fetchData = showCityBikes || showCargoBikes;
- useEffect(() => {
- if (showCityBikes || showCargoBikes || embedded) {
- fetchCityBikesData('CBS', setCityBikeStatistics);
- }
- }, [showCityBikes, showCargoBikes, embedded]);
+ const { iotData: cityBikeStationsData } = useIotDataFetch('CBI', fetchData, embedded);
+ const { iotData: cityBikeStatistics } = useIotDataFetch('CBS', fetchData, embedded);
const cityBikeStations = [];
/** Separate cargo bike stations from city bike stations */
- const cargoBikeStations = cityBikeStationsData.reduce((acc, curr) => {
+ const cargoBikeStations = cityBikeStationsData?.reduce((acc, curr) => {
if (curr.name.includes('eCargo bikes')) {
acc.push(curr);
} else {
@@ -86,7 +78,7 @@ const CityBikes = () => {
const fitBounds = (renderData, data) => {
if (renderData) {
const bounds = [];
- data.forEach((item) => {
+ data.forEach(item => {
bounds.push([item.lat, item.lon]);
});
map.fitBounds(bounds);
@@ -101,15 +93,19 @@ const CityBikes = () => {
}, [showCityBikes, showCargoBikes]);
const renderCityBikeMarkers = (isValid, data, icon) => (isValid ? (
- data.map((item) => (
+ data.map(item => (
Varauslinkit :
iOS
diff --git a/src/components/MobilityPlatform/CityBikes/components/CityBikesContent/index.js b/src/components/MobilityPlatform/CityBikes/components/CityBikesContent/index.js index 02e8bbfb7..7b70b4508 100644 --- a/src/components/MobilityPlatform/CityBikes/components/CityBikesContent/index.js +++ b/src/components/MobilityPlatform/CityBikes/components/CityBikesContent/index.js @@ -1,6 +1,3 @@ -import { withStyles } from '@mui/styles'; -import { injectIntl } from 'react-intl'; import CityBikesContent from './CityBikesContent'; -import styles from './styles'; -export default withStyles(styles)(injectIntl(CityBikesContent)); +export default CityBikesContent; diff --git a/src/components/MobilityPlatform/CityBikes/components/CityBikesContent/styles.js b/src/components/MobilityPlatform/CityBikes/components/CityBikesContent/styles.js deleted file mode 100644 index ce800f972..000000000 --- a/src/components/MobilityPlatform/CityBikes/components/CityBikesContent/styles.js +++ /dev/null @@ -1,21 +0,0 @@ -export default theme => ({ - popupInner: { - margin: theme.spacing(2), - }, - subtitle: { - marginBottom: theme.spacing(1), - paddingBottom: theme.spacing(0.5), - borderBottom: '1px solid #000000', - width: '88%', - }, - paragraph: { - marginBottom: theme.spacing(0.4), - }, - bold: { - fontWeight: 'bold', - }, - link: { - color: theme.palette.link.main, - textDecoration: 'underline', - }, -}); diff --git a/src/components/MobilityPlatform/CrossWalks/CrossWalks.js b/src/components/MobilityPlatform/CrossWalks/CrossWalks.js index 30ce3d823..b86796364 100644 --- a/src/components/MobilityPlatform/CrossWalks/CrossWalks.js +++ b/src/components/MobilityPlatform/CrossWalks/CrossWalks.js @@ -1,5 +1,5 @@ /* eslint-disable global-require */ -import React, { useState } from 'react'; +import React, { useState, useEffect } from 'react'; import PropTypes from 'prop-types'; import { useSelector } from 'react-redux'; import { useMap, useMapEvents } from 'react-leaflet'; @@ -59,8 +59,10 @@ const CrossWalks = ({ mapObject }) => { const fetchBox = MapUtility.getBboxFromBounds(wideBounds, true); const isDetailZoom = zoomLevel >= mapObject.options.detailZoom; + const controller = new AbortController(); const handleCrossWalks = () => { + const { signal } = controller; const options = { type_name: 'CrossWalkSign', page_size: 3000, @@ -70,10 +72,12 @@ const CrossWalks = ({ mapObject }) => { (openMobilityPlatform && isDetailZoom) || (embedded && isDetailZoom) ) { - fetchMobilityMapData(options, setCrossWalksData); + fetchMobilityMapData(options, setCrossWalksData, signal); } }; + useEffect(() => () => controller.abort(), []); + const mapEvent = useMapEvents({ zoomend() { setZoomLevel(mapEvent.getZoom()); @@ -87,18 +91,16 @@ const CrossWalks = ({ mapObject }) => { const renderData = isDetailZoom && setRender(paramValue, embedded, showCrossWalks, crossWalksData, isDataValid); return ( - <> - {renderData - ? crossWalksData.map(item => ( -({ - container: { - margin: theme.spacing(1), - }, - headerContainer: { - width: '85%', - borderBottom: '1px solid #000', - paddingBottom: theme.spacing(0.5), - }, - textContainer: { - marginTop: theme.spacing(0.5), - }, - contentInner: { - marginLeft: theme.spacing(1), - marginBottom: theme.spacing(1), - }, - margin: { - margin: theme.spacing(0.4), - }, -}); diff --git a/src/components/MobilityPlatform/InfoTextBox/InfoTextBox.js b/src/components/MobilityPlatform/InfoTextBox/InfoTextBox.js index 9dea299ce..4665924e9 100644 --- a/src/components/MobilityPlatform/InfoTextBox/InfoTextBox.js +++ b/src/components/MobilityPlatform/InfoTextBox/InfoTextBox.js @@ -1,40 +1,52 @@ import { Link, Typography } from '@mui/material'; import PropTypes from 'prop-types'; import React from 'react'; +import { useIntl } from 'react-intl'; +import styled from '@emotion/styled'; +import { StyledLinkText } from '../styled/styled'; const InfoTextBox = ({ - classes, intl, infoText, linkUrl, linkText, reducePadding, -}) => ( -
({ - container: { - textAlign: 'left', - borderTop: 'rgb(193, 193, 193)', - }, - link: { - marginTop: theme.spacing(0.5), - color: theme.palette.link.main, - textDecoration: 'underline', - }, - padding: { - padding: theme.spacing(2), - }, - paddingSm: { - padding: '1rem 0.5rem 0.5rem 0', - }, -}); diff --git a/src/components/MobilityPlatform/LoadingPlaces/components/LoadingPlacesContent/LoadingPlacesContent.js b/src/components/MobilityPlatform/LoadingPlaces/components/LoadingPlacesContent/LoadingPlacesContent.js index c6c73ed21..cee4e16d0 100644 --- a/src/components/MobilityPlatform/LoadingPlaces/components/LoadingPlacesContent/LoadingPlacesContent.js +++ b/src/components/MobilityPlatform/LoadingPlaces/components/LoadingPlacesContent/LoadingPlacesContent.js @@ -1,8 +1,10 @@ import PropTypes from 'prop-types'; import React from 'react'; +import styled from '@emotion/styled'; import TextComponent from '../../../TextComponent'; +import { StyledContainer, StyledHeaderContainer } from '../../../styled/styled'; -const LoadingPlacesContent = ({ classes, item }) => { +const LoadingPlacesContent = ({ item }) => { const loadingPlaceName = { fi: item.name_fi, en: item.name_en, @@ -16,29 +18,42 @@ const LoadingPlacesContent = ({ classes, item }) => { }; const loadingPlaceInfo = ( -
- Testi -
-- Osoite: Testikatu -
--
- Testi -
--
- Testitieto -
--
- Testitieto -
-+ Postinumeroalue: 20210 +
++ Joustava Jänis +
++ 10 +
+ ({
- container: {
- margin: theme.spacing(1),
- },
- headerContainer: {
- width: '85%',
- borderBottom: '1px solid #000',
- paddingBottom: theme.spacing(0.5),
- },
- textContainer: {
- marginTop: theme.spacing(0.5),
- },
- contentInner: {
- marginLeft: theme.spacing(1),
- marginBottom: theme.spacing(1),
- },
- margin: {
- margin: theme.spacing(0.4),
- },
- marginTop: {
- marginTop: theme.spacing(0.4),
- },
-});
diff --git a/src/components/MobilityPlatform/ParkAndRideStops/ParkAndRideBikes/components/ParkAndRideBikesContent/ParkAndRideBikesContent.js b/src/components/MobilityPlatform/ParkAndRideStops/ParkAndRideBikes/components/ParkAndRideBikesContent/ParkAndRideBikesContent.js
index 1f8c0e682..32405b8e1 100644
--- a/src/components/MobilityPlatform/ParkAndRideStops/ParkAndRideBikes/components/ParkAndRideBikesContent/ParkAndRideBikesContent.js
+++ b/src/components/MobilityPlatform/ParkAndRideStops/ParkAndRideBikes/components/ParkAndRideBikesContent/ParkAndRideBikesContent.js
@@ -1,8 +1,8 @@
import PropTypes from 'prop-types';
import React from 'react';
-import styled from '@emotion/styled';
import { Typography } from '@mui/material';
import { useIntl } from 'react-intl';
+import { StyledContainer, StyledHeaderContainer, StyledTextContainer } from '../../../../styled/styled';
import TextComponent from '../../../../TextComponent';
const ParkAndRideBikesContent = ({ item }) => {
@@ -36,40 +36,22 @@ const ParkAndRideBikesContent = ({ item }) => {
{
+const DisabledParkingContent = ({ item }) => {
+ const intl = useIntl();
const getLocaleText = useLocaleText();
- const renderAccessInfo = (accessValue) => {
+ const renderAccessInfo = accessValue => {
const accessValueLower = accessValue.toLowerCase();
if (accessValueLower === 'vapaa paasy') {
return (
-
({ - container: { - margin: theme.spacing(1), - }, - headerContainer: { - width: '85%', - borderBottom: '1px solid #000', - paddingBottom: theme.spacing(0.5), - }, - textContainer: { - marginTop: theme.spacing(0.5), - }, - margin: { - margin: theme.spacing(0.4), - }, -}); diff --git a/src/components/MobilityPlatform/Parking/PublicParking/components/PublicParkingContent/PublicParkingContent.js b/src/components/MobilityPlatform/Parking/PublicParking/components/PublicParkingContent/PublicParkingContent.js index f4480ebcb..654c865dc 100644 --- a/src/components/MobilityPlatform/Parking/PublicParking/components/PublicParkingContent/PublicParkingContent.js +++ b/src/components/MobilityPlatform/Parking/PublicParking/components/PublicParkingContent/PublicParkingContent.js @@ -1,18 +1,22 @@ import { Typography } from '@mui/material'; import PropTypes from 'prop-types'; import React from 'react'; +import { useIntl } from 'react-intl'; +import { StyledContainer, StyledHeaderContainer, StyledTextContainer } from '../../../../styled/styled'; import TextComponent from '../../../../TextComponent'; -const PublicParkingContent = ({ classes, intl, item }) => { +const PublicParkingContent = ({ item }) => { + const intl = useIntl(); + const renderText = (msgId, value) => ( -
({ - container: { - margin: theme.spacing(1), - }, - headerContainer: { - width: '85%', - borderBottom: '1px solid #000', - paddingBottom: theme.spacing(0.5), - }, - textContainer: { - marginTop: theme.spacing(0.5), - }, - margin: { - margin: theme.spacing(0.4), - }, -}); diff --git a/src/components/MobilityPlatform/Parking/RentalCarParking/components/RentalCarParkingContent/RentalCarParkingContent.js b/src/components/MobilityPlatform/Parking/RentalCarParking/components/RentalCarParkingContent/RentalCarParkingContent.js index 7c68228dd..5027db54e 100644 --- a/src/components/MobilityPlatform/Parking/RentalCarParking/components/RentalCarParkingContent/RentalCarParkingContent.js +++ b/src/components/MobilityPlatform/Parking/RentalCarParking/components/RentalCarParkingContent/RentalCarParkingContent.js @@ -1,20 +1,24 @@ import { Typography } from '@mui/material'; import PropTypes from 'prop-types'; import React from 'react'; +import { useIntl } from 'react-intl'; +import { StyledContainer, StyledHeaderContainer, StyledTextContainer } from '../../../../styled/styled'; import TextComponent from '../../../../TextComponent'; -const RentalCarParkingContent = ({ classes, intl, item }) => { +const RentalCarParkingContent = ({ item }) => { + const intl = useIntl(); + const renderText = (msgId, value) => ( -
({ - container: { - margin: theme.spacing(1), - }, - headerContainer: { - width: '85%', - borderBottom: '1px solid #000', - paddingBottom: theme.spacing(0.5), - }, - textContainer: { - marginTop: theme.spacing(0.5), - }, - margin: { - margin: theme.spacing(0.4), - }, -}); diff --git a/src/components/MobilityPlatform/ParkingChargeZones/components/ParkingChargeZoneContent/ParkingChargeZoneContent.js b/src/components/MobilityPlatform/ParkingChargeZones/components/ParkingChargeZoneContent/ParkingChargeZoneContent.js index f5429c2fa..851b82646 100644 --- a/src/components/MobilityPlatform/ParkingChargeZones/components/ParkingChargeZoneContent/ParkingChargeZoneContent.js +++ b/src/components/MobilityPlatform/ParkingChargeZones/components/ParkingChargeZoneContent/ParkingChargeZoneContent.js @@ -1,40 +1,77 @@ import { Typography } from '@mui/material'; import PropTypes from 'prop-types'; import React from 'react'; +import { useIntl } from 'react-intl'; +import styled from '@emotion/styled'; +import { StyledHeaderContainer, StyledTextContainer } from '../../../styled/styled'; -const ParkingChargeZoneContent = ({ classes, intl, parkingChargeZone }) => { - const renderText = (msgId, objValue, isTitle) => ( -
- Maksullisuus arkisin - : - - 9 - 18 + Maksullisuus arkisin: 9 - 18
- Maksullisuus lauantaisin - : - - 9 - 15 + Maksullisuus lauantaisin: 9 - 15
- Maksullisuus sunnuntaisin - : - - Maksuton + Maksullisuus sunnuntaisin: Maksuton
- Hinta - : - - 3 €/h + Hinta: 3 €/h
- Sijainti: Katuosa -
-- Maksu: 1,8 €/t + Maksu: 0,5 €/h
- Lisätietoja: Testiteksti + Lisätietoja: Taksa 0,5€/h ensimmäiset 8h, 0,2€/h aika yli 8h
({ - container: { - margin: theme.spacing(1.25), - }, - title: { - width: '85%', - borderBottom: '1px solid #000000', - marginBottom: theme.spacing(1), - paddingBottom: theme.spacing(0.8), - }, - text: { - paddingBottom: theme.spacing(1), - }, -}); diff --git a/src/components/MobilityPlatform/PolygonComponent/PolygonComponent.js b/src/components/MobilityPlatform/PolygonComponent/PolygonComponent.js index f63d31f60..3d27c08a9 100644 --- a/src/components/MobilityPlatform/PolygonComponent/PolygonComponent.js +++ b/src/components/MobilityPlatform/PolygonComponent/PolygonComponent.js @@ -1,8 +1,9 @@ import React from 'react'; import { PropTypes } from 'prop-types'; +import { StyledPopupWrapper, StyledPopupInner } from '../styled/styled'; const PolygonComponent = ({ - classes, item, useContrast, pathOptions, children, + item, useContrast, pathOptions, children, }) => { const { Polygon, Popup } = global.rL; @@ -12,30 +13,33 @@ const PolygonComponent = ({ pathOptions={pathOptions} positions={item.geometry_coords} eventHandlers={{ - mouseover: (e) => { + mouseover: e => { e.target.setStyle({ fillOpacity: useContrast ? '0.6' : '0.2' }); }, - mouseout: (e) => { + mouseout: e => { e.target.setStyle({ fillOpacity: useContrast ? '0.3' : '0.2' }); }, }} > -
Välillä: 1.10 - 30.4
@@ -41,7 +47,7 @@ exports[`
Välillä: 1.5 - 30.9
diff --git a/src/components/MobilityPlatform/PublicToilets/components/PublicToiletsContent/index.js b/src/components/MobilityPlatform/PublicToilets/components/PublicToiletsContent/index.js
index 3e8973508..c844c64bc 100644
--- a/src/components/MobilityPlatform/PublicToilets/components/PublicToiletsContent/index.js
+++ b/src/components/MobilityPlatform/PublicToilets/components/PublicToiletsContent/index.js
@@ -1,6 +1,3 @@
-import { withStyles } from '@mui/styles';
-import { injectIntl } from 'react-intl';
import PublicToiletsContent from './PublicToiletsContent';
-import styles from './styles';
-export default withStyles(styles)(injectIntl(PublicToiletsContent));
+export default PublicToiletsContent;
diff --git a/src/components/MobilityPlatform/PublicToilets/components/PublicToiletsContent/styles.js b/src/components/MobilityPlatform/PublicToilets/components/PublicToiletsContent/styles.js
deleted file mode 100644
index 9251213f1..000000000
--- a/src/components/MobilityPlatform/PublicToilets/components/PublicToiletsContent/styles.js
+++ /dev/null
@@ -1,20 +0,0 @@
-export default theme => ({
- container: {
- margin: theme.spacing(1),
- },
- headerContainer: {
- width: '85%',
- borderBottom: '1px solid #000',
- paddingBottom: theme.spacing(0.5),
- },
- textContainer: {
- marginTop: theme.spacing(0.5),
- },
- contentInner: {
- marginLeft: theme.spacing(1),
- marginBottom: theme.spacing(1),
- },
- marginTop: {
- marginTop: theme.spacing(0.5),
- },
-});
diff --git a/src/components/MobilityPlatform/RailwayStations/RailwayStations.js b/src/components/MobilityPlatform/RailwayStations/RailwayStations.js
index ba28978d7..0f79444eb 100644
--- a/src/components/MobilityPlatform/RailwayStations/RailwayStations.js
+++ b/src/components/MobilityPlatform/RailwayStations/RailwayStations.js
@@ -9,6 +9,7 @@ import { useAccessibleMap } from '../../../redux/selectors/settings';
import { fetchRailwaysData } from '../mobilityPlatformRequests/mobilityPlatformRequests';
import { createIcon, isDataValid } from '../utils/utils';
import RailwayStationsContent from './components/RailwayStationsContent';
+import { StyledPopupWrapper, StyledPopupInner } from '../styled/styled';
const RailwayStations = () => {
const [railwayStations, setRailwayStations] = useState([]);
@@ -25,9 +26,12 @@ const RailwayStations = () => {
const customIcon = icon(createIcon(useContrast ? railwayIconBw : railwayIcon));
useEffect(() => {
+ const controller = new AbortController();
+ const { signal } = controller;
if (showRailwayStations && !railwayStations.length) {
- fetchRailwaysData('metadata/stations', setRailwayStations);
+ fetchRailwaysData('metadata/stations', setRailwayStations, signal);
}
+ return () => controller.abort();
}, [showRailwayStations]);
/** Separate railway stations of Turku, eg. Turku station and Kupittaa */
@@ -49,9 +53,13 @@ const RailwayStations = () => {
return renderData
? railwayStationsTku.map(item => (
Ei lähteviä junia
@@ -33,15 +37,19 @@ exports[`Ei saapuvia junia
diff --git a/src/components/MobilityPlatform/RailwayStations/components/RailwayStationsContent/index.js b/src/components/MobilityPlatform/RailwayStations/components/RailwayStationsContent/index.js index 40c76cd7f..4c40dd131 100644 --- a/src/components/MobilityPlatform/RailwayStations/components/RailwayStationsContent/index.js +++ b/src/components/MobilityPlatform/RailwayStations/components/RailwayStationsContent/index.js @@ -1,4 +1,3 @@ -import { injectIntl } from 'react-intl'; import RailwayStationsContent from './RailwayStationsContent'; -export default injectIntl(RailwayStationsContent); +export default RailwayStationsContent; diff --git a/src/components/MobilityPlatform/RentalCars/RentalCars.js b/src/components/MobilityPlatform/RentalCars/RentalCars.js index 1618b5ebe..378d5ae0c 100644 --- a/src/components/MobilityPlatform/RentalCars/RentalCars.js +++ b/src/components/MobilityPlatform/RentalCars/RentalCars.js @@ -1,5 +1,4 @@ /* eslint-disable react-hooks/exhaustive-deps */ -import { PropTypes } from 'prop-types'; import React, { useEffect, useState } from 'react'; import { useMap, useMapEvents } from 'react-leaflet'; import { useSelector } from 'react-redux'; @@ -8,13 +7,13 @@ import providerIcon from 'servicemap-ui-turku/assets/icons/icons-icon_24rent.svg import rentalCarIcon from 'servicemap-ui-turku/assets/icons/icons-icon_rental_car.svg'; import { useMobilityPlatformContext } from '../../../context/MobilityPlatformContext'; import { useAccessibleMap } from '../../../redux/selectors/settings'; -import { fetchIotData } from '../mobilityPlatformRequests/mobilityPlatformRequests'; +import useIotDataFetch from '../utils/useIotDataFetch'; import { isDataValid, setRender, checkMapType } from '../utils/utils'; import { isEmbed } from '../../../utils/path'; +import { StyledPopupWrapper, StyledPopupInner } from '../styled/styled'; import RentalCarsContent from './components/RentalCarsContent'; -const RentalCars = ({ classes }) => { - const [rentalCarsData, setRentalCarsData] = useState([]); +const RentalCars = () => { const [zoomLevel, setZoomLevel] = useState(13); const { showRentalCars } = useMobilityPlatformContext(); @@ -40,11 +39,7 @@ const RentalCars = ({ classes }) => { iconSize: zoomLevel < 14 ? [45, 45] : [50, 56], }); - useEffect(() => { - if (showRentalCars || embedded) { - fetchIotData('R24', setRentalCarsData); - } - }, [showRentalCars, embedded]); + const { iotData: rentalCarsData } = useIotDataFetch('R24', showRentalCars, embedded); const map = useMap(); @@ -54,7 +49,7 @@ const RentalCars = ({ classes }) => { useEffect(() => { if (renderData && !embedded) { const bounds = []; - rentalCarsData.forEach((item) => { + rentalCarsData.forEach(item => { bounds.push([item.homeLocationData.coordinates.latitude, item.homeLocationData.coordinates.longitude]); }); map.fitBounds(bounds); @@ -62,32 +57,26 @@ const RentalCars = ({ classes }) => { }, [showRentalCars, rentalCarsData]); return ( - <> - {renderData ? ( - rentalCarsData.filter(item => item.availabilityData.available).map(item => ( - ({
- container: {
- margin: theme.spacing(1),
- },
- title: {
- width: '94%',
- borderBottom: '1px solid #000000',
- marginBottom: theme.spacing(1),
- },
- text: {
- paddingBottom: theme.spacing(1),
- },
- linkContainer: {
- paddingBottom: theme.spacing(1),
- width: '55%',
- },
- link: {
- color: theme.palette.link.main,
- textDecoration: 'underline',
- },
-});
diff --git a/src/components/MobilityPlatform/RentalCars/index.js b/src/components/MobilityPlatform/RentalCars/index.js
index 750f28c9b..45d73d1b0 100644
--- a/src/components/MobilityPlatform/RentalCars/index.js
+++ b/src/components/MobilityPlatform/RentalCars/index.js
@@ -1,6 +1,3 @@
-import { withStyles } from '@mui/styles';
-import { injectIntl } from 'react-intl';
import RentalCars from './RentalCars';
-import styles from './styles';
-export default withStyles(styles)(injectIntl(RentalCars));
+export default RentalCars;
diff --git a/src/components/MobilityPlatform/RentalCars/styles.js b/src/components/MobilityPlatform/RentalCars/styles.js
deleted file mode 100644
index f89a68ef2..000000000
--- a/src/components/MobilityPlatform/RentalCars/styles.js
+++ /dev/null
@@ -1,5 +0,0 @@
-export default theme => ({
- popupInner: {
- padding: theme.spacing(1.5),
- },
-});
diff --git a/src/components/MobilityPlatform/Roadworks/Roadworks.js b/src/components/MobilityPlatform/Roadworks/Roadworks.js
index e54355e02..e1b622d60 100644
--- a/src/components/MobilityPlatform/Roadworks/Roadworks.js
+++ b/src/components/MobilityPlatform/Roadworks/Roadworks.js
@@ -1,21 +1,28 @@
/* eslint-disable react-hooks/exhaustive-deps */
-import React, { useEffect, useState } from 'react';
+import React, { useEffect } from 'react';
import { useSelector } from 'react-redux';
import { useMap } from 'react-leaflet';
import roadworksIcon from 'servicemap-ui-turku/assets/icons/icons-icon_roadworks.svg';
import roadworksIconBw from 'servicemap-ui-turku/assets/icons/contrast/icons-icon_roadworks-bw.svg';
import { useMobilityPlatformContext } from '../../../context/MobilityPlatformContext';
-import { fetchParkingAreaGeometries } from '../mobilityPlatformRequests/mobilityPlatformRequests';
import {
createIcon, isDataValid, grayOptionsBase, whiteOptionsBase,
} from '../utils/utils';
import { useAccessibleMap, getCitySettings } from '../../../redux/selectors/settings';
import config from '../../../../config';
+import useRoadworksDataFetch from '../utils/useRoadworksDataFetch';
+import { StyledPopupWrapper, StyledPopupInner } from '../styled/styled';
import RoadworksContent from './components/RoadworksContent';
const Roadworks = () => {
- const [roadworksData, setRoadworksData] = useState([]);
- const [trafficAnnouncementsData, setTrafficAnnouncementsData] = useState([]);
+ const getOptions = typeStr => {
+ const options = {
+ page_size: 200,
+ is_active: true,
+ situation_type_str: typeStr,
+ };
+ return options;
+ };
const { showRoadworks } = useMobilityPlatformContext();
@@ -27,31 +34,16 @@ const Roadworks = () => {
const useContrast = useSelector(useAccessibleMap);
const citySettings = useSelector(getCitySettings);
- const roadworksUrl = config.roadworksAPI;
- const isRoadworksUrl = !roadworksUrl || roadworksUrl === 'undefined' ? null : roadworksUrl;
-
const customIcon = icon(createIcon(useContrast ? roadworksIconBw : roadworksIcon));
const grayOptions = grayOptionsBase({ dashArray: '2, 5, 8' });
const whiteOptions = whiteOptionsBase({ dashArray: !useContrast ? '1, 8' : null });
- useEffect(() => {
- const endpoint = `${isRoadworksUrl}?inactiveHours=0&includeAreaGeometry=true&situationType=ROAD_WORK`;
- if (showRoadworks && isRoadworksUrl) {
- fetchParkingAreaGeometries(endpoint, setRoadworksData);
- }
- }, [showRoadworks]);
-
- useEffect(() => {
- const endpoint = `${isRoadworksUrl}?inactiveHours=0&includeAreaGeometry=true&situationType=TRAFFIC_ANNOUNCEMENT`;
- if (showRoadworks && isRoadworksUrl) {
- fetchParkingAreaGeometries(endpoint, setTrafficAnnouncementsData);
- }
- }, [showRoadworks]);
-
+ const { data: roadworksData } = useRoadworksDataFetch(getOptions('ROAD_WORK'), showRoadworks);
+ const { data: trafficAnnouncementsData } = useRoadworksDataFetch(getOptions('TRAFFIC_ANNOUNCEMENT'), showRoadworks);
const roadworksDataFull = [].concat(roadworksData, trafficAnnouncementsData);
- const checkCitySettings = (citiesArray) => {
+ const checkCitySettings = citiesArray => {
if (citiesArray?.length > 0) {
return citiesArray;
}
@@ -60,63 +52,98 @@ const Roadworks = () => {
/** Separate roadworks of Turku from the rest */
const roadworksFiltered = roadworksDataFull.reduce((acc, curr) => {
- const roadWorkDetails = curr?.properties?.announcements[0];
- const selectedCities = config.cities.filter((c) => citySettings[c]);
+ const roadWorkDetails = curr?.announcements[0];
+ const selectedCities = config.cities.filter(c => citySettings[c]);
const cities = checkCitySettings(selectedCities);
if (
- cities.includes(roadWorkDetails?.locationDetails?.roadAddressLocation?.primaryPoint?.municipality.toLowerCase())
+ cities.includes(roadWorkDetails?.location?.details?.primaryPoint?.municipality.toLowerCase())
) {
acc.push(curr);
}
return acc;
}, []);
- /** Separate roadworks that contain Point type geometry from the rest */
- const roadworksPoints = roadworksFiltered.reduce((acc, curr) => {
- if (curr.geometry.type === 'Point') {
+ /**
+ * Separate roadworks from the rest by geometry type (eg. POINT or LINESTRING)
+ * @param {array} data
+ * @param {string} geomType
+ * @returns array
+ */
+ const filterRoadworksByGeometry = (data, geomType) => data.reduce((acc, curr) => {
+ if (curr?.announcements[0]?.location?.geometry?.includes(geomType)) {
acc.push(curr);
}
return acc;
}, []);
- /** Separate roadworks that contain LineString type geometry from the rest */
- const roadworksLines = roadworksFiltered.reduce((acc, curr) => {
- if (curr.geometry.type === 'LineString') {
- acc.push(curr);
- }
- return acc;
- }, []);
+ const roadworksPoints = filterRoadworksByGeometry(roadworksFiltered, 'POINT');
+ const roadworksLines = filterRoadworksByGeometry(roadworksFiltered, ';LINESTRING');
+ const roadworksMultiLines = filterRoadworksByGeometry(roadworksFiltered, 'MULTILINESTRING');
- /** Separate roadworks that contain MultiLineString type geometry from the rest */
- const roadworksMultiLines = roadworksFiltered.reduce((acc, curr) => {
- if (curr.geometry.type === 'MultiLineString') {
- acc.push(curr);
+ /**
+ * Gets coordinates from string, for example 'SRID=4326;POINT (22.37835 60.40831)'.
+ * Use regex to get numerical values and place those inside an array
+ * @param {string} inputString
+ * @returns {*array} coordinates
+ */
+ const getPointCoordinates = inputString => {
+ const regex = /POINT \((\d+\.\d+) (\d+\.\d+)\)/;
+ const match = inputString.match(regex);
+ if (match) {
+ const coordinates = [parseFloat(match[2]), parseFloat(match[1])];
+ return coordinates;
}
- return acc;
- }, []);
+ return [];
+ };
/**
- * Swap coordinates of linestrings
- * @param {array} inputData
+ * Get coordinates from string that includes geometry in linestring format.
+ * Remove letters and special characters and return nested array from numbers.
+ * @param {string} lineString
* @returns array
*/
- const swapCoords = (inputData) => {
- if (inputData?.length > 0) {
- return inputData.map((coordinates) => [coordinates[1], coordinates[0]]);
- }
- return inputData;
+ const getLineCoordinates = lineString => {
+ const coordinatesString = lineString.replace(/^SRID=\d+;LINESTRING \((.*)\)$/, '$1');
+ const coordinatePairs = coordinatesString.split(', ').map(pair => pair.split(' '));
+ const coordinates = coordinatePairs.map(pair => [parseFloat(pair[1]), parseFloat(pair[0])]);
+ return coordinates;
};
/**
- * Swap coordinates of multi linestring
- * @param {array} inputData
+ * Get coordinates from string that includes geometry in multilinestring format.
+ * Remove letters and special characters and return nested array from numbers.
+ * @param {string} inputString
* @returns array
*/
- const swapCoordsMulti = (inputData) => {
- if (inputData?.length > 0) {
- return inputData.map((innerArray) => innerArray.map((coordinates) => [coordinates[1], coordinates[0]]));
- }
- return inputData;
+ const getMultiLineCoordinates = inputString => {
+ const multiLineStrings = inputString.replace(/^SRID=\d+;MULTILINESTRING \((.*)\)$/, '$1').split('), ');
+ const nestedCoordinates = multiLineStrings.map(lineString => {
+ const cleanedLineString = lineString.replace(/^\(/, '').replace(/\)$/, '');
+ const coordinatePairs = cleanedLineString.split(', ').map(pair => pair.split(' '));
+ return coordinatePairs.map(pair => [parseFloat(pair[1]), parseFloat(pair[0])]);
+ });
+ return nestedCoordinates;
+ };
+
+ /**
+ * Get single pair of coordinates from nested arrays (2 or 3 levels).
+ * @param {array} data
+ * @param {boolean} isMulti
+ * @returns array
+ */
+ const getSingleCoordinates = (data, isMulti) => {
+ const coords = isMulti ? data[0][0] : data[0];
+ return [coords[0], coords[1]];
+ };
+
+ const parseMultiAndGetSingleCoordinates = multilineStr => {
+ const coordinates = getMultiLineCoordinates(multilineStr);
+ return getSingleCoordinates(coordinates, true);
+ };
+
+ const parseLineAndGetSingleCoordinates = lineStr => {
+ const coordinates = getLineCoordinates(lineStr);
+ return getSingleCoordinates(coordinates, false);
};
const areMarkersValid = isDataValid(showRoadworks, roadworksPoints);
@@ -126,58 +153,64 @@ const Roadworks = () => {
useEffect(() => {
if (areMultiLinesValid) {
const bounds = [];
- roadworksMultiLines.forEach((item) => {
- bounds.push(swapCoordsMulti(item.geometry.coordinates));
+ roadworksMultiLines.forEach(item => {
+ bounds.push(getMultiLineCoordinates(item?.announcements[0]?.location?.geometry));
});
map.fitBounds(bounds);
}
}, [showRoadworks, roadworksMultiLines]);
- const renderContent = (item) => (
-
- Aika: 05.11.2023 - 05.12.2023
+ Aika: 10.04.2024 - 05.06.2024
Varauslinkit
:
iOS
- Nopeusrajoitus: 40 km/t
-
+ Nopeusrajoitus: 40 km/t
+ {
+ const intl = useIntl();
-const TextContent = ({
- classes, intl, titleId, translationId,
-}) => {
const singleValTypo = (messageId, isTitle) => (
-
- Sähköpotkulautojen pysäköinti kartalla näkyville alueille on kielletty.
-
+ Sähköpotkulautojen pysäköinti kartalla näkyville alueille on kielletty.
+
- Turun kaupunkipyörät eli tuttavallisemmin föllärit, ovat pyöriä, joita kuka vaan voi vuokrata Donkey Republicin sovelluksella. Föllärin voi vuokrata kertamaksulla, kuukausimaksulla tai koko kesän kattavalla kausimaksulla.
-
+ Turun kaupunkipyörät eli tuttavallisemmin föllärit, ovat pyöriä, joita kuka vaan voi vuokrata Donkey Republicin sovelluksella. Föllärin voi vuokrata kertamaksulla, kuukausimaksulla tai koko kesän kattavalla kausimaksulla.
+
+ Jos sinulla on käytössä Fölin kausikortti, jonka kausi on vähintään 30 päivää, sisältää oikeuden käyttää fölläreitä tunnin ajan kerrallaan maksutta. Vuokrattavia pyöriä on 700 ja asemia yli 70 kappaletta.
+
+ Lue lisää kaupunkipyöristä:
+
- https://www.foli.fi/fi/aikataulut-ja-reitit/fölifillarit
-
+ https://www.foli.fi/fi/aikataulut-ja-reitit/fölifillarit
+
- Kartan tiedot tulevat Donkey Republicin rajapinnasta reaaliajassa.
-
+ Kartan tiedot tulevat Donkey Republicin rajapinnasta reaaliajassa.
+
-
- testikuvaus
-
Reittejä ladataan.
diff --git a/src/views/MobilitySettingsView/components/EmptyRouteList/index.js b/src/views/MobilitySettingsView/components/EmptyRouteList/index.js
index b4e3b57c7..6ec1e263d 100644
--- a/src/views/MobilitySettingsView/components/EmptyRouteList/index.js
+++ b/src/views/MobilitySettingsView/components/EmptyRouteList/index.js
@@ -1,6 +1,3 @@
-import { withStyles } from '@mui/styles';
-import { injectIntl } from 'react-intl';
import EmptyRouteList from './EmptyRouteList';
-import styles from './styles';
-export default withStyles(styles)(injectIntl(EmptyRouteList));
+export default EmptyRouteList;
diff --git a/src/views/MobilitySettingsView/components/EmptyRouteList/styles.js b/src/views/MobilitySettingsView/components/EmptyRouteList/styles.js
deleted file mode 100644
index ced94006d..000000000
--- a/src/views/MobilitySettingsView/components/EmptyRouteList/styles.js
+++ /dev/null
@@ -1,8 +0,0 @@
-const styles = theme => ({
- paragraph: {
- textAlign: 'left',
- padding: theme.spacing(1.5),
- },
-});
-
-export default styles;
diff --git a/src/views/MobilitySettingsView/components/ExtendedInfo/ExtendedInfo.js b/src/views/MobilitySettingsView/components/ExtendedInfo/ExtendedInfo.js
index 8f33f764b..ddc6cdd10 100644
--- a/src/views/MobilitySettingsView/components/ExtendedInfo/ExtendedInfo.js
+++ b/src/views/MobilitySettingsView/components/ExtendedInfo/ExtendedInfo.js
@@ -1,42 +1,62 @@
import { Typography } from '@mui/material';
import PropTypes from 'prop-types';
import React from 'react';
+import { useIntl } from 'react-intl';
+import styled from '@emotion/styled';
-const ExtendedInfo = ({ classes, intl, translations }) => {
- const text = (message, props = {}) => (
-
- Turussa on käytössä kolme eri vyöhykettä, joilla on eri tuntimaksut.
-
+ Turussa on käytössä kolme eri vyöhykettä, joilla on eri tuntimaksut.
+
- Ensimmäinen vyöhyke (ydinkeskusta-alue): 3,60 €/tunti (1.1.2023 alkaen)
-
+ Ensimmäinen vyöhyke (ydinkeskusta-alue): 3,60 €/tunti (1.1.2023 alkaen)
+
- Toinen vyöhyke : 1,80 €/tunti (1.1.2023 alkaen)
-
+ Toinen vyöhyke : 1,80 €/tunti (1.1.2023 alkaen)
+
- Kolmas vyöhyke: 0,60 €/tunti
-
+ Kolmas vyöhyke: 0,60 €/tunti
+
- 3. vyöhyke on voimassa 2. vyöhykkeen rajojen, sekä kaupungin rajojen välisellä alueella.
-
+ 3. vyöhyke on voimassa 2. vyöhykkeen rajojen, sekä kaupungin rajojen välisellä alueella.
+
+ Maksullisuus määräytyy kuitenkin aina voimassa olevien liikennemerkkien mukaisesti ja koskee Turun kaupungin katutilaa ja kaupungin omia alueita, kuten kauppahallia ja kaupungintaloa.
+
-
- Reitin pituus:
-
- 100
-
- km.
-
- EuroVelo 10 on eurooppalainen Suomen rannikkoa seuraava polkupyöräreitti. Helsingin ja Turun välisellä matkalla reitti on merkitty opastein.
-
+ EuroVelo 10 on eurooppalainen Suomen rannikkoa seuraava polkupyöräreitti. Helsingin ja Turun välisellä matkalla reitti on merkitty opastein.
+
- Sähköpotkulauta
-
-
+ Sähköpotkulauta
+
- Pysäköintikieltoalue
-
-
+ Pysäköintikieltoalue
+
- {districtItems.map((district) => {
+ {districtItems.map(district => {
const opened = openCategory === district.id;
const selected = selectedDistrictType === district.id;
return (
diff --git a/src/views/AreaView/components/MobilityResultTab/MobilityResultTab.js b/src/views/AreaView/components/MobilityResultTab/MobilityResultTab.js
new file mode 100644
index 000000000..22d2209e0
--- /dev/null
+++ b/src/views/AreaView/components/MobilityResultTab/MobilityResultTab.js
@@ -0,0 +1,52 @@
+import React from 'react';
+import { List, ListItem } from '@mui/material';
+import styled from '@emotion/styled';
+import { useMobilityPlatformContext } from '../../../../context/MobilityPlatformContext';
+import MobilityToggleButton from '../../../MobilitySettingsView/components/MobilityToggleButton';
+import InfoTextBox from '../../../../components/MobilityPlatform/InfoTextBox/InfoTextBox';
+
+const MobilityResultTab = () => {
+ const { showMobilityResults, setShowMobilityResults } = useMobilityPlatformContext();
+
+ const toggleMobilityResults = () => {
+ setShowMobilityResults(current => !current);
+ };
+
+ return (
+
+
+
{
- layerCategoryKeys.map((key) => {
+ layerCategoryKeys.map(key => {
const layerCategory = layerCategories[key];
const selected = layerCategory.type === selectedCategory;
const titleText = `${formatMessage({ id: `area.list.statistic.${layerCategory.type}` })} ${layerCategory.year}`;
@@ -215,24 +214,21 @@ const StatisticalDistrictListComponent = ({
};
return (
- <>
- { isFetchingDistricts
- ? (
-
- {filteredServiceList.map((service) => {
+ {filteredServiceList.map(service => {
const units = statisticalDistrictUnits
.filter(u => u?.services?.some(s => s.id === service.id));
const disableUnitAccordion = !selectedServices[service.id] || units.length === 0;
@@ -213,7 +211,6 @@ UnitCheckbox.defaultProps = {
export default StatisticalDistrictUnitListComponent;
-
const StyledRowContainer = styled('div')`
display: flex;
flex-direction: row;
diff --git a/src/views/AreaView/components/styled/styled.js b/src/views/AreaView/components/styled/styled.js
new file mode 100644
index 000000000..3994cbcd4
--- /dev/null
+++ b/src/views/AreaView/components/styled/styled.js
@@ -0,0 +1,137 @@
+import styled from '@emotion/styled';
+import {
+ Divider, List, ListItem, Typography,
+} from '@mui/material';
+import { SMAccordion } from '../../../../components';
+
+/**
+ * Common styled components for AreaView
+ */
+const levelTwo = () => ({
+ backgroundColor: 'rgb(250,250,250)',
+});
+
+const levelThree = () => ({
+ backgroundColor: 'rgb(245,245,245)',
+});
+
+const levelFour = () => ({
+ backgroundColor: 'rgb(240,240,240)',
+});
+
+const StyledDivider = styled(Divider)(() => ({
+ marginLeft: -72,
+}));
+
+const StyledDistrictServiceList = styled('div')(() => ({
+ boxShadow: 'inset 0px 4px 4px rgba(0, 0, 0, 0.06)',
+}));
+
+const StyledDistrictServiceListLevelFour = styled(StyledDistrictServiceList)(() => levelFour());
+const StyledDistrictServiceListLevelThree = styled(StyledDistrictServiceList)(() => levelThree());
+const StyledListLevelThree = styled(List)(() => levelThree());
+
+const StyledServiceList = styled('div')(({ theme }) => ({
+ paddingTop: theme.spacing(2),
+ paddingBottom: theme.spacing(2),
+ paddingLeft: 77,
+ backgroundColor: 'rgb(230,243,254)',
+}));
+
+const StyledServiceTabServiceList = styled('div')(({ theme }) => ({
+ paddingLeft: theme.spacing(10),
+ paddingTop: theme.spacing(2),
+ paddingBottom: theme.spacing(2),
+}));
+
+const StyledListItem = styled(ListItem)(({ theme }) => ({
+ padding: 0,
+ minHeight: theme.spacing(7),
+}));
+
+const StyledAreaListItem = styled(StyledListItem)(({ theme }) => ({
+ paddingLeft: theme.spacing(8),
+ paddingRight: theme.spacing(2),
+}));
+
+const StyledListNoPadding = styled(List)(({ theme }) => ({
+ padding: 0,
+ marginTop: theme.spacing(0),
+ marginBottom: theme.spacing(0),
+ '& li:last-of-type': {
+ borderBottom: 'none',
+ },
+}));
+
+const StyledListNoPaddingLevelTwo = styled(StyledListNoPadding)(() => levelTwo());
+
+const StyledListNoPaddingLevelThree = styled(StyledListNoPadding)(() => levelThree());
+
+const StyledUnitsAccordion = styled(SMAccordion)(() => ({
+ height: 48,
+ backgroundColor: 'rgba(222, 222, 222, 0.56)',
+}));
+
+const StyledCaptionText = styled(Typography)(() => ({
+ color: '#000',
+ fontWeight: 'normal',
+}));
+
+const StyledLoadingText = styled('div')(() => ({
+ display: 'flex',
+ alignItems: 'center',
+ justifyContent: 'center',
+ height: 56,
+}));
+
+const StyledBoldText = styled(Typography)(() => ({
+ fontWeight: 'bold',
+}));
+
+const StyledCheckBoxIcon = styled('span')(() => ({
+ margin: 2,
+ width: 18,
+ height: 18,
+ backgroundColor: '#fff',
+ border: '0.5px solid #949494',
+ boxShadow: 'inset 1px 1px 2px rgba(0, 0, 0, 0.05)',
+ borderRadius: 2,
+}));
+
+const StyledUnitListArea = styled('div')(() => ({
+ textAlign: 'left',
+ backgroundColor: 'rgba(222, 222, 222, 0.56)',
+}));
+
+const StyledAccordionServiceTitle = styled(SMAccordion)(({ theme }) => ({
+ paddingLeft: theme.spacing(10),
+}));
+
+const StyledUnitList = styled(List)(({ theme }) => ({
+ paddingLeft: theme.spacing(10),
+ paddingRight: theme.spacing(4),
+ paddingBottom: theme.spacing(1),
+}));
+
+export {
+ StyledDivider,
+ StyledDistrictServiceList,
+ StyledDistrictServiceListLevelThree,
+ StyledDistrictServiceListLevelFour,
+ StyledListLevelThree,
+ StyledListItem,
+ StyledAreaListItem,
+ StyledListNoPadding,
+ StyledListNoPaddingLevelTwo,
+ StyledListNoPaddingLevelThree,
+ StyledServiceList,
+ StyledServiceTabServiceList,
+ StyledUnitsAccordion,
+ StyledCaptionText,
+ StyledLoadingText,
+ StyledBoldText,
+ StyledCheckBoxIcon,
+ StyledUnitListArea,
+ StyledAccordionServiceTitle,
+ StyledUnitList,
+};
diff --git a/src/views/EmbedderView/EmbedderView.js b/src/views/EmbedderView/EmbedderView.js
index c8c57ca36..ebcb62892 100644
--- a/src/views/EmbedderView/EmbedderView.js
+++ b/src/views/EmbedderView/EmbedderView.js
@@ -12,16 +12,17 @@ import { useSelector } from 'react-redux';
import * as smurl from './utils/url';
import isClient, { uppercaseFirst } from '../../utils';
import { getEmbedURL, getLanguage } from './utils/utils';
-import EmbedController from './components/EmbedController';
-import IFramePreview from './components/IFramePreview';
import paths from '../../../config/paths';
import embedderConfig from './embedderConfig';
import SettingsUtility from '../../utils/settings';
import useLocaleText from '../../utils/useLocaleText';
import { useUserLocale } from '../../utils/user';
+import { useMobilityPlatformContext } from '../../context/MobilityPlatformContext';
+import config from '../../../config';
+import EmbedController from './components/EmbedController';
+import IFramePreview from './components/IFramePreview';
import EmbedHTML from './components/EmbedHTML';
import TopBar from '../../components/TopBar';
-import config from '../../../config';
import { CloseButton, SMButton } from '../../components';
const hideCitiesIn = [
@@ -60,7 +61,7 @@ const EmbedderView = ({
}
const cityOption = (search?.city !== '' && search?.city?.split(',')) || citySettings;
- const citiesToReduce = cityOption.length > 0 ? cityOption : embedderConfig.CITIES.filter((v) => v);
+ const citiesToReduce = cityOption.length > 0 ? cityOption : embedderConfig.CITIES.filter(v => v);
// If external theme (by Turku) is true, then can be used to select which content to render
const externalTheme = config.themePKG;
@@ -77,12 +78,15 @@ const EmbedderView = ({
const defaultFixedHeight = embedderConfig.DEFAULT_CUSTOM_WIDTH;
const iframeConfig = embedderConfig.DEFAULT_IFRAME_PROPERTIES || {};
const defaultService = 'none';
- const page = useSelector((state) => state.user.page);
- const selectedUnit = useSelector((state) => state.selectedUnit.unit.data);
- const currentService = useSelector((state) => state.service.current);
+ const page = useSelector(state => state.user.page);
+ const selectedUnit = useSelector(state => state.selectedUnit.unit.data);
+ const currentService = useSelector(state => state.service.current);
const getLocaleText = useLocaleText();
const userLocale = useUserLocale();
+ const { showAccessibilityAreas, accessibilityAreasData } = useMobilityPlatformContext();
+ const hasAccessibilityAreas = accessibilityAreasData.some(item => item?.extra?.kohde_ID === selectedUnit?.id);
+
// States
const [language, setLanguage] = useState(defaultLanguage);
const [map, setMap] = useState(defaultMap);
@@ -109,6 +113,9 @@ const EmbedderView = ({
const [underPass, setUnderpass] = useState(false);
const [overPass, setOverPass] = useState(false);
const [publicBenches, setPublicBenches] = useState(false);
+ const [accessibilityAreas, setAccessibilityAreas] = useState(showAccessibilityAreas.all);
+ const [accessibilityAreasWalk, setAccessibilityAreasWalk] = useState(showAccessibilityAreas.walking);
+ const [accessibilityAreasBicycle, setAccessibilityAreasBicycle] = useState(showAccessibilityAreas.cycling);
const boundsRef = useRef([]);
const dialogRef = useRef();
@@ -136,6 +143,9 @@ const EmbedderView = ({
underPass,
overPass,
publicBenches,
+ accessibilityAreas,
+ accessibilityAreasWalk,
+ accessibilityAreasBicycle,
bbox: selectedBbox,
});
@@ -171,7 +181,7 @@ const EmbedderView = ({
buttons[0].focus();
};
- const setBoundsRef = useCallback((bounds) => {
+ const setBoundsRef = useCallback(bounds => {
boundsRef.current = bounds;
}, []);
@@ -194,7 +204,7 @@ const EmbedderView = ({
};
// Run timeout function and cancel previous if it exists
- const runTimeoutFunction = (func) => {
+ const runTimeoutFunction = func => {
if (timeout) {
clearTimeout(timeout);
}
@@ -202,7 +212,7 @@ const EmbedderView = ({
};
// Figure out embed html
- const createEmbedHTML = useCallback((url) => {
+ const createEmbedHTML = useCallback(url => {
const showListBottom = showUnitList === 'bottom';
if (!url) {
return '';
@@ -247,13 +257,13 @@ const EmbedderView = ({
showUnitList,
]);
- const showCities = (embedUrl) => {
+ const showCities = embedUrl => {
if (typeof embedUrl !== 'string') {
return false;
}
const originalUrl = embedUrl.replace('/embed', '');
let show = true;
- hideCitiesIn.forEach((r) => {
+ hideCitiesIn.forEach(r => {
if (show) {
show = !r.test(originalUrl);
}
@@ -261,13 +271,13 @@ const EmbedderView = ({
return show;
};
- const showServices = (embedUrl) => {
+ const showServices = embedUrl => {
if (typeof embedUrl !== 'string') {
return false;
}
const originalUrl = embedUrl.replace('/embed', '');
let show = true;
- hideServicesIn.forEach((r) => {
+ hideServicesIn.forEach(r => {
if (show) {
show = !r.test(originalUrl);
}
@@ -279,8 +289,8 @@ const EmbedderView = ({
* Render language controls
*/
const renderLanguageControl = () => {
- const description = (locale) => intl.formatMessage({ id: `embedder.language.description.${locale}` });
- const languageControls = (generateLabel) => Object.keys(embedderConfig.LANGUAGES).map((lang) => ({
+ const description = locale => intl.formatMessage({ id: `embedder.language.description.${locale}` });
+ const languageControls = generateLabel => Object.keys(embedderConfig.LANGUAGES).map(lang => ({
value: lang,
label: `${uppercaseFirst(
embedderConfig.LANGUAGES[userLocale][lang],
@@ -306,8 +316,8 @@ const EmbedderView = ({
* Render map controls
*/
const renderMapTypeControl = () => {
- const getLabel = (map) => intl.formatMessage({ id: `settings.map.${map}` });
- const mapControls = (generateLabel) => embedderConfig.BACKGROUND_MAPS.map((map) => ({
+ const getLabel = map => intl.formatMessage({ id: `settings.map.${map}` });
+ const mapControls = generateLabel => embedderConfig.BACKGROUND_MAPS.map(map => ({
value: map,
label: `${generateLabel(map)}`,
}));
@@ -332,12 +342,12 @@ const EmbedderView = ({
return null;
}
const cities = city;
- const cityControls = embedderConfig.CITIES.filter((v) => v).map((city) => ({
+ const cityControls = embedderConfig.CITIES.filter(v => v).map(city => ({
key: city,
value: !!cities[city],
label: uppercaseFirst(city),
icon: null,
- onChange: (v) => {
+ onChange: v => {
const newCities = {};
Object.assign(newCities, cities);
newCities[city] = v;
@@ -362,8 +372,8 @@ const EmbedderView = ({
if (!showServices(embedUrl)) {
return null;
}
- const getLabel = (service) => intl.formatMessage({ id: `embedder.service.${service}` });
- const serviceControls = (generateLabel) => ['none', 'common', 'all'].map((service) => ({
+ const getLabel = service => intl.formatMessage({ id: `embedder.service.${service}` });
+ const serviceControls = generateLabel => ['none', 'common', 'all'].map(service => ({
value: service,
label: generateLabel(service),
}));
@@ -491,17 +501,40 @@ const EmbedderView = ({
{
key: 'units',
value: showUnits,
- onChange: (v) => setShowUnits(v),
+ onChange: v => setShowUnits(v),
icon: null,
labelId: 'embedder.options.label.units',
},
+ {
+ key: 'accessibilityAreas',
+ value: accessibilityAreas,
+ onChange: v => setAccessibilityAreas(v),
+ icon: null,
+ labelId: 'embedder.options.label.units.accessibilityAreas',
+ },
+ {
+ key: 'accessibilityAreasWalk',
+ value: accessibilityAreasWalk,
+ onChange: v => setAccessibilityAreasWalk(v),
+ icon: null,
+ labelId: 'embedder.options.label.units.accessibilityAreas.walk',
+ },
+ {
+ key: 'accessibilityAreasBicycle',
+ value: accessibilityAreasBicycle,
+ onChange: v => setAccessibilityAreasBicycle(v),
+ icon: null,
+ labelId: 'embedder.options.label.units.accessibilityAreas.bicycle',
+ },
];
+ const controlsBasic = controls.filter(item => item.key === 'units');
+
return (
- {
+
+
+ {
checkboxControls.map(item => (
-
{categories.map(category => (
-
-
+
- {text(translations.message2, { className: classes.margin })}
+
+ {text(translations.message2, true)}
{text(translations.message3)}
-