@eeacms/volto-embed 9.0.1 → 9.0.3

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.
@@ -1,6 +1,5 @@
1
1
  import React from 'react';
2
2
  import renderer from 'react-test-renderer';
3
- import configureStore from 'redux-mock-store';
4
3
  import { Provider } from 'react-intl-redux';
5
4
  import config from '@plone/volto/registry';
6
5
 
@@ -9,32 +8,9 @@ import installEmbedMaps from '.';
9
8
 
10
9
  installEmbedMaps(config);
11
10
 
12
- const mockStore = configureStore();
13
-
14
- jest.mock('@plone/volto/components', () => ({
15
- __esModule: true,
16
- SidebarPortal: jest.requireActual(
17
- '@plone/volto/components/manage/Sidebar/SidebarPortal',
18
- ).default,
19
- UniversalLink: ({ children, href }) => {
20
- return <a href={href}>{children}</a>;
21
- },
22
- }));
23
-
24
- const store = mockStore({
25
- intl: {
26
- locale: 'en',
27
- messages: {},
28
- },
29
- content: {
30
- create: {},
31
- },
32
- connected_data_parameters: {},
33
- });
34
-
35
11
  test('renders an edit embed map block component', () => {
36
12
  const component = renderer.create(
37
- <Provider store={store}>
13
+ <Provider store={global.store}>
38
14
  <Edit
39
15
  id="my-map"
40
16
  data={{
@@ -57,7 +33,7 @@ test('renders an edit embed map block component', () => {
57
33
  useVisibilitySensor: false,
58
34
  }}
59
35
  pathname="/news"
60
- selected={false}
36
+ selected={true}
61
37
  block="1234"
62
38
  index={1}
63
39
  onChangeBlock={() => {}}
@@ -51,6 +51,7 @@ function View(props) {
51
51
  data={{
52
52
  ...maps,
53
53
  useVisibilitySensor,
54
+ height: props.data.height || maps.height,
54
55
  with_notes,
55
56
  with_sources,
56
57
  with_more_info,
@@ -1,6 +1,5 @@
1
1
  import React from 'react';
2
2
  import renderer from 'react-test-renderer';
3
- import configureStore from 'redux-mock-store';
4
3
  import { Provider } from 'react-intl-redux';
5
4
  import config from '@plone/volto/registry';
6
5
 
@@ -9,28 +8,9 @@ import installEmbedMaps from '.';
9
8
 
10
9
  installEmbedMaps(config);
11
10
 
12
- const mockStore = configureStore();
13
-
14
- jest.mock('@plone/volto/components', () => ({
15
- __esModule: true,
16
- UniversalLink: ({ children, href }) => {
17
- return <a href={href}>{children}</a>;
18
- },
19
- }));
20
-
21
11
  test('renders a view embed map block component', () => {
22
- const store = mockStore({
23
- intl: {
24
- locale: 'en',
25
- messages: {},
26
- },
27
- content: {
28
- create: {},
29
- },
30
- connected_data_parameters: {},
31
- });
32
12
  const component = renderer.create(
33
- <Provider store={store}>
13
+ <Provider store={global.store}>
34
14
  <View
35
15
  id="my-map"
36
16
  data={{
@@ -8,7 +8,7 @@ const applyConfig = (config) => {
8
8
  id: 'embed_maps',
9
9
  title: 'Embed interactive Map',
10
10
  icon: sliderSVG,
11
- group: 'common',
11
+ group: 'data_visualizations',
12
12
  edit: EmbedMap,
13
13
  view: EmbedView,
14
14
  restricted: false,
@@ -1,11 +1,24 @@
1
- export default () => {
1
+ import { defineMessages } from 'react-intl';
2
+
3
+ const messages = defineMessages({
4
+ CSSHeight: {
5
+ id: 'CSS height',
6
+ defaultMessage: 'CSS height',
7
+ },
8
+ CSSMapHeightDescription: {
9
+ id: 'Map height',
10
+ defaultMessage: 'Map height',
11
+ },
12
+ });
13
+
14
+ export default (props) => {
2
15
  return {
3
- title: 'Embed Map',
16
+ title: 'Embed interactive Map',
4
17
  fieldsets: [
5
18
  {
6
19
  id: 'default',
7
20
  title: 'Default',
8
- fields: ['url'],
21
+ fields: ['url', 'height'],
9
22
  },
10
23
  {
11
24
  id: 'toolbar',
@@ -24,6 +37,18 @@ export default () => {
24
37
  title: 'Map url',
25
38
  widget: 'url',
26
39
  },
40
+ height: {
41
+ title: (
42
+ <a
43
+ rel="noreferrer"
44
+ target="_blank"
45
+ href="https://developer.mozilla.org/en-US/docs/Web/CSS/height"
46
+ >
47
+ {props.intl.formatMessage(messages.CSSHeight)}
48
+ </a>
49
+ ),
50
+ description: props.intl.formatMessage(messages.CSSMapHeightDescription),
51
+ },
27
52
  with_notes: {
28
53
  title: 'Show note',
29
54
  type: 'boolean',
@@ -50,13 +75,8 @@ export default () => {
50
75
  type: 'boolean',
51
76
  defaultValue: true,
52
77
  },
53
- tableau_height: {
54
- title: 'Height',
55
- type: 'text',
56
- defaultValue: '700',
57
- },
58
78
  },
59
79
 
60
- required: ['tableau_vis_url'],
80
+ required: [],
61
81
  };
62
82
  };
@@ -4,12 +4,11 @@
4
4
  */
5
5
 
6
6
  import React, { Component } from 'react';
7
- import { isString } from 'lodash';
7
+ import { isEqual, isString } from 'lodash';
8
8
  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
- import { isEqual } from 'lodash';
13
12
  import { withBlockExtensions } from '@plone/volto/helpers';
14
13
  import { compose } from 'redux';
15
14
  import { Icon, SidebarPortal } from '@plone/volto/components';
@@ -1,79 +1,83 @@
1
1
  import React from 'react';
2
2
  import renderer from 'react-test-renderer';
3
- import configureStore from 'redux-mock-store';
4
3
  import { Provider } from 'react-intl-redux';
5
4
  import config from '@plone/volto/registry';
6
5
 
7
6
  import Edit from './Edit';
8
7
 
9
- const mockStore = configureStore();
10
-
11
- jest.mock('@plone/volto/components', () => ({
12
- __esModule: true,
13
- SidebarPortal: jest.requireActual(
14
- '@plone/volto/components/manage/Sidebar/SidebarPortal',
15
- ).default,
16
- UniversalLink: ({ children, href }) => {
17
- return <a href={href}>{children}</a>;
18
- },
19
- }));
20
-
21
- const store = mockStore({
22
- intl: {
23
- locale: 'en',
24
- messages: {},
25
- },
26
- content: {
27
- create: {},
28
- },
29
- connected_data_parameters: {},
30
- });
8
+ describe('Test Maps Block editing', () => {
9
+ config.blocks.blocksConfig = {
10
+ ...config.blocks.blocksConfig,
11
+ maps: {
12
+ id: 'maps',
13
+ title: 'Maps',
14
+ group: 'media',
15
+ extensions: {},
16
+ variations: [],
17
+ restricted: false,
18
+ mostUsed: true,
19
+ sidebarTab: 1,
20
+ security: {
21
+ addPermission: [],
22
+ view: [],
23
+ },
24
+ },
25
+ };
31
26
 
32
- config.blocks.blocksConfig = {
33
- ...config.blocks.blocksConfig,
34
- maps: {
35
- id: 'maps',
36
- title: 'Maps',
37
- group: 'media',
38
- extensions: {},
39
- variations: [],
40
- restricted: false,
41
- mostUsed: true,
42
- sidebarTab: 1,
43
- security: {
44
- addPermission: [],
45
- view: [],
27
+ const data = {
28
+ '@type': 'maps',
29
+ url:
30
+ '<iframe src="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d11255.043736345397!2d24.6862147!3d45.15143895!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x474d3248f30cd7b5%3A0x307c5acf21ded9e3!2sHotel%20Posada!5e0!3m2!1sro!2sro!4v1701254795494!5m2!1sro!2sro" width="600" height="450" style="border:0;" allowfullscreen="" loading="lazy" referrerpolicy="no-referrer-when-downgrade"></iframe>',
31
+ dataprotection: {
32
+ enabled: false,
33
+ privacy_statement: 'This is a privacy statement',
46
34
  },
47
- },
48
- };
35
+ useVisibilitySensor: false,
36
+ };
37
+
38
+ test('test-1', () => {
39
+ const component = renderer.create(
40
+ <Provider store={global.store}>
41
+ <Edit
42
+ data={data}
43
+ pathname="/news"
44
+ selected={false}
45
+ block="1234"
46
+ index={1}
47
+ onChangeBlock={() => {}}
48
+ onSelectBlock={() => {}}
49
+ onDeleteBlock={() => {}}
50
+ onFocusPreviousBlock={() => {}}
51
+ onFocusNextBlock={() => {}}
52
+ handleKeyDown={() => {}}
53
+ content={{}}
54
+ />
55
+ </Provider>,
56
+ );
57
+ const json = component.toJSON();
58
+ expect(json).toMatchSnapshot();
59
+ });
49
60
 
50
- test('renders an edit map block component', () => {
51
- const component = renderer.create(
52
- <Provider store={store}>
53
- <Edit
54
- data={{
55
- '@type': 'maps',
56
- url:
57
- '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',
58
- dataprotection: {
59
- enabled: false,
60
- },
61
- useVisibilitySensor: false,
62
- }}
63
- pathname="/news"
64
- selected={false}
65
- block="1234"
66
- index={1}
67
- onChangeBlock={() => {}}
68
- onSelectBlock={() => {}}
69
- onDeleteBlock={() => {}}
70
- onFocusPreviousBlock={() => {}}
71
- onFocusNextBlock={() => {}}
72
- handleKeyDown={() => {}}
73
- content={{}}
74
- />
75
- </Provider>,
76
- );
77
- const json = component.toJSON();
78
- expect(json).toMatchSnapshot();
61
+ test('test-2', () => {
62
+ const component = renderer.create(
63
+ <Provider store={global.store}>
64
+ <Edit
65
+ data={data}
66
+ pathname="/news"
67
+ selected={true}
68
+ block="1234"
69
+ index={1}
70
+ onChangeBlock={() => {}}
71
+ onSelectBlock={() => {}}
72
+ onDeleteBlock={() => {}}
73
+ onFocusPreviousBlock={() => {}}
74
+ onFocusNextBlock={() => {}}
75
+ handleKeyDown={() => {}}
76
+ content={{}}
77
+ />
78
+ </Provider>,
79
+ );
80
+ const json = component.toJSON();
81
+ expect(json).toMatchSnapshot();
82
+ });
79
83
  });
@@ -1,8 +1,7 @@
1
1
  import React from 'react';
2
- import { BlockDataForm } from '@plone/volto/components';
3
2
  import { useIntl, defineMessages } from 'react-intl';
3
+ import { Icon, BlockDataForm } from '@plone/volto/components';
4
4
  import globeSVG from '@plone/volto/icons/globe.svg';
5
- import { Icon } from '@plone/volto/components';
6
5
  import { Segment } from 'semantic-ui-react';
7
6
  import { addPrivacyProtectionToSchema } from '@eeacms/volto-embed';
8
7
  import { MapsSchema } from './schema';
@@ -30,7 +30,7 @@ const View = ({ data, intl, id }) => {
30
30
  className={cx(
31
31
  'block maps align',
32
32
  {
33
- center: !Boolean(data.align),
33
+ center: !data.align,
34
34
  },
35
35
  data.align,
36
36
  )}
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
+ import { render } from '@testing-library/react';
2
3
  import renderer from 'react-test-renderer';
3
- import configureStore from 'redux-mock-store';
4
4
  import { Provider } from 'react-intl-redux';
5
5
  import config from '@plone/volto/registry';
6
6
 
@@ -9,15 +9,6 @@ import installEmbedMaps from '.';
9
9
 
10
10
  installEmbedMaps(config);
11
11
 
12
- const mockStore = configureStore();
13
-
14
- jest.mock('@plone/volto/components', () => ({
15
- __esModule: true,
16
- UniversalLink: ({ children, href }) => {
17
- return <a href={href}>{children}</a>;
18
- },
19
- }));
20
-
21
12
  config.blocks.blocksConfig = {
22
13
  ...config.blocks.blocksConfig,
23
14
  maps: {
@@ -36,32 +27,65 @@ config.blocks.blocksConfig = {
36
27
  },
37
28
  };
38
29
 
39
- test('renders a view map block component', () => {
40
- const store = mockStore({
41
- intl: {
42
- locale: 'en',
43
- messages: {},
30
+ describe('Test Maps Block rendering', () => {
31
+ const data = {
32
+ '@type': 'maps',
33
+ url:
34
+ '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',
35
+ useVisibilitySensor: false,
36
+ dataprotection: {
37
+ enabled: false,
44
38
  },
45
- content: {
46
- create: {},
47
- },
48
- connected_data_parameters: {},
39
+ };
40
+
41
+ test('test-1', () => {
42
+ const component = renderer.create(
43
+ <Provider store={global.store}>
44
+ <View data={data} />
45
+ </Provider>,
46
+ );
47
+ const json = component.toJSON();
48
+ expect(json).toMatchSnapshot();
49
+ });
50
+
51
+ test('test-2', () => {
52
+ const component = renderer.create(
53
+ <Provider store={global.store}>
54
+ <View
55
+ data={{
56
+ ...data,
57
+ height: '100vh',
58
+ }}
59
+ />
60
+ </Provider>,
61
+ );
62
+ const json = component.toJSON();
63
+ expect(json).toMatchSnapshot();
64
+ });
65
+
66
+ test('test-3', () => {
67
+ const Component = (props) => (
68
+ <Provider store={global.store}>
69
+ <View
70
+ data={{
71
+ ...data,
72
+ dataprotection: {
73
+ ...data.dataprotection,
74
+ enabled: true,
75
+ },
76
+ height: '100vh',
77
+ useVisibilitySensor: false,
78
+ }}
79
+ />
80
+ </Provider>
81
+ );
82
+ const { container, rerender } = render(<Component />);
83
+
84
+ expect(container).toMatchSnapshot();
85
+
86
+ container.querySelector('.privacy-button button').click();
87
+
88
+ rerender(<Component />);
89
+ expect(container).toMatchSnapshot();
49
90
  });
50
- const component = renderer.create(
51
- <Provider store={store}>
52
- <View
53
- data={{
54
- '@type': 'maps',
55
- url:
56
- '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',
57
- useVisibilitySensor: false,
58
- dataprotection: {
59
- enabled: false,
60
- },
61
- }}
62
- />
63
- </Provider>,
64
- );
65
- const json = component.toJSON();
66
- expect(json).toMatchSnapshot();
67
91
  });
@@ -1,19 +1,35 @@
1
1
  import { defineMessages } from 'react-intl';
2
2
 
3
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
+ },
4
20
  CSSHeight: {
5
21
  id: 'CSS height',
6
- defineMessages: 'CSS height',
22
+ defaultMessage: 'CSS height',
7
23
  },
8
- CSSHeightDescription: {
9
- id: 'Iframe height',
10
- defineMessages: 'Iframe height',
24
+ CSSMapHeightDescription: {
25
+ id: 'Map height',
26
+ defaultMessage: 'Map height',
11
27
  },
12
28
  });
13
29
 
14
30
  export const MapsSchema = (props) => {
15
31
  return {
16
- title: props.intl.messages['Maps'],
32
+ title: props.intl.formatMessage(messages.Maps),
17
33
  block: 'Maps',
18
34
  fieldsets: [
19
35
  {
@@ -25,14 +41,14 @@ export const MapsSchema = (props) => {
25
41
 
26
42
  properties: {
27
43
  url: {
28
- title: props.intl.messages['Maps URL'],
44
+ title: props.intl.formatMessage(messages.MapsURL),
29
45
  widget: 'url',
30
46
  },
31
47
  title: {
32
- title: props.intl.messages['Alt text'],
48
+ title: props.intl.formatMessage(messages.AltText),
33
49
  },
34
50
  align: {
35
- title: props.intl.messages['Alignment'],
51
+ title: props.intl.formatMessage(messages.Alignment),
36
52
  widget: 'align',
37
53
  },
38
54
  height: {
@@ -45,7 +61,7 @@ export const MapsSchema = (props) => {
45
61
  {props.intl.formatMessage(messages.CSSHeight)}
46
62
  </a>
47
63
  ),
48
- description: props.intl.formatMessage(messages.CSSHeightDescription),
64
+ description: props.intl.formatMessage(messages.CSSMapHeightDescription),
49
65
  },
50
66
  },
51
67
  required: [],
@@ -1,7 +1,16 @@
1
+ import { uniqBy } from 'lodash';
1
2
  import installMaps from './Maps';
2
3
  import installEmbedMaps from './EmbedMaps';
3
4
 
4
5
  export default function installBlocks(config) {
6
+ config.blocks.groupBlocksOrder = uniqBy(
7
+ [
8
+ ...config.blocks.groupBlocksOrder,
9
+ { id: 'data_visualizations', title: 'Data Visualizations' },
10
+ ],
11
+ 'id',
12
+ );
13
+
5
14
  return [installMaps, installEmbedMaps].reduce(
6
15
  (acc, apply) => apply(acc),
7
16
  config,
@@ -1,4 +1,5 @@
1
1
  import React, { useEffect, useState, useRef } from 'react';
2
+ import { isNaN, isNumber } from 'lodash';
2
3
  import { compose } from 'redux';
3
4
  import { connect } from 'react-redux';
4
5
  import { defineMessages, injectIntl } from 'react-intl';
@@ -21,6 +22,14 @@ const messages = defineMessages({
21
22
  },
22
23
  });
23
24
 
25
+ function getHeight(height) {
26
+ const asNumber = isNumber(Number(height)) && !isNaN(Number(height));
27
+ if (asNumber) {
28
+ return `${height}px`;
29
+ }
30
+ return height;
31
+ }
32
+
24
33
  function EmbedMap({ data, intl, id, screen }) {
25
34
  const el = useRef();
26
35
  const [mobile, setMobile] = useState(false);
@@ -58,7 +67,7 @@ function EmbedMap({ data, intl, id, screen }) {
58
67
  <PrivacyProtection
59
68
  data={data}
60
69
  id={id}
61
- height={data.height}
70
+ height={getHeight(data.height)}
62
71
  useVisibilitySensor={data.useVisibilitySensor ?? true}
63
72
  >
64
73
  <iframe
@@ -67,7 +76,7 @@ function EmbedMap({ data, intl, id, screen }) {
67
76
  className="google-map"
68
77
  frameBorder="0"
69
78
  allowFullScreen
70
- style={data.height ? { height: data.height } : {}}
79
+ style={data.height ? { height: getHeight(data.height) } : {}}
71
80
  />
72
81
  </PrivacyProtection>
73
82
  </div>
@@ -80,6 +89,7 @@ function EmbedMap({ data, intl, id, screen }) {
80
89
  {data.with_more_info && <MoreInfo href={data['@id']} />}
81
90
  </div>
82
91
  <div className="right-col">
92
+ {data.with_share && <Share href={data['@id']} />}
83
93
  {data.with_enlarge && (
84
94
  <Enlarge className="enlarge-embed-maps">
85
95
  <EmbedMap
@@ -97,7 +107,6 @@ function EmbedMap({ data, intl, id, screen }) {
97
107
  />
98
108
  </Enlarge>
99
109
  )}
100
- {data.with_share && <Share href={data['@id']} />}
101
110
  </div>
102
111
  </div>
103
112
  </div>
@@ -1,20 +1,10 @@
1
1
  import React from 'react';
2
2
  import renderer from 'react-test-renderer';
3
- import configureStore from 'redux-mock-store';
4
3
  import { Provider } from 'react-intl-redux';
5
4
  import config from '@plone/volto/registry';
6
5
 
7
6
  import EmbedMap from './EmbedMap';
8
7
 
9
- const mockStore = configureStore();
10
-
11
- jest.mock('@plone/volto/components', () => ({
12
- __esModule: true,
13
- UniversalLink: ({ children, href }) => {
14
- return <a href={href}>{children}</a>;
15
- },
16
- }));
17
-
18
8
  config.blocks.blocksConfig = {
19
9
  ...config.blocks.blocksConfig,
20
10
  maps: {
@@ -34,18 +24,8 @@ config.blocks.blocksConfig = {
34
24
  };
35
25
 
36
26
  test('renders map component', () => {
37
- const store = mockStore({
38
- intl: {
39
- locale: 'en',
40
- messages: {},
41
- },
42
- content: {
43
- create: {},
44
- },
45
- connected_data_parameters: {},
46
- });
47
27
  const component = renderer.create(
48
- <Provider store={store}>
28
+ <Provider store={global.store}>
49
29
  <EmbedMap
50
30
  id="my-map"
51
31
  data={{
@@ -110,7 +110,8 @@ const PrivacyProtection = (props) => {
110
110
  state.router?.location?.pathname,
111
111
  );
112
112
  });
113
- const url = getFilteredURL(data.url, connected_data_parameters);
113
+ const mapUrl = data.url || data.vis_url;
114
+ const url = getFilteredURL(mapUrl, connected_data_parameters);
114
115
 
115
116
  const height = React.useMemo(() => {
116
117
  if (!props.height || enabled || !show) return 'auto';
@@ -187,7 +188,7 @@ const PrivacyProtection = (props) => {
187
188
  >
188
189
  {!enabled || show ? (
189
190
  children
190
- ) : !__DEVELOPMENT__ && !image ? (
191
+ ) : !__DEVELOPMENT__ && !image && !process.env.JEST_WORKER_ID ? (
191
192
  <Dimmer active>
192
193
  <Loader />
193
194
  </Dimmer>