@eeacms/volto-cca-policy 0.3.73 → 0.3.75

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.
Files changed (66) hide show
  1. package/.eslintrc.js +8 -4
  2. package/CHANGELOG.md +68 -2
  3. package/package.json +11 -10
  4. package/src/components/manage/Blocks/ASTNavigation/schema.js +3 -1
  5. package/src/components/manage/Blocks/C3SIndicatorsGlossaryBlock/schema.js +3 -1
  6. package/src/components/manage/Blocks/C3SIndicatorsListingBlock/schema.js +3 -1
  7. package/src/components/manage/Blocks/C3SIndicatorsOverviewBlock/schema.js +3 -1
  8. package/src/components/manage/Blocks/CaseStudyExplorer/FeatureDisplay.jsx +6 -1
  9. package/src/components/manage/Blocks/CaseStudyExplorer/styles.less +1 -1
  10. package/src/components/manage/Blocks/CollectionStatistics/styles.less +1 -1
  11. package/src/components/manage/Blocks/ContentLinks/schema.js +3 -1
  12. package/src/components/manage/Blocks/CountryMapHeatIndex/euro-countries-simplified.js +46197 -0
  13. package/src/components/manage/Blocks/CountryMapHeatIndex/styles.less +1 -1
  14. package/src/components/manage/Blocks/CountryMapObservatory/mapstyle.js +28 -26
  15. package/src/components/manage/Blocks/CountryMapObservatory/styles.less +1 -1
  16. package/src/components/manage/Blocks/CountryMapProfile/OLView.jsx +5 -5
  17. package/src/components/manage/Blocks/CountryMapProfile/euro-countries-simplified.js +46197 -0
  18. package/src/components/manage/Blocks/CountryMapProfile/styles.less +1 -1
  19. package/src/components/manage/Blocks/CountryProfileDetail/View.test.jsx +1 -2
  20. package/src/components/manage/Blocks/FlourishEmbedBlock/schema.js +3 -1
  21. package/src/components/manage/Blocks/RASTBlock/schema.js +3 -1
  22. package/src/components/manage/Blocks/ReadMore/schema.js +3 -1
  23. package/src/components/manage/Blocks/RelevantAceContent/schema.js +3 -1
  24. package/src/components/manage/Blocks/SearchAceContent/schema.js +3 -1
  25. package/src/components/manage/Blocks/TransRegionSelect/schema.js +3 -1
  26. package/src/components/manage/Blocks/index.js +0 -1
  27. package/src/components/theme/ASTNavigation/ASTNavigation.jsx +2 -3
  28. package/src/components/theme/BannerTitle/BannerTitle.jsx +2 -0
  29. package/src/components/theme/Header/Header.jsx +32 -22
  30. package/src/components/theme/Header/LanguageSwitch.jsx +2 -2
  31. package/src/components/theme/Views/BrokenLinks.jsx +0 -2
  32. package/src/components/theme/Views/CcaEventView.jsx +2 -4
  33. package/src/components/theme/Views/DatabaseItemView.test.jsx +1 -2
  34. package/src/components/theme/Widgets/GeolocationWidget.jsx +0 -2
  35. package/src/customizations/@plone/volto-slate/utils/volto-blocks.js +2 -5
  36. package/src/customizations/@plone/volto-slate/widgets/HtmlSlateWidget.jsx +30 -9
  37. package/src/customizations/@plone/volto-slate/widgets/README.md +15 -1
  38. package/src/customizations/volto/components/manage/Blocks/Grid/grid-1.svg +6 -0
  39. package/src/customizations/volto/components/manage/Blocks/Grid/grid-2.svg +9 -0
  40. package/src/customizations/volto/components/manage/Blocks/Grid/grid-3.svg +10 -0
  41. package/src/customizations/volto/components/manage/Blocks/Grid/grid-4.svg +11 -0
  42. package/src/customizations/volto/components/manage/Blocks/Grid/grid-5.svg +13 -0
  43. package/src/customizations/volto/components/manage/Blocks/Grid/grid-6.svg +14 -0
  44. package/src/customizations/volto/components/manage/Blocks/Grid/templates.js +61 -0
  45. package/src/customizations/volto/components/theme/App/App.jsx +3 -1
  46. package/src/customizations/volto/helpers/Html/Html.jsx +2 -9
  47. package/src/customizations/volto/middleware/api.js +190 -186
  48. package/src/customizations/volto/server.jsx +1 -1
  49. package/src/express-middleware.js +4 -2
  50. package/src/helpers/Utils.jsx +15 -2
  51. package/src/helpers/country_map/euro-countries-simplified.js +3 -1
  52. package/src/index.js +2 -8
  53. package/src/search/cca/views.js +3 -1
  54. package/src/search/health_observatory/views-health.js +3 -1
  55. package/src/store/middleware.js +38 -37
  56. package/theme/globals/blocks.less +4 -0
  57. package/theme/globals/mission.less +2 -9
  58. package/theme/globals/observatory.less +2 -2
  59. package/theme/globals/views.less +25 -0
  60. package/src/components/theme/Views/brokenlinks.less +0 -21
  61. package/src/components/theme/Widgets/geolocation.css +0 -3
  62. package/src/customizations/volto/components/manage/UniversalLink/UniversalLink.test.jsx +0 -229
  63. package/src/customizations/volto/components/manage/Widgets/ArrayWidget.jsx +0 -428
  64. package/src/customizations/volto/components/manage/Widgets/Readme.md +0 -5
  65. package/src/customizations/volto/components/theme/Footer/Footer.jsx +0 -96
  66. package/src/policy.js +0 -135
@@ -36,8 +36,8 @@
36
36
  z-index: 10;
37
37
  display: none;
38
38
  padding: 3px;
39
- background-color: #2a2a2a;
40
39
  border-radius: 3px;
40
+ background-color: #2a2a2a;
41
41
  color: white;
42
42
  font-size: 10px;
43
43
  }
@@ -13,8 +13,7 @@ describe('View', () => {
13
13
  const properties = {
14
14
  '@components': {
15
15
  countryprofile: {
16
- html:
17
- '{"menu":[],"content":[],"html":"","updated":"","message_top":"", "top_accordeon":""}',
16
+ html: '{"menu":[],"content":[],"html":"","updated":"","message_top":"", "top_accordeon":""}',
18
17
  },
19
18
  },
20
19
  };
@@ -1,4 +1,4 @@
1
- export default {
1
+ const schema = {
2
2
  title: 'Flourish visualization block',
3
3
  fieldsets: [
4
4
  {
@@ -15,3 +15,5 @@ export default {
15
15
  },
16
16
  required: [],
17
17
  };
18
+
19
+ export default schema;
@@ -1,6 +1,6 @@
1
1
  const fields = ['root_path', 'skip_items', 'show_subfolders'];
2
2
 
3
- export default {
3
+ const schema = {
4
4
  title: 'RAST',
5
5
 
6
6
  fieldsets: [
@@ -37,3 +37,5 @@ export default {
37
37
 
38
38
  required: [],
39
39
  };
40
+
41
+ export default schema;
@@ -1,4 +1,4 @@
1
- export default {
1
+ const schema = {
2
2
  title: 'Read more',
3
3
  fieldsets: [
4
4
  {
@@ -40,3 +40,5 @@ export default {
40
40
  },
41
41
  required: [],
42
42
  };
43
+
44
+ export default schema;
@@ -23,7 +23,7 @@ const Item = () => ({
23
23
  required: ['title'],
24
24
  });
25
25
 
26
- export default {
26
+ const schema = {
27
27
  title: 'Relevant Ace Content',
28
28
  fieldsets: [
29
29
  {
@@ -153,3 +153,5 @@ export default {
153
153
  },
154
154
  required: [],
155
155
  };
156
+
157
+ export default schema;
@@ -1,4 +1,4 @@
1
- export default {
1
+ const schema = {
2
2
  title: 'Search Ace Content',
3
3
  fieldsets: [
4
4
  {
@@ -98,3 +98,5 @@ export default {
98
98
  },
99
99
  required: [],
100
100
  };
101
+
102
+ export default schema;
@@ -1,4 +1,4 @@
1
- export default {
1
+ const schema = {
2
2
  title: 'Trans Region Select',
3
3
  fieldsets: [
4
4
  {
@@ -20,3 +20,5 @@ export default {
20
20
  },
21
21
  required: [],
22
22
  };
23
+
24
+ export default schema;
@@ -22,7 +22,6 @@ import installASTNavigation from './ASTNavigation';
22
22
  import installFlourishEmbedBlock from './FlourishEmbedBlock';
23
23
  import installDataConnectedEmbed from './DataConnectedEmbedBlock';
24
24
 
25
- // import installMKHMap from './MKHMap';
26
25
  // import installCountryMapHeatIndex from './CountryMapHeatIndex';
27
26
  import installCountryMapProfile from './CountryMapProfile';
28
27
 
@@ -18,9 +18,8 @@ const ASTNavigation = (props) => {
18
18
  const searchSubrequests = useSelector((state) => state.search.subrequests);
19
19
  const items = searchSubrequests?.ast?.items || [];
20
20
  const isAdaptationSupportTool = isAdaptationSupportToolURL(rootPath);
21
- const isUrbanAdaptationSupportTool = isUrbanAdaptationSupportToolURL(
22
- rootPath,
23
- );
21
+ const isUrbanAdaptationSupportTool =
22
+ isUrbanAdaptationSupportToolURL(rootPath);
24
23
 
25
24
  React.useEffect(() => {
26
25
  if (isAdaptationSupportTool) {
@@ -29,6 +29,7 @@ const BannerTitle = (props) => {
29
29
  <TitleBlockView
30
30
  {...props}
31
31
  data={{
32
+ '@type': 'title',
32
33
  info: [{ description: '' }],
33
34
  hideContentType: false,
34
35
  hideCreationDate: false,
@@ -38,6 +39,7 @@ const BannerTitle = (props) => {
38
39
  hideShareButton: false,
39
40
  }}
40
41
  metadata={content}
42
+ properties={content}
41
43
  />
42
44
  </>
43
45
  ) : null}
@@ -4,10 +4,10 @@
4
4
  */
5
5
 
6
6
  import React from 'react';
7
- import { compose } from 'recompose';
8
- import { withRouter } from 'react-router-dom';
9
7
  import { Dropdown, Image } from 'semantic-ui-react';
10
8
  import { connect, useDispatch, useSelector } from 'react-redux';
9
+
10
+ import { withRouter } from 'react-router-dom';
11
11
  import { UniversalLink } from '@plone/volto/components';
12
12
  import {
13
13
  getBaseUrl,
@@ -16,14 +16,18 @@ import {
16
16
  toPublicURL,
17
17
  BodyClass,
18
18
  } from '@plone/volto/helpers';
19
- import config from '@plone/volto/registry';
20
19
  import { getNavigation } from '@plone/volto/actions';
21
20
  import { Header, Logo } from '@eeacms/volto-eea-design-system/ui';
22
21
  import { usePrevious } from '@eeacms/volto-eea-design-system/helpers';
23
- import LanguageSwitch from './LanguageSwitch';
22
+ import eeaFlag from '@eeacms/volto-eea-design-system/../theme/themes/eea/assets/images/Header/eea.png';
23
+
24
+ import config from '@plone/volto/registry';
25
+ import { compose } from 'recompose';
26
+
24
27
  import cx from 'classnames';
28
+ import loadable from '@loadable/component';
25
29
 
26
- import eeaFlag from '@eeacms/volto-eea-design-system/../theme/themes/eea/assets/images/Header/eea.png';
30
+ const LazyLanguageSwitcher = loadable(() => import('./LanguageSwitch'));
27
31
 
28
32
  function removeTrailingSlash(path) {
29
33
  while (path.endsWith('/')) {
@@ -63,8 +67,7 @@ const DirectLinkLogo = ({
63
67
  /**
64
68
  * EEA Specific Header component.
65
69
  */
66
- const EEAHeader = (props) => {
67
- const { pathname, token, items, subsite } = props;
70
+ const EEAHeader = ({ pathname, token, items, history, subsite }) => {
68
71
  const router_pathname = useSelector((state) => {
69
72
  return removeTrailingSlash(state.router?.location?.pathname) || '';
70
73
  });
@@ -76,10 +79,12 @@ const EEAHeader = (props) => {
76
79
  const has_home_layout =
77
80
  layout === 'homepage_inverse_view' ||
78
81
  (__CLIENT__ && document.body.classList.contains('homepage-inverse'));
82
+
79
83
  return (
80
84
  has_home_layout &&
81
85
  (removeTrailingSlash(pathname) === router_pathname ||
82
- router_pathname.endsWith('/edit'))
86
+ router_pathname.endsWith('/edit') ||
87
+ router_pathname.endsWith('/add'))
83
88
  );
84
89
  });
85
90
 
@@ -95,20 +100,17 @@ const EEAHeader = (props) => {
95
100
  React.useEffect(() => {
96
101
  const { settings } = config;
97
102
  const base_url = getBaseUrl(pathname);
103
+
104
+ // Check if navigation data needs to be fetched based on the API expander availability
98
105
  if (!hasApiExpander('navigation', base_url)) {
99
106
  dispatch(getNavigation(base_url, settings.navDepth));
100
107
  }
101
- }, [pathname, dispatch]);
102
108
 
103
- React.useEffect(() => {
109
+ // Additional check for token changes
104
110
  if (token !== previousToken) {
105
- const { settings } = config;
106
- const base = getBaseUrl(pathname);
107
- if (!hasApiExpander('navigation', base)) {
108
- dispatch(getNavigation(base, settings.navDepth));
109
- }
111
+ dispatch(getNavigation(base_url, settings.navDepth));
110
112
  }
111
- }, [token, dispatch, pathname, previousToken]);
113
+ }, [pathname, token, dispatch, previousToken]);
112
114
 
113
115
  const subsiteView = subsiteHeaderOpts.filter((v) =>
114
116
  router_pathname.match(v.matchpath),
@@ -125,21 +127,22 @@ const EEAHeader = (props) => {
125
127
  {isHomePageInverse && <BodyClass className="homepage" />}
126
128
  <Header.TopHeader>
127
129
  <Header.TopItem className="official-union">
128
- <Image src={eeaFlag} alt="eea flag"></Image>
130
+ <Image src={eeaFlag} alt="European Union flag"></Image>
129
131
  <Header.TopDropdownMenu
130
132
  text="An official website of the European Union | How do you know?"
131
133
  tabletText="EEA information systems"
132
- mobileText=" "
134
+ mobileText="EEA information systems"
133
135
  icon="chevron down"
134
136
  aria-label="dropdown"
135
- className=""
137
+ classNameHeader="mobile-sr-only"
136
138
  viewportWidth={width}
137
139
  >
138
- {/* eslint-disable-next-line jsx-a11y/no-static-element-interactions */}
139
140
  <div
140
141
  className="content"
141
142
  onClick={(evt) => evt.stopPropagation()}
142
143
  onKeyDown={(evt) => evt.stopPropagation()}
144
+ tabIndex={0}
145
+ role={'presentation'}
143
146
  >
144
147
  <p>
145
148
  All official European Union website addresses are in the{' '}
@@ -148,6 +151,7 @@ const EEAHeader = (props) => {
148
151
  <a
149
152
  href="https://europa.eu/european-union/contact/institutions-bodies_en"
150
153
  target="_blank"
154
+ rel="noopener"
151
155
  onKeyDown={(evt) => evt.stopPropagation()}
152
156
  >
153
157
  See all EU institutions and bodies
@@ -162,15 +166,17 @@ const EEAHeader = (props) => {
162
166
  <Header.TopDropdownMenu
163
167
  id="theme-sites"
164
168
  text={headerOpts.partnerLinks.title}
169
+ aria-label={headerOpts.partnerLinks.title}
165
170
  viewportWidth={width}
166
171
  >
167
- <div className="wrapper">
172
+ <div className="wrapper" tabIndex={0} role={'presentation'}>
168
173
  {headerOpts.partnerLinks.links.map((item, index) => (
169
174
  <Dropdown.Item key={index}>
170
175
  <a
171
176
  href={item.href}
172
177
  className="site"
173
178
  target="_blank"
179
+ rel="noopener"
174
180
  onKeyDown={(evt) => evt.stopPropagation()}
175
181
  >
176
182
  {item.title}
@@ -182,7 +188,11 @@ const EEAHeader = (props) => {
182
188
  </Header.TopItem>
183
189
  )}
184
190
 
185
- {config.settings.isMultilingual && <LanguageSwitch {...props} />}
191
+ {config.settings.isMultilingual &&
192
+ config.settings.supportedLanguages.length > 1 &&
193
+ config.settings.hasLanguageDropdown && (
194
+ <LazyLanguageSwitcher width={width} history={history} />
195
+ )}
186
196
  </div>
187
197
  </Header.TopHeader>
188
198
  <Header.Main
@@ -2,12 +2,12 @@ import React from 'react';
2
2
  import { find } from 'lodash';
3
3
  import { useAtom } from 'jotai';
4
4
  import { useSelector } from 'react-redux';
5
+ import { FormattedMessage } from 'react-intl';
5
6
  import { Dropdown, Image } from 'semantic-ui-react';
6
7
  import { flattenToAppURL } from '@plone/volto/helpers';
7
- import config from '@plone/volto/registry';
8
8
  import { Header } from '@eeacms/volto-eea-design-system/ui';
9
+ import config from '@plone/volto/registry';
9
10
  import cx from 'classnames';
10
- import { FormattedMessage } from 'react-intl';
11
11
 
12
12
  import globeIcon from '@eeacms/volto-eea-design-system/../theme/themes/eea/assets/images/Header/global-line.svg';
13
13
 
@@ -11,8 +11,6 @@ import {
11
11
  TableRow,
12
12
  } from 'semantic-ui-react';
13
13
 
14
- import './brokenlinks.less';
15
-
16
14
  function Filter({ column }) {
17
15
  const columnFilterValue = column.getFilterValue();
18
16
  const { filterVariant } = column.columnDef.meta ?? {};
@@ -47,10 +47,8 @@ function CcaEventView(props) {
47
47
  contact_email,
48
48
  } = content;
49
49
 
50
- const {
51
- blocks: filteredBlocks,
52
- blocks_layout: filteredBlocksLayout,
53
- } = filterBlocks(content, ['tabs_block', 'metadataSection']);
50
+ const { blocks: filteredBlocks, blocks_layout: filteredBlocksLayout } =
51
+ filterBlocks(content, ['tabs_block', 'metadataSection']);
54
52
 
55
53
  const titleBlock = Object.values(filteredBlocks).find(
56
54
  (block) => block['@type'] === 'title',
@@ -33,8 +33,7 @@ describe('DatabaseItemView', () => {
33
33
  title: 'My DatabaseItemView',
34
34
  long_description: {
35
35
  'content-type': null,
36
- data:
37
- '<p>Nam commodo suscipit quam. Praesent egestas neque eu enim. Quisque rutrum.</p>',
36
+ data: '<p>Nam commodo suscipit quam. Praesent egestas neque eu enim. Quisque rutrum.</p>',
38
37
  encoding: 'utf-8',
39
38
  },
40
39
  publication_date: '2022-06-24',
@@ -7,8 +7,6 @@ import { injectIntl } from 'react-intl';
7
7
  import { FormFieldWrapper } from '@plone/volto/components';
8
8
  import MapContainer from './GeolocationWidgetMapContainer';
9
9
 
10
- import './geolocation.css';
11
-
12
10
  const defaultValue = {
13
11
  latitude: 55.6761,
14
12
  longitude: 12.5683,
@@ -249,11 +249,8 @@ export function deconstructToVoltoBlocks(editor) {
249
249
  return new Promise((resolve, reject) => {
250
250
  if (!editor?.children) return;
251
251
 
252
- const {
253
- properties,
254
- onChangeFormData,
255
- onSelectBlock,
256
- } = editor.getBlockProps();
252
+ const { properties, onChangeFormData, onSelectBlock } =
253
+ editor.getBlockProps();
257
254
  const blocksFieldname = getBlocksFieldname(properties);
258
255
  const blocksLayoutFieldname = getBlocksLayoutFieldname(properties);
259
256
 
@@ -3,6 +3,7 @@
3
3
  */
4
4
 
5
5
  import React from 'react';
6
+ import { debounce } from 'lodash';
6
7
  import ReactDOMServer from 'react-dom/server';
7
8
  import configureStore from 'redux-mock-store';
8
9
  import { MemoryRouter } from 'react-router-dom';
@@ -14,7 +15,6 @@ import SlateEditor from '@plone/volto-slate/editor/SlateEditor';
14
15
  import { serializeNodes } from '@plone/volto-slate/editor/render';
15
16
  import { makeEditor } from '@plone/volto-slate/utils';
16
17
  import deserialize from '@plone/volto-slate/editor/deserialize';
17
-
18
18
  import {
19
19
  createEmptyParagraph,
20
20
  normalizeExternalData,
@@ -25,8 +25,7 @@ import '@plone/volto-slate/widgets/style.css';
25
25
 
26
26
  const messages = defineMessages({
27
27
  error: {
28
- id:
29
- 'An error has occurred while editing "{name}" field. We have been notified and we are looking into it. Please save your work and retry. If the issue persists please contact the site administrator.',
28
+ id: 'An error has occurred while editing "{name}" field. We have been notified and we are looking into it. Please save your work and retry. If the issue persists please contact the site administrator.',
30
29
  defaultMessage:
31
30
  'An error has occurred while editing "{name}" field. We have been notified and we are looking into it. Please save your work and retry. If the issue persists please contact the site administrator.',
32
31
  },
@@ -59,8 +58,6 @@ const HtmlSlateWidget = (props) => {
59
58
  <MemoryRouter>{serializeNodes(value || [])}</MemoryRouter>
60
59
  </Provider>,
61
60
  );
62
- // console.log('toHtml value', JSON.stringify(value));
63
- // console.log('toHtml html', html);
64
61
 
65
62
  return {
66
63
  'content-type': value ? value['content-type'] : 'text/html',
@@ -93,6 +90,7 @@ const HtmlSlateWidget = (props) => {
93
90
  parent.removeChild(div);
94
91
  });
95
92
  };
93
+
96
94
  const fromHtml = React.useCallback(
97
95
  (value) => {
98
96
  const html = value?.data || '';
@@ -122,15 +120,38 @@ const HtmlSlateWidget = (props) => {
122
120
  [editor],
123
121
  );
124
122
 
125
- const valueFromHtml = React.useMemo(() => {
126
- return fromHtml(value);
123
+ const lastSavedHtmlRef = React.useRef(value?.data);
124
+
125
+ const [valueFromHtml, setValueFromHtml] = React.useState(() =>
126
+ fromHtml(value),
127
+ );
128
+
129
+ React.useEffect(() => {
130
+ if (value?.data !== lastSavedHtmlRef.current) {
131
+ setValueFromHtml(fromHtml(value));
132
+ }
127
133
  }, [value, fromHtml]);
128
134
 
135
+ const debouncedOnChange = React.useMemo(() => {
136
+ return debounce((newSlateValue) => {
137
+ const htmlValue = toHtml(newSlateValue);
138
+ lastSavedHtmlRef.current = htmlValue.data;
139
+ onChange(id, htmlValue);
140
+ }, 100);
141
+ }, [id, onChange, toHtml]);
142
+
143
+ React.useEffect(() => {
144
+ return () => {
145
+ debouncedOnChange.cancel();
146
+ };
147
+ }, [debouncedOnChange]);
148
+
129
149
  const handleChange = React.useCallback(
130
150
  (newValue) => {
131
- onChange(id, toHtml(newValue));
151
+ setValueFromHtml(newValue);
152
+ debouncedOnChange(newValue);
132
153
  },
133
- [onChange, toHtml, id],
154
+ [debouncedOnChange],
134
155
  );
135
156
 
136
157
  const handleClick = React.useCallback(() => {
@@ -16,4 +16,18 @@ and this:
16
16
  let data = deserialize(editor, body, { collapseWhitespace: true });
17
17
  ```
18
18
 
19
- Also added `unwrapDivs()` to unwrap `<div>` elements and wrap loose text nodes in `<p>` before deserialization. This fixes issues where content inside `<div>` tags was not recognized by the Slate editor and appeared empty or uneditable in edit mode.
19
+ Fix missing content inside `<div>` tag:
20
+
21
+ Added `unwrapDivs()` to unwrap `<div>` elements and wrap loose text nodes in `<p>` before deserialization. This fixes issues where content inside `<div>` tags was not recognized by the Slate editor and appeared empty or uneditable in edit mode.
22
+
23
+ Preserve trailing spaces:
24
+
25
+ Fixes issue where typing a space at the end of a line wouldn’t persist due to `collapseWhitespace: true` during deserialization.
26
+
27
+ ```js
28
+ const [valueFromHtml, setValueFromHtml] = React.useState(() =>
29
+ fromHtml(value),
30
+ );
31
+
32
+ const debouncedOnChange = useMemo(() => debounce(...), [...]);
33
+ ```
@@ -0,0 +1,6 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="96" height="96" viewBox="0 0 96 96">
2
+ <g fill="none" fill-rule="evenodd">
3
+ <rect width="96" height="96" fill="#9FD1E5" rx="3"/>
4
+ <rect width="67" height="53" fill="#FFF" opacity=".9" transform="translate(15 22)"/>
5
+ </g>
6
+ </svg>
@@ -0,0 +1,9 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="96" height="96" viewBox="0 0 96 96">
2
+ <g fill="none" fill-rule="evenodd">
3
+ <rect width="96" height="96" fill="#9FD1E5" rx="3"/>
4
+ <g fill="#FFF" opacity=".9" transform="translate(9 22)">
5
+ <rect width="37" height="53"/>
6
+ <rect width="37" height="53" x="42"/>
7
+ </g>
8
+ </g>
9
+ </svg>
@@ -0,0 +1,10 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="96" height="96" viewBox="0 0 96 96">
2
+ <g fill="none" fill-rule="evenodd">
3
+ <rect width="96" height="96" fill="#9FD1E5" rx="3"/>
4
+ <g fill="#FFF" opacity=".9" transform="translate(6 22)">
5
+ <rect width="25" height="53" x="58"/>
6
+ <rect width="25" height="53"/>
7
+ <rect width="25" height="53" x="29"/>
8
+ </g>
9
+ </g>
10
+ </svg>
@@ -0,0 +1,11 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="96" height="96" viewBox="0 0 96 96">
2
+ <g fill="none" fill-rule="evenodd">
3
+ <rect width="96" height="96" fill="#9FD1E5" rx="3"/>
4
+ <g fill="#FFF" opacity=".9" transform="translate(8 22)">
5
+ <rect width="18" height="53" x="42"/>
6
+ <rect width="18" height="53" x="63"/>
7
+ <rect width="18" height="53"/>
8
+ <rect width="18" height="53" x="21"/>
9
+ </g>
10
+ </g>
11
+ </svg>
@@ -0,0 +1,13 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <svg width="96" height="96" version="1.1" viewBox="0 0 96 96" xmlns="http://www.w3.org/2000/svg">
3
+ <g fill-rule="evenodd">
4
+ <rect width="96" height="96" rx="3" fill="#9FD1E5"/>
5
+ <g transform="matrix(.80193 0 0 1 24.044 22)" fill="#fff" opacity=".9">
6
+ <rect x="42" width="18" height="53"/>
7
+ <rect x="63" width="18" height="53"/>
8
+ <rect width="18" height="53"/>
9
+ <rect x="21" width="18" height="53"/>
10
+ <rect x="-21.024" width="18" height="53"/>
11
+ </g>
12
+ </g>
13
+ </svg>
@@ -0,0 +1,14 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <svg width="96" height="96" version="1.1" viewBox="0 0 96 96" xmlns="http://www.w3.org/2000/svg">
3
+ <g fill-rule="evenodd">
4
+ <rect width="96" height="96" rx="3" fill="#9FD1E5"/>
5
+ <g transform="matrix(.66542 0 0 1 35.101 22)" fill="#fff" opacity=".9">
6
+ <rect x="42" width="18" height="53"/>
7
+ <rect x="63" width="18" height="53"/>
8
+ <rect width="18" height="53"/>
9
+ <rect x="21" width="18" height="53"/>
10
+ <rect x="-21.024" width="18" height="53"/>
11
+ <rect x="-42.165" width="18" height="53"/>
12
+ </g>
13
+ </g>
14
+ </svg>
@@ -0,0 +1,61 @@
1
+ import { defineMessages } from 'react-intl';
2
+ import { blocksFormGenerator } from '@plone/volto/helpers';
3
+
4
+ import gridTemplate1 from './grid-1.svg';
5
+ import gridTemplate2 from './grid-2.svg';
6
+ import gridTemplate3 from './grid-3.svg';
7
+ import gridTemplate4 from './grid-4.svg';
8
+ import gridTemplate5 from './grid-5.svg';
9
+ import gridTemplate6 from './grid-6.svg';
10
+
11
+ const messages = defineMessages({
12
+ column: {
13
+ id: 'column',
14
+ defaultMessage: 'column',
15
+ },
16
+ columns: {
17
+ id: 'columns',
18
+ defaultMessage: 'columns',
19
+ },
20
+ });
21
+
22
+ const templates = (type) => (intl) => [
23
+ {
24
+ image: gridTemplate1,
25
+ id: 'gridtemplateone',
26
+ title: `1 ${intl.formatMessage(messages.column)}`,
27
+ blocksData: blocksFormGenerator(1, type),
28
+ },
29
+ {
30
+ image: gridTemplate2,
31
+ id: 'gridtemplatetwo',
32
+ title: `2 ${intl.formatMessage(messages.columns)}`,
33
+ blocksData: blocksFormGenerator(2, type),
34
+ },
35
+ {
36
+ image: gridTemplate3,
37
+ id: 'gridtemplatethree',
38
+ title: `3 ${intl.formatMessage(messages.columns)}`,
39
+ blocksData: blocksFormGenerator(3, type),
40
+ },
41
+ {
42
+ image: gridTemplate4,
43
+ id: 'gridtemplatefour',
44
+ title: `4 ${intl.formatMessage(messages.columns)}`,
45
+ blocksData: blocksFormGenerator(4, type),
46
+ },
47
+ {
48
+ image: gridTemplate5,
49
+ id: 'gridtemplatefive',
50
+ title: `5 ${intl.formatMessage(messages.columns)}`,
51
+ blocksData: blocksFormGenerator(5, type),
52
+ },
53
+ {
54
+ image: gridTemplate6,
55
+ id: 'gridtemplatesix',
56
+ title: `6 ${intl.formatMessage(messages.columns)}`,
57
+ blocksData: blocksFormGenerator(6, type),
58
+ },
59
+ ];
60
+
61
+ export default templates;
@@ -238,7 +238,9 @@ export const fetchContent = async ({ store, location }) => {
238
238
 
239
239
  const visitor = ([id, data]) => {
240
240
  const blockType = data['@type'];
241
- const { getAsyncData } = blocksConfig[blockType];
241
+ const block = blocksConfig[blockType];
242
+ if (!block) return;
243
+ const { getAsyncData } = block;
242
244
  if (getAsyncData) {
243
245
  const p = getAsyncData({
244
246
  store,
@@ -88,15 +88,8 @@ class Html extends Component {
88
88
  * @returns {string} Markup for the component.
89
89
  */
90
90
  render() {
91
- const {
92
- extractor,
93
- markup,
94
- store,
95
- criticalCss,
96
- apiPath,
97
- publicURL,
98
- nonce,
99
- } = this.props;
91
+ const { extractor, markup, store, criticalCss, apiPath, publicURL, nonce } =
92
+ this.props;
100
93
  const head = Helmet.rewind();
101
94
  const bodyClass = join(BodyClass.rewind(), ' ');
102
95
  const htmlAttributes = head.htmlAttributes.toComponent();