@eeacms/volto-embed 6.0.0 → 7.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.husky/pre-commit +2 -0
- package/CHANGELOG.md +41 -1
- package/DEVELOP.md +67 -13
- package/README.md +28 -11
- package/RELEASE.md +14 -14
- package/cypress.config.js +2 -2
- package/docker-compose.yml +32 -0
- package/jest-addon.config.js +3 -0
- package/locales/de/LC_MESSAGES/volto.po +67 -0
- package/locales/en/LC_MESSAGES/volto.po +67 -0
- package/locales/it/LC_MESSAGES/volto.po +67 -0
- package/locales/ro/LC_MESSAGES/volto.po +67 -0
- package/locales/volto.pot +69 -0
- package/package.json +39 -11
- package/src/{Iframe/EditIframe.jsx → Blocks/Maps/Edit.jsx} +30 -22
- package/src/Blocks/Maps/Edit.test.jsx +119 -0
- package/src/Blocks/Maps/MapsSidebar.jsx +52 -0
- package/src/{Iframe/ViewIframe.jsx → Blocks/Maps/View.jsx} +7 -11
- package/src/Blocks/Maps/index.js +12 -0
- package/src/Blocks/Maps/schema.js +67 -0
- package/src/Blocks/index.js +5 -0
- package/src/PrivacyProtection/PrivacyProtection.jsx +3 -1
- package/src/PrivacyProtection/styles.less +0 -5
- package/src/Toolbar/Enlarge.jsx +29 -0
- package/src/Toolbar/FigureNote.jsx +45 -0
- package/src/Toolbar/MoreInfo.jsx +20 -0
- package/src/Toolbar/Share.jsx +89 -0
- package/src/Toolbar/Sources.jsx +74 -0
- package/src/Toolbar/index.jsx +5 -0
- package/src/Toolbar/styles.less +209 -0
- package/src/index.js +4 -10
- package/.i18n.babel.config.js +0 -1
- package/src/Iframe/index.js +0 -4
- package/src/Iframe/schema.js +0 -39
package/locales/volto.pot
CHANGED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
msgid ""
|
|
2
|
+
msgstr ""
|
|
3
|
+
"Project-Id-Version: Plone\n"
|
|
4
|
+
"POT-Creation-Date: 2023-08-29T17:13:33.263Z\n"
|
|
5
|
+
"Last-Translator: Plone i18n <plone-i18n@lists.sourceforge.net>\n"
|
|
6
|
+
"Language-Team: Plone i18n <plone-i18n@lists.sourceforge.net>\n"
|
|
7
|
+
"MIME-Version: 1.0\n"
|
|
8
|
+
"Content-Type: text/plain; charset=utf-8\n"
|
|
9
|
+
"Content-Transfer-Encoding: 8bit\n"
|
|
10
|
+
"Plural-Forms: nplurals=1; plural=0;\n"
|
|
11
|
+
"Language-Code: en\n"
|
|
12
|
+
"Language-Name: English\n"
|
|
13
|
+
"Preferred-Encodings: utf-8\n"
|
|
14
|
+
"Domain: volto\n"
|
|
15
|
+
|
|
16
|
+
#: Iframe/EditIframe
|
|
17
|
+
# defaultMessage: Center
|
|
18
|
+
msgid "Center"
|
|
19
|
+
msgstr ""
|
|
20
|
+
|
|
21
|
+
#: Iframe/EditIframe
|
|
22
|
+
# defaultMessage: Embed code error, please follow the instructions and try again.
|
|
23
|
+
msgid "Embed code error, please follow the instructions and try again."
|
|
24
|
+
msgstr ""
|
|
25
|
+
|
|
26
|
+
#: Iframe/ViewIframe
|
|
27
|
+
# defaultMessage: Embeded Google Maps
|
|
28
|
+
msgid "Embeded Google Maps"
|
|
29
|
+
msgstr ""
|
|
30
|
+
|
|
31
|
+
#: Iframe/EditIframe
|
|
32
|
+
# defaultMessage: Enter map Embed Code
|
|
33
|
+
msgid "Enter map Embed Code"
|
|
34
|
+
msgstr ""
|
|
35
|
+
|
|
36
|
+
#: Iframe/EditIframe
|
|
37
|
+
# defaultMessage: Full
|
|
38
|
+
msgid "Full"
|
|
39
|
+
msgstr ""
|
|
40
|
+
|
|
41
|
+
#: Iframe/EditIframe
|
|
42
|
+
# defaultMessage: Google Maps Embedded Block
|
|
43
|
+
msgid "Google Maps Embedded Block"
|
|
44
|
+
msgstr ""
|
|
45
|
+
|
|
46
|
+
#: Iframe/EditIframe
|
|
47
|
+
# defaultMessage: Left
|
|
48
|
+
msgid "Left"
|
|
49
|
+
msgstr ""
|
|
50
|
+
|
|
51
|
+
#: PrivacyProtection/PrivacyProtection
|
|
52
|
+
# defaultMessage: Live image generated
|
|
53
|
+
msgid "Live image generated"
|
|
54
|
+
msgstr ""
|
|
55
|
+
|
|
56
|
+
#: Iframe/EditIframe
|
|
57
|
+
# defaultMessage: Please enter the Embed Code provided by Google Maps -> Share -> Embed map. It should contain the <iframe> code on it.
|
|
58
|
+
msgid "Please enter the Embed Code provided by Google Maps -> Share -> Embed map. It should contain the <iframe> code on it."
|
|
59
|
+
msgstr ""
|
|
60
|
+
|
|
61
|
+
#: Iframe/EditIframe
|
|
62
|
+
# defaultMessage: Right
|
|
63
|
+
msgid "Right"
|
|
64
|
+
msgstr ""
|
|
65
|
+
|
|
66
|
+
#: PrivacyProtection/PrivacyProtection
|
|
67
|
+
# defaultMessage: Success
|
|
68
|
+
msgid "Success"
|
|
69
|
+
msgstr ""
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@eeacms/volto-embed",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "7.0.0",
|
|
4
4
|
"description": "Embed external content",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"author": "European Environment Agency: IDM2 A-Team",
|
|
@@ -27,21 +27,49 @@
|
|
|
27
27
|
"@cypress/code-coverage": "^3.10.0",
|
|
28
28
|
"@plone/scripts": "*",
|
|
29
29
|
"babel-plugin-transform-class-properties": "^6.24.1",
|
|
30
|
+
"husky": "^8.0.3",
|
|
31
|
+
"lint-staged": "^14.0.1",
|
|
30
32
|
"md5": "^2.3.0"
|
|
31
33
|
},
|
|
34
|
+
"lint-staged": {
|
|
35
|
+
"src/**/*.{js,jsx,ts,tsx,json}": [
|
|
36
|
+
"make lint-fix",
|
|
37
|
+
"make prettier-fix"
|
|
38
|
+
],
|
|
39
|
+
"src/**/*.{jsx}": [
|
|
40
|
+
"make i18n"
|
|
41
|
+
],
|
|
42
|
+
"theme/**/*.{css,less}": [
|
|
43
|
+
"make stylelint-fix"
|
|
44
|
+
],
|
|
45
|
+
"src/**/*.{css,less}": [
|
|
46
|
+
"make stylelint-fix"
|
|
47
|
+
],
|
|
48
|
+
"theme/**/*.overrides": [
|
|
49
|
+
"make stylelint-fix"
|
|
50
|
+
],
|
|
51
|
+
"src/**/*.overrides": [
|
|
52
|
+
"make stylelint-fix"
|
|
53
|
+
]
|
|
54
|
+
},
|
|
32
55
|
"scripts": {
|
|
33
56
|
"release": "release-it",
|
|
34
57
|
"release-major-beta": "release-it major --preRelease=beta",
|
|
35
58
|
"release-beta": "release-it --preRelease=beta",
|
|
36
59
|
"bootstrap": "npm install -g ejs; npm link ejs; node bootstrap",
|
|
37
|
-
"
|
|
38
|
-
"
|
|
39
|
-
"
|
|
40
|
-
"
|
|
41
|
-
"
|
|
42
|
-
"
|
|
43
|
-
"
|
|
44
|
-
"
|
|
45
|
-
"
|
|
60
|
+
"test": "make test",
|
|
61
|
+
"test:fix": "make test-update",
|
|
62
|
+
"pre-commit": "yarn stylelint:fix && yarn prettier:fix && yarn lint:fix",
|
|
63
|
+
"stylelint": "make stylelint",
|
|
64
|
+
"stylelint:overrides": "make stylelint-overrides",
|
|
65
|
+
"stylelint:fix": "make stylelint-fix",
|
|
66
|
+
"prettier": "make prettier",
|
|
67
|
+
"prettier:fix": "make prettier-fix",
|
|
68
|
+
"lint": "make lint",
|
|
69
|
+
"lint:fix": "make lint-fix",
|
|
70
|
+
"i18n": "make i18n",
|
|
71
|
+
"cypress:run": "make cypress-run",
|
|
72
|
+
"cypress:open": "make cypress-open",
|
|
73
|
+
"prepare": "husky install"
|
|
46
74
|
}
|
|
47
|
-
}
|
|
75
|
+
}
|
|
@@ -9,17 +9,15 @@ import PropTypes from 'prop-types';
|
|
|
9
9
|
import { Button, Input, Message } from 'semantic-ui-react';
|
|
10
10
|
import { defineMessages, FormattedMessage, injectIntl } from 'react-intl';
|
|
11
11
|
import cx from 'classnames';
|
|
12
|
-
|
|
12
|
+
import { isEqual } from 'lodash';
|
|
13
|
+
import { withBlockExtensions } from '@plone/volto/helpers';
|
|
14
|
+
import { compose } from 'redux';
|
|
13
15
|
import { Icon, SidebarPortal } from '@plone/volto/components';
|
|
14
|
-
import InlineForm from '@plone/volto/components/manage/Form/InlineForm';
|
|
15
16
|
import clearSVG from '@plone/volto/icons/clear.svg';
|
|
16
17
|
import aheadSVG from '@plone/volto/icons/ahead.svg';
|
|
17
18
|
import mapsBlockSVG from '@plone/volto/components/manage/Blocks/Maps/block-maps.svg';
|
|
18
|
-
import
|
|
19
|
-
import
|
|
20
|
-
PrivacyProtection,
|
|
21
|
-
addPrivacyProtectionToSchema,
|
|
22
|
-
} from '../PrivacyProtection';
|
|
19
|
+
import PrivacyProtection from '@eeacms/volto-embed/PrivacyProtection/PrivacyProtection';
|
|
20
|
+
import MapsSidebar from './MapsSidebar';
|
|
23
21
|
|
|
24
22
|
const messages = defineMessages({
|
|
25
23
|
MapsBlockInputPlaceholder: {
|
|
@@ -90,6 +88,19 @@ class Edit extends Component {
|
|
|
90
88
|
this.onKeyDownVariantMenuForm = this.onKeyDownVariantMenuForm.bind(this);
|
|
91
89
|
}
|
|
92
90
|
|
|
91
|
+
/**
|
|
92
|
+
* @param {*} nextProps
|
|
93
|
+
* @returns {boolean}
|
|
94
|
+
* @memberof Edit
|
|
95
|
+
*/
|
|
96
|
+
shouldComponentUpdate(nextProps) {
|
|
97
|
+
return (
|
|
98
|
+
this.props.selected ||
|
|
99
|
+
nextProps.selected ||
|
|
100
|
+
!isEqual(this.props.data, nextProps.data)
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
|
|
93
104
|
/**
|
|
94
105
|
* Backward compatibility
|
|
95
106
|
* @method componentDidMount
|
|
@@ -196,6 +207,9 @@ class Edit extends Component {
|
|
|
196
207
|
* @returns {string} Markup for the component.
|
|
197
208
|
*/
|
|
198
209
|
render() {
|
|
210
|
+
const placeholder =
|
|
211
|
+
this.props.data.placeholder ||
|
|
212
|
+
this.props.intl.formatMessage(messages.MapsBlockInputPlaceholder);
|
|
199
213
|
return (
|
|
200
214
|
<div
|
|
201
215
|
className={cx(
|
|
@@ -224,6 +238,11 @@ class Edit extends Component {
|
|
|
224
238
|
className="google-map"
|
|
225
239
|
frameBorder="0"
|
|
226
240
|
allowFullScreen
|
|
241
|
+
style={
|
|
242
|
+
this.props.data.height
|
|
243
|
+
? { height: this.props.data.height }
|
|
244
|
+
: {}
|
|
245
|
+
}
|
|
227
246
|
/>
|
|
228
247
|
</PrivacyProtection>
|
|
229
248
|
</div>
|
|
@@ -235,9 +254,7 @@ class Edit extends Component {
|
|
|
235
254
|
<Input
|
|
236
255
|
onKeyDown={this.onKeyDownVariantMenuForm}
|
|
237
256
|
onChange={this.onChangeUrl}
|
|
238
|
-
placeholder={
|
|
239
|
-
messages.MapsBlockInputPlaceholder,
|
|
240
|
-
)}
|
|
257
|
+
placeholder={placeholder}
|
|
241
258
|
value={this.state.url}
|
|
242
259
|
// Prevents propagation to the Dropzone and the opening
|
|
243
260
|
// of the upload browser dialog
|
|
@@ -287,22 +304,13 @@ class Edit extends Component {
|
|
|
287
304
|
</center>
|
|
288
305
|
</Message>
|
|
289
306
|
)}
|
|
307
|
+
{!this.props.selected && <div className="map-overlay" />}
|
|
290
308
|
<SidebarPortal selected={this.props.selected}>
|
|
291
|
-
<
|
|
292
|
-
schema={addPrivacyProtectionToSchema(schema)}
|
|
293
|
-
title={schema.title}
|
|
294
|
-
onChangeField={(id, value) => {
|
|
295
|
-
this.props.onChangeBlock(this.props.block, {
|
|
296
|
-
...this.props.data,
|
|
297
|
-
[id]: value,
|
|
298
|
-
});
|
|
299
|
-
}}
|
|
300
|
-
formData={this.props.data}
|
|
301
|
-
/>
|
|
309
|
+
<MapsSidebar {...this.props} resetSubmitUrl={this.resetSubmitUrl} />
|
|
302
310
|
</SidebarPortal>
|
|
303
311
|
</div>
|
|
304
312
|
);
|
|
305
313
|
}
|
|
306
314
|
}
|
|
307
315
|
|
|
308
|
-
export default injectIntl(Edit);
|
|
316
|
+
export default compose(injectIntl, withBlockExtensions)(Edit);
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/* eslint-disable no-unused-vars */
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import config from '@plone/volto/registry';
|
|
4
|
+
import { render, fireEvent, screen } from '@testing-library/react';
|
|
5
|
+
import { Provider } from 'react-intl-redux';
|
|
6
|
+
import configureStore from 'redux-mock-store';
|
|
7
|
+
import Edit from './Edit';
|
|
8
|
+
import '@testing-library/jest-dom/extend-expect';
|
|
9
|
+
|
|
10
|
+
const mockStore = configureStore();
|
|
11
|
+
|
|
12
|
+
const store = mockStore(() => ({
|
|
13
|
+
connected_data_parameters: {},
|
|
14
|
+
router: {
|
|
15
|
+
location: {
|
|
16
|
+
pathname: '',
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
intl: {
|
|
20
|
+
locale: 'en',
|
|
21
|
+
messages: {},
|
|
22
|
+
},
|
|
23
|
+
}));
|
|
24
|
+
|
|
25
|
+
config.blocks.blocksConfig = {
|
|
26
|
+
...config.blocks.blocksConfig,
|
|
27
|
+
maps: {
|
|
28
|
+
id: 'maps',
|
|
29
|
+
title: 'Maps',
|
|
30
|
+
group: 'media',
|
|
31
|
+
extensions: {},
|
|
32
|
+
variations: [],
|
|
33
|
+
restricted: false,
|
|
34
|
+
mostUsed: true,
|
|
35
|
+
sidebarTab: 1,
|
|
36
|
+
security: {
|
|
37
|
+
addPermission: [],
|
|
38
|
+
view: [],
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
jest.mock(
|
|
44
|
+
'@eeacms/volto-embed/PrivacyProtection/PrivacyProtection',
|
|
45
|
+
() => ({ children }) => children,
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
describe('Edit', () => {
|
|
49
|
+
it('renders without crashing', () => {
|
|
50
|
+
render(
|
|
51
|
+
<Provider store={store}>
|
|
52
|
+
<Edit
|
|
53
|
+
selected={false}
|
|
54
|
+
block="block"
|
|
55
|
+
index={1}
|
|
56
|
+
data={{
|
|
57
|
+
'@type': 'maps',
|
|
58
|
+
url:
|
|
59
|
+
'https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d3027.7835278268726!2d14.38842915203974!3d40.634655679238854!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x133b994881d943cb%3A0x6ab93db57d3272f0!2sHotel+Mediterraneo+Sorrento!5e0!3m2!1sen!2ses!4v1550168740166',
|
|
60
|
+
}}
|
|
61
|
+
pathname="/"
|
|
62
|
+
onChangeBlock={() => {}}
|
|
63
|
+
onSelectBlock={() => {}}
|
|
64
|
+
onDeleteBlock={() => {}}
|
|
65
|
+
onFocusPreviousBlock={() => {}}
|
|
66
|
+
onFocusNextBlock={() => {}}
|
|
67
|
+
handleKeyDown={() => {}}
|
|
68
|
+
/>
|
|
69
|
+
</Provider>,
|
|
70
|
+
);
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it('submits url when button is clicked', async () => {
|
|
74
|
+
const url =
|
|
75
|
+
'https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d3027.7835278268726!2d14.38842915203974!3d40.634655679238854!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x133b994881d943cb%3A0x6ab93db57d3272f0!2sHotel+Mediterraneo+Sorrento!5e0!3m2!1sen!2ses!4v1550168740166';
|
|
76
|
+
|
|
77
|
+
const { container, getByPlaceholderText } = render(
|
|
78
|
+
<Provider store={store}>
|
|
79
|
+
<Edit
|
|
80
|
+
selected={false}
|
|
81
|
+
block="block"
|
|
82
|
+
index={1}
|
|
83
|
+
data={{
|
|
84
|
+
'@type': 'maps',
|
|
85
|
+
dataprotection: {
|
|
86
|
+
privacy_statement: 'test',
|
|
87
|
+
},
|
|
88
|
+
}}
|
|
89
|
+
pathname="/"
|
|
90
|
+
onChangeBlock={() => {}}
|
|
91
|
+
onSelectBlock={() => {}}
|
|
92
|
+
onDeleteBlock={() => {}}
|
|
93
|
+
onFocusPreviousBlock={() => {}}
|
|
94
|
+
onFocusNextBlock={() => {}}
|
|
95
|
+
handleKeyDown={() => {}}
|
|
96
|
+
/>
|
|
97
|
+
</Provider>,
|
|
98
|
+
);
|
|
99
|
+
|
|
100
|
+
const input = getByPlaceholderText('Enter map Embed Code');
|
|
101
|
+
|
|
102
|
+
fireEvent.click(input);
|
|
103
|
+
fireEvent.change(input, { target: { value: url } });
|
|
104
|
+
// screen.debug();
|
|
105
|
+
// expect(input.value).toBe(url);
|
|
106
|
+
|
|
107
|
+
// fireEvent.click(container.querySelector('button.cancel'));
|
|
108
|
+
|
|
109
|
+
// fireEvent.keyDown(input, { key: 'Enter', code: 'Enter' });
|
|
110
|
+
// fireEvent.keyDown(input, { key: 'Escape', code: 'Escape' });
|
|
111
|
+
// fireEvent.keyDown(input, { key: 'KeyA', code: 'KeyA' });
|
|
112
|
+
|
|
113
|
+
// fireEvent.change(input, { target: { value: '<iframe src="test"/>' } });
|
|
114
|
+
// fireEvent.keyDown(input, { key: 'Enter', code: 'Enter' });
|
|
115
|
+
|
|
116
|
+
// const button = container.querySelector('button.ui.basic.primary.button');
|
|
117
|
+
// fireEvent.click(button);
|
|
118
|
+
});
|
|
119
|
+
});
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { BlockDataForm } from '@plone/volto/components';
|
|
3
|
+
import { useIntl, defineMessages } from 'react-intl';
|
|
4
|
+
import globeSVG from '@plone/volto/icons/globe.svg';
|
|
5
|
+
import { Icon } from '@plone/volto/components';
|
|
6
|
+
import { Segment } from 'semantic-ui-react';
|
|
7
|
+
import { addPrivacyProtectionToSchema } from '@eeacms/volto-embed';
|
|
8
|
+
import { MapsSchema } from './schema';
|
|
9
|
+
|
|
10
|
+
const messages = defineMessages({
|
|
11
|
+
Maps: {
|
|
12
|
+
id: 'Maps',
|
|
13
|
+
defaultMessage: 'Maps',
|
|
14
|
+
},
|
|
15
|
+
NoMaps: {
|
|
16
|
+
id: 'No map selected',
|
|
17
|
+
defaultMessage: 'No map selected',
|
|
18
|
+
},
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
const MapsSidebar = (props) => {
|
|
22
|
+
const { data, block, onChangeBlock } = props;
|
|
23
|
+
const intl = useIntl();
|
|
24
|
+
const schema = addPrivacyProtectionToSchema(MapsSchema({ ...props, intl }));
|
|
25
|
+
|
|
26
|
+
return (
|
|
27
|
+
<>
|
|
28
|
+
{!data.url ? (
|
|
29
|
+
<Segment className="sidebar-metadata-container" secondary>
|
|
30
|
+
{props.intl.formatMessage(messages.NoMaps)}
|
|
31
|
+
<Icon name={globeSVG} size="100px" color="#b8c6c8" />
|
|
32
|
+
</Segment>
|
|
33
|
+
) : (
|
|
34
|
+
<BlockDataForm
|
|
35
|
+
schema={schema}
|
|
36
|
+
title={intl.formatMessage(messages.Maps)}
|
|
37
|
+
onChangeField={(id, value) => {
|
|
38
|
+
onChangeBlock(block, {
|
|
39
|
+
...data,
|
|
40
|
+
[id]: value,
|
|
41
|
+
});
|
|
42
|
+
}}
|
|
43
|
+
onChangeBlock={onChangeBlock}
|
|
44
|
+
formData={data}
|
|
45
|
+
block={block}
|
|
46
|
+
/>
|
|
47
|
+
)}
|
|
48
|
+
</>
|
|
49
|
+
);
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
export default MapsSidebar;
|
|
@@ -7,7 +7,9 @@ import React from 'react';
|
|
|
7
7
|
import { defineMessages, injectIntl } from 'react-intl';
|
|
8
8
|
import PropTypes from 'prop-types';
|
|
9
9
|
import cx from 'classnames';
|
|
10
|
-
import {
|
|
10
|
+
import { compose } from 'redux';
|
|
11
|
+
import { withBlockExtensions } from '@plone/volto/helpers';
|
|
12
|
+
import PrivacyProtection from '@eeacms/volto-embed/PrivacyProtection/PrivacyProtection';
|
|
11
13
|
|
|
12
14
|
const messages = defineMessages({
|
|
13
15
|
EmbededGoogleMaps: {
|
|
@@ -32,17 +34,11 @@ const View = ({ data, intl, id }) => {
|
|
|
32
34
|
},
|
|
33
35
|
data.align,
|
|
34
36
|
)}
|
|
35
|
-
style={
|
|
36
|
-
data.align === 'full'
|
|
37
|
-
? { position: 'static', height: data.height }
|
|
38
|
-
: { height: data.height }
|
|
39
|
-
}
|
|
40
37
|
>
|
|
41
38
|
<div
|
|
42
|
-
className={cx({
|
|
43
|
-
'full-width
|
|
39
|
+
className={cx('maps-inner', {
|
|
40
|
+
'full-width': data.align === 'full',
|
|
44
41
|
})}
|
|
45
|
-
style={{ height: '100%' }}
|
|
46
42
|
>
|
|
47
43
|
<PrivacyProtection data={data} id={id}>
|
|
48
44
|
<iframe
|
|
@@ -51,7 +47,7 @@ const View = ({ data, intl, id }) => {
|
|
|
51
47
|
className="google-map"
|
|
52
48
|
frameBorder="0"
|
|
53
49
|
allowFullScreen
|
|
54
|
-
style={{ height: data.height }}
|
|
50
|
+
style={data.height ? { height: data.height } : {}}
|
|
55
51
|
/>
|
|
56
52
|
</PrivacyProtection>
|
|
57
53
|
</div>
|
|
@@ -68,4 +64,4 @@ View.propTypes = {
|
|
|
68
64
|
data: PropTypes.objectOf(PropTypes.any).isRequired,
|
|
69
65
|
};
|
|
70
66
|
|
|
71
|
-
export default injectIntl(View);
|
|
67
|
+
export default compose(injectIntl, withBlockExtensions)(View);
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { defineMessages } from 'react-intl';
|
|
2
|
+
|
|
3
|
+
const messages = defineMessages({
|
|
4
|
+
Maps: {
|
|
5
|
+
id: 'Maps',
|
|
6
|
+
defaultMessage: 'Maps',
|
|
7
|
+
},
|
|
8
|
+
AltText: {
|
|
9
|
+
id: 'Alt text',
|
|
10
|
+
defaultMessage: 'Alt text',
|
|
11
|
+
},
|
|
12
|
+
MapsURL: {
|
|
13
|
+
id: 'Maps URL',
|
|
14
|
+
defaultMessage: 'Maps URL',
|
|
15
|
+
},
|
|
16
|
+
Alignment: {
|
|
17
|
+
id: 'Alignment',
|
|
18
|
+
defaultMessage: 'Alignment',
|
|
19
|
+
},
|
|
20
|
+
CSSHeight: {
|
|
21
|
+
id: 'CSSHeight',
|
|
22
|
+
defineMessages: 'CSS height',
|
|
23
|
+
},
|
|
24
|
+
CSSHeightDescription: {
|
|
25
|
+
id: 'CSSHeightDescription',
|
|
26
|
+
defineMessages: 'Iframe height',
|
|
27
|
+
},
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
export const MapsSchema = (props) => ({
|
|
31
|
+
title: props.intl.formatMessage(messages.Maps),
|
|
32
|
+
block: 'Maps',
|
|
33
|
+
fieldsets: [
|
|
34
|
+
{
|
|
35
|
+
id: 'default',
|
|
36
|
+
title: 'Default',
|
|
37
|
+
fields: ['url', 'title', 'align', 'height'],
|
|
38
|
+
},
|
|
39
|
+
],
|
|
40
|
+
|
|
41
|
+
properties: {
|
|
42
|
+
url: {
|
|
43
|
+
title: props.intl.formatMessage(messages.MapsURL),
|
|
44
|
+
widget: 'url',
|
|
45
|
+
},
|
|
46
|
+
title: {
|
|
47
|
+
title: props.intl.formatMessage(messages.AltText),
|
|
48
|
+
},
|
|
49
|
+
align: {
|
|
50
|
+
title: props.intl.formatMessage(messages.Alignment),
|
|
51
|
+
widget: 'align',
|
|
52
|
+
},
|
|
53
|
+
height: {
|
|
54
|
+
title: (
|
|
55
|
+
<a
|
|
56
|
+
rel="noreferrer"
|
|
57
|
+
target="_blank"
|
|
58
|
+
href="https://developer.mozilla.org/en-US/docs/Web/CSS/height"
|
|
59
|
+
>
|
|
60
|
+
{props.intl.formatMessage(messages.CSSHeight)}
|
|
61
|
+
</a>
|
|
62
|
+
),
|
|
63
|
+
description: props.intl.formatMessage(messages.CSSHeightDescription),
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
required: [],
|
|
67
|
+
});
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import React, { useState } from 'react';
|
|
2
|
+
import cx from 'classnames';
|
|
2
3
|
import { compose } from 'redux';
|
|
3
4
|
import { useSelector, useDispatch } from 'react-redux';
|
|
4
5
|
import VisibilitySensor from 'react-visibility-sensor';
|
|
@@ -77,6 +78,7 @@ const CookieWatcher = (domain_key, cookies, pollingRate = 250) => {
|
|
|
77
78
|
|
|
78
79
|
const PrivacyProtection = (props) => {
|
|
79
80
|
const {
|
|
81
|
+
className,
|
|
80
82
|
children,
|
|
81
83
|
data = {},
|
|
82
84
|
id,
|
|
@@ -168,7 +170,7 @@ const PrivacyProtection = (props) => {
|
|
|
168
170
|
>
|
|
169
171
|
{visible ? (
|
|
170
172
|
<div
|
|
171
|
-
className=
|
|
173
|
+
className={cx('privacy-protection-wrapper', className)}
|
|
172
174
|
style={{
|
|
173
175
|
position: 'relative',
|
|
174
176
|
height: height && (!enabled || !show) ? `${height}px` : 'auto',
|
|
@@ -17,17 +17,12 @@
|
|
|
17
17
|
text-align: center;
|
|
18
18
|
|
|
19
19
|
.wrapped {
|
|
20
|
-
// position: absolute;
|
|
21
|
-
// top: 50%;
|
|
22
|
-
// left: 50%;
|
|
23
20
|
width: 300px;
|
|
24
21
|
padding: 1.4rem;
|
|
25
22
|
margin: 0 auto;
|
|
26
23
|
background: white;
|
|
27
24
|
border-radius: 5px;
|
|
28
25
|
opacity: 1;
|
|
29
|
-
// -ms-transform: translate(-50%, -50%);
|
|
30
|
-
// transform: translate(-50%, -50%);
|
|
31
26
|
}
|
|
32
27
|
|
|
33
28
|
.discreet,
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import React, { useState } from 'react';
|
|
2
|
+
import { Modal } from 'semantic-ui-react';
|
|
3
|
+
|
|
4
|
+
const EnlargeWidget = ({ children }) => {
|
|
5
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
6
|
+
|
|
7
|
+
return (
|
|
8
|
+
<div className="enlarge">
|
|
9
|
+
<button className="trigger-button" onClick={() => setIsOpen(true)}>
|
|
10
|
+
<i className="ri-fullscreen-line" />
|
|
11
|
+
Enlarge
|
|
12
|
+
</button>
|
|
13
|
+
<Modal
|
|
14
|
+
open={isOpen}
|
|
15
|
+
closeIcon={
|
|
16
|
+
<span className="close icon">
|
|
17
|
+
<i class="ri-close-line" />
|
|
18
|
+
</span>
|
|
19
|
+
}
|
|
20
|
+
onClose={() => setIsOpen(false)}
|
|
21
|
+
className="enlarge-modal"
|
|
22
|
+
>
|
|
23
|
+
<Modal.Content>{children}</Modal.Content>
|
|
24
|
+
</Modal>
|
|
25
|
+
</div>
|
|
26
|
+
);
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export default EnlargeWidget;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Popup } from 'semantic-ui-react';
|
|
3
|
+
import { isArray, isString } from 'lodash';
|
|
4
|
+
import cx from 'classnames';
|
|
5
|
+
import {
|
|
6
|
+
serializeNodes,
|
|
7
|
+
serializeNodesToText,
|
|
8
|
+
} from '@plone/volto-slate/editor/render';
|
|
9
|
+
|
|
10
|
+
export const serializeText = (notes) => {
|
|
11
|
+
const content = isArray(notes) ? serializeNodes(notes) : notes;
|
|
12
|
+
const text = isArray(notes)
|
|
13
|
+
? serializeNodesToText(notes)
|
|
14
|
+
: isString(notes)
|
|
15
|
+
? notes
|
|
16
|
+
: '';
|
|
17
|
+
if (!text) return <p>There are no notes set for this visualization</p>;
|
|
18
|
+
return content;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export default function FigureNote({ notes = [] }) {
|
|
22
|
+
const [open, setOpen] = React.useState(false);
|
|
23
|
+
|
|
24
|
+
return (
|
|
25
|
+
<Popup
|
|
26
|
+
popper={{ id: 'vis-toolbar-popup', className: 'figure-note-popup' }}
|
|
27
|
+
position="bottom left"
|
|
28
|
+
on="click"
|
|
29
|
+
open={open}
|
|
30
|
+
onClose={() => {
|
|
31
|
+
setOpen(false);
|
|
32
|
+
}}
|
|
33
|
+
onOpen={() => {
|
|
34
|
+
setOpen(true);
|
|
35
|
+
}}
|
|
36
|
+
trigger={
|
|
37
|
+
<div className="figure-note">
|
|
38
|
+
<button className={cx('trigger-button', { open })}>Note</button>
|
|
39
|
+
</div>
|
|
40
|
+
}
|
|
41
|
+
>
|
|
42
|
+
<Popup.Content>{serializeText(notes)}</Popup.Content>
|
|
43
|
+
</Popup>
|
|
44
|
+
);
|
|
45
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { UniversalLink } from '@plone/volto/components';
|
|
3
|
+
|
|
4
|
+
const Link = ({ children, ...props }) => {
|
|
5
|
+
if (props.href) {
|
|
6
|
+
return <UniversalLink {...props}>{children}</UniversalLink>;
|
|
7
|
+
}
|
|
8
|
+
return <span {...props}>{children}</span>;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export default function MoreInfo({ href }) {
|
|
12
|
+
return (
|
|
13
|
+
<div className="more-info">
|
|
14
|
+
<Link href={href} className="trigger-button">
|
|
15
|
+
<span>More info</span>
|
|
16
|
+
<i class="ri-external-link-line" />
|
|
17
|
+
</Link>
|
|
18
|
+
</div>
|
|
19
|
+
);
|
|
20
|
+
}
|