@eeacms/volto-eea-website-theme 1.7.0 → 1.8.1

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/CHANGELOG.md CHANGED
@@ -4,7 +4,39 @@ All notable changes to this project will be documented in this file. Dates are d
4
4
 
5
5
  Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
6
6
 
7
- ### [1.7.0](https://github.com/eea/volto-eea-website-theme/compare/1.6.4...1.7.0) - 7 February 2023
7
+ ### [1.8.1](https://github.com/eea/volto-eea-website-theme/compare/1.8.0...1.8.1) - 9 February 2023
8
+
9
+ #### :rocket: New Features
10
+
11
+ - feat(NotFound): wrap withRootNavigation in NotFound to have menu in 404 [nileshgulia1 - [`9f66a69`](https://github.com/eea/volto-eea-website-theme/commit/9f66a69b005f1a3d5446c67a1649c895f8c87d87)]
12
+ - feat(search): Make random suggestions to show [kreafox - [`e62041e`](https://github.com/eea/volto-eea-website-theme/commit/e62041ead4895e9c4d85dc2c93895607c71b2f1a)]
13
+ - feat(search): Max 6 suggestions [kreafox - [`99ffc75`](https://github.com/eea/volto-eea-website-theme/commit/99ffc754fddad95f44893f30ac3bfc76aacadb43)]
14
+
15
+ #### :bug: Bug Fixes
16
+
17
+ - fix(search): Fix undefined value [kreafox - [`51d49c2`](https://github.com/eea/volto-eea-website-theme/commit/51d49c2786ce97f7886e3d03d328a3858182b23a)]
18
+
19
+ #### :hammer_and_wrench: Others
20
+
21
+ - do not customize 404 [nileshgulia1 - [`446c1cd`](https://github.com/eea/volto-eea-website-theme/commit/446c1cdd121dd80a9e1efac2ee897b050eb99215)]
22
+ - test(lint): Fix lint [Alin Voinea - [`57722a3`](https://github.com/eea/volto-eea-website-theme/commit/57722a3477295cde2735d8a366c46e4105a9f9a3)]
23
+ - Update config.js [Tiberiu Ichim - [`a1685b8`](https://github.com/eea/volto-eea-website-theme/commit/a1685b85ea0badec5dca8655c2ea7e6d11afbece)]
24
+ - Updated search header configuration [Tiberiu Ichim - [`8e3d9e9`](https://github.com/eea/volto-eea-website-theme/commit/8e3d9e9339919351ac8bb9fffde12744432ce313)]
25
+ ### [1.8.0](https://github.com/eea/volto-eea-website-theme/compare/1.7.0...1.8.0) - 8 February 2023
26
+
27
+ #### :rocket: New Features
28
+
29
+ - feat(align): Move text align to slate buttons - refs 160747 [Alin Voinea - [`24d8fe5`](https://github.com/eea/volto-eea-website-theme/commit/24d8fe5a74afc2b61dc622b368d3fe5b8b422390)]
30
+
31
+ #### :nail_care: Enhancements
32
+
33
+ - change(object-browser): Popup is hoverable in object browser nav #99 from eea/object_browser_nav_popup_hoverable [ichim-david - [`205c2c4`](https://github.com/eea/volto-eea-website-theme/commit/205c2c48803ce5814f71aea932038bf72272459e)]
34
+
35
+ #### :hammer_and_wrench: Others
36
+
37
+ - Release 1.8.0 [Alin Voinea - [`f15437f`](https://github.com/eea/volto-eea-website-theme/commit/f15437f9c9fd978431d3af48410d3ab9746be9fb)]
38
+ - Popup is hoverable in object browser nav [andreiggr - [`a944bff`](https://github.com/eea/volto-eea-website-theme/commit/a944bff8026b40c481bec474f2b509dc5c8b044a)]
39
+ ### [1.7.0](https://github.com/eea/volto-eea-website-theme/compare/1.6.4...1.7.0) - 8 February 2023
8
40
 
9
41
  #### :rocket: New Features
10
42
 
@@ -25,7 +57,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
25
57
 
26
58
  #### :hammer_and_wrench: Others
27
59
 
28
- - Release 1.7.0 [Alin Voinea - [`065c0d0`](https://github.com/eea/volto-eea-website-theme/commit/065c0d05cb43458463e3ca293bd51b32d2e89f34)]
29
60
  - Use scale for img in obj browser and preview in popup [andreiggr - [`e78e21d`](https://github.com/eea/volto-eea-website-theme/commit/e78e21d0b35d69242833914ff41455f24d31927b)]
30
61
  ### [1.6.4](https://github.com/eea/volto-eea-website-theme/compare/1.6.3...1.6.4) - 31 January 2023
31
62
 
@@ -73,6 +104,7 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
73
104
 
74
105
  - For some reasons types is a string [Alin Voinea - [`3769a09`](https://github.com/eea/volto-eea-website-theme/commit/3769a0981181d5b633f3498daebbe96be8b4b833)]
75
106
  - Fix(redirect): o.filter - refs #157627 [Alin Voinea - [`deb23da`](https://github.com/eea/volto-eea-website-theme/commit/deb23da846444cc96539697fd798429ae0abe89e)]
107
+ - Add Sonarqube tag using advisory-board-frontend addons list [EEA Jenkins - [`f1fffc5`](https://github.com/eea/volto-eea-website-theme/commit/f1fffc5db96725440863d545580b4e76cce4b796)]
76
108
  ### [1.5.0](https://github.com/eea/volto-eea-website-theme/compare/1.4.2...1.5.0) - 9 January 2023
77
109
 
78
110
  #### :hammer_and_wrench: Others
@@ -106,6 +138,7 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
106
138
 
107
139
  - Release 1.4.0 [Alin Voinea - [`bd42a0d`](https://github.com/eea/volto-eea-website-theme/commit/bd42a0d26e928cac5d99933194755da3db06b341)]
108
140
  - bump version to use as volto-eea-design-system [David Ichim - [`f4be047`](https://github.com/eea/volto-eea-website-theme/commit/f4be047328b46399b03b612d378b18aaf82e7dc1)]
141
+ - Add Sonarqube tag using advisory-board-frontend addons list [EEA Jenkins - [`9b7cfef`](https://github.com/eea/volto-eea-website-theme/commit/9b7cfefb4d34fc1c948015e491feb370f9795bd8)]
109
142
  - test(Jenkins): Run tests and cypress with latest canary @plone/volto [Alin Voinea - [`df252a9`](https://github.com/eea/volto-eea-website-theme/commit/df252a9bfed0bb86cadf53c59dd1603b1e2cd822)]
110
143
  ### [1.3.2](https://github.com/eea/volto-eea-website-theme/compare/1.3.1...1.3.2) - 16 December 2022
111
144
 
@@ -115,6 +148,7 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
115
148
 
116
149
  #### :hammer_and_wrench: Others
117
150
 
151
+ - Add Sonarqube tag using cca-frontend addons list [EEA Jenkins - [`a43c658`](https://github.com/eea/volto-eea-website-theme/commit/a43c658a7920c8df95e763b9a637f38ce77eba2c)]
118
152
  - Better razzle.config [Tiberiu Ichim - [`81dbf48`](https://github.com/eea/volto-eea-website-theme/commit/81dbf48815fb27facb4f82c9b764540fdf188b2e)]
119
153
  - Better razzle.config [Tiberiu Ichim - [`7bc9da2`](https://github.com/eea/volto-eea-website-theme/commit/7bc9da2cd837ab62a95cd29979cdd9b0055b7d67)]
120
154
  ### [1.3.1](https://github.com/eea/volto-eea-website-theme/compare/1.3.0...1.3.1) - 28 November 2022
@@ -123,6 +157,9 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
123
157
 
124
158
  - feat(Footer): Bring back footer contacts extra actions - refs #151856 [Alin Voinea - [`6c19413`](https://github.com/eea/volto-eea-website-theme/commit/6c194139420c9fd847692d180db1c1593e2483de)]
125
159
 
160
+ #### :hammer_and_wrench: Others
161
+
162
+ - yarn 3 [Alin Voinea - [`ea7a709`](https://github.com/eea/volto-eea-website-theme/commit/ea7a7094945312776e9b6f44e371178603e92139)]
126
163
  ### [1.3.0](https://github.com/eea/volto-eea-website-theme/compare/1.2.0...1.3.0) - 22 November 2022
127
164
 
128
165
  #### :rocket: New Features
@@ -163,6 +200,7 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
163
200
  - Add subsite class to body [Tiberiu Ichim - [`74d700f`](https://github.com/eea/volto-eea-website-theme/commit/74d700fbfd6249a8604762a7e4e49cce857db0f3)]
164
201
  - Add subsite info to header [Tiberiu Ichim - [`47daf8b`](https://github.com/eea/volto-eea-website-theme/commit/47daf8bb6374a1222040626b19d4154df7ba1b83)]
165
202
  - fix eslint [Miu Razvan - [`eb8d0a7`](https://github.com/eea/volto-eea-website-theme/commit/eb8d0a790bc70c0aae256c6ff35f63c4885f338e)]
203
+ - Add Sonarqube tag using circularity-frontend addons list [EEA Jenkins - [`cc578a4`](https://github.com/eea/volto-eea-website-theme/commit/cc578a413b205a8e61e091fab3a88f94cedefc89)]
166
204
  ### [1.1.0](https://github.com/eea/volto-eea-website-theme/compare/1.0.0...1.1.0) - 28 October 2022
167
205
 
168
206
  #### :nail_care: Enhancements
@@ -210,6 +248,7 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
210
248
 
211
249
  #### :hammer_and_wrench: Others
212
250
 
251
+ - Add Sonarqube tag using eea-website-frontend addons list [EEA Jenkins - [`33b56ac`](https://github.com/eea/volto-eea-website-theme/commit/33b56acb13fbaf0c5b79e8fc6e13c4b699c79c90)]
213
252
  ### [0.7.3](https://github.com/eea/volto-eea-website-theme/compare/0.7.2...0.7.3) - 22 September 2022
214
253
 
215
254
  #### :hammer_and_wrench: Others
@@ -477,6 +516,7 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
477
516
  - Header refactor, add custom logo #5 [ichim-david - [`4950235`](https://github.com/eea/volto-eea-website-theme/commit/49502358105437cfeac3b144e6d301cb59aa2346)]
478
517
  - Update footer.config with new publication card component [ichim-david - [`2e38e9a`](https://github.com/eea/volto-eea-website-theme/commit/2e38e9a417f835009d60c80d4eb4b30229f55e45)]
479
518
  - feature(breadcrumbs): implement eea-design-system breadcrumb as Volto component #32 #7 [ichim-david - [`181af41`](https://github.com/eea/volto-eea-website-theme/commit/181af4125ce2b9ddac56dab4723cb11c26633221)]
519
+ - Add Sonarqube tag using eea-website-frontend addons list [EEA Jenkins - [`da8ceb6`](https://github.com/eea/volto-eea-website-theme/commit/da8ceb68ea68bfbc9504e48ccd4d68277f11ab9a)]
480
520
  - use breadcrumbs from eea-design-system [nileshgulia1 - [`db2f9e9`](https://github.com/eea/volto-eea-website-theme/commit/db2f9e9a4327420a3cce9a9903cd88549b129eab)]
481
521
  - Update theme.config [ichim-david - [`8eca4f4`](https://github.com/eea/volto-eea-website-theme/commit/8eca4f40397a4aeca6d39029c92db78968d37064)]
482
522
  - Added keyContent component to theme.config [ichim-david - [`d86f202`](https://github.com/eea/volto-eea-website-theme/commit/d86f202d0274d839487a88b51cae9a0e899beb23)]
@@ -518,4 +558,5 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
518
558
 
519
559
  #### :hammer_and_wrench: Others
520
560
 
561
+ - yarn bootstrap [Alin Voinea - [`6995e9e`](https://github.com/eea/volto-eea-website-theme/commit/6995e9e091f21fdbbdffa8a44fc0e2c626f6d46a)]
521
562
  - Initial commit [Alin Voinea - [`6a9c03a`](https://github.com/eea/volto-eea-website-theme/commit/6a9c03a7cebe71ca87e82cf58c42904063e9d8d3)]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eeacms/volto-eea-website-theme",
3
- "version": "1.7.0",
3
+ "version": "1.8.1",
4
4
  "description": "@eeacms/volto-eea-website-theme: Volto add-on",
5
5
  "main": "src/index.js",
6
6
  "author": "European Environment Agency: IDM2 A-Team",
@@ -0,0 +1,6 @@
1
+ import { compose } from 'redux';
2
+ import { injectIntl } from 'react-intl';
3
+ import { withRootNavigation } from '@eeacms/volto-eea-website-theme/hocs';
4
+ import { NotFound } from '@plone/volto/components';
5
+
6
+ export default compose(injectIntl, withRootNavigation)(NotFound);
package/src/config.js CHANGED
@@ -258,17 +258,29 @@ export const headerSearchBox = [
258
258
  {
259
259
  isDefault: true,
260
260
  path: '/en/advanced-search',
261
- placeholder: 'Search...',
262
- description:
263
- 'Looking for more information? Try searching the full EEA website content',
264
- buttonTitle: 'Go to full site search',
261
+ placeholder: 'Search or ask your question...',
262
+ description: 'For more search options',
263
+ buttonTitle: 'Go to advanced search',
264
+ searchSuggestions: {
265
+ maxToShow: 6,
266
+ suggestionsTitle: 'Try our suggestions',
267
+ suggestions: [
268
+ 'What is PFAS?',
269
+ 'Which transport mode has the lowest pollution?',
270
+ 'Which countries use most renewable energy?',
271
+ 'How many premature deaths are attributed to PM2.5?',
272
+ 'How many premature deaths are attributed to air pollution?',
273
+ 'How much have new cars co2 emissions decreased?',
274
+ 'What countries had the highest land take in the EEA-39?',
275
+ 'How many people are exposed to air pollution?',
276
+ ],
277
+ },
265
278
  },
266
279
  {
267
280
  path: '/en/datahub',
268
281
  placeholder: 'Search Datahub...',
269
- description:
270
- 'Looking for more information? Try searching the full EEA website content',
271
- buttonTitle: 'Go to full site search',
282
+ description: 'Looking for more information?',
283
+ buttonTitle: 'Go to advanced search',
272
284
  },
273
285
  ];
274
286
 
@@ -12,32 +12,12 @@ export const StyleSchema = () => {
12
12
  title: 'Preset styles',
13
13
  fields: ['style_name'],
14
14
  },
15
- {
16
- id: 'text',
17
- title: 'Text',
18
- fields: ['textAlign', 'fontWeight'],
19
- },
20
15
  ],
21
16
  properties: {
22
17
  style_name: {
23
18
  title: 'Style',
24
19
  widget: 'style_select',
25
20
  },
26
- textAlign: {
27
- title: 'Text align',
28
- widget: 'style_text_align',
29
- },
30
- fontWeight: {
31
- title: 'Font weight',
32
- description: 'The weight (or boldness) of the font',
33
- choices: [
34
- ['300', 'Light'],
35
- ['400', 'Regular'],
36
- ['500', 'Medium'],
37
- ['600', 'SemiBold'],
38
- ['700', 'Bold'],
39
- ],
40
- },
41
21
  },
42
22
  required: [],
43
23
  };
@@ -1,9 +1,15 @@
1
1
  import React from 'react';
2
- import { Container, Input } from 'semantic-ui-react';
2
+ import { Container, Input, List } from 'semantic-ui-react';
3
3
  import { withRouter } from 'react-router-dom';
4
4
  import { useClickOutside } from '@eeacms/volto-eea-design-system/helpers';
5
5
  import config from '@plone/volto/registry';
6
6
 
7
+ const getRandomItems = (arr, max) => {
8
+ return arr.slice(0, max).map(function () {
9
+ return this.splice(Math.floor(Math.random() * this.length), 1)[0];
10
+ }, arr.slice());
11
+ };
12
+
7
13
  function HeaderSearchPopUp({
8
14
  history,
9
15
  location,
@@ -18,8 +24,18 @@ function HeaderSearchPopUp({
18
24
  location.pathname.includes(v.path),
19
25
  );
20
26
  const activeView = localView.length > 0 ? localView[0] : defaultView[0];
21
-
27
+ const {
28
+ path,
29
+ placeholder,
30
+ buttonTitle,
31
+ description,
32
+ searchSuggestions,
33
+ } = activeView;
34
+ const { suggestionsTitle, suggestions, maxToShow } = searchSuggestions || {};
22
35
  const [text, setText] = React.useState('');
36
+ const visibleSuggestions = suggestions
37
+ ? getRandomItems(suggestions, maxToShow)
38
+ : [];
23
39
 
24
40
  useClickOutside({ targetRefs: [nodeRef, ...triggerRefs], callback: onClose });
25
41
 
@@ -29,7 +45,7 @@ function HeaderSearchPopUp({
29
45
  };
30
46
 
31
47
  const onSubmit = (event) => {
32
- history.push(`${activeView.path}?q=${text}`);
48
+ history.push(`${path}?q=${text}`);
33
49
 
34
50
  if (window?.searchContext?.resetSearch) {
35
51
  window.searchContext.resetSearch({ searchTerm: text });
@@ -39,11 +55,21 @@ function HeaderSearchPopUp({
39
55
  event.preventDefault();
40
56
  };
41
57
 
58
+ const onClickHandler = (suggestion) => {
59
+ history.push(`${path}?q=${suggestion}`);
60
+
61
+ if (window?.searchContext?.resetSearch) {
62
+ window.searchContext.resetSearch({ searchTerm: suggestion });
63
+ }
64
+
65
+ onClose();
66
+ };
67
+
42
68
  return (
43
69
  <div id="search-box" ref={nodeRef}>
44
- <form method="get" onSubmit={onSubmit}>
70
+ <div className="wrapper">
45
71
  <Container>
46
- <div className="wrapper">
72
+ <form method="get" onSubmit={onSubmit}>
47
73
  <Input
48
74
  ref={searchInputRef}
49
75
  className="search"
@@ -53,26 +79,41 @@ function HeaderSearchPopUp({
53
79
  link: true,
54
80
  onClick: onSubmit,
55
81
  }}
56
- placeholder={activeView.placeholder}
82
+ placeholder={placeholder}
57
83
  fluid
58
84
  />
59
- </div>
85
+ </form>
86
+ {searchSuggestions && suggestions.length > 0 && (
87
+ <div className="search-suggestions">
88
+ {suggestionsTitle && <h4>{suggestionsTitle}</h4>}
89
+
90
+ <List>
91
+ {visibleSuggestions.map((item, i) => {
92
+ return (
93
+ <List.Item key={i} onClick={() => onClickHandler(item)}>
94
+ {item}
95
+ </List.Item>
96
+ );
97
+ })}
98
+ </List>
99
+ </div>
100
+ )}
60
101
  </Container>
61
- </form>
62
- {activeView.buttonTitle && (
63
- <div className="advanced-search">
64
- <Container>
65
- <p>{activeView.description}</p>
66
- <a
67
- href={defaultView[0].path}
68
- className="ui button white inverted"
69
- title="Advanced search"
70
- >
71
- {activeView.buttonTitle}
72
- </a>
73
- </Container>
74
- </div>
75
- )}
102
+ {buttonTitle && (
103
+ <div className="advanced-search">
104
+ <Container>
105
+ <div>{description}</div>
106
+ <a
107
+ href={defaultView[0].path}
108
+ className="ui button white inverted"
109
+ title="Advanced search"
110
+ >
111
+ {buttonTitle}
112
+ </a>
113
+ </Container>
114
+ </div>
115
+ )}
116
+ </div>
76
117
  </div>
77
118
  );
78
119
  }
@@ -0,0 +1,2 @@
1
+ This is customized because of stupid logic implemented in the attributes
2
+ calculation. This should be moved to volto proper. The difference is in Element
@@ -0,0 +1,165 @@
1
+ import React from 'react';
2
+ import { renderToStaticMarkup } from 'react-dom/server';
3
+ import { Node, Text } from 'slate';
4
+ import cx from 'classnames';
5
+ import { isEmpty, isEqual, omit } from 'lodash';
6
+ import config from '@plone/volto/registry';
7
+
8
+ const OMITTED = ['editor', 'path'];
9
+
10
+ // TODO: read, see if relevant
11
+ // https://reactjs.org/docs/higher-order-components.html#dont-use-hocs-inside-the-render-method
12
+ export const Element = ({ element, attributes = {}, extras, ...rest }) => {
13
+ const { slate } = config.settings;
14
+ const { elements } = slate;
15
+ const El = elements[element.type] || elements['default'];
16
+
17
+ // CUSTOMIZATION Code fix
18
+ const attrs = Object.keys(attributes || {}).reduce(
19
+ (acc, k) => {
20
+ if (!isEmpty(attributes[k])) {
21
+ if (k === 'className') {
22
+ acc.className = cx(attributes.className, acc.className);
23
+ } else {
24
+ acc[k] = attributes[k];
25
+ }
26
+ }
27
+ return acc;
28
+ },
29
+ element.styleName ? { className: element.styleName } : {},
30
+ );
31
+ // END CUSTOMIZATION
32
+
33
+ attrs.ref = attributes?.ref; // never remove the ref
34
+
35
+ return (
36
+ <El
37
+ element={element}
38
+ {...omit(rest, OMITTED)}
39
+ attributes={attrs}
40
+ extras={extras}
41
+ />
42
+ );
43
+ };
44
+
45
+ export const Leaf = ({ children, ...rest }) => {
46
+ const { attributes, leaf, mode } = rest;
47
+ let { leafs } = config.settings.slate;
48
+
49
+ children = Object.keys(leafs).reduce((acc, name) => {
50
+ return Object.keys(leaf).includes(name)
51
+ ? leafs[name]({ children: acc })
52
+ : acc;
53
+ }, children);
54
+
55
+ const classNames = {
56
+ [`highlight-${leaf.highlightType}`]: mode !== 'view' && leaf.highlightType,
57
+ 'highlight-selection': mode !== 'view' && leaf.isSelection,
58
+ };
59
+
60
+ // stylemenu support
61
+ for (const prop in leaf) {
62
+ if (prop.startsWith('style-')) {
63
+ classNames[prop.substring(6)] = true;
64
+ }
65
+ }
66
+
67
+ const klass = cx(classNames);
68
+
69
+ return mode === 'view' ? (
70
+ typeof children === 'string' ? (
71
+ children.split('\n').map((t, i) => {
72
+ // Softbreak support. Should do a plugin?
73
+ return (
74
+ <React.Fragment key={`${i}`}>
75
+ {children.indexOf('\n') > -1 &&
76
+ children.split('\n').length - 1 > i ? (
77
+ <>
78
+ {klass ? <span className={klass}>{t}</span> : t}
79
+ <br />
80
+ </>
81
+ ) : klass ? (
82
+ <span className={klass}>{t}</span>
83
+ ) : (
84
+ t
85
+ )}
86
+ </React.Fragment>
87
+ );
88
+ })
89
+ ) : (
90
+ <span className={klass}>{children}</span>
91
+ )
92
+ ) : (
93
+ <span {...attributes} className={klass}>
94
+ {children}
95
+ </span>
96
+ );
97
+ };
98
+
99
+ const serializeData = (node) => {
100
+ return JSON.stringify({ type: node.type, data: node.data });
101
+ };
102
+
103
+ export const serializeNodes = (nodes, getAttributes, extras = {}) => {
104
+ const editor = { children: nodes || [] };
105
+
106
+ const _serializeNodes = (nodes) => {
107
+ return (nodes || []).map(([node, path], i) => {
108
+ return Text.isText(node) ? (
109
+ <Leaf path={path} leaf={node} text={node} mode="view" key={path}>
110
+ {node.text}
111
+ </Leaf>
112
+ ) : (
113
+ <Element
114
+ path={path}
115
+ element={node}
116
+ mode="view"
117
+ key={path}
118
+ data-slate-data={node.data ? serializeData(node) : null}
119
+ attributes={
120
+ isEqual(path, [0])
121
+ ? getAttributes
122
+ ? getAttributes(node, path)
123
+ : null
124
+ : null
125
+ }
126
+ extras={extras}
127
+ >
128
+ {_serializeNodes(Array.from(Node.children(editor, path)))}
129
+ </Element>
130
+ );
131
+ });
132
+ };
133
+
134
+ return _serializeNodes(Array.from(Node.children(editor, [])));
135
+ };
136
+
137
+ /**
138
+ * Get the concatenated text string of a node's content.
139
+ *
140
+ * Note that this WILL include spaces between block node leafs in contrary to
141
+ * the original slate method. This function joins text of nodes with
142
+ * separating spaces to produce a string for indexing purposes.
143
+ *
144
+ */
145
+ const ConcatenatedString = (node) => {
146
+ if (Text.isText(node)) {
147
+ return node.text.trim();
148
+ } else {
149
+ return node.children.map(ConcatenatedString).join(' ');
150
+ }
151
+ };
152
+
153
+ /**
154
+ * @function serializeNodesToText
155
+ *
156
+ * @param {Array[Node]} nodes
157
+ *
158
+ * @returns {string}
159
+ */
160
+ export const serializeNodesToText = (nodes) => {
161
+ return nodes.map(ConcatenatedString).join('\n');
162
+ };
163
+
164
+ export const serializeNodesToHtml = (nodes) =>
165
+ renderToStaticMarkup(serializeNodes(nodes));
@@ -71,6 +71,7 @@ const ObjectBrowserNav = ({
71
71
  >
72
72
  <span title={`${item['@id']} (${item['@type']})`}>
73
73
  <Popup
74
+ hoverable
74
75
  key={item['@id']}
75
76
  content={
76
77
  <>
@@ -0,0 +1,3 @@
1
+ import withRootNavigation from './withRootNavigation';
2
+
3
+ export { withRootNavigation };
@@ -0,0 +1,29 @@
1
+ import React from 'react';
2
+ import { connect, useDispatch } from 'react-redux';
3
+ import { getBaseUrl, hasApiExpander } from '@plone/volto/helpers';
4
+ import { getNavigation } from '@plone/volto/actions';
5
+ import config from '@plone/volto/registry';
6
+
7
+ export default function withRootNavigation(WrappedComponent) {
8
+ return connect(
9
+ (state) => {
10
+ return {
11
+ items: state.navigation.items,
12
+ lang: state.intl.locale,
13
+ };
14
+ },
15
+ { getNavigation },
16
+ )((props) => {
17
+ const dispatch = useDispatch();
18
+ React.useEffect(() => {
19
+ const { settings } = config;
20
+ const currentLang = props.lang;
21
+ const base_url = getBaseUrl(`/${currentLang}`);
22
+ if (!hasApiExpander('navigation', base_url)) {
23
+ dispatch(getNavigation(base_url, settings.navDepth));
24
+ }
25
+ }, [props.lang, dispatch]);
26
+
27
+ return <WrappedComponent {...props} items={props.items} />;
28
+ });
29
+ }
package/src/index.js CHANGED
@@ -2,20 +2,16 @@ import * as eea from './config';
2
2
  import InpageNavigation from '@eeacms/volto-eea-design-system/ui/InpageNavigation/InpageNavigation';
3
3
  import installCustomTitle from '@eeacms/volto-eea-website-theme/components/manage/Blocks/Title';
4
4
  import CustomCSS from '@eeacms/volto-eea-website-theme/components/theme/CustomCSS/CustomCSS';
5
+ import NotFound from '@eeacms/volto-eea-website-theme/components/theme/NotFound/NotFound';
5
6
  import DraftBackground from '@eeacms/volto-eea-website-theme/components/theme/DraftBackground/DraftBackground';
6
7
  import { TokenWidget } from '@eeacms/volto-eea-website-theme/components/theme/Widgets/TokenWidget';
7
8
  import SubsiteClass from './components/theme/SubsiteClass';
8
9
  import HomePageView from '@eeacms/volto-eea-website-theme/components/theme/Homepage/HomePageView';
9
10
  import HomePageInverseView from '@eeacms/volto-eea-website-theme/components/theme/Homepage/HomePageInverseView';
10
11
  import { Icon } from '@plone/volto/components';
11
- import { MarkElementButton } from '@plone/volto-slate/editor/ui';
12
- import installCallout from '@plone/volto-slate/editor/plugins/Callout';
13
- import paintSVG from '@plone/volto/icons/paint.svg';
14
12
  import contentBoxSVG from './icons/content-box.svg';
15
- import lightIcon from './icons/light.svg';
16
- import smallIcon from './icons/small.svg';
17
13
  import voltoCustomMiddleware from './middleware/voltoCustom';
18
- import { List } from 'semantic-ui-react';
14
+ import installSlate from './slate';
19
15
 
20
16
  const applyConfig = (config) => {
21
17
  // EEA specific settings
@@ -53,7 +49,10 @@ const applyConfig = (config) => {
53
49
  homepage_view: 'Homepage view',
54
50
  homepage_inverse_view: 'Homepage white view',
55
51
  };
56
-
52
+ config.views.errorViews = {
53
+ ...config.views.errorViews,
54
+ '404': NotFound,
55
+ };
57
56
  // Apply accordion block customization
58
57
  if (config.blocks.blocksConfig.accordion) {
59
58
  config.blocks.blocksConfig.accordion.semanticIcon = 'ri-arrow-down-s-line';
@@ -111,141 +110,7 @@ const applyConfig = (config) => {
111
110
  },
112
111
  ];
113
112
 
114
- if (config.settings.slate) {
115
- // Callout slate button
116
- config = installCallout(config);
117
-
118
- // Remove blockquote, italic, strikethrough slate button from toolbarButtons
119
- config.settings.slate.toolbarButtons = config.settings.slate.toolbarButtons.filter(
120
- (item) => !['blockquote', 'italic', 'strikethrough'].includes(item),
121
- );
122
-
123
- // Remove blockquote, italic, strikethrough slate button from expandedToolbarButtons
124
- config.settings.slate.expandedToolbarButtons = config.settings.slate.expandedToolbarButtons.filter(
125
- (item) => !['blockquote', 'italic', 'strikethrough'].includes(item),
126
- );
127
-
128
- // Remove 'underline' and 'italic' hotkeys
129
- config.settings.slate.hotkeys = Object.keys(config.settings.slate.hotkeys)
130
- .filter((item) => !['mod+u', 'mod+i'].includes(item))
131
- .reduce((out, key) => {
132
- out[key] = config.settings.slate.hotkeys[key];
133
- return out;
134
- }, {});
135
-
136
- // Small button
137
- if (!config.settings.slate.toolbarButtons.includes('small')) {
138
- config.settings.slate.elements.small = ({ children }) => (
139
- <small>{children}</small>
140
- );
141
-
142
- config.settings.slate.buttons.small = (props) => (
143
- <MarkElementButton
144
- title="Small"
145
- format="small"
146
- icon={smallIcon}
147
- {...props}
148
- />
149
- );
150
-
151
- config.settings.slate.inlineElements = [
152
- ...config.settings.slate.inlineElements,
153
- 'small',
154
- ];
155
-
156
- config.settings.slate.toolbarButtons = [
157
- ...config.settings.slate.toolbarButtons.slice(0, 1),
158
- 'small',
159
- ...config.settings.slate.toolbarButtons.slice(1),
160
- ];
161
-
162
- config.settings.slate.hotkeys['mod+s'] = {
163
- format: 'small',
164
- type: 'inline',
165
- };
166
- }
167
-
168
- // Light button
169
- if (!config.settings.slate.toolbarButtons.includes('light')) {
170
- config.settings.slate.elements.light = ({ children }) => (
171
- <span className="fw-light">{children}</span>
172
- );
173
-
174
- config.settings.slate.buttons.light = (props) => (
175
- <MarkElementButton
176
- title="Light"
177
- format="light"
178
- icon={lightIcon}
179
- {...props}
180
- />
181
- );
182
-
183
- config.settings.slate.inlineElements = [
184
- ...config.settings.slate.inlineElements,
185
- 'light',
186
- ];
187
-
188
- config.settings.slate.toolbarButtons = [
189
- ...config.settings.slate.toolbarButtons.slice(0, 1),
190
- 'light',
191
- ...config.settings.slate.toolbarButtons.slice(1),
192
- ];
193
-
194
- config.settings.slate.hotkeys['mod+l'] = {
195
- format: 'light',
196
- type: 'inline',
197
- };
198
- }
199
-
200
- // Clear formatting
201
- if (!config.settings.slate.toolbarButtons.includes('clearformatting')) {
202
- config.settings.slate.toolbarButtons = [
203
- ...config.settings.slate.toolbarButtons,
204
- 'clearformatting',
205
- ];
206
- }
207
-
208
- // Align Slate Lists to EEA Design System
209
- config.settings.slate.elements.ul = ({ attributes, children }) => (
210
- <List bulleted as="ul" {...attributes}>
211
- {children}
212
- </List>
213
- );
214
-
215
- config.settings.slate.elements.ol = ({ attributes, children }) => (
216
- <List ordered as="ol" {...attributes}>
217
- {children}
218
- </List>
219
- );
220
-
221
- config.settings.slate.elements.li = ({ attributes, children }) => (
222
- <List.Item as="li" {...attributes}>
223
- {children}
224
- </List.Item>
225
- );
226
-
227
- // Slate StyleMenu configuration
228
- config.settings.slate.styleMenu = {
229
- ...(config.settings.slate.styleMenu || {}),
230
- blockStyles: [
231
- {
232
- cssClass: 'primary',
233
- label: 'Primary',
234
- icon: () => <Icon name={paintSVG} size="18px" />,
235
- },
236
- {
237
- cssClass: 'secondary',
238
- label: 'Secondary',
239
- icon: () => <Icon name={paintSVG} size="18px" />,
240
- },
241
- {
242
- cssClass: 'tertiary',
243
- label: 'Tertiary',
244
- icon: () => <Icon name={paintSVG} size="18px" />,
245
- },
246
- ],
247
- };
248
- }
113
+ config = installSlate(config);
249
114
 
250
115
  // Custom block-style colors
251
116
  config.settings.available_colors = eea.colors;
package/src/slate.js ADDED
@@ -0,0 +1,323 @@
1
+ import React from 'react';
2
+ import { List } from 'semantic-ui-react';
3
+ import { MarkElementButton, ToolbarButton } from '@plone/volto-slate/editor/ui';
4
+ import installCallout from '@plone/volto-slate/editor/plugins/Callout';
5
+ import { Icon } from '@plone/volto/components';
6
+ import { Editor, Transforms } from 'slate';
7
+ import { useSlate } from 'slate-react';
8
+
9
+ import formatClearIcon from '@plone/volto/icons/format-clear.svg';
10
+ import paintSVG from '@plone/volto/icons/paint.svg';
11
+ import alignLeftIcon from '@plone/volto/icons/align-left.svg';
12
+ import alignRightIcon from '@plone/volto/icons/align-right.svg';
13
+ import alignCenterIcon from '@plone/volto/icons/align-center.svg';
14
+ import alignJustifyIcon from '@plone/volto/icons/align-justify.svg';
15
+ import lightIcon from './icons/light.svg';
16
+ import smallIcon from './icons/small.svg';
17
+
18
+ const toggleBlockClassFormat = (editor, format) => {
19
+ const levels = Array.from(Editor.levels(editor, editor.selection));
20
+ const [, [, path]] = levels;
21
+ Transforms.setNodes(
22
+ editor,
23
+ { styleName: format },
24
+ {
25
+ at: path,
26
+ },
27
+ );
28
+ return;
29
+ };
30
+
31
+ const isBlockClassActive = (editor, format) => {
32
+ if (!editor.selection) return false;
33
+ const levels = Array.from(Editor.levels(editor, editor.selection));
34
+ const [, [node]] = levels;
35
+ return node.styleName === format;
36
+ };
37
+
38
+ function BlockClassButton({ format, icon, ...props }) {
39
+ const editor = useSlate();
40
+
41
+ const isActive = isBlockClassActive(editor, format);
42
+
43
+ const handleMouseDown = React.useCallback(
44
+ (event) => {
45
+ event.preventDefault();
46
+ toggleBlockClassFormat(editor, format);
47
+ },
48
+ [editor, format], // , isActive
49
+ );
50
+
51
+ return (
52
+ <ToolbarButton
53
+ {...props}
54
+ active={isActive}
55
+ onMouseDown={handleMouseDown}
56
+ icon={icon}
57
+ />
58
+ );
59
+ }
60
+
61
+ const clearFormatting = (editor) => {
62
+ Transforms.setNodes(editor, {
63
+ type: 'p',
64
+ styleName: null,
65
+ });
66
+ Transforms.unwrapNodes(editor, {
67
+ match: (n) => n.type && n.type !== 'p',
68
+ mode: 'all',
69
+ split: false,
70
+ });
71
+ };
72
+
73
+ const ClearFormattingButton = ({ icon, ...props }) => {
74
+ const editor = useSlate();
75
+
76
+ const handleMouseDown = React.useCallback(
77
+ (event) => {
78
+ event.preventDefault();
79
+ clearFormatting(editor);
80
+ },
81
+ [editor],
82
+ );
83
+
84
+ return <ToolbarButton {...props} onMouseDown={handleMouseDown} icon={icon} />;
85
+ };
86
+
87
+ export default function installSlate(config) {
88
+ if (config.settings.slate) {
89
+ // Callout slate button
90
+ config = installCallout(config);
91
+
92
+ config.settings.slate.buttons.clearformatting = (props) => (
93
+ <ClearFormattingButton title="Clear formatting" icon={formatClearIcon} />
94
+ );
95
+
96
+ // Remove blockquote, italic, strikethrough slate button from toolbarButtons
97
+ config.settings.slate.toolbarButtons = config.settings.slate.toolbarButtons.filter(
98
+ (item) => !['blockquote', 'italic', 'strikethrough'].includes(item),
99
+ );
100
+
101
+ // Remove blockquote, italic, strikethrough slate button from expandedToolbarButtons
102
+ config.settings.slate.expandedToolbarButtons = config.settings.slate.expandedToolbarButtons.filter(
103
+ (item) => !['blockquote', 'italic', 'strikethrough'].includes(item),
104
+ );
105
+
106
+ // Remove 'underline' and 'italic' hotkeys
107
+ config.settings.slate.hotkeys = Object.keys(config.settings.slate.hotkeys)
108
+ .filter((item) => !['mod+u', 'mod+i'].includes(item))
109
+ .reduce((out, key) => {
110
+ out[key] = config.settings.slate.hotkeys[key];
111
+ return out;
112
+ }, {});
113
+
114
+ // Small button
115
+ if (!config.settings.slate.toolbarButtons.includes('small')) {
116
+ config.settings.slate.elements.small = ({ children }) => (
117
+ <small>{children}</small>
118
+ );
119
+
120
+ config.settings.slate.buttons.small = (props) => (
121
+ <MarkElementButton
122
+ title="Small"
123
+ format="small"
124
+ icon={smallIcon}
125
+ {...props}
126
+ />
127
+ );
128
+
129
+ config.settings.slate.inlineElements = [
130
+ ...config.settings.slate.inlineElements,
131
+ 'small',
132
+ ];
133
+
134
+ config.settings.slate.toolbarButtons = [
135
+ ...config.settings.slate.toolbarButtons.slice(0, 1),
136
+ 'small',
137
+ ...config.settings.slate.toolbarButtons.slice(1),
138
+ ];
139
+
140
+ config.settings.slate.hotkeys['mod+s'] = {
141
+ format: 'small',
142
+ type: 'inline',
143
+ };
144
+ }
145
+
146
+ // Light button
147
+ if (!config.settings.slate.toolbarButtons.includes('light')) {
148
+ config.settings.slate.elements.light = ({ children }) => (
149
+ <span className="fw-light">{children}</span>
150
+ );
151
+
152
+ config.settings.slate.buttons.light = (props) => (
153
+ <MarkElementButton
154
+ title="Light"
155
+ format="light"
156
+ icon={lightIcon}
157
+ {...props}
158
+ />
159
+ );
160
+
161
+ config.settings.slate.inlineElements = [
162
+ ...config.settings.slate.inlineElements,
163
+ 'light',
164
+ ];
165
+
166
+ config.settings.slate.toolbarButtons = [
167
+ ...config.settings.slate.toolbarButtons.slice(0, 1),
168
+ 'light',
169
+ ...config.settings.slate.toolbarButtons.slice(1),
170
+ ];
171
+
172
+ config.settings.slate.hotkeys['mod+l'] = {
173
+ format: 'light',
174
+ type: 'inline',
175
+ };
176
+ }
177
+
178
+ // Align Slate Lists to EEA Design System
179
+ config.settings.slate.elements.ul = ({ attributes, children }) => (
180
+ <List bulleted as="ul" {...attributes}>
181
+ {children}
182
+ </List>
183
+ );
184
+
185
+ config.settings.slate.elements.ol = ({ attributes, children }) => (
186
+ <List ordered as="ol" {...attributes}>
187
+ {children}
188
+ </List>
189
+ );
190
+
191
+ config.settings.slate.elements.li = ({ attributes, children }) => (
192
+ <List.Item as="li" {...attributes}>
193
+ {children}
194
+ </List.Item>
195
+ );
196
+
197
+ // Slate StyleMenu configuration
198
+ config.settings.slate.styleMenu = {
199
+ ...(config.settings.slate.styleMenu || {}),
200
+ blockStyles: [
201
+ {
202
+ cssClass: 'primary',
203
+ label: 'Primary',
204
+ icon: () => <Icon name={paintSVG} size="18px" />,
205
+ },
206
+ {
207
+ cssClass: 'secondary',
208
+ label: 'Secondary',
209
+ icon: () => <Icon name={paintSVG} size="18px" />,
210
+ },
211
+ {
212
+ cssClass: 'tertiary',
213
+ label: 'Tertiary',
214
+ icon: () => <Icon name={paintSVG} size="18px" />,
215
+ },
216
+ ],
217
+ };
218
+
219
+ // Text Align buttons
220
+
221
+ // Align left
222
+ if (!config.settings.slate.toolbarButtons.includes('text-left')) {
223
+ config.settings.slate.buttons['text-left'] = (props) => (
224
+ <BlockClassButton
225
+ format="text-left"
226
+ icon={alignLeftIcon}
227
+ title="Align left"
228
+ {...props}
229
+ />
230
+ );
231
+
232
+ config.settings.slate.toolbarButtons = [
233
+ ...config.settings.slate.toolbarButtons,
234
+ 'separator',
235
+ 'text-left',
236
+ ];
237
+
238
+ config.settings.slate.expandedToolbarButtons = [
239
+ ...config.settings.slate.expandedToolbarButtons,
240
+ 'separator',
241
+ 'text-left',
242
+ ];
243
+ }
244
+
245
+ // Align center
246
+ if (!config.settings.slate.toolbarButtons.includes('text-center')) {
247
+ config.settings.slate.buttons['text-center'] = (props) => (
248
+ <BlockClassButton
249
+ format="text-center"
250
+ icon={alignCenterIcon}
251
+ title="Align center"
252
+ {...props}
253
+ />
254
+ );
255
+
256
+ config.settings.slate.toolbarButtons = [
257
+ ...config.settings.slate.toolbarButtons,
258
+ 'text-center',
259
+ ];
260
+
261
+ config.settings.slate.expandedToolbarButtons = [
262
+ ...config.settings.slate.expandedToolbarButtons,
263
+ 'text-center',
264
+ ];
265
+ }
266
+
267
+ // Align right
268
+ if (!config.settings.slate.toolbarButtons.includes('text-right')) {
269
+ config.settings.slate.buttons['text-right'] = (props) => (
270
+ <BlockClassButton
271
+ format="text-right"
272
+ icon={alignRightIcon}
273
+ title="Align right"
274
+ {...props}
275
+ />
276
+ );
277
+
278
+ config.settings.slate.toolbarButtons = [
279
+ ...config.settings.slate.toolbarButtons,
280
+ 'text-right',
281
+ ];
282
+
283
+ config.settings.slate.expandedToolbarButtons = [
284
+ ...config.settings.slate.expandedToolbarButtons,
285
+ 'text-right',
286
+ ];
287
+ }
288
+
289
+ // Align justify
290
+ if (!config.settings.slate.toolbarButtons.includes('text-justify')) {
291
+ config.settings.slate.buttons['text-justify'] = (props) => (
292
+ <BlockClassButton
293
+ format="text-justify"
294
+ icon={alignJustifyIcon}
295
+ title="Align justify"
296
+ {...props}
297
+ />
298
+ );
299
+
300
+ config.settings.slate.toolbarButtons = [
301
+ ...config.settings.slate.toolbarButtons,
302
+ 'text-justify',
303
+ 'separator',
304
+ ];
305
+
306
+ config.settings.slate.expandedToolbarButtons = [
307
+ ...config.settings.slate.expandedToolbarButtons,
308
+ 'text-justify',
309
+ 'separator',
310
+ ];
311
+ }
312
+
313
+ // Clear formatting
314
+ if (!config.settings.slate.toolbarButtons.includes('clearformatting')) {
315
+ config.settings.slate.toolbarButtons = [
316
+ ...config.settings.slate.toolbarButtons,
317
+ 'clearformatting',
318
+ ];
319
+ }
320
+ }
321
+
322
+ return config;
323
+ }