diff --git a/package.json b/package.json index 3d357d2..c6d05c4 100644 --- a/package.json +++ b/package.json @@ -110,15 +110,15 @@ "node": "^10 || ^12" }, "dependencies": { - "@eeacms/volto-blocks-form": "github:eea/volto-blocks-form#0.5.2", + "@eeacms/volto-blocks-form": "github:eea/volto-blocks-form#1.0.0", "@eeacms/volto-metadata-block": "github:eea/volto-metadata-block#1.0.1", - "@eeacms/volto-object-widget": "github:eea/volto-object-widget#0.2.3", - "@eeacms/volto-widget-toggle": "github:eea/volto-widget-toggle#0.1.0", + "@eeacms/volto-object-widget": "github:eea/volto-object-widget#1.0.0", + "@eeacms/volto-widget-toggle": "github:eea/volto-widget-toggle#1.0.0", "@eeacms/volto-widgets-view": "github:eea/volto-widgets-view#1.0.1", "@eeacms/volto-slate-metadata-mentions": "github:eea/volto-slate-metadata-mentions#0.4.2", "@material/react-linear-progress": "^0.15.0", "@plone/volto": "github:eea/volto#8.2.6-beta1", - "volto-slate": "github:eea/volto-slate#0.9.0-beta.4", + "volto-slate": "github:eea/volto-slate#0.9.2", "axios": "^0.20.0", "jsonp": "^0.2.1", "ol": "^6.4.3", diff --git a/src/components/manage/Blocks/DiscodataOpenlayersMapBlock/Edit.jsx b/src/components/manage/Blocks/DiscodataOpenlayersMapBlock/Edit.jsx index 87012db..637cd6c 100644 --- a/src/components/manage/Blocks/DiscodataOpenlayersMapBlock/Edit.jsx +++ b/src/components/manage/Blocks/DiscodataOpenlayersMapBlock/Edit.jsx @@ -28,6 +28,14 @@ const getSchema = (props) => { title: 'Has regions features', defaultValue: false, }, + privacy: { + type: 'array', + title: 'Privacy', + choices: [ + ['small', 'Small'], + ['big', 'Big'], + ], + }, filterSource: { type: 'array', title: 'Filter source', diff --git a/src/components/manage/Blocks/DiscodataOpenlayersMapBlock/PrivacyProtection.jsx b/src/components/manage/Blocks/DiscodataOpenlayersMapBlock/PrivacyProtection.jsx new file mode 100644 index 0000000..8c6d358 --- /dev/null +++ b/src/components/manage/Blocks/DiscodataOpenlayersMapBlock/PrivacyProtection.jsx @@ -0,0 +1,131 @@ +import React, { useState } from 'react'; +import VisibilitySensor from 'react-visibility-sensor'; +import { Placeholder } from 'semantic-ui-react'; +import cookie from 'react-cookie'; +import ReactTooltip from 'react-tooltip'; +import { Button, Checkbox, Message, Image } from 'semantic-ui-react'; +import Icon from '@plone/volto/components/theme/Icon/Icon'; +import infoSVG from '@plone/volto/icons/info.svg'; +import { settings } from '~/config'; + +import 'volto-embed/css/embed-styles.css'; + +const key = (domain_key) => `accept-${domain_key}`; + +const getExpDays = () => + typeof settings.embedCookieExpirationDays !== 'undefined' + ? settings.embedCookieExpirationDays + : 90; + +function saveCookie(domain_key) { + const date = new Date(); + date.setDate(date.getDate() + getExpDays()); + + cookie.save(key(domain_key), 'true', { + path: '/', + expires: date, + }); +} + +function canShow(domain_key) { + return cookie.load(key(domain_key)) === 'true'; +} + +export default ({ children, data = {}, block, onShow, ...rest }) => { + const { dataprotection = {} } = data; + const [visible, setVisibility] = useState(false); + const defaultShow = canShow(dataprotection.privacy_cookie_key); + const [show, setShow] = useState(defaultShow); + const [remember, setRemember] = useState(defaultShow); + + return ( + { + !visible && isVisible && setVisibility(true); + }} + partialVisibility={true} + offset={{ bottom: 200 }} + > + {visible ? ( + <> + {!dataprotection.enabled || show ? ( + children + ) : ( +
+
+
+ {dataprotection.type === 'big' ? ( + +
+ + ) : ( + '' + )} +
+ {dataprotection.type === 'small' ? ( + + + + ) : ( + '' + )} + +
+ +
+ { + setRemember(checked); + }} + checked={remember} + /> +
+ +

+ Your choice will be saved in a cookie managed by{' '} + {settings.ownDomain || '.eea.europa.eu'} that will expire in{' '} + {getExpDays()} days. +

+
+
+
+ )} + + + ) : ( + + + + )} + + ); +}; diff --git a/src/components/manage/Blocks/DiscodataOpenlayersMapBlock/View.jsx b/src/components/manage/Blocks/DiscodataOpenlayersMapBlock/View.jsx index 7d58856..1d04051 100644 --- a/src/components/manage/Blocks/DiscodataOpenlayersMapBlock/View.jsx +++ b/src/components/manage/Blocks/DiscodataOpenlayersMapBlock/View.jsx @@ -1,5 +1,7 @@ +/* eslint-disable */ /* REACT */ import React, { useState, useRef, useEffect } from 'react'; +import cookie from 'react-cookie'; import { useHistory } from 'react-router-dom'; import { compose } from 'redux'; import { connect } from 'react-redux'; @@ -13,13 +15,15 @@ import { settings } from '~/config'; import { isArray, isObject } from 'lodash'; // VOLTO import { Icon as VoltoIcon } from '@plone/volto/components'; +import PrivacyProtection from './PrivacyProtection'; // VOLTO-DATABLOCKS import { setQueryParam } from 'volto-datablocks/actions'; // SEMANTIC REACT UI -import { Grid, Header, Loader, Dimmer } from 'semantic-ui-react'; +import { Grid, Header, Loader, Dimmer, Image } from 'semantic-ui-react'; // SVGs import clearSVG from '@plone/volto/icons/clear.svg'; import navigationSVG from '@plone/volto/icons/navigation.svg'; +import mapPlaceholder from '~/components/manage/Blocks/DiscodataOpenlayersMapBlock/map_placeholder.png'; // STYLES import 'ol/ol.css'; import './style.css'; @@ -36,6 +40,12 @@ const splitBy = (arr, delimiter) => { return ''; }; +const key = (domain_key) => `accept-${domain_key}`; + +const canShow = (domain_key) => { + return cookie.load(key(domain_key)) === 'true'; +}; + let Map, View, Overlay, @@ -94,6 +104,7 @@ const OpenlayersMapView = (props) => { const [loader, setLoader] = useState(false); const [mapRendered, setMapRendered] = useState(false); const [firstFilteringUpdate, setFirstFilteringUpdate] = useState(false); + const [prepareMapRender, setPrepareMapRender] = useState(false); const selectedSiteRef = useRef(null); const selectedSiteCoordinates = useRef(null); const regionsSourceWhere = useRef(''); @@ -110,8 +121,17 @@ const OpenlayersMapView = (props) => { const filterSource = props.data?.filterSource?.value || 'query_params'; const zoomSwitch = 6; const currentMapZoom = state.map?.element - ? state.map.element.getView().getZoom() + ? state.map.element?.getView().getZoom() : null; + const dataprotection = { + enabled: true, + privacy_statement: + 'This map is hosted by a third party [Environmental Systems Research Institute, INC: "ESRI"]. By showing th external content you accept the terms and conditions of www.esri.com. This includes their cookie policies, which e have no control over.', + privacy_cookie_key: 'map', + placeholder_image: mapPlaceholder, + type: props.data.privacy?.value || 'big' + }; + let queryParams; if (filterSource === 'query_params') { @@ -203,8 +223,13 @@ const OpenlayersMapView = (props) => { return ViewYourAreaControl; })(Control); } - renderMap(); - setMapRendered(true); + if ( + canShow(dataprotection.privacy_cookie_key) && + document.getElementById('map') + ) { + renderMap(); + setMapRendered(true); + } } mounted.current = true; return () => { @@ -216,7 +241,6 @@ const OpenlayersMapView = (props) => { useEffect(() => { if (selectedSite && mapRendered) { selectedSiteRef.current = selectedSite; - console.log('SET STYLE FOR SELECTED SITE'); selectedSite.setStyle( new Style({ image: new CircleStyle({ @@ -251,7 +275,7 @@ const OpenlayersMapView = (props) => { }, [state]) useEffect(() => { - if (mapRendered) { + if (mapRendered && stateRef.current.map.element) { if (['byLocationTerm', 'bySiteTerm'].includes(state.updateMapPosition)) { onSourceChange(); } else if (['byAdvancedFilters'].includes(state.updateMapPosition)) { @@ -275,6 +299,29 @@ const OpenlayersMapView = (props) => { /* eslint-disable-next-line */ }, [state.map.sitesSourceQuery?.where, state.updateMapPosition]) + useEffect(() => { + if ( + (mounted.current && + !mapRendered && + prepareMapRender && + document.getElementById('map')) || + (mounted.current && + !mapRendered && + !prepareMapRender && + document.getElementById('map') && + canShow(dataprotection.privacy_cookie_key)) + ) { + renderMap(); + setMapRendered(true); + } + }, [ + mounted, + mapRendered, + prepareMapRender, + document.getElementById('map'), + canShow(dataprotection.privacy_cookie_key), + ]); + if (mapRendered && !firstFilteringUpdate) { updateFilters(); updateRegionsFilters(); @@ -562,7 +609,6 @@ const OpenlayersMapView = (props) => { const item = data.results?.[0]; selectedSiteCoordinates.current = [item.x, item.y]; if (item && item.x && item.y) { - console.log('REFRESH SOURCE'); stateRef.current.map.sitesSourceLayer.getSource().refresh(); stateRef.current.map.element.getView().animate({ center: selectedSiteCoordinates.current, @@ -987,15 +1033,12 @@ const OpenlayersMapView = (props) => { const closestFeature = sitesSource.getClosestFeatureToCoordinate( selectedSiteCoordinates.current, ); - console.log('SET SELECTED SITE'); setSelectedSite(closestFeature); selectedSiteCoordinates.current = null; } } }); - sitesSource.on('changefeature', function (e) { - console.log('CHANGE'); - }); + if (hasPopups) { if (document && document.documentElement?.clientWidth > 500) { map.on('pointermove', function (evt) { @@ -1094,213 +1137,229 @@ const OpenlayersMapView = (props) => { return (
{props.mode === 'edit' ?

Openlayer map

: ''} -
-