@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 +69 -0
- package/locales/volto.pot +8 -3
- package/package.json +1 -3
- package/src/customizations/volto/components/manage/Blocks/HTML/Edit.jsx +371 -0
- package/src/index.js +3 -9
- package/src/components/Blocks/ContextNavigation/ContextNavigationEdit.jsx +0 -45
- package/src/components/Blocks/ContextNavigation/ContextNavigationEdit.test.jsx +0 -88
- package/src/components/Blocks/ContextNavigation/ContextNavigationView.jsx +0 -14
- package/src/components/Blocks/ContextNavigation/ContextNavigationView.test.jsx +0 -71
- package/src/components/Blocks/ContextNavigation/index.js +0 -30
- package/src/components/Blocks/ContextNavigation/schema.js +0 -88
- package/src/components/Blocks/ContextNavigation/variations/Accordion.jsx +0 -175
- package/src/components/Blocks/ContextNavigation/variations/Default.jsx +0 -9
- package/src/components/Blocks/ContextNavigation/variations/index.js +0 -18
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:
|
|
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.
|
|
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;
|