@eeacms/volto-eea-website-policy 2.2.3 → 2.3.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,6 +4,75 @@ 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
+ ### [2.3.1](https://github.com/eea/volto-eea-website-policy/compare/2.3.0...2.3.1) - 30 January 2025
8
+
9
+ #### :bug: Bug Fixes
10
+
11
+ - fix: error on edititing html block and make it readonly - refs #282438 [Teodor Voicu - [`302e393`](https://github.com/eea/volto-eea-website-policy/commit/302e393c8214465673d757b50b89d89574f0f4a8)]
12
+
13
+ ### [2.3.0](https://github.com/eea/volto-eea-website-policy/compare/2.2.3...2.3.0) - 11 October 2024
14
+
15
+ #### :rocket: New Features
16
+
17
+ - feat(ContextNavigation): improve accordion outside click handling [David Ichim - [`0eb27ac`](https://github.com/eea/volto-eea-website-policy/commit/0eb27acf6d8fd04ecb7f003d4fe2de65b0077168)]
18
+ - feat(ContextNavigation): wrap accordion summary and list in container on tablet [David Ichim - [`43b659f`](https://github.com/eea/volto-eea-website-policy/commit/43b659fab611c24d42b46fc7e57cbb9e292e5f6e)]
19
+ - feat(ContextNavigation): add aria-label to context navigation [David Ichim - [`5c7241d`](https://github.com/eea/volto-eea-website-policy/commit/5c7241d44146751b370b8d960d28efabd607c870)]
20
+ - feat: use isMenuOpenOnOutsideClick to detect outside clicks [nileshgulia1 - [`5bef098`](https://github.com/eea/volto-eea-website-policy/commit/5bef098d7dd6b9829fbb4c1341747aecad89fce5)]
21
+ - feat: add accordion variation for contextNavigation block [nileshgulia1 - [`a8fdad8`](https://github.com/eea/volto-eea-website-policy/commit/a8fdad8c1902224b56e6e4f30357546ef9de40dc)]
22
+ - feat(contextNavigation): add variations support [nileshgulia1 - [`4c984c8`](https://github.com/eea/volto-eea-website-policy/commit/4c984c8eadfcf0eb7aed0541fb8737fc2b1b2e27)]
23
+
24
+ #### :bug: Bug Fixes
25
+
26
+ - fix: cypress [nileshgulia1 - [`5df3c21`](https://github.com/eea/volto-eea-website-policy/commit/5df3c21f0e7043aa80e35077246be75a52c3c7e4)]
27
+ - fix(contextNav): make accordion expands initially, fix tests [nileshgulia1 - [`9bfa568`](https://github.com/eea/volto-eea-website-policy/commit/9bfa568ac9b584e4e3d9dea0675e82a93304a25f)]
28
+ - fix(context-navigation): set active accordion on initial mounts [nileshgulia1 - [`de902b1`](https://github.com/eea/volto-eea-website-policy/commit/de902b1fb1e06d50bc9a39bf589e8ededa6ec2a1)]
29
+ - fix: addKeyDown handlers [nileshgulia1 - [`7150f64`](https://github.com/eea/volto-eea-website-policy/commit/7150f641ab46c885b90474e37ff0bf294868ba95)]
30
+ - fix: make accordion accessible, add details tag [nileshgulia1 - [`d1e5f29`](https://github.com/eea/volto-eea-website-policy/commit/d1e5f29bf62801bf1b3f12f1417729acc1a010b0)]
31
+ - fix: compute is_current for nested items also [nileshgulia1 - [`3e66745`](https://github.com/eea/volto-eea-website-policy/commit/3e66745f39bcd4ac861124a16bfaa5685ec11e47)]
32
+ - fix: acitve states on accordion and links elements [nileshgulia1 - [`1b4426f`](https://github.com/eea/volto-eea-website-policy/commit/1b4426f8ce44f11cc10d73dd08f213c0b891c488)]
33
+ - fix: behave as links when no childs are present [nileshgulia1 - [`c6ac493`](https://github.com/eea/volto-eea-website-policy/commit/c6ac4937519d41f631757472f49f0b609ed8cda1)]
34
+
35
+ #### :nail_care: Enhancements
36
+
37
+ - change(navigation): moved navigation block with the side nav within volto-eea-website-theme #270999 #99 from eea/270999_report_navigation [Ichim David - [`f37254e`](https://github.com/eea/volto-eea-website-policy/commit/f37254e403ac3ce13c4b8d7bcecb54c811c8cad8)]
38
+ - change(contextNavigation): use withEEASideMenu in accordion variation [nileshgulia1 - [`24927d8`](https://github.com/eea/volto-eea-website-policy/commit/24927d8bb6c44e9a3267183ac0a0fd0c0aa58bd4)]
39
+ - change(accordion): simplify logic and improve render by have a list of elements instead of div tags [David Ichim - [`9c73cd5`](https://github.com/eea/volto-eea-website-policy/commit/9c73cd55b5303df958c64a12a251f9a9b15d35ef)]
40
+
41
+ #### :house: Internal changes
42
+
43
+ - chore(eslint):add tabIndex [nileshgulia1 - [`53a3ac2`](https://github.com/eea/volto-eea-website-policy/commit/53a3ac2bf52499fde069fbe57c5efc3f11eaa485)]
44
+ - chore: fix eslint [nileshgulia1 - [`acad444`](https://github.com/eea/volto-eea-website-policy/commit/acad4440314a9f5464cc1b2f10eb3ab1489ff54a)]
45
+
46
+ #### :hammer_and_wrench: Others
47
+
48
+ - removed test for context navigation after the move to volto-eea-website-theme [David Ichim - [`696f0a1`](https://github.com/eea/volto-eea-website-policy/commit/696f0a11c3a8401c064293053490265ffb644215)]
49
+ - bumped package version to 2.3.0 [David Ichim - [`fd88b99`](https://github.com/eea/volto-eea-website-policy/commit/fd88b99d92cb991171807788d8abea3d86832142)]
50
+ - removed ContextNavigation block moved within eea-website-theme [David Ichim - [`361b887`](https://github.com/eea/volto-eea-website-policy/commit/361b8877c02596b971c1ecabd84d8eaa89d3000f)]
51
+ - removed double rolesWhoCanChangeLayout setting [David Ichim - [`37dab9e`](https://github.com/eea/volto-eea-website-policy/commit/37dab9ef04dc1497655e49186f398b5dd53f39b1)]
52
+ - use contextnavigation in policy [nileshgulia1 - [`eea2258`](https://github.com/eea/volto-eea-website-policy/commit/eea2258244c146ff682e055ffb88cf0b9020da93)]
53
+ - move contextNav to volto-eea-website-theme [nileshgulia1 - [`07aa147`](https://github.com/eea/volto-eea-website-policy/commit/07aa14746a0253f75dc7c63610e1998eae6ffbf5)]
54
+ - Add Sonarqube tag using eea-website-frontend addons list [EEA Jenkins - [`f620f72`](https://github.com/eea/volto-eea-website-policy/commit/f620f72b1bee27d9215b4cec5ddbe125ae0f7030)]
55
+ - Add Sonarqube tag using eea-website-frontend addons list [EEA Jenkins - [`13b94c3`](https://github.com/eea/volto-eea-website-policy/commit/13b94c308e20970b4a30e1ec12734e8eaabfffb9)]
56
+ - Add Sonarqube tag using eea-website-frontend addons list [EEA Jenkins - [`8ebc23d`](https://github.com/eea/volto-eea-website-policy/commit/8ebc23dac8134ffed5b8f89d117cec1a13790c2c)]
57
+ - Add Sonarqube tag using eea-website-frontend addons list [EEA Jenkins - [`a57c3eb`](https://github.com/eea/volto-eea-website-policy/commit/a57c3eb88ad31cc50f5321c406ac5b5d918bf623)]
58
+ - Add Sonarqube tag using eea-website-frontend addons list [EEA Jenkins - [`f26c537`](https://github.com/eea/volto-eea-website-policy/commit/f26c537fa75fcb6eedad808a933a8a0689eda9f8)]
59
+ - Add Sonarqube tag using eea-website-frontend addons list [EEA Jenkins - [`b1491ca`](https://github.com/eea/volto-eea-website-policy/commit/b1491ca3c9f07a7b91b9e892b0e53e4cf82762ce)]
60
+ - Added extra handleOutsideClick on Accordion mobile and tablet to close when clicking besides the smaller menu [David Ichim - [`6d36534`](https://github.com/eea/volto-eea-website-policy/commit/6d365349ba9f779b527344d6d109c77d77501acf)]
61
+ - close nav on tablet or mobile resolution by default [David Ichim - [`9e119d2`](https://github.com/eea/volto-eea-website-policy/commit/9e119d23d50dd5a614279da6ec3ccc369a16ba19)]
62
+ - dropped useless code [David Ichim - [`7f5c122`](https://github.com/eea/volto-eea-website-policy/commit/7f5c122c596eb4db7f0ea4c81708b3c88aca657b)]
63
+ - Added initial context navigation block test for both Default and Accordion variations [David Ichim - [`7257385`](https://github.com/eea/volto-eea-website-policy/commit/7257385a69f3b7b3541c1a78588504812741d59f)]
64
+ - more sonarqube warning fixing [David Ichim - [`e676f77`](https://github.com/eea/volto-eea-website-policy/commit/e676f77a35578ddbc7f03d7c340084d24375bc67)]
65
+ - Removed leftover schema enhancer in favor of normal schema editing [David Ichim - [`b67f3c4`](https://github.com/eea/volto-eea-website-policy/commit/b67f3c412bd31efb1a4bbe2b6b6e1140a55bc32a)]
66
+ - fix sonarqube warning regarding missing onKeyDown for summary tag [David Ichim - [`e0fabbf`](https://github.com/eea/volto-eea-website-policy/commit/e0fabbf31609d8e3c706b13ae09c5c52f6a836c7)]
67
+ - use accordion-list-title instead of title class [David Ichim - [`4ee90f2`](https://github.com/eea/volto-eea-website-policy/commit/4ee90f23d3e3d306c5b26bcd405cc85df390f34d)]
68
+ - Added aria-controls, aria-labelledby and region role for better a11y support for accordion [David Ichim - [`a946170`](https://github.com/eea/volto-eea-website-policy/commit/a946170070dd9edd198338f70f19cd47e75e22d7)]
69
+ - bump size of accordion open close icon [David Ichim - [`b42ee13`](https://github.com/eea/volto-eea-website-policy/commit/b42ee1368ec83c2dc7f724d5e417d8b14c337459)]
70
+ - Added extra classes needed to properly style the accordion style context-navigation [David Ichim - [`bdd5aca`](https://github.com/eea/volto-eea-website-policy/commit/bdd5aca036e81de505051c4d84099bc0c37d54e1)]
71
+ - Improve filtering of navigation using portal_type passed to restapi [David Ichim - [`3a4ae52`](https://github.com/eea/volto-eea-website-policy/commit/3a4ae525a028445bb03686a68c4aeb926fdac39b)]
72
+ - WIP: filter portal_types in contextNavigation block [nileshgulia1 - [`b417ca1`](https://github.com/eea/volto-eea-website-policy/commit/b417ca14397da944220508df75ab38cd8a36f22d)]
73
+ - Lint fix [David Ichim - [`c41d684`](https://github.com/eea/volto-eea-website-policy/commit/c41d68481325009a918078f9870c22e9253638e4)]
74
+ - Added classes to ul and li of accordion context navigation [David Ichim - [`08cd8a6`](https://github.com/eea/volto-eea-website-policy/commit/08cd8a653308a49a137529264536e8aa024c6580)]
75
+ - Fix: also add expand icon when no name is set [nileshgulia1 - [`a06ab09`](https://github.com/eea/volto-eea-website-policy/commit/a06ab0989dc46962a68913dc8836be69d0349a04)]
7
76
  ### [2.2.3](https://github.com/eea/volto-eea-website-policy/compare/2.2.2...2.2.3) - 19 September 2024
8
77
 
9
78
  #### :rocket: New Features
package/locales/volto.pot CHANGED
@@ -1,16 +1,21 @@
1
1
  msgid ""
2
2
  msgstr ""
3
3
  "Project-Id-Version: Plone\n"
4
- "POT-Creation-Date: 2023-06-28T10:48:22.678Z\n"
4
+ "POT-Creation-Date: 2024-09-02T18:05:47.779Z\n"
5
5
  "Last-Translator: Plone i18n <plone-i18n@lists.sourceforge.net>\n"
6
6
  "Language-Team: Plone i18n <plone-i18n@lists.sourceforge.net>\n"
7
- "MIME-Version: 1.0\n"
8
7
  "Content-Type: text/plain; charset=utf-8\n"
9
8
  "Content-Transfer-Encoding: 8bit\n"
10
9
  "Plural-Forms: nplurals=1; plural=0;\n"
10
+ "MIME-Version: 1.0\n"
11
11
  "Language-Code: en\n"
12
12
  "Language-Name: English\n"
13
13
  "Preferred-Encodings: utf-8\n"
14
14
  "Domain: volto\n"
15
15
 
16
-
16
+ #. Default: "Navigation"
17
+ #: components/Blocks/ContextNavigation/variations/Accordion
18
+ #: components/Blocks/ContextNavigation/variations/AccordionClaude
19
+ #: components/Blocks/ContextNavigation/variations/AccordionOriginal
20
+ msgid "Navigation"
21
+ msgstr ""
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eeacms/volto-eea-website-policy",
3
- "version": "2.2.3",
3
+ "version": "2.3.1",
4
4
  "description": "@eeacms/volto-eea-website-policy: Volto add-on",
5
5
  "main": "src/index.js",
6
6
  "author": "European Environment Agency: IDM2 A-Team",
@@ -17,12 +17,10 @@
17
17
  "url": "git@github.com:eea/volto-eea-website-policy.git"
18
18
  },
19
19
  "addons": [
20
- "@eeacms/volto-block-toc",
21
20
  "@eeacms/volto-widget-dataprovenance",
22
21
  "@plone-collective/volto-authomatic"
23
22
  ],
24
23
  "dependencies": {
25
- "@eeacms/volto-block-toc": "*",
26
24
  "@eeacms/volto-widget-dataprovenance": "*",
27
25
  "@plone-collective/volto-authomatic": "*"
28
26
  },
@@ -0,0 +1,371 @@
1
+ /**
2
+ * Edit html block.
3
+ * @module components/manage/Blocks/HTML/Edit
4
+ */
5
+
6
+ import { compose } from 'redux';
7
+ import React, { Component } from 'react';
8
+ import PropTypes from 'prop-types';
9
+ import { Button, Popup } from 'semantic-ui-react';
10
+ import { defineMessages, injectIntl } from 'react-intl';
11
+ import loadable from '@loadable/component';
12
+ import { isEqual } from 'lodash';
13
+
14
+ import { Icon } from '@plone/volto/components';
15
+ import { injectLazyLibs } from '@plone/volto/helpers/Loadable/Loadable';
16
+ import showSVG from '@plone/volto/icons/show.svg';
17
+ // import clearSVG from '@plone/volto/icons/clear.svg';
18
+ // import codeSVG from '@plone/volto/icons/code.svg';
19
+ // import indentSVG from '@plone/volto/icons/indent.svg';
20
+
21
+ const Editor = loadable(() => import('react-simple-code-editor'));
22
+
23
+ const messages = defineMessages({
24
+ source: {
25
+ id: 'Source',
26
+ defaultMessage: 'Source',
27
+ },
28
+ preview: {
29
+ id: 'Preview',
30
+ defaultMessage: 'Preview',
31
+ },
32
+ placeholder: {
33
+ id: '<p>Add some HTML here</p>',
34
+ defaultMessage: '<p>Add some HTML here</p>',
35
+ },
36
+ prettier: {
37
+ id: 'Prettify your code',
38
+ defaultMessage: 'Prettify your code',
39
+ },
40
+ clear: {
41
+ id: 'Clear',
42
+ defaultMessage: 'Clear',
43
+ },
44
+ code: {
45
+ id: 'Code',
46
+ defaultMessage: 'Code',
47
+ },
48
+ });
49
+
50
+ /**
51
+ * Edit html block class.
52
+ * @class Edit
53
+ * @extends Component
54
+ */
55
+ class Edit extends Component {
56
+ /**
57
+ * Property types.
58
+ * @property {Object} propTypes Property types.
59
+ * @static
60
+ */
61
+ static propTypes = {
62
+ selected: PropTypes.bool.isRequired,
63
+ block: PropTypes.string.isRequired,
64
+ index: PropTypes.number.isRequired,
65
+ data: PropTypes.objectOf(PropTypes.any).isRequired,
66
+ onChangeBlock: PropTypes.func.isRequired,
67
+ onSelectBlock: PropTypes.func.isRequired,
68
+ onDeleteBlock: PropTypes.func.isRequired,
69
+ handleKeyDown: PropTypes.func.isRequired,
70
+ editable: PropTypes.bool,
71
+ };
72
+
73
+ /**
74
+ * Default properties
75
+ * @property {Object} defaultProps Default properties.
76
+ * @static
77
+ */
78
+ static defaultProps = {
79
+ editable: true,
80
+ };
81
+ /**
82
+ * Constructor
83
+ * @method constructor
84
+ * @param {Object} props Component properties
85
+ */
86
+ constructor(props) {
87
+ super(props);
88
+ this.state = {
89
+ isPreview: false,
90
+ };
91
+ this.onChangeCode = this.onChangeCode.bind(this);
92
+ this.onPreview = this.onPreview.bind(this);
93
+ this.onCodeEditor = this.onCodeEditor.bind(this);
94
+ }
95
+
96
+ codeEditorRef = React.createRef();
97
+ savedSelection = {};
98
+
99
+ componentDidUpdate(prevProps, prevState, snapshot) {
100
+ if (this.codeEditorRef.current) {
101
+ this.savedSelection = snapshot;
102
+ this.restoreSelectionAndFocus(this.codeEditorRef.current);
103
+ }
104
+ }
105
+
106
+ /**
107
+ * @param {*} nextProps
108
+ * @param {*} nextState
109
+ * @returns {boolean}
110
+ * @memberof Edit
111
+ */
112
+ shouldComponentUpdate(nextProps) {
113
+ // Always rerender when the DOM node is not created for the Editor (the
114
+ // first call to shouldComponentUpdate).
115
+ if (!this._input) {
116
+ return true;
117
+ }
118
+
119
+ // Rerender the entire component when the Editor in it changes its selection
120
+ // because this way we get a call to getSnapshotBeforeUpdate where we can
121
+ // save the selection.
122
+ return (
123
+ this.props.selected ||
124
+ !isEqual(this.props.data, nextProps.data) ||
125
+ this._input.selectionStart !== this.savedSelection.selectionStart ||
126
+ this._input.selectionEnd !== this.savedSelection.selectionEnd
127
+ );
128
+ }
129
+
130
+ /**
131
+ * Change html handler
132
+ * @method onChangeCode
133
+ * @param {string} code New value html
134
+ * @returns {undefined}
135
+ */
136
+ onChangeCode(code) {
137
+ this.props.onChangeBlock(this.props.block, {
138
+ ...this.props.data,
139
+ html: code,
140
+ });
141
+ }
142
+
143
+ getValue() {
144
+ return this.props.data.html || '';
145
+ }
146
+
147
+ /**
148
+ * Preview mode handler
149
+ * @method onPreview
150
+ * @returns {undefined}
151
+ */
152
+ async onPreview() {
153
+ try {
154
+ const code = (
155
+ await this.props.prettierStandalone.format(this.getValue(), {
156
+ parser: 'html',
157
+ plugins: [this.props.prettierParserHtml],
158
+ })
159
+ ).trim();
160
+ this.setState(
161
+ {
162
+ isPreview: !this.state.isPreview,
163
+ },
164
+ () => this.onChangeCode(code),
165
+ );
166
+ } catch (ex) {
167
+ // error while parsing the user-typed HTML
168
+ // TODO: show a toast notification or something similar to the user
169
+ }
170
+ }
171
+
172
+ /**
173
+ * Prettify handler
174
+ * @method onPrettify
175
+ * @returns {undefined}
176
+ */
177
+ onPrettify = async () => {
178
+ try {
179
+ const code = (
180
+ await this.props.prettierStandalone.format(this.getValue(), {
181
+ parser: 'html',
182
+ plugins: [this.props.prettierParserHtml],
183
+ })
184
+ ).trim();
185
+ this.onChangeCode(code);
186
+ } catch (ex) {
187
+ // error while parsing the user-typed HTML
188
+ // TODO: show a toast notification or something similar to the user
189
+ }
190
+ };
191
+
192
+ /**
193
+ * Code Editor mode handler
194
+ * @method onPreview
195
+ * @returns {undefined}
196
+ */
197
+ onCodeEditor() {
198
+ this.setState({ isPreview: !this.state.isPreview });
199
+ }
200
+
201
+ getSelection = (editor) => {
202
+ if (!editor || !editor._input) {
203
+ return {};
204
+ }
205
+
206
+ return {
207
+ selectionStart: editor._input.selectionStart || 0,
208
+ selectionEnd: editor._input.selectionEnd || 0,
209
+ };
210
+ };
211
+
212
+ getSnapshotBeforeUpdate(prevProps, prevState) {
213
+ return this.codeEditorRef.current
214
+ ? this.getSelection(this.codeEditorRef.current)
215
+ : {};
216
+ }
217
+
218
+ restoreSelectionAndFocus = (editor) => {
219
+ if (!editor || !editor._input) {
220
+ return;
221
+ }
222
+ // Don't restore selection when the block is not selected.
223
+ if (
224
+ this.props.selected &&
225
+ editor._input &&
226
+ typeof this.savedSelection?.selectionStart === 'number' &&
227
+ typeof this.savedSelection?.selectionEnd === 'number'
228
+ ) {
229
+ editor._input.selectionStart = this.savedSelection?.selectionStart;
230
+ editor._input.selectionEnd = this.savedSelection?.selectionEnd;
231
+ editor._input.focus();
232
+ }
233
+ };
234
+
235
+ /**
236
+ * Render method.
237
+ * @method render
238
+ * @returns {string} Markup for the component.
239
+ */
240
+ render() {
241
+ const placeholder =
242
+ this.props.data.placeholder ||
243
+ this.props.intl.formatMessage(messages.placeholder);
244
+ const value = this.getValue();
245
+ return (
246
+ <>
247
+ {this.props.selected && value && (
248
+ <div className="toolbar">
249
+ {/* Hide temporary this feature in toolbar.*/}
250
+ {/* <Popup
251
+ trigger={
252
+ <Button
253
+ icon
254
+ basic
255
+ aria-label={this.props.intl.formatMessage(messages.source)}
256
+ active={!this.state.isPreview}
257
+ onClick={this.onCodeEditor}
258
+ >
259
+ <Icon name={codeSVG} size="24px" />
260
+ </Button>
261
+ }
262
+ position="top center"
263
+ content={this.props.intl.formatMessage(messages.code)}
264
+ size="mini"
265
+ /> */}
266
+ <Popup
267
+ trigger={
268
+ <Button
269
+ icon
270
+ basic
271
+ aria-label={this.props.intl.formatMessage(messages.preview)}
272
+ active={this.state.isPreview}
273
+ onClick={this.onPreview}
274
+ >
275
+ <Icon name={showSVG} size="24px" />
276
+ </Button>
277
+ }
278
+ position="top center"
279
+ content={this.props.intl.formatMessage(messages.preview)}
280
+ size="mini"
281
+ />
282
+ {/* Hide temporary this feature in toolbar. */}
283
+ {/* <Popup
284
+ trigger={
285
+ <Button
286
+ icon
287
+ basic
288
+ aria-label={this.props.intl.formatMessage(messages.prettier)}
289
+ onClick={this.onPrettify}
290
+ >
291
+ <Icon name={indentSVG} size="24px" />
292
+ </Button>
293
+ }
294
+ position="top center"
295
+ content={this.props.intl.formatMessage(messages.prettier)}
296
+ size="mini"
297
+ />
298
+ <div className="separator" />
299
+ <Popup
300
+ trigger={
301
+ <Button.Group>
302
+ <Button icon basic onClick={() => this.onChangeCode('')}>
303
+ <Icon name={clearSVG} size="24px" color="#e40166" />
304
+ </Button>
305
+ </Button.Group>
306
+ }
307
+ position="top center"
308
+ content={this.props.intl.formatMessage(messages.clear)}
309
+ size="mini"
310
+ /> */}
311
+ </div>
312
+ )}
313
+ {this.state.isPreview ? (
314
+ <div dangerouslySetInnerHTML={{ __html: value }} />
315
+ ) : (
316
+ <Editor
317
+ value={this.getValue()}
318
+ readOnly={true}
319
+ placeholder={placeholder}
320
+ onValueChange={(code) => this.onChangeCode(code)}
321
+ highlight={
322
+ this.props.prismCore?.highlight &&
323
+ this.props.prismCore?.languages?.html
324
+ ? (code) =>
325
+ this.props.prismCore.highlight(
326
+ code,
327
+ this.props.prismCore.languages.html,
328
+ 'html',
329
+ )
330
+ : () => {}
331
+ }
332
+ padding={8}
333
+ className="html-editor"
334
+ ref={(node) => {
335
+ if (node) {
336
+ this.codeEditorRef.current = node;
337
+ }
338
+ }}
339
+ ignoreTabKey={true}
340
+ />
341
+ )}
342
+ </>
343
+ );
344
+ }
345
+ }
346
+
347
+ const withPrismMarkup = (WrappedComponent) => (props) => {
348
+ const [loaded, setLoaded] = React.useState();
349
+ const promise = React.useRef(null);
350
+ const cancelled = React.useRef(false);
351
+
352
+ React.useEffect(() => {
353
+ promise.current = import('prismjs/components/prism-markup');
354
+ promise.current.then(() => {
355
+ if (!cancelled.current) {
356
+ setLoaded(true);
357
+ }
358
+ });
359
+ return () => {
360
+ cancelled.current = true;
361
+ };
362
+ }, []);
363
+
364
+ return loaded ? <WrappedComponent {...props} /> : null;
365
+ };
366
+
367
+ export default compose(
368
+ injectLazyLibs(['prettierStandalone', 'prettierParserHtml', 'prismCore']),
369
+ withPrismMarkup,
370
+ injectIntl,
371
+ )(Edit);
package/src/index.js CHANGED
@@ -1,5 +1,4 @@
1
1
  import { runtimeConfig } from '@plone/volto/runtime_config';
2
- import installContextNavigationBlock from '@eeacms/volto-eea-website-policy/components/Blocks/ContextNavigation';
3
2
  import { appendGroup } from './helpers';
4
3
  import { FrequencyOfDissemination } from '@eeacms/volto-eea-website-policy/components/Widgets/FrequencyOfDissemination';
5
4
 
@@ -13,6 +12,9 @@ const restrictedBlocks = [
13
12
  'dataqueryfilter',
14
13
  'dottedTableChart',
15
14
  'simpleDataConnectedTable',
15
+ 'video',
16
+ 'maps',
17
+ 'html',
16
18
  ];
17
19
 
18
20
  const overrideBlocks = {
@@ -98,14 +100,6 @@ const applyConfig = (config) => {
98
100
  ...config.settings.eea,
99
101
  rolesWhoCanChangeLayout: ['Manager'],
100
102
  };
101
- config.settings.eea.rolesWhoCanChangeLayout = ['Manager'];
102
-
103
- // Custom blocks
104
- // context navigation
105
- config = [installContextNavigationBlock].reduce(
106
- (acc, apply) => apply(acc),
107
- config,
108
- );
109
103
 
110
104
  // Add groups
111
105
  config.blocks.groupBlocksOrder = appendGroup(
@@ -1,45 +0,0 @@
1
- import React from 'react';
2
- import { EditSchema } from './schema';
3
- import { SidebarPortal } from '@plone/volto/components';
4
- import BlockDataForm from '@plone/volto/components/manage/Form/BlockDataForm';
5
-
6
- import ContextNavigationView from './ContextNavigationView';
7
-
8
- const ContextNavigationFillEdit = (props) => {
9
- const contentTypes = props.properties?.['@components']?.types;
10
- const availableTypes = React.useMemo(
11
- () => contentTypes?.map((type) => [type.id, type.title || type.name]),
12
- [contentTypes],
13
- );
14
-
15
- const schema = React.useMemo(
16
- () => EditSchema({ availableTypes }),
17
- [availableTypes],
18
- );
19
-
20
- return (
21
- <>
22
- <h3>Context navigation</h3>
23
- <ContextNavigationView {...props} mode="edit" />{' '}
24
- <SidebarPortal selected={props.selected}>
25
- <BlockDataForm
26
- schema={schema}
27
- title={schema.title}
28
- onChangeField={(id, value) => {
29
- props.onChangeBlock(props.block, {
30
- ...props.data,
31
- [id]: value,
32
- });
33
- }}
34
- onChangeBlock={props.onChangeBlock}
35
- formData={props.data}
36
- block={props.block}
37
- navRoot={props.navRoot}
38
- contentType={props.contentType}
39
- />
40
- </SidebarPortal>
41
- </>
42
- );
43
- };
44
-
45
- export default ContextNavigationFillEdit;
@@ -1,88 +0,0 @@
1
- import React from 'react';
2
- import { render, fireEvent } from '@testing-library/react';
3
- import ContextNavigationEdit from './ContextNavigationEdit';
4
- import { Router } from 'react-router-dom';
5
- import { Provider } from 'react-intl-redux';
6
- import configureStore from 'redux-mock-store';
7
- import { createMemoryHistory } from 'history';
8
- import '@testing-library/jest-dom/extend-expect';
9
-
10
- jest.mock('@plone/volto/components', () => ({
11
- InlineForm: ({ onChangeField }) => (
12
- <div>
13
- <p>InlineForm</p>
14
- <input id="test" onChange={onChangeField} />
15
- </div>
16
- ),
17
- SidebarPortal: ({ children, selected }) =>
18
- selected ? (
19
- <div>
20
- <div>SidebarPortal</div>
21
- {children}
22
- </div>
23
- ) : null,
24
- }));
25
-
26
- jest.mock('@plone/volto/components/theme/Navigation/ContextNavigation', () => {
27
- return {
28
- __esModule: true,
29
- default: ({ params }) => {
30
- return <div>ConnectedContextNavigation {params.root_path}</div>;
31
- },
32
- };
33
- });
34
-
35
- jest.mock('@plone/volto/helpers', () => ({
36
- withBlockExtensions: jest.fn((Component) => Component),
37
- emptyBlocksForm: jest.fn(),
38
- getBlocksLayoutFieldname: () => 'blocks_layout',
39
- withVariationSchemaEnhancer: jest.fn((Component) => Component),
40
- }));
41
-
42
- const mockStore = configureStore();
43
- const store = mockStore({
44
- intl: {
45
- locale: 'en',
46
- messages: {},
47
- },
48
- });
49
-
50
- describe('ContextNavigationEdit', () => {
51
- it('renders corectly', () => {
52
- const history = createMemoryHistory();
53
- const { getByText, queryByText } = render(
54
- <Provider store={store}>
55
- <Router history={history}>
56
- <ContextNavigationEdit selected={false} />
57
- </Router>
58
- ,
59
- </Provider>,
60
- );
61
-
62
- expect(getByText('Context navigation')).toBeInTheDocument();
63
- expect(getByText('ConnectedContextNavigation')).toBeInTheDocument();
64
- expect(queryByText('InlineForm')).toBeNull();
65
- expect(queryByText('SidebarPortal')).toBeNull();
66
- });
67
-
68
- it('renders corectly', () => {
69
- const history = createMemoryHistory();
70
- const { container, getByText } = render(
71
- <Provider store={store}>
72
- <Router history={history}>
73
- <ContextNavigationEdit selected={true} onChangeBlock={() => {}} />
74
- </Router>
75
- ,
76
- </Provider>,
77
- );
78
-
79
- expect(getByText('Context navigation')).toBeInTheDocument();
80
- expect(getByText('ConnectedContextNavigation')).toBeInTheDocument();
81
- expect(getByText('InlineForm')).toBeInTheDocument();
82
- expect(getByText('SidebarPortal')).toBeInTheDocument();
83
-
84
- fireEvent.change(container.querySelector('#test'), {
85
- target: { value: 'test' },
86
- });
87
- });
88
- });
@@ -1,14 +0,0 @@
1
- import React from 'react';
2
- import { flattenToAppURL, withBlockExtensions } from '@plone/volto/helpers';
3
- import DefaultTemplate from './variations/Default';
4
-
5
- const ContextNavigationView = (props = {}) => {
6
- const { variation, data = {} } = props;
7
- const navProps = { ...data };
8
- const root_path = data?.root_node?.[0]?.['@id'];
9
- if (root_path) navProps['root_path'] = flattenToAppURL(root_path);
10
- const Renderer = variation?.view ?? DefaultTemplate;
11
- return <Renderer params={navProps} mode={props.mode} />;
12
- };
13
-
14
- export default withBlockExtensions(ContextNavigationView);
@@ -1,71 +0,0 @@
1
- import React from 'react';
2
- import { render } from '@testing-library/react';
3
- import ContextNavigationView from './ContextNavigationView';
4
- import { Router } from 'react-router-dom';
5
- import { Provider } from 'react-intl-redux';
6
- import configureStore from 'redux-mock-store';
7
- import { createMemoryHistory } from 'history';
8
- import '@testing-library/jest-dom/extend-expect';
9
-
10
- jest.mock('@plone/volto/components/theme/Navigation/ContextNavigation', () => {
11
- return {
12
- __esModule: true,
13
- default: ({ params }) => {
14
- return <div>ConnectedContextNavigation {params.root_path}</div>;
15
- },
16
- };
17
- });
18
-
19
- jest.mock('@plone/volto/helpers', () => ({
20
- withBlockExtensions: jest.fn((Component) => Component),
21
- emptyBlocksForm: jest.fn(),
22
- getBlocksLayoutFieldname: () => 'blocks_layout',
23
- flattenToAppURL: () => '',
24
- }));
25
-
26
- const mockStore = configureStore();
27
- const store = mockStore({
28
- intl: {
29
- locale: 'en',
30
- messages: {},
31
- },
32
- });
33
-
34
- describe('ContextNavigationView', () => {
35
- let history;
36
- beforeEach(() => {
37
- history = createMemoryHistory();
38
- });
39
-
40
- it('renders corectly', () => {
41
- const { container } = render(
42
- <Provider store={store}>
43
- <Router history={history}>
44
- <ContextNavigationView />
45
- </Router>
46
- </Provider>,
47
- );
48
-
49
- expect(container.firstChild).toHaveTextContent(
50
- 'ConnectedContextNavigation',
51
- );
52
- });
53
-
54
- it('renders corectly', () => {
55
- const { container } = render(
56
- <Provider store={store}>
57
- <Router history={history}>
58
- <ContextNavigationView
59
- data={{
60
- navProps: { root_path: 'https://localhost:3000/test' },
61
- root_node: [{ '@id': 'root_node' }],
62
- }}
63
- />
64
- </Router>
65
- </Provider>,
66
- );
67
- expect(container.firstChild).toHaveTextContent(
68
- 'ConnectedContextNavigation',
69
- );
70
- });
71
- });
@@ -1,30 +0,0 @@
1
- import codeSVG from '@plone/volto/icons/code.svg';
2
- import ContextNavigationEdit from './ContextNavigationEdit';
3
- import ContextNavigationView from './ContextNavigationView';
4
- import BlockSettingsSchema from '@plone/volto/components/manage/Blocks/Block/Schema';
5
- import variations from './variations';
6
-
7
- const applyConfig = (config) => {
8
- config.blocks.blocksConfig.contextNavigation = {
9
- id: 'contextNavigation',
10
- title: 'Navigation',
11
- icon: codeSVG,
12
- group: 'site',
13
- view: ContextNavigationView,
14
- edit: ContextNavigationEdit,
15
- schema: BlockSettingsSchema,
16
- restricted: true,
17
- variations,
18
- mostUsed: true,
19
- blockHasOwnFocusManagement: true,
20
- sidebarTab: 1,
21
- security: {
22
- addPermission: [],
23
- view: [],
24
- },
25
- };
26
-
27
- return config;
28
- };
29
-
30
- export default applyConfig;
@@ -1,88 +0,0 @@
1
- export const EditSchema = ({ availableTypes }) => {
2
- return {
3
- title: 'Navigation',
4
- fieldsets: [
5
- {
6
- id: 'default',
7
- title: 'Default',
8
- fields: [
9
- 'name',
10
- 'root_node',
11
- 'portal_type',
12
- 'includeTop',
13
- 'currentFolderOnly',
14
- 'topLevel',
15
- 'bottomLevel',
16
- 'no_icons',
17
- 'thumb_scale',
18
- 'no_thumbs',
19
- ],
20
- },
21
- ],
22
- required: [],
23
- properties: {
24
- name: {
25
- title: 'Title',
26
- description: 'The title of the navigation tree',
27
- },
28
- root_node: {
29
- title: 'Root node',
30
- description:
31
- 'You may search for and choose a folder to act as the root of the navigation tree. Leave blank to use the Plone site root.',
32
- widget: 'object_browser',
33
- // TODO: these don't work. Why?
34
- mode: 'link',
35
- selectedItemAttrs: ['Title', 'Description'],
36
- },
37
- portal_type: {
38
- title: 'Filter children',
39
- description: 'Only show child items of this content type',
40
- choices: availableTypes,
41
- isMulti: true,
42
- },
43
- includeTop: {
44
- title: 'Include top node',
45
- description:
46
- "Whether or not to show the top, or 'root', node in the navigation tree. This is affected by the 'Start level' setting.",
47
- type: 'boolean',
48
- },
49
- currentFolderOnly: {
50
- title: 'Only show the contents of the current folder',
51
- description:
52
- 'If selected, the navigation tree will only show the current folder and its children at all times.',
53
- type: 'boolean',
54
- },
55
-
56
- topLevel: {
57
- title: 'Start level',
58
- description:
59
- 'An integer value that specifies the number of folder levels below the site root that must be exceeded before the navigation tree will display. 0 means that the navigation tree should be displayed everywhere including pages in the root of the site. 1 means the tree only shows up inside folders located in the root and downwards, never showing at the top level.',
60
- type: 'number',
61
- default: 1,
62
- },
63
- bottomLevel: {
64
- title: 'Navigation tree depth',
65
- description:
66
- 'How many folders should be included before the navigation tree stops. 0 means no limit. 1 only includes the root folder.',
67
- type: 'number',
68
- default: 0,
69
- },
70
- no_icons: {
71
- title: 'Suppress icons',
72
- description:
73
- 'If enabled, the portlet will not show document type icons.',
74
- type: 'boolean',
75
- },
76
- thumb_scale: {
77
- title: 'Override thumb scale',
78
- description:
79
- "Enter a valid scale name (see 'Image Handling' control panel) to override (e.g. icon, tile, thumb, mini, preview, ... ). Leave empty to use default (see 'Site' control panel).",
80
- },
81
- no_thumbs: {
82
- title: 'Suppress thumbs',
83
- type: 'boolean',
84
- description: 'If enabled, the portlet will not show thumbs.',
85
- },
86
- },
87
- };
88
- };
@@ -1,175 +0,0 @@
1
- import cx from 'classnames';
2
- import PropTypes from 'prop-types';
3
- import React from 'react';
4
- import { defineMessages, useIntl } from 'react-intl';
5
- import { withRouter } from 'react-router';
6
- import { compose } from 'redux';
7
- import { Accordion } from 'semantic-ui-react';
8
-
9
- import Slugger from 'github-slugger';
10
-
11
- import { Icon, UniversalLink } from '@plone/volto/components';
12
- import { withContentNavigation } from '@plone/volto/components/theme/Navigation/withContentNavigation';
13
- import withEEASideMenu from '@eeacms/volto-block-toc/hocs/withEEASideMenu';
14
- import { flattenToAppURL } from '@plone/volto/helpers';
15
-
16
- import downIcon from '@plone/volto/icons/down-key.svg';
17
- import upIcon from '@plone/volto/icons/up-key.svg';
18
-
19
- const messages = defineMessages({
20
- navigation: {
21
- id: 'Navigation',
22
- defaultMessage: 'Navigation',
23
- },
24
- });
25
-
26
- const AccordionNavigation = ({
27
- navigation = {},
28
- device,
29
- isMenuOpenOnOutsideClick,
30
- }) => {
31
- const { items = [], title, has_custom_name } = navigation;
32
- const intl = useIntl();
33
- const navOpen = ['mobile', 'tablet'].includes(device) ? false : true;
34
- const [isNavOpen, setIsNavOpen] = React.useState(navOpen);
35
- const [activeItems, setActiveItems] = React.useState({});
36
-
37
- const onClickSummary = React.useCallback((e) => {
38
- e.preventDefault();
39
- setIsNavOpen((prev) => !prev);
40
- }, []);
41
-
42
- React.useEffect(() => {
43
- if (isMenuOpenOnOutsideClick === false) setIsNavOpen(false);
44
- }, [isMenuOpenOnOutsideClick]);
45
-
46
- const onKeyDownSummary = React.useCallback(
47
- (e) => {
48
- if (e.keyCode === 13 || e.keyCode === 32) {
49
- e.preventDefault();
50
- onClickSummary(e);
51
- }
52
- },
53
- [onClickSummary],
54
- );
55
-
56
- const renderItems = ({ item, level = 0 }) => {
57
- const {
58
- title,
59
- href,
60
- is_current,
61
- is_in_path,
62
- items: childItems,
63
- type,
64
- } = item;
65
- const hasChildItems = childItems && childItems.length > 0;
66
- const normalizedTitle = Slugger.slug(title);
67
-
68
- const checkIfActive = () => {
69
- return activeItems[href] !== undefined ? activeItems[href] : is_in_path;
70
- };
71
-
72
- const isActive = checkIfActive();
73
-
74
- const handleTitleClick = () => {
75
- setActiveItems((prev) => ({ ...prev, [href]: !isActive }));
76
- };
77
-
78
- return (
79
- <li
80
- className={cx({
81
- is_in_path,
82
- 'accordion-list-title': !hasChildItems,
83
- 'accordion-list-item': hasChildItems,
84
- })}
85
- key={href}
86
- >
87
- {hasChildItems ? (
88
- <Accordion className="default">
89
- <Accordion.Title
90
- active={isActive}
91
- as={'button'}
92
- aria-expanded={isActive}
93
- onClick={handleTitleClick}
94
- aria-controls={`accordion-content-${normalizedTitle}`}
95
- id={`accordion-title-${normalizedTitle}`}
96
- >
97
- <span className="title-text">{title}</span>
98
- <Icon name={isActive ? upIcon : downIcon} size="32px" />
99
- </Accordion.Title>
100
- <Accordion.Content
101
- active={isActive}
102
- id={`accordion-content-${normalizedTitle}`}
103
- aria-labelledby={`accordion-title-${normalizedTitle}`}
104
- role="region"
105
- >
106
- <ul className="accordion-list">
107
- {childItems.map((child) =>
108
- renderItems({ item: child, level: level + 1 }),
109
- )}
110
- </ul>
111
- </Accordion.Content>
112
- </Accordion>
113
- ) : (
114
- <UniversalLink
115
- href={flattenToAppURL(href)}
116
- className={cx(`title-link contenttype-${type}`, {
117
- current: is_current,
118
- in_path: is_in_path,
119
- })}
120
- >
121
- {title}
122
- </UniversalLink>
123
- )}
124
- </li>
125
- );
126
- };
127
-
128
- return items.length ? (
129
- <>
130
- <nav className="context-navigation">
131
- <details open={isNavOpen}>
132
- {/* eslint-disable-next-line */}
133
- <summary
134
- className="context-navigation-header accordion-header"
135
- onClick={onClickSummary}
136
- onKeyDown={onKeyDownSummary}
137
- >
138
- {has_custom_name ? title : intl.formatMessage(messages.navigation)}
139
- <Icon name={isNavOpen ? upIcon : downIcon} size="40px" />
140
- </summary>
141
- <ul className="context-navigation-list accordion-list">
142
- {items.map((item) => renderItems({ item }))}
143
- </ul>
144
- </details>
145
- </nav>
146
- </>
147
- ) : null;
148
- };
149
-
150
- AccordionNavigation.propTypes = {
151
- /**
152
- * Navigation tree returned from @contextnavigation restapi endpoint
153
- */
154
- navigation: PropTypes.shape({
155
- items: PropTypes.arrayOf(
156
- PropTypes.shape({
157
- title: PropTypes.string,
158
- url: PropTypes.string,
159
- href: PropTypes.string,
160
- is_current: PropTypes.bool,
161
- is_in_path: PropTypes.bool,
162
- items: PropTypes.array,
163
- type: PropTypes.string,
164
- }),
165
- ),
166
- has_custom_name: PropTypes.bool,
167
- title: PropTypes.string,
168
- }),
169
- };
170
-
171
- export default compose(
172
- withRouter,
173
- withContentNavigation,
174
- withEEASideMenu,
175
- )(AccordionNavigation);
@@ -1,9 +0,0 @@
1
- import React from 'react';
2
- import ConnectedContextNavigation from '@plone/volto/components/theme/Navigation/ContextNavigation';
3
-
4
- const Default = (props) => {
5
- const { params } = props;
6
- return <ConnectedContextNavigation params={params} />;
7
- };
8
-
9
- export default Default;
@@ -1,18 +0,0 @@
1
- import Accordion from './Accordion';
2
- import Default from './Default';
3
-
4
- const contextBlockVariations = [
5
- {
6
- id: 'default',
7
- title: 'Listing (default)',
8
- view: Default,
9
- isDefault: true,
10
- },
11
- {
12
- id: 'accordion',
13
- title: 'Accordion',
14
- view: Accordion,
15
- },
16
- ];
17
-
18
- export default contextBlockVariations;