@eeacms/volto-eea-website-theme 1.20.0 → 1.22.0
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/.husky/pre-commit +2 -0
- package/CHANGELOG.md +36 -0
- package/cypress.config.js +2 -2
- package/jest-addon.config.js +4 -4
- package/locales/de/LC_MESSAGES/volto.po +48 -0
- package/locales/en/LC_MESSAGES/volto.po +62 -0
- package/locales/it/LC_MESSAGES/volto.po +48 -0
- package/locales/ro/LC_MESSAGES/volto.po +48 -0
- package/locales/volto.pot +49 -1
- package/package.json +28 -2
- package/src/components/manage/Blocks/GroupBlockTemplate/FlexGroup/FlexGroup.jsx +128 -0
- package/src/components/manage/Blocks/GroupBlockTemplate/FlexGroup/RenderBlocks.jsx +75 -0
- package/src/components/manage/Blocks/GroupBlockTemplate/FlexGroup/editor-flex.less +14 -0
- package/src/components/manage/Blocks/Title/schema.js +4 -0
- package/src/components/theme/Banner/View.jsx +2 -0
- package/src/customizations/@root/theme.js +2 -0
- package/src/customizations/volto/components/manage/Blocks/LeadImage/AlignChooser.jsx +1 -1
- package/src/customizations/volto/components/manage/Blocks/LeadImage/AlignChooser.test.js +50 -0
- package/src/customizations/volto/components/manage/Sharing/Sharing.jsx +55 -22
- package/src/customizations/volto/components/manage/Sharing/Sharing.test.jsx +72 -0
- package/src/customizations/volto/components/theme/ContactForm/ContactForm.test.js +66 -0
- package/src/index.js +27 -0
package/CHANGELOG.md
CHANGED
@@ -4,6 +4,42 @@ 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.22.0](https://github.com/eea/volto-eea-website-theme/compare/1.21.0...1.22.0) - 26 September 2023
|
8
|
+
|
9
|
+
#### :rocket: New Features
|
10
|
+
|
11
|
+
- feat: Sync Sharing component customzation to Volto 16.24.0 - refs #256039 [Alin Voinea - [`5dd215e`](https://github.com/eea/volto-eea-website-theme/commit/5dd215e4782e3ef47d558a8d57f979979496e5d9)]
|
12
|
+
|
13
|
+
#### :bug: Bug Fixes
|
14
|
+
|
15
|
+
- fix(tests): fix failing cypress tests [kreafox - [`6f729e4`](https://github.com/eea/volto-eea-website-theme/commit/6f729e40780cd02999685382f51903e0b988d647)]
|
16
|
+
- fix(tests): fix failing cypress tests [kreafox - [`cccf2c5`](https://github.com/eea/volto-eea-website-theme/commit/cccf2c561621e60ae76b1eab6a34a078f72b6bce)]
|
17
|
+
- fix(tests): fix failing cypress tests [kreafox - [`89f7572`](https://github.com/eea/volto-eea-website-theme/commit/89f7572850928501812b7cbaeea2db7346aeda82)]
|
18
|
+
- fix(tests): fix failing cypress tests [kreafox - [`fc4d65d`](https://github.com/eea/volto-eea-website-theme/commit/fc4d65de6b437cf699f70babb76de80be9b80681)]
|
19
|
+
|
20
|
+
#### :house: Internal changes
|
21
|
+
|
22
|
+
- style: lint-staged reorder in package.json [Alin Voinea - [`e9db5f2`](https://github.com/eea/volto-eea-website-theme/commit/e9db5f22d8d6b43383d40d3cb6415ee7ab4c9e70)]
|
23
|
+
|
24
|
+
#### :hammer_and_wrench: Others
|
25
|
+
|
26
|
+
- Release 1.22.0 [Alin Voinea - [`50f6493`](https://github.com/eea/volto-eea-website-theme/commit/50f649344153f7501f6e9f917fc0a44923271bd2)]
|
27
|
+
- test: EN locales, pre-commit fix, feature PRs checks Refs #257193 [valentinab25 - [`56b7442`](https://github.com/eea/volto-eea-website-theme/commit/56b744237da1f9ba688b7b2e06a20e1758364c31)]
|
28
|
+
### [1.21.0](https://github.com/eea/volto-eea-website-theme/compare/1.20.0...1.21.0) - 5 September 2023
|
29
|
+
|
30
|
+
#### :house: Internal changes
|
31
|
+
|
32
|
+
- chore: fix tests [nileshgulia1 - [`c432106`](https://github.com/eea/volto-eea-website-theme/commit/c432106e0d5794383b4eac2a0027f4cd2f48cc28)]
|
33
|
+
- chore: add cypress for new code [nileshgulia1 - [`c989488`](https://github.com/eea/volto-eea-website-theme/commit/c989488946b2ab8b9e9da281dd668a0dc49efa56)]
|
34
|
+
- chore: cosmetics [Alin Voinea - [`442b64e`](https://github.com/eea/volto-eea-website-theme/commit/442b64ea3055f4e4f5d5bff9114c90c4a516a512)]
|
35
|
+
|
36
|
+
#### :hammer_and_wrench: Others
|
37
|
+
|
38
|
+
- test: Update ContactForm snapshot [Alin Voinea - [`e322b51`](https://github.com/eea/volto-eea-website-theme/commit/e322b510c3d0aa092d7a30a3af48b1d049aca5bb)]
|
39
|
+
- test: Add jest tests for ContactForm [Alin Voinea - [`e4a4c28`](https://github.com/eea/volto-eea-website-theme/commit/e4a4c2877bdb7c57a361751430c06136a37e37b0)]
|
40
|
+
- test: Add jest tests for AlignChooser [Alin Voinea - [`06edf05`](https://github.com/eea/volto-eea-website-theme/commit/06edf05f8f38c43f9b0bbd7ad45a9d73a7ff66aa)]
|
41
|
+
- bump package version [David Ichim - [`7ba2dd7`](https://github.com/eea/volto-eea-website-theme/commit/7ba2dd7d91183bda602de8da0f7823a1e8016df5)]
|
42
|
+
- i18n: Add en [Alin Voinea - [`e421605`](https://github.com/eea/volto-eea-website-theme/commit/e4216054129654c9ce06962d164b5a28f8c60d2b)]
|
7
43
|
### [1.20.0](https://github.com/eea/volto-eea-website-theme/compare/1.19.0...1.20.0) - 29 August 2023
|
8
44
|
|
9
45
|
#### :bug: Bug Fixes
|
package/cypress.config.js
CHANGED
@@ -2,12 +2,12 @@ const { defineConfig } = require('cypress');
|
|
2
2
|
|
3
3
|
module.exports = defineConfig({
|
4
4
|
viewportWidth: 1280,
|
5
|
-
defaultCommandTimeout:
|
5
|
+
defaultCommandTimeout: 5000,
|
6
6
|
chromeWebSecurity: false,
|
7
7
|
reporter: 'junit',
|
8
8
|
video: true,
|
9
9
|
retries: {
|
10
|
-
runMode:
|
10
|
+
runMode: 1,
|
11
11
|
openMode: 0,
|
12
12
|
},
|
13
13
|
reporterOptions: {
|
package/jest-addon.config.js
CHANGED
@@ -11,4 +11,52 @@ msgstr ""
|
|
11
11
|
"Content-Transfer-Encoding: \n"
|
12
12
|
"Plural-Forms: \n"
|
13
13
|
|
14
|
+
#: components/theme/Banner/View
|
15
|
+
# defaultMessage: Created
|
16
|
+
msgid "Created"
|
17
|
+
msgstr ""
|
18
|
+
|
19
|
+
#: components/theme/Banner/View
|
20
|
+
# defaultMessage: Download
|
21
|
+
msgid "Download"
|
22
|
+
msgstr ""
|
23
|
+
|
24
|
+
#: components/theme/Logo
|
25
|
+
# defaultMessage: European Environment Agency
|
26
|
+
msgid "European Environment Agency"
|
27
|
+
msgstr ""
|
28
|
+
|
29
|
+
#: components/theme/Banner/View
|
30
|
+
# defaultMessage: Modified
|
31
|
+
msgid "Modified"
|
32
|
+
msgstr ""
|
33
|
+
|
34
|
+
#: components/theme/Banner/View
|
35
|
+
# defaultMessage: Published
|
36
|
+
msgid "Published"
|
37
|
+
msgstr ""
|
14
38
|
|
39
|
+
#: components/theme/Banner/View
|
40
|
+
# defaultMessage: Share
|
41
|
+
msgid "Share"
|
42
|
+
msgstr ""
|
43
|
+
|
44
|
+
#: components/theme/Banner/View
|
45
|
+
# defaultMessage: Share to
|
46
|
+
msgid "Share to"
|
47
|
+
msgstr ""
|
48
|
+
|
49
|
+
#: components/theme/Logo
|
50
|
+
# defaultMessage: Site
|
51
|
+
msgid "Site"
|
52
|
+
msgstr ""
|
53
|
+
|
54
|
+
#: components/manage/Blocks/Title/Edit
|
55
|
+
# defaultMessage: Type the title…
|
56
|
+
msgid "Type the title…"
|
57
|
+
msgstr ""
|
58
|
+
|
59
|
+
#: components/theme/Banner/View
|
60
|
+
# defaultMessage: RSS Feed
|
61
|
+
msgid "rssFeed"
|
62
|
+
msgstr ""
|
@@ -0,0 +1,62 @@
|
|
1
|
+
msgid ""
|
2
|
+
msgstr ""
|
3
|
+
"Project-Id-Version: \n"
|
4
|
+
"Report-Msgid-Bugs-To: \n"
|
5
|
+
"POT-Creation-Date: \n"
|
6
|
+
"PO-Revision-Date: \n"
|
7
|
+
"Last-Translator: \n"
|
8
|
+
"Language: \n"
|
9
|
+
"Language-Team: \n"
|
10
|
+
"Content-Type: \n"
|
11
|
+
"Content-Transfer-Encoding: \n"
|
12
|
+
"Plural-Forms: \n"
|
13
|
+
|
14
|
+
#: components/theme/Banner/View
|
15
|
+
# defaultMessage: Created
|
16
|
+
msgid "Created"
|
17
|
+
msgstr ""
|
18
|
+
|
19
|
+
#: components/theme/Banner/View
|
20
|
+
# defaultMessage: Download
|
21
|
+
msgid "Download"
|
22
|
+
msgstr ""
|
23
|
+
|
24
|
+
#: components/theme/Logo
|
25
|
+
# defaultMessage: European Environment Agency
|
26
|
+
msgid "European Environment Agency"
|
27
|
+
msgstr ""
|
28
|
+
|
29
|
+
#: components/theme/Banner/View
|
30
|
+
# defaultMessage: Modified
|
31
|
+
msgid "Modified"
|
32
|
+
msgstr ""
|
33
|
+
|
34
|
+
#: components/theme/Banner/View
|
35
|
+
# defaultMessage: Published
|
36
|
+
msgid "Published"
|
37
|
+
msgstr ""
|
38
|
+
|
39
|
+
#: components/theme/Banner/View
|
40
|
+
# defaultMessage: Share
|
41
|
+
msgid "Share"
|
42
|
+
msgstr ""
|
43
|
+
|
44
|
+
#: components/theme/Banner/View
|
45
|
+
# defaultMessage: Share to
|
46
|
+
msgid "Share to"
|
47
|
+
msgstr ""
|
48
|
+
|
49
|
+
#: components/theme/Logo
|
50
|
+
# defaultMessage: Site
|
51
|
+
msgid "Site"
|
52
|
+
msgstr ""
|
53
|
+
|
54
|
+
#: components/manage/Blocks/Title/Edit
|
55
|
+
# defaultMessage: Type the title…
|
56
|
+
msgid "Type the title…"
|
57
|
+
msgstr ""
|
58
|
+
|
59
|
+
#: components/theme/Banner/View
|
60
|
+
# defaultMessage: RSS Feed
|
61
|
+
msgid "rssFeed"
|
62
|
+
msgstr ""
|
@@ -11,4 +11,52 @@ msgstr ""
|
|
11
11
|
"Content-Transfer-Encoding: \n"
|
12
12
|
"Plural-Forms: \n"
|
13
13
|
|
14
|
+
#: components/theme/Banner/View
|
15
|
+
# defaultMessage: Created
|
16
|
+
msgid "Created"
|
17
|
+
msgstr ""
|
18
|
+
|
19
|
+
#: components/theme/Banner/View
|
20
|
+
# defaultMessage: Download
|
21
|
+
msgid "Download"
|
22
|
+
msgstr ""
|
23
|
+
|
24
|
+
#: components/theme/Logo
|
25
|
+
# defaultMessage: European Environment Agency
|
26
|
+
msgid "European Environment Agency"
|
27
|
+
msgstr ""
|
28
|
+
|
29
|
+
#: components/theme/Banner/View
|
30
|
+
# defaultMessage: Modified
|
31
|
+
msgid "Modified"
|
32
|
+
msgstr ""
|
33
|
+
|
34
|
+
#: components/theme/Banner/View
|
35
|
+
# defaultMessage: Published
|
36
|
+
msgid "Published"
|
37
|
+
msgstr ""
|
14
38
|
|
39
|
+
#: components/theme/Banner/View
|
40
|
+
# defaultMessage: Share
|
41
|
+
msgid "Share"
|
42
|
+
msgstr ""
|
43
|
+
|
44
|
+
#: components/theme/Banner/View
|
45
|
+
# defaultMessage: Share to
|
46
|
+
msgid "Share to"
|
47
|
+
msgstr ""
|
48
|
+
|
49
|
+
#: components/theme/Logo
|
50
|
+
# defaultMessage: Site
|
51
|
+
msgid "Site"
|
52
|
+
msgstr ""
|
53
|
+
|
54
|
+
#: components/manage/Blocks/Title/Edit
|
55
|
+
# defaultMessage: Type the title…
|
56
|
+
msgid "Type the title…"
|
57
|
+
msgstr ""
|
58
|
+
|
59
|
+
#: components/theme/Banner/View
|
60
|
+
# defaultMessage: RSS Feed
|
61
|
+
msgid "rssFeed"
|
62
|
+
msgstr ""
|
@@ -11,4 +11,52 @@ msgstr ""
|
|
11
11
|
"Content-Transfer-Encoding: \n"
|
12
12
|
"Plural-Forms: \n"
|
13
13
|
|
14
|
+
#: components/theme/Banner/View
|
15
|
+
# defaultMessage: Created
|
16
|
+
msgid "Created"
|
17
|
+
msgstr ""
|
18
|
+
|
19
|
+
#: components/theme/Banner/View
|
20
|
+
# defaultMessage: Download
|
21
|
+
msgid "Download"
|
22
|
+
msgstr ""
|
23
|
+
|
24
|
+
#: components/theme/Logo
|
25
|
+
# defaultMessage: European Environment Agency
|
26
|
+
msgid "European Environment Agency"
|
27
|
+
msgstr ""
|
28
|
+
|
29
|
+
#: components/theme/Banner/View
|
30
|
+
# defaultMessage: Modified
|
31
|
+
msgid "Modified"
|
32
|
+
msgstr ""
|
33
|
+
|
34
|
+
#: components/theme/Banner/View
|
35
|
+
# defaultMessage: Published
|
36
|
+
msgid "Published"
|
37
|
+
msgstr ""
|
14
38
|
|
39
|
+
#: components/theme/Banner/View
|
40
|
+
# defaultMessage: Share
|
41
|
+
msgid "Share"
|
42
|
+
msgstr ""
|
43
|
+
|
44
|
+
#: components/theme/Banner/View
|
45
|
+
# defaultMessage: Share to
|
46
|
+
msgid "Share to"
|
47
|
+
msgstr ""
|
48
|
+
|
49
|
+
#: components/theme/Logo
|
50
|
+
# defaultMessage: Site
|
51
|
+
msgid "Site"
|
52
|
+
msgstr ""
|
53
|
+
|
54
|
+
#: components/manage/Blocks/Title/Edit
|
55
|
+
# defaultMessage: Type the title…
|
56
|
+
msgid "Type the title…"
|
57
|
+
msgstr ""
|
58
|
+
|
59
|
+
#: components/theme/Banner/View
|
60
|
+
# defaultMessage: RSS Feed
|
61
|
+
msgid "rssFeed"
|
62
|
+
msgstr ""
|
package/locales/volto.pot
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
msgid ""
|
2
2
|
msgstr ""
|
3
3
|
"Project-Id-Version: Plone\n"
|
4
|
-
"POT-Creation-Date: 2023-
|
4
|
+
"POT-Creation-Date: 2023-08-29T17:13:27.797Z\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
7
|
"MIME-Version: 1.0\n"
|
@@ -13,4 +13,52 @@ msgstr ""
|
|
13
13
|
"Preferred-Encodings: utf-8\n"
|
14
14
|
"Domain: volto\n"
|
15
15
|
|
16
|
+
#: components/theme/Banner/View
|
17
|
+
# defaultMessage: Created
|
18
|
+
msgid "Created"
|
19
|
+
msgstr ""
|
20
|
+
|
21
|
+
#: components/theme/Banner/View
|
22
|
+
# defaultMessage: Download
|
23
|
+
msgid "Download"
|
24
|
+
msgstr ""
|
25
|
+
|
26
|
+
#: components/theme/Logo
|
27
|
+
# defaultMessage: European Environment Agency
|
28
|
+
msgid "European Environment Agency"
|
29
|
+
msgstr ""
|
30
|
+
|
31
|
+
#: components/theme/Banner/View
|
32
|
+
# defaultMessage: Modified
|
33
|
+
msgid "Modified"
|
34
|
+
msgstr ""
|
35
|
+
|
36
|
+
#: components/theme/Banner/View
|
37
|
+
# defaultMessage: Published
|
38
|
+
msgid "Published"
|
39
|
+
msgstr ""
|
16
40
|
|
41
|
+
#: components/theme/Banner/View
|
42
|
+
# defaultMessage: Share
|
43
|
+
msgid "Share"
|
44
|
+
msgstr ""
|
45
|
+
|
46
|
+
#: components/theme/Banner/View
|
47
|
+
# defaultMessage: Share to
|
48
|
+
msgid "Share to"
|
49
|
+
msgstr ""
|
50
|
+
|
51
|
+
#: components/theme/Logo
|
52
|
+
# defaultMessage: Site
|
53
|
+
msgid "Site"
|
54
|
+
msgstr ""
|
55
|
+
|
56
|
+
#: components/manage/Blocks/Title/Edit
|
57
|
+
# defaultMessage: Type the title…
|
58
|
+
msgid "Type the title…"
|
59
|
+
msgstr ""
|
60
|
+
|
61
|
+
#: components/theme/Banner/View
|
62
|
+
# defaultMessage: RSS Feed
|
63
|
+
msgid "rssFeed"
|
64
|
+
msgstr ""
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@eeacms/volto-eea-website-theme",
|
3
|
-
"version": "1.
|
3
|
+
"version": "1.22.0",
|
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",
|
@@ -14,6 +14,7 @@
|
|
14
14
|
"react"
|
15
15
|
],
|
16
16
|
"addons": [
|
17
|
+
"@eeacms/volto-group-block",
|
17
18
|
"@eeacms/volto-eea-design-system",
|
18
19
|
"volto-subsites"
|
19
20
|
],
|
@@ -23,15 +24,39 @@
|
|
23
24
|
},
|
24
25
|
"dependencies": {
|
25
26
|
"@eeacms/volto-eea-design-system": "*",
|
27
|
+
"@eeacms/volto-group-block": "*",
|
26
28
|
"volto-subsites": "*"
|
27
29
|
},
|
28
30
|
"devDependencies": {
|
29
31
|
"@cypress/code-coverage": "^3.10.0",
|
30
32
|
"@plone/scripts": "*",
|
31
33
|
"babel-plugin-transform-class-properties": "^6.24.1",
|
34
|
+
"husky": "*",
|
35
|
+
"lint-staged": "*",
|
32
36
|
"md5": "^2.3.0",
|
33
37
|
"postcss-less": "6.0.0"
|
34
38
|
},
|
39
|
+
"lint-staged": {
|
40
|
+
"src/**/*.{js,jsx,ts,tsx,json}": [
|
41
|
+
"make lint-fix",
|
42
|
+
"make prettier-fix"
|
43
|
+
],
|
44
|
+
"src/**/*.{jsx}": [
|
45
|
+
"make i18n"
|
46
|
+
],
|
47
|
+
"theme/**/*.{css,less}": [
|
48
|
+
"make stylelint-fix"
|
49
|
+
],
|
50
|
+
"src/**/*.{css,less}": [
|
51
|
+
"make stylelint-fix"
|
52
|
+
],
|
53
|
+
"theme/**/*.overrides": [
|
54
|
+
"make stylelint-fix"
|
55
|
+
],
|
56
|
+
"src/**/*.overrides": [
|
57
|
+
"make stylelint-fix"
|
58
|
+
]
|
59
|
+
},
|
35
60
|
"scripts": {
|
36
61
|
"release": "release-it",
|
37
62
|
"release-major-beta": "release-it major --preRelease=beta",
|
@@ -49,6 +74,7 @@
|
|
49
74
|
"lint:fix": "make lint-fix",
|
50
75
|
"i18n": "make i18n",
|
51
76
|
"cypress:run": "make cypress-run",
|
52
|
-
"cypress:open": "make cypress-open"
|
77
|
+
"cypress:open": "make cypress-open",
|
78
|
+
"prepare": "husky install"
|
53
79
|
}
|
54
80
|
}
|
@@ -0,0 +1,128 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
import { Button } from 'semantic-ui-react';
|
3
|
+
import { Icon, BlocksForm } from '@plone/volto/components';
|
4
|
+
import EditBlockWrapper from '@eeacms/volto-group-block/components/manage/Blocks/Group/EditBlockWrapper';
|
5
|
+
|
6
|
+
import helpSVG from '@plone/volto/icons/help.svg';
|
7
|
+
import RenderBlocks from './RenderBlocks';
|
8
|
+
import './editor-flex.less';
|
9
|
+
|
10
|
+
const FlexGroup = (props) => {
|
11
|
+
const {
|
12
|
+
block,
|
13
|
+
data,
|
14
|
+
onChangeBlock,
|
15
|
+
onChangeField,
|
16
|
+
pathname,
|
17
|
+
selected,
|
18
|
+
selectedBlock,
|
19
|
+
onSelectBlock,
|
20
|
+
setSelectedBlock,
|
21
|
+
multiSelected,
|
22
|
+
manage,
|
23
|
+
childBlocksForm,
|
24
|
+
formDescription,
|
25
|
+
isEditMode,
|
26
|
+
} = props;
|
27
|
+
const metadata = props.metadata || props.properties;
|
28
|
+
const blockState = {};
|
29
|
+
const { no_of_columns = 2 } = data;
|
30
|
+
const flexClassNames = `ui unstackable items row flex-items-wrapper items-${no_of_columns}-columns`;
|
31
|
+
|
32
|
+
React.useEffect(() => {
|
33
|
+
const dragDropList = document?.querySelector(
|
34
|
+
`.flex-blocks-form[data-block="${block}"] [data-rbd-droppable-id]`,
|
35
|
+
);
|
36
|
+
if (dragDropList) dragDropList.setAttribute('class', flexClassNames);
|
37
|
+
}, [flexClassNames, block, isEditMode]);
|
38
|
+
|
39
|
+
// Get editing instructions from block settings or props
|
40
|
+
let instructions = data?.instructions?.data || data?.instructions;
|
41
|
+
if (!instructions || instructions === '<p><br/></p>') {
|
42
|
+
instructions = formDescription;
|
43
|
+
}
|
44
|
+
|
45
|
+
return (
|
46
|
+
<div className="flex-blocks-form" data-block={block}>
|
47
|
+
{isEditMode ? (
|
48
|
+
<BlocksForm
|
49
|
+
metadata={metadata}
|
50
|
+
properties={childBlocksForm}
|
51
|
+
manage={manage}
|
52
|
+
selectedBlock={selected ? selectedBlock : null}
|
53
|
+
allowedBlocks={data.allowedBlocks}
|
54
|
+
title={data.placeholder}
|
55
|
+
description={instructions}
|
56
|
+
onSelectBlock={(id, l, e) => {
|
57
|
+
const isMultipleSelection = e
|
58
|
+
? e.shiftKey || e.ctrlKey || e.metaKey
|
59
|
+
: false;
|
60
|
+
onSelectBlock(id, isMultipleSelection, e, selectedBlock);
|
61
|
+
}}
|
62
|
+
onChangeFormData={(newFormData) => {
|
63
|
+
onChangeBlock(block, {
|
64
|
+
...data,
|
65
|
+
data: newFormData,
|
66
|
+
});
|
67
|
+
}}
|
68
|
+
onChangeField={(id, value) => {
|
69
|
+
if (['blocks', 'blocks_layout'].indexOf(id) > -1) {
|
70
|
+
blockState[id] = value;
|
71
|
+
onChangeBlock(block, {
|
72
|
+
...data,
|
73
|
+
data: {
|
74
|
+
...data.data,
|
75
|
+
...blockState,
|
76
|
+
},
|
77
|
+
});
|
78
|
+
} else {
|
79
|
+
onChangeField(id, value);
|
80
|
+
}
|
81
|
+
}}
|
82
|
+
pathname={pathname}
|
83
|
+
>
|
84
|
+
{({ draginfo }, editBlock, blockProps) => (
|
85
|
+
<div className="flex-item">
|
86
|
+
<div className="item-wrapper">
|
87
|
+
<EditBlockWrapper
|
88
|
+
draginfo={draginfo}
|
89
|
+
blockProps={blockProps}
|
90
|
+
disabled={data.disableInnerButtons}
|
91
|
+
extraControls={
|
92
|
+
<>
|
93
|
+
{instructions && (
|
94
|
+
<>
|
95
|
+
<Button
|
96
|
+
icon
|
97
|
+
basic
|
98
|
+
title="Section help"
|
99
|
+
onClick={() => {
|
100
|
+
setSelectedBlock();
|
101
|
+
const tab = manage ? 0 : 1;
|
102
|
+
props.setSidebarTab(tab);
|
103
|
+
}}
|
104
|
+
>
|
105
|
+
<Icon name={helpSVG} className="" size="19px" />
|
106
|
+
</Button>
|
107
|
+
</>
|
108
|
+
)}
|
109
|
+
</>
|
110
|
+
}
|
111
|
+
multiSelected={multiSelected.includes(blockProps.block)}
|
112
|
+
>
|
113
|
+
{editBlock}
|
114
|
+
</EditBlockWrapper>
|
115
|
+
</div>
|
116
|
+
</div>
|
117
|
+
)}
|
118
|
+
</BlocksForm>
|
119
|
+
) : (
|
120
|
+
<div className={flexClassNames}>
|
121
|
+
<RenderBlocks metadata={metadata} content={data?.data || {}} />
|
122
|
+
</div>
|
123
|
+
)}
|
124
|
+
</div>
|
125
|
+
);
|
126
|
+
};
|
127
|
+
|
128
|
+
export default FlexGroup;
|
@@ -0,0 +1,75 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
import { getBaseUrl, applyBlockDefaults } from '@plone/volto/helpers';
|
3
|
+
import { defineMessages, injectIntl } from 'react-intl';
|
4
|
+
import { map } from 'lodash';
|
5
|
+
import {
|
6
|
+
getBlocksFieldname,
|
7
|
+
getBlocksLayoutFieldname,
|
8
|
+
hasBlocksData,
|
9
|
+
} from '@plone/volto/helpers';
|
10
|
+
import StyleWrapper from '@plone/volto/components/manage/Blocks/Block/StyleWrapper';
|
11
|
+
import config from '@plone/volto/registry';
|
12
|
+
import { ViewDefaultBlock } from '@plone/volto/components';
|
13
|
+
|
14
|
+
const messages = defineMessages({
|
15
|
+
unknownBlock: {
|
16
|
+
id: 'Unknown Block',
|
17
|
+
defaultMessage: 'Unknown Block {block}',
|
18
|
+
},
|
19
|
+
invalidBlock: {
|
20
|
+
id: 'Invalid Block',
|
21
|
+
defaultMessage: 'Invalid block - Will be removed on saving',
|
22
|
+
},
|
23
|
+
});
|
24
|
+
|
25
|
+
const RenderBlocks = (props) => {
|
26
|
+
const { content, intl, location, metadata } = props;
|
27
|
+
const blocksFieldname = getBlocksFieldname(content);
|
28
|
+
const blocksLayoutFieldname = getBlocksLayoutFieldname(content);
|
29
|
+
const blocksConfig = props.blocksConfig || config.blocks.blocksConfig;
|
30
|
+
const CustomTag = props.as || React.Fragment;
|
31
|
+
|
32
|
+
return hasBlocksData(content) ? (
|
33
|
+
<CustomTag>
|
34
|
+
{map(content[blocksLayoutFieldname].items, (block) => {
|
35
|
+
const Block =
|
36
|
+
blocksConfig[content[blocksFieldname]?.[block]?.['@type']]?.view ||
|
37
|
+
ViewDefaultBlock;
|
38
|
+
|
39
|
+
const blockData = applyBlockDefaults({
|
40
|
+
data: content[blocksFieldname][block],
|
41
|
+
intl,
|
42
|
+
metadata,
|
43
|
+
properties: content,
|
44
|
+
});
|
45
|
+
|
46
|
+
return Block ? (
|
47
|
+
<div className="flex-item" key={block}>
|
48
|
+
<StyleWrapper key={block} id={block}>
|
49
|
+
<Block
|
50
|
+
id={block}
|
51
|
+
metadata={metadata}
|
52
|
+
properties={content}
|
53
|
+
data={blockData}
|
54
|
+
path={getBaseUrl(location?.pathname || '')}
|
55
|
+
blocksConfig={blocksConfig}
|
56
|
+
/>
|
57
|
+
</StyleWrapper>
|
58
|
+
</div>
|
59
|
+
) : blockData ? (
|
60
|
+
<div key={block}>
|
61
|
+
{intl.formatMessage(messages.unknownBlock, {
|
62
|
+
block: content[blocksFieldname]?.[block]?.['@type'],
|
63
|
+
})}
|
64
|
+
</div>
|
65
|
+
) : (
|
66
|
+
<div key={block}>{intl.formatMessage(messages.invalidBlock)}</div>
|
67
|
+
);
|
68
|
+
})}
|
69
|
+
</CustomTag>
|
70
|
+
) : (
|
71
|
+
''
|
72
|
+
);
|
73
|
+
};
|
74
|
+
|
75
|
+
export default injectIntl(RenderBlocks);
|
@@ -0,0 +1,14 @@
|
|
1
|
+
@import (multiple) '../../theme.config';
|
2
|
+
|
3
|
+
@type: 'extra';
|
4
|
+
@element: 'custom';
|
5
|
+
|
6
|
+
@baseWidth: 100%;
|
7
|
+
|
8
|
+
// on edit ensure add button is next to the block input area
|
9
|
+
.flex-blocks-form {
|
10
|
+
.item-wrapper {
|
11
|
+
position: relative;
|
12
|
+
width: 100%;
|
13
|
+
}
|
14
|
+
}
|
@@ -55,6 +55,7 @@ export default {
|
|
55
55
|
'hideCreationDate',
|
56
56
|
'hidePublishingDate',
|
57
57
|
'hideModificationDate',
|
58
|
+
'subtitle',
|
58
59
|
'info',
|
59
60
|
],
|
60
61
|
},
|
@@ -94,6 +95,9 @@ export default {
|
|
94
95
|
title: 'Hide download button',
|
95
96
|
type: 'boolean',
|
96
97
|
},
|
98
|
+
subtitle: {
|
99
|
+
title: 'Subtitle',
|
100
|
+
},
|
97
101
|
rssLinks: {
|
98
102
|
title: 'RSS Links',
|
99
103
|
widget: 'object_list',
|
@@ -80,6 +80,7 @@ const View = (props) => {
|
|
80
80
|
copyrightIcon,
|
81
81
|
copyrightPosition,
|
82
82
|
rssLinks,
|
83
|
+
subtitle,
|
83
84
|
// contentType,
|
84
85
|
} = props.data;
|
85
86
|
const copyrightPrefix =
|
@@ -199,6 +200,7 @@ const View = (props) => {
|
|
199
200
|
</>
|
200
201
|
}
|
201
202
|
>
|
203
|
+
{subtitle && <Banner.Subtitle>{subtitle}</Banner.Subtitle>}
|
202
204
|
<Title config={banner.title} properties={metadata} />
|
203
205
|
<Banner.Metadata>
|
204
206
|
<Banner.MetadataField
|
@@ -0,0 +1,50 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
import configureStore from 'redux-mock-store';
|
3
|
+
import { Provider } from 'react-intl-redux';
|
4
|
+
import { render } from '@testing-library/react';
|
5
|
+
import AlignChooser from './AlignChooser';
|
6
|
+
|
7
|
+
const mockStore = configureStore();
|
8
|
+
|
9
|
+
describe('AlignChooser', () => {
|
10
|
+
const props = {
|
11
|
+
align: 'left',
|
12
|
+
onChangeBlock: jest.fn(),
|
13
|
+
data: { copyrightPosition: 'left' },
|
14
|
+
block: '123',
|
15
|
+
actions: ['left', 'right', 'center', 'full'],
|
16
|
+
};
|
17
|
+
const store = mockStore({
|
18
|
+
intl: {
|
19
|
+
locale: 'en',
|
20
|
+
messages: {},
|
21
|
+
},
|
22
|
+
});
|
23
|
+
|
24
|
+
it('renders the align buttons', () => {
|
25
|
+
const { container } = render(
|
26
|
+
<Provider store={store}>
|
27
|
+
<AlignChooser {...props} />
|
28
|
+
</Provider>,
|
29
|
+
);
|
30
|
+
expect(container).toMatchSnapshot();
|
31
|
+
});
|
32
|
+
|
33
|
+
it('calls onChangeBlock when an align button is clicked', () => {
|
34
|
+
const { container } = render(
|
35
|
+
<Provider store={store}>
|
36
|
+
<AlignChooser {...props} />
|
37
|
+
</Provider>,
|
38
|
+
);
|
39
|
+
expect(container).toMatchSnapshot();
|
40
|
+
});
|
41
|
+
|
42
|
+
it('marks the active align button as active', () => {
|
43
|
+
const { container } = render(
|
44
|
+
<Provider store={store}>
|
45
|
+
<AlignChooser {...props} />
|
46
|
+
</Provider>,
|
47
|
+
);
|
48
|
+
expect(container).toMatchSnapshot();
|
49
|
+
});
|
50
|
+
});
|
@@ -14,7 +14,7 @@ import { Portal } from 'react-portal';
|
|
14
14
|
import {
|
15
15
|
Button,
|
16
16
|
Checkbox,
|
17
|
-
Container,
|
17
|
+
Container as SemanticContainer,
|
18
18
|
Form,
|
19
19
|
Icon as IconOld,
|
20
20
|
Input,
|
@@ -28,6 +28,7 @@ import { updateSharing, getSharing } from '@plone/volto/actions';
|
|
28
28
|
import { getBaseUrl } from '@plone/volto/helpers';
|
29
29
|
import { Icon, Toolbar, Toast } from '@plone/volto/components';
|
30
30
|
import { toast } from 'react-toastify';
|
31
|
+
import config from '@plone/volto/registry';
|
31
32
|
|
32
33
|
import aheadSVG from '@plone/volto/icons/ahead.svg';
|
33
34
|
import clearSVG from '@plone/volto/icons/clear.svg';
|
@@ -144,6 +145,7 @@ class SharingComponent extends Component {
|
|
144
145
|
this.onToggleInherit = this.onToggleInherit.bind(this);
|
145
146
|
this.state = {
|
146
147
|
search: '',
|
148
|
+
isLoading: false,
|
147
149
|
inherit: props.inherit,
|
148
150
|
entries: props.entries,
|
149
151
|
isClient: false,
|
@@ -224,7 +226,17 @@ class SharingComponent extends Component {
|
|
224
226
|
*/
|
225
227
|
onSearch(event) {
|
226
228
|
event.preventDefault();
|
227
|
-
this.
|
229
|
+
this.setState({ isLoading: true });
|
230
|
+
this.props
|
231
|
+
.getSharing(getBaseUrl(this.props.pathname), this.state.search)
|
232
|
+
.then(() => {
|
233
|
+
this.setState({ isLoading: false });
|
234
|
+
})
|
235
|
+
.catch((error) => {
|
236
|
+
this.setState({ isLoading: false });
|
237
|
+
// eslint-disable-next-line no-console
|
238
|
+
console.error('Error searching users or groups', error);
|
239
|
+
});
|
228
240
|
}
|
229
241
|
|
230
242
|
/**
|
@@ -245,9 +257,9 @@ class SharingComponent extends Component {
|
|
245
257
|
* @returns {undefined}
|
246
258
|
*/
|
247
259
|
onToggleInherit() {
|
248
|
-
this.setState({
|
249
|
-
inherit: !
|
250
|
-
});
|
260
|
+
this.setState((state) => ({
|
261
|
+
inherit: !state.inherit,
|
262
|
+
}));
|
251
263
|
}
|
252
264
|
|
253
265
|
/**
|
@@ -288,11 +300,17 @@ class SharingComponent extends Component {
|
|
288
300
|
* @returns {string} Markup for the component.
|
289
301
|
*/
|
290
302
|
render() {
|
303
|
+
const Container =
|
304
|
+
config.getComponent({ name: 'Container' }).component || SemanticContainer;
|
305
|
+
|
291
306
|
return (
|
292
307
|
<Container id="page-sharing">
|
293
308
|
<Helmet title={this.props.intl.formatMessage(messages.sharing)} />
|
294
309
|
<Segment.Group raised>
|
295
|
-
<Pluggable
|
310
|
+
<Pluggable
|
311
|
+
name="sharing-component"
|
312
|
+
params={{ isLoading: this.state.isLoading }}
|
313
|
+
/>
|
296
314
|
<Plug pluggable="sharing-component" id="sharing-component-title">
|
297
315
|
<Segment className="primary">
|
298
316
|
<FormattedMessage
|
@@ -314,20 +332,29 @@ class SharingComponent extends Component {
|
|
314
332
|
</Segment>
|
315
333
|
</Plug>
|
316
334
|
<Plug pluggable="sharing-component" id="sharing-component-search">
|
317
|
-
|
318
|
-
|
319
|
-
<
|
320
|
-
<
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
335
|
+
{({ isLoading }) => {
|
336
|
+
return (
|
337
|
+
<Segment>
|
338
|
+
<Form onSubmit={this.onSearch}>
|
339
|
+
<Form.Field>
|
340
|
+
<Input
|
341
|
+
name="SearchableText"
|
342
|
+
action={{
|
343
|
+
icon: 'search',
|
344
|
+
loading: isLoading,
|
345
|
+
disabled: isLoading,
|
346
|
+
}}
|
347
|
+
placeholder={this.props.intl.formatMessage(
|
348
|
+
messages.searchForUserOrGroup,
|
349
|
+
)}
|
350
|
+
onChange={this.onChangeSearch}
|
351
|
+
id="sharing-component-search"
|
352
|
+
/>
|
353
|
+
</Form.Field>
|
354
|
+
</Form>
|
355
|
+
</Segment>
|
356
|
+
);
|
357
|
+
}}
|
331
358
|
</Plug>
|
332
359
|
<Plug
|
333
360
|
pluggable="sharing-component"
|
@@ -400,9 +427,15 @@ class SharingComponent extends Component {
|
|
400
427
|
<Segment attached>
|
401
428
|
<Form.Field>
|
402
429
|
<Checkbox
|
403
|
-
|
430
|
+
id="inherit-permissions-checkbox"
|
431
|
+
name="inherit-permissions-checkbox"
|
432
|
+
defaultChecked={this.state.inherit}
|
404
433
|
onChange={this.onToggleInherit}
|
405
|
-
label={
|
434
|
+
label={
|
435
|
+
<label htmlFor="inherit-permissions-checkbox">
|
436
|
+
{this.props.intl.formatMessage(messages.inherit)}
|
437
|
+
</label>
|
438
|
+
}
|
406
439
|
/>
|
407
440
|
</Form.Field>
|
408
441
|
<p className="help">
|
@@ -0,0 +1,72 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
import renderer from 'react-test-renderer';
|
3
|
+
import configureStore from 'redux-mock-store';
|
4
|
+
import { Provider } from 'react-intl-redux';
|
5
|
+
import jwt from 'jsonwebtoken';
|
6
|
+
import { MemoryRouter } from 'react-router-dom';
|
7
|
+
import { PluggablesProvider } from '@plone/volto/components/manage/Pluggable';
|
8
|
+
|
9
|
+
import Sharing from './Sharing';
|
10
|
+
|
11
|
+
const mockStore = configureStore();
|
12
|
+
|
13
|
+
jest.mock('react-portal', () => ({
|
14
|
+
Portal: jest.fn(() => <div id="Portal" />),
|
15
|
+
}));
|
16
|
+
|
17
|
+
describe('Sharing', () => {
|
18
|
+
it('renders a sharing component', () => {
|
19
|
+
const store = mockStore({
|
20
|
+
userSession: {
|
21
|
+
token: jwt.sign({ sub: 'john-doe' }, 'secret'),
|
22
|
+
},
|
23
|
+
sharing: {
|
24
|
+
data: {
|
25
|
+
entries: [
|
26
|
+
{
|
27
|
+
id: 'john-doe',
|
28
|
+
disabled: false,
|
29
|
+
login: 'john-doe',
|
30
|
+
roles: {
|
31
|
+
Contributer: true,
|
32
|
+
},
|
33
|
+
title: 'John Doe',
|
34
|
+
type: 'user',
|
35
|
+
},
|
36
|
+
],
|
37
|
+
inherit: true,
|
38
|
+
available_roles: [
|
39
|
+
{
|
40
|
+
id: 'Contributor',
|
41
|
+
title: 'Can add',
|
42
|
+
},
|
43
|
+
],
|
44
|
+
},
|
45
|
+
update: {
|
46
|
+
loading: false,
|
47
|
+
loaded: true,
|
48
|
+
},
|
49
|
+
},
|
50
|
+
content: {
|
51
|
+
data: {
|
52
|
+
title: 'Blog',
|
53
|
+
},
|
54
|
+
},
|
55
|
+
intl: {
|
56
|
+
locale: 'en',
|
57
|
+
messages: {},
|
58
|
+
},
|
59
|
+
});
|
60
|
+
const component = renderer.create(
|
61
|
+
<Provider store={store}>
|
62
|
+
<PluggablesProvider>
|
63
|
+
<MemoryRouter>
|
64
|
+
<Sharing location={{ pathname: '/blog' }} />
|
65
|
+
</MemoryRouter>
|
66
|
+
</PluggablesProvider>
|
67
|
+
</Provider>,
|
68
|
+
);
|
69
|
+
const json = component.toJSON();
|
70
|
+
expect(json).toMatchSnapshot();
|
71
|
+
});
|
72
|
+
});
|
@@ -0,0 +1,66 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
import renderer from 'react-test-renderer';
|
3
|
+
import configureStore from 'redux-mock-store';
|
4
|
+
import { Provider } from 'react-intl-redux';
|
5
|
+
import { MemoryRouter } from 'react-router-dom';
|
6
|
+
import ContactForm from './ContactForm';
|
7
|
+
|
8
|
+
jest.mock('react-portal', () => ({
|
9
|
+
Portal: jest.fn(() => <div id="Portal" />),
|
10
|
+
}));
|
11
|
+
|
12
|
+
const mockStore = configureStore();
|
13
|
+
|
14
|
+
describe('Contact form', () => {
|
15
|
+
it('renders a contact form', () => {
|
16
|
+
const store = mockStore({
|
17
|
+
emailNotification: {
|
18
|
+
error: {},
|
19
|
+
loaded: false,
|
20
|
+
loading: false,
|
21
|
+
},
|
22
|
+
intl: {
|
23
|
+
locale: 'en',
|
24
|
+
messages: {},
|
25
|
+
},
|
26
|
+
userSession: {},
|
27
|
+
content: {},
|
28
|
+
});
|
29
|
+
const component = renderer.create(
|
30
|
+
<Provider store={store}>
|
31
|
+
<MemoryRouter>
|
32
|
+
<ContactForm location={{ pathname: '/blog' }} />
|
33
|
+
</MemoryRouter>
|
34
|
+
</Provider>,
|
35
|
+
);
|
36
|
+
const json = component.toJSON();
|
37
|
+
expect(json).toMatchSnapshot();
|
38
|
+
});
|
39
|
+
|
40
|
+
it('renders a contact form with error message', () => {
|
41
|
+
const store = mockStore({
|
42
|
+
emailNotification: {
|
43
|
+
error: {
|
44
|
+
message: 'Error foo',
|
45
|
+
},
|
46
|
+
loaded: false,
|
47
|
+
loading: false,
|
48
|
+
},
|
49
|
+
intl: {
|
50
|
+
locale: 'en',
|
51
|
+
messages: {},
|
52
|
+
},
|
53
|
+
userSession: {},
|
54
|
+
content: {},
|
55
|
+
});
|
56
|
+
const component = renderer.create(
|
57
|
+
<Provider store={store}>
|
58
|
+
<MemoryRouter>
|
59
|
+
<ContactForm location={{ pathname: '/' }} />
|
60
|
+
</MemoryRouter>
|
61
|
+
</Provider>,
|
62
|
+
);
|
63
|
+
const json = component.toJSON();
|
64
|
+
expect(json).toMatchSnapshot();
|
65
|
+
});
|
66
|
+
});
|
package/src/index.js
CHANGED
@@ -15,6 +15,7 @@ import installLayoutSettingsBlock from '@eeacms/volto-eea-website-theme/componen
|
|
15
15
|
|
16
16
|
import BaseTag from './components/theme/BaseTag';
|
17
17
|
import SubsiteClass from './components/theme/SubsiteClass';
|
18
|
+
import FlexGroup from '@eeacms/volto-eea-website-theme/components/manage/Blocks/GroupBlockTemplate/FlexGroup/FlexGroup';
|
18
19
|
import contentBoxSVG from './icons/content-box.svg';
|
19
20
|
|
20
21
|
import installSlate from './slate';
|
@@ -122,6 +123,32 @@ const applyConfig = (config) => {
|
|
122
123
|
};
|
123
124
|
}
|
124
125
|
}
|
126
|
+
//Group block flex variation
|
127
|
+
if (config.blocks.blocksConfig.group) {
|
128
|
+
config.blocks.blocksConfig.group.variations = [
|
129
|
+
...(config.blocks.blocksConfig.group.variations || []),
|
130
|
+
{
|
131
|
+
id: 'flex group',
|
132
|
+
isDefault: false,
|
133
|
+
title: 'Flex Group',
|
134
|
+
template: FlexGroup,
|
135
|
+
schemaEnhancer: ({ schema, formData, intl }) => {
|
136
|
+
schema.fieldsets[0].fields.push('no_of_columns');
|
137
|
+
schema.properties.no_of_columns = {
|
138
|
+
title: 'No. of columns',
|
139
|
+
description: 'Choose the number of flex columns',
|
140
|
+
choices: [
|
141
|
+
[2, 2],
|
142
|
+
[3, 3],
|
143
|
+
[4, 4],
|
144
|
+
[5, 5],
|
145
|
+
],
|
146
|
+
};
|
147
|
+
return schema;
|
148
|
+
},
|
149
|
+
},
|
150
|
+
];
|
151
|
+
}
|
125
152
|
|
126
153
|
// Apply columns block customization
|
127
154
|
if (config.blocks.blocksConfig.columnsBlock) {
|