@eeacms/volto-eea-website-theme 3.15.0 → 3.16.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/CHANGELOG.md +9 -3
- package/locales/de/LC_MESSAGES/volto.po +45 -0
- package/locales/en/LC_MESSAGES/volto.po +45 -0
- package/locales/it/LC_MESSAGES/volto.po +45 -0
- package/locales/ro/LC_MESSAGES/volto.po +45 -0
- package/locales/volto.pot +46 -1
- package/package.json +1 -1
- package/src/customizations/volto/components/theme/Error/ErrorBoundary.jsx +47 -0
- package/src/customizations/volto/server.jsx +14 -2
- package/src/hocs/withErrorBoundary.jsx +29 -0
- package/src/hocs/withErrorBoundary.test.jsx +104 -0
package/CHANGELOG.md
CHANGED
|
@@ -4,15 +4,21 @@ 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
|
-
### [3.
|
|
7
|
+
### [3.16.0](https://github.com/eea/volto-eea-website-theme/compare/3.15.0...3.16.0) - 4 December 2025
|
|
8
8
|
|
|
9
9
|
#### :rocket: New Features
|
|
10
10
|
|
|
11
|
-
- feat:
|
|
11
|
+
- feat: Custom Error boundary - refs #291209 [Nilesh - [`6d0cf06`](https://github.com/eea/volto-eea-website-theme/commit/6d0cf06d5c3603359eda6986c69e131e0265b8d9)]
|
|
12
12
|
|
|
13
13
|
#### :hammer_and_wrench: Others
|
|
14
14
|
|
|
15
|
-
- Release 3.
|
|
15
|
+
- Release 3.16.0 [Alin Voinea - [`d947957`](https://github.com/eea/volto-eea-website-theme/commit/d947957b1597a3b651da1b9581ce661fd441109f)]
|
|
16
|
+
### [3.15.0](https://github.com/eea/volto-eea-website-theme/compare/3.14.1...3.15.0) - 3 December 2025
|
|
17
|
+
|
|
18
|
+
#### :rocket: New Features
|
|
19
|
+
|
|
20
|
+
- feat: Add restricted options for group block - refs #294358 [dobri1408 - [`e23808d`](https://github.com/eea/volto-eea-website-theme/commit/e23808d2fa6ca252032b5a82915fe175b26be913)]
|
|
21
|
+
|
|
16
22
|
### [3.14.1](https://github.com/eea/volto-eea-website-theme/compare/3.14.0...3.14.1) - 17 November 2025
|
|
17
23
|
|
|
18
24
|
### [3.14.0](https://github.com/eea/volto-eea-website-theme/compare/3.13.0...3.14.0) - 6 November 2025
|
|
@@ -11,6 +11,11 @@ msgstr ""
|
|
|
11
11
|
"Content-Transfer-Encoding: \n"
|
|
12
12
|
"Plural-Forms: \n"
|
|
13
13
|
|
|
14
|
+
#. Default: "Add"
|
|
15
|
+
#: components/theme/Widgets/SimpleArrayWidget
|
|
16
|
+
msgid "Add"
|
|
17
|
+
msgstr ""
|
|
18
|
+
|
|
14
19
|
#. Default: "Choices"
|
|
15
20
|
#: components/theme/Widgets/CreatableSelectWidget
|
|
16
21
|
msgid "Choices"
|
|
@@ -51,11 +56,31 @@ msgstr ""
|
|
|
51
56
|
msgid "Group"
|
|
52
57
|
msgstr ""
|
|
53
58
|
|
|
59
|
+
#. Default: "Hide Children From Navigation"
|
|
60
|
+
#: components/theme/Widgets/NavigationBehaviorWidget
|
|
61
|
+
msgid "Hide Children From Navigation"
|
|
62
|
+
msgstr ""
|
|
63
|
+
|
|
54
64
|
#. Default: "Invalid block - Will be removed on saving"
|
|
55
65
|
#: components/manage/Blocks/GroupBlockTemplate/FlexGroup/RenderBlocks
|
|
56
66
|
msgid "Invalid Block"
|
|
57
67
|
msgstr ""
|
|
58
68
|
|
|
69
|
+
#. Default: "Load Main Navigation Routes"
|
|
70
|
+
#: components/theme/Widgets/NavigationBehaviorWidget
|
|
71
|
+
msgid "Load Main Navigation Routes"
|
|
72
|
+
msgstr ""
|
|
73
|
+
|
|
74
|
+
#. Default: "Menu Item Children List Columns"
|
|
75
|
+
#: components/theme/Widgets/NavigationBehaviorWidget
|
|
76
|
+
msgid "Menu Item Children List Columns"
|
|
77
|
+
msgstr ""
|
|
78
|
+
|
|
79
|
+
#. Default: "Menu Item Columns"
|
|
80
|
+
#: components/theme/Widgets/NavigationBehaviorWidget
|
|
81
|
+
msgid "Menu Item Columns"
|
|
82
|
+
msgstr ""
|
|
83
|
+
|
|
59
84
|
#. Default: "Modified"
|
|
60
85
|
#: components/theme/Banner/View
|
|
61
86
|
msgid "Modified"
|
|
@@ -78,11 +103,21 @@ msgstr ""
|
|
|
78
103
|
msgid "No value"
|
|
79
104
|
msgstr ""
|
|
80
105
|
|
|
106
|
+
#. Default: "Preparing download"
|
|
107
|
+
#: components/theme/PrintLoader/PrintLoader
|
|
108
|
+
msgid "Preparing download"
|
|
109
|
+
msgstr ""
|
|
110
|
+
|
|
81
111
|
#. Default: "Published"
|
|
82
112
|
#: components/theme/Banner/View
|
|
83
113
|
msgid "Published"
|
|
84
114
|
msgstr ""
|
|
85
115
|
|
|
116
|
+
#. Default: "Remove"
|
|
117
|
+
#: components/theme/Widgets/SimpleArrayWidget
|
|
118
|
+
msgid "Remove"
|
|
119
|
+
msgstr ""
|
|
120
|
+
|
|
86
121
|
#. Default: "Required"
|
|
87
122
|
#: components/theme/Widgets/CreatableSelectWidget
|
|
88
123
|
msgid "Required"
|
|
@@ -146,6 +181,16 @@ msgstr ""
|
|
|
146
181
|
msgid "User"
|
|
147
182
|
msgstr ""
|
|
148
183
|
|
|
184
|
+
#. Default: "Restrict access to this block based on user permissions"
|
|
185
|
+
#: index
|
|
186
|
+
msgid "restrictedBlockDescription"
|
|
187
|
+
msgstr ""
|
|
188
|
+
|
|
189
|
+
#. Default: "Restricted block"
|
|
190
|
+
#: index
|
|
191
|
+
msgid "restrictedBlockTitle"
|
|
192
|
+
msgstr ""
|
|
193
|
+
|
|
149
194
|
#. Default: "RSS Feed"
|
|
150
195
|
#: components/theme/Banner/View
|
|
151
196
|
msgid "rssFeed"
|
|
@@ -11,6 +11,11 @@ msgstr ""
|
|
|
11
11
|
"Content-Transfer-Encoding: \n"
|
|
12
12
|
"Plural-Forms: \n"
|
|
13
13
|
|
|
14
|
+
#. Default: "Add"
|
|
15
|
+
#: components/theme/Widgets/SimpleArrayWidget
|
|
16
|
+
msgid "Add"
|
|
17
|
+
msgstr ""
|
|
18
|
+
|
|
14
19
|
#. Default: "Choices"
|
|
15
20
|
#: components/theme/Widgets/CreatableSelectWidget
|
|
16
21
|
msgid "Choices"
|
|
@@ -51,11 +56,31 @@ msgstr ""
|
|
|
51
56
|
msgid "Group"
|
|
52
57
|
msgstr ""
|
|
53
58
|
|
|
59
|
+
#. Default: "Hide Children From Navigation"
|
|
60
|
+
#: components/theme/Widgets/NavigationBehaviorWidget
|
|
61
|
+
msgid "Hide Children From Navigation"
|
|
62
|
+
msgstr ""
|
|
63
|
+
|
|
54
64
|
#. Default: "Invalid block - Will be removed on saving"
|
|
55
65
|
#: components/manage/Blocks/GroupBlockTemplate/FlexGroup/RenderBlocks
|
|
56
66
|
msgid "Invalid Block"
|
|
57
67
|
msgstr ""
|
|
58
68
|
|
|
69
|
+
#. Default: "Load Main Navigation Routes"
|
|
70
|
+
#: components/theme/Widgets/NavigationBehaviorWidget
|
|
71
|
+
msgid "Load Main Navigation Routes"
|
|
72
|
+
msgstr ""
|
|
73
|
+
|
|
74
|
+
#. Default: "Menu Item Children List Columns"
|
|
75
|
+
#: components/theme/Widgets/NavigationBehaviorWidget
|
|
76
|
+
msgid "Menu Item Children List Columns"
|
|
77
|
+
msgstr ""
|
|
78
|
+
|
|
79
|
+
#. Default: "Menu Item Columns"
|
|
80
|
+
#: components/theme/Widgets/NavigationBehaviorWidget
|
|
81
|
+
msgid "Menu Item Columns"
|
|
82
|
+
msgstr ""
|
|
83
|
+
|
|
59
84
|
#. Default: "Modified"
|
|
60
85
|
#: components/theme/Banner/View
|
|
61
86
|
msgid "Modified"
|
|
@@ -78,11 +103,21 @@ msgstr ""
|
|
|
78
103
|
msgid "No value"
|
|
79
104
|
msgstr ""
|
|
80
105
|
|
|
106
|
+
#. Default: "Preparing download"
|
|
107
|
+
#: components/theme/PrintLoader/PrintLoader
|
|
108
|
+
msgid "Preparing download"
|
|
109
|
+
msgstr ""
|
|
110
|
+
|
|
81
111
|
#. Default: "Published"
|
|
82
112
|
#: components/theme/Banner/View
|
|
83
113
|
msgid "Published"
|
|
84
114
|
msgstr ""
|
|
85
115
|
|
|
116
|
+
#. Default: "Remove"
|
|
117
|
+
#: components/theme/Widgets/SimpleArrayWidget
|
|
118
|
+
msgid "Remove"
|
|
119
|
+
msgstr ""
|
|
120
|
+
|
|
86
121
|
#. Default: "Required"
|
|
87
122
|
#: components/theme/Widgets/CreatableSelectWidget
|
|
88
123
|
msgid "Required"
|
|
@@ -146,6 +181,16 @@ msgstr ""
|
|
|
146
181
|
msgid "User"
|
|
147
182
|
msgstr ""
|
|
148
183
|
|
|
184
|
+
#. Default: "Restrict access to this block based on user permissions"
|
|
185
|
+
#: index
|
|
186
|
+
msgid "restrictedBlockDescription"
|
|
187
|
+
msgstr ""
|
|
188
|
+
|
|
189
|
+
#. Default: "Restricted block"
|
|
190
|
+
#: index
|
|
191
|
+
msgid "restrictedBlockTitle"
|
|
192
|
+
msgstr ""
|
|
193
|
+
|
|
149
194
|
#. Default: "RSS Feed"
|
|
150
195
|
#: components/theme/Banner/View
|
|
151
196
|
msgid "rssFeed"
|
|
@@ -11,6 +11,11 @@ msgstr ""
|
|
|
11
11
|
"Content-Transfer-Encoding: \n"
|
|
12
12
|
"Plural-Forms: \n"
|
|
13
13
|
|
|
14
|
+
#. Default: "Add"
|
|
15
|
+
#: components/theme/Widgets/SimpleArrayWidget
|
|
16
|
+
msgid "Add"
|
|
17
|
+
msgstr ""
|
|
18
|
+
|
|
14
19
|
#. Default: "Choices"
|
|
15
20
|
#: components/theme/Widgets/CreatableSelectWidget
|
|
16
21
|
msgid "Choices"
|
|
@@ -51,11 +56,31 @@ msgstr ""
|
|
|
51
56
|
msgid "Group"
|
|
52
57
|
msgstr ""
|
|
53
58
|
|
|
59
|
+
#. Default: "Hide Children From Navigation"
|
|
60
|
+
#: components/theme/Widgets/NavigationBehaviorWidget
|
|
61
|
+
msgid "Hide Children From Navigation"
|
|
62
|
+
msgstr ""
|
|
63
|
+
|
|
54
64
|
#. Default: "Invalid block - Will be removed on saving"
|
|
55
65
|
#: components/manage/Blocks/GroupBlockTemplate/FlexGroup/RenderBlocks
|
|
56
66
|
msgid "Invalid Block"
|
|
57
67
|
msgstr ""
|
|
58
68
|
|
|
69
|
+
#. Default: "Load Main Navigation Routes"
|
|
70
|
+
#: components/theme/Widgets/NavigationBehaviorWidget
|
|
71
|
+
msgid "Load Main Navigation Routes"
|
|
72
|
+
msgstr ""
|
|
73
|
+
|
|
74
|
+
#. Default: "Menu Item Children List Columns"
|
|
75
|
+
#: components/theme/Widgets/NavigationBehaviorWidget
|
|
76
|
+
msgid "Menu Item Children List Columns"
|
|
77
|
+
msgstr ""
|
|
78
|
+
|
|
79
|
+
#. Default: "Menu Item Columns"
|
|
80
|
+
#: components/theme/Widgets/NavigationBehaviorWidget
|
|
81
|
+
msgid "Menu Item Columns"
|
|
82
|
+
msgstr ""
|
|
83
|
+
|
|
59
84
|
#. Default: "Modified"
|
|
60
85
|
#: components/theme/Banner/View
|
|
61
86
|
msgid "Modified"
|
|
@@ -78,11 +103,21 @@ msgstr ""
|
|
|
78
103
|
msgid "No value"
|
|
79
104
|
msgstr ""
|
|
80
105
|
|
|
106
|
+
#. Default: "Preparing download"
|
|
107
|
+
#: components/theme/PrintLoader/PrintLoader
|
|
108
|
+
msgid "Preparing download"
|
|
109
|
+
msgstr ""
|
|
110
|
+
|
|
81
111
|
#. Default: "Published"
|
|
82
112
|
#: components/theme/Banner/View
|
|
83
113
|
msgid "Published"
|
|
84
114
|
msgstr ""
|
|
85
115
|
|
|
116
|
+
#. Default: "Remove"
|
|
117
|
+
#: components/theme/Widgets/SimpleArrayWidget
|
|
118
|
+
msgid "Remove"
|
|
119
|
+
msgstr ""
|
|
120
|
+
|
|
86
121
|
#. Default: "Required"
|
|
87
122
|
#: components/theme/Widgets/CreatableSelectWidget
|
|
88
123
|
msgid "Required"
|
|
@@ -146,6 +181,16 @@ msgstr ""
|
|
|
146
181
|
msgid "User"
|
|
147
182
|
msgstr ""
|
|
148
183
|
|
|
184
|
+
#. Default: "Restrict access to this block based on user permissions"
|
|
185
|
+
#: index
|
|
186
|
+
msgid "restrictedBlockDescription"
|
|
187
|
+
msgstr ""
|
|
188
|
+
|
|
189
|
+
#. Default: "Restricted block"
|
|
190
|
+
#: index
|
|
191
|
+
msgid "restrictedBlockTitle"
|
|
192
|
+
msgstr ""
|
|
193
|
+
|
|
149
194
|
#. Default: "RSS Feed"
|
|
150
195
|
#: components/theme/Banner/View
|
|
151
196
|
msgid "rssFeed"
|
|
@@ -11,6 +11,11 @@ msgstr ""
|
|
|
11
11
|
"Content-Transfer-Encoding: \n"
|
|
12
12
|
"Plural-Forms: \n"
|
|
13
13
|
|
|
14
|
+
#. Default: "Add"
|
|
15
|
+
#: components/theme/Widgets/SimpleArrayWidget
|
|
16
|
+
msgid "Add"
|
|
17
|
+
msgstr ""
|
|
18
|
+
|
|
14
19
|
#. Default: "Choices"
|
|
15
20
|
#: components/theme/Widgets/CreatableSelectWidget
|
|
16
21
|
msgid "Choices"
|
|
@@ -51,11 +56,31 @@ msgstr ""
|
|
|
51
56
|
msgid "Group"
|
|
52
57
|
msgstr ""
|
|
53
58
|
|
|
59
|
+
#. Default: "Hide Children From Navigation"
|
|
60
|
+
#: components/theme/Widgets/NavigationBehaviorWidget
|
|
61
|
+
msgid "Hide Children From Navigation"
|
|
62
|
+
msgstr ""
|
|
63
|
+
|
|
54
64
|
#. Default: "Invalid block - Will be removed on saving"
|
|
55
65
|
#: components/manage/Blocks/GroupBlockTemplate/FlexGroup/RenderBlocks
|
|
56
66
|
msgid "Invalid Block"
|
|
57
67
|
msgstr ""
|
|
58
68
|
|
|
69
|
+
#. Default: "Load Main Navigation Routes"
|
|
70
|
+
#: components/theme/Widgets/NavigationBehaviorWidget
|
|
71
|
+
msgid "Load Main Navigation Routes"
|
|
72
|
+
msgstr ""
|
|
73
|
+
|
|
74
|
+
#. Default: "Menu Item Children List Columns"
|
|
75
|
+
#: components/theme/Widgets/NavigationBehaviorWidget
|
|
76
|
+
msgid "Menu Item Children List Columns"
|
|
77
|
+
msgstr ""
|
|
78
|
+
|
|
79
|
+
#. Default: "Menu Item Columns"
|
|
80
|
+
#: components/theme/Widgets/NavigationBehaviorWidget
|
|
81
|
+
msgid "Menu Item Columns"
|
|
82
|
+
msgstr ""
|
|
83
|
+
|
|
59
84
|
#. Default: "Modified"
|
|
60
85
|
#: components/theme/Banner/View
|
|
61
86
|
msgid "Modified"
|
|
@@ -78,11 +103,21 @@ msgstr ""
|
|
|
78
103
|
msgid "No value"
|
|
79
104
|
msgstr ""
|
|
80
105
|
|
|
106
|
+
#. Default: "Preparing download"
|
|
107
|
+
#: components/theme/PrintLoader/PrintLoader
|
|
108
|
+
msgid "Preparing download"
|
|
109
|
+
msgstr ""
|
|
110
|
+
|
|
81
111
|
#. Default: "Published"
|
|
82
112
|
#: components/theme/Banner/View
|
|
83
113
|
msgid "Published"
|
|
84
114
|
msgstr ""
|
|
85
115
|
|
|
116
|
+
#. Default: "Remove"
|
|
117
|
+
#: components/theme/Widgets/SimpleArrayWidget
|
|
118
|
+
msgid "Remove"
|
|
119
|
+
msgstr ""
|
|
120
|
+
|
|
86
121
|
#. Default: "Required"
|
|
87
122
|
#: components/theme/Widgets/CreatableSelectWidget
|
|
88
123
|
msgid "Required"
|
|
@@ -146,6 +181,16 @@ msgstr ""
|
|
|
146
181
|
msgid "User"
|
|
147
182
|
msgstr ""
|
|
148
183
|
|
|
184
|
+
#. Default: "Restrict access to this block based on user permissions"
|
|
185
|
+
#: index
|
|
186
|
+
msgid "restrictedBlockDescription"
|
|
187
|
+
msgstr ""
|
|
188
|
+
|
|
189
|
+
#. Default: "Restricted block"
|
|
190
|
+
#: index
|
|
191
|
+
msgid "restrictedBlockTitle"
|
|
192
|
+
msgstr ""
|
|
193
|
+
|
|
149
194
|
#. Default: "RSS Feed"
|
|
150
195
|
#: components/theme/Banner/View
|
|
151
196
|
msgid "rssFeed"
|
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: 2025-
|
|
4
|
+
"POT-Creation-Date: 2025-12-04T18:19:53.476Z\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
|
"Content-Type: text/plain; charset=utf-8\n"
|
|
@@ -13,6 +13,11 @@ msgstr ""
|
|
|
13
13
|
"Preferred-Encodings: utf-8\n"
|
|
14
14
|
"Domain: volto\n"
|
|
15
15
|
|
|
16
|
+
#. Default: "Add"
|
|
17
|
+
#: components/theme/Widgets/SimpleArrayWidget
|
|
18
|
+
msgid "Add"
|
|
19
|
+
msgstr ""
|
|
20
|
+
|
|
16
21
|
#. Default: "Choices"
|
|
17
22
|
#: components/theme/Widgets/CreatableSelectWidget
|
|
18
23
|
msgid "Choices"
|
|
@@ -53,11 +58,31 @@ msgstr ""
|
|
|
53
58
|
msgid "Group"
|
|
54
59
|
msgstr ""
|
|
55
60
|
|
|
61
|
+
#. Default: "Hide Children From Navigation"
|
|
62
|
+
#: components/theme/Widgets/NavigationBehaviorWidget
|
|
63
|
+
msgid "Hide Children From Navigation"
|
|
64
|
+
msgstr ""
|
|
65
|
+
|
|
56
66
|
#. Default: "Invalid block - Will be removed on saving"
|
|
57
67
|
#: components/manage/Blocks/GroupBlockTemplate/FlexGroup/RenderBlocks
|
|
58
68
|
msgid "Invalid Block"
|
|
59
69
|
msgstr ""
|
|
60
70
|
|
|
71
|
+
#. Default: "Load Main Navigation Routes"
|
|
72
|
+
#: components/theme/Widgets/NavigationBehaviorWidget
|
|
73
|
+
msgid "Load Main Navigation Routes"
|
|
74
|
+
msgstr ""
|
|
75
|
+
|
|
76
|
+
#. Default: "Menu Item Children List Columns"
|
|
77
|
+
#: components/theme/Widgets/NavigationBehaviorWidget
|
|
78
|
+
msgid "Menu Item Children List Columns"
|
|
79
|
+
msgstr ""
|
|
80
|
+
|
|
81
|
+
#. Default: "Menu Item Columns"
|
|
82
|
+
#: components/theme/Widgets/NavigationBehaviorWidget
|
|
83
|
+
msgid "Menu Item Columns"
|
|
84
|
+
msgstr ""
|
|
85
|
+
|
|
61
86
|
#. Default: "Modified"
|
|
62
87
|
#: components/theme/Banner/View
|
|
63
88
|
msgid "Modified"
|
|
@@ -80,11 +105,21 @@ msgstr ""
|
|
|
80
105
|
msgid "No value"
|
|
81
106
|
msgstr ""
|
|
82
107
|
|
|
108
|
+
#. Default: "Preparing download"
|
|
109
|
+
#: components/theme/PrintLoader/PrintLoader
|
|
110
|
+
msgid "Preparing download"
|
|
111
|
+
msgstr ""
|
|
112
|
+
|
|
83
113
|
#. Default: "Published"
|
|
84
114
|
#: components/theme/Banner/View
|
|
85
115
|
msgid "Published"
|
|
86
116
|
msgstr ""
|
|
87
117
|
|
|
118
|
+
#. Default: "Remove"
|
|
119
|
+
#: components/theme/Widgets/SimpleArrayWidget
|
|
120
|
+
msgid "Remove"
|
|
121
|
+
msgstr ""
|
|
122
|
+
|
|
88
123
|
#. Default: "Required"
|
|
89
124
|
#: components/theme/Widgets/CreatableSelectWidget
|
|
90
125
|
msgid "Required"
|
|
@@ -148,6 +183,16 @@ msgstr ""
|
|
|
148
183
|
msgid "User"
|
|
149
184
|
msgstr ""
|
|
150
185
|
|
|
186
|
+
#. Default: "Restrict access to this block based on user permissions"
|
|
187
|
+
#: index
|
|
188
|
+
msgid "restrictedBlockDescription"
|
|
189
|
+
msgstr ""
|
|
190
|
+
|
|
191
|
+
#. Default: "Restricted block"
|
|
192
|
+
#: index
|
|
193
|
+
msgid "restrictedBlockTitle"
|
|
194
|
+
msgstr ""
|
|
195
|
+
|
|
151
196
|
#. Default: "RSS Feed"
|
|
152
197
|
#: components/theme/Banner/View
|
|
153
198
|
msgid "rssFeed"
|
package/package.json
CHANGED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import config from '@plone/volto/registry';
|
|
3
|
+
|
|
4
|
+
class ErrorBoundary extends React.Component {
|
|
5
|
+
constructor(props) {
|
|
6
|
+
super(props);
|
|
7
|
+
this.state = { hasError: false, error: null };
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
static getDerivedStateFromError(error) {
|
|
11
|
+
return { hasError: true, error };
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
componentDidCatch(error, errorInfo) {
|
|
15
|
+
if (this.props.error) {
|
|
16
|
+
//pass error to error-reporting service
|
|
17
|
+
config.settings.errorHandlers?.forEach((handler) => {
|
|
18
|
+
if (typeof handler === 'function') {
|
|
19
|
+
handler(error);
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
if (this.props.onError) {
|
|
23
|
+
this.props.onError(error, errorInfo);
|
|
24
|
+
}
|
|
25
|
+
} else {
|
|
26
|
+
// eslint-disable-next-line
|
|
27
|
+
console.error(error, errorInfo);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
render() {
|
|
32
|
+
const ErrorPage =
|
|
33
|
+
this.props.fallback || config.getComponent('ErrorBoundary')?.component;
|
|
34
|
+
if (this.state.hasError) {
|
|
35
|
+
if (ErrorPage) {
|
|
36
|
+
// You can render any custom fallback UI
|
|
37
|
+
return <ErrorPage name={this.props.name} error={this.state.error} />;
|
|
38
|
+
} else {
|
|
39
|
+
return <pre className="error">{`<error: ${this.props.name}>`}</pre>;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return this.props.children;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export default ErrorBoundary;
|
|
@@ -80,10 +80,16 @@ if (middleware.length) server.use('/', middleware);
|
|
|
80
80
|
server.use(function (err, req, res, next) {
|
|
81
81
|
if (err) {
|
|
82
82
|
const { store } = res.locals;
|
|
83
|
+
const ErrorComponent =
|
|
84
|
+
config.getComponent('ErrorBoundary')?.component || null;
|
|
83
85
|
const errorPage = (
|
|
84
86
|
<Provider store={store} onError={reactIntlErrorHandler}>
|
|
85
87
|
<StaticRouter context={{}} location={req.url}>
|
|
86
|
-
|
|
88
|
+
{ErrorComponent ? (
|
|
89
|
+
<ErrorComponent error={err} />
|
|
90
|
+
) : (
|
|
91
|
+
<ErrorPage message={err.message} />
|
|
92
|
+
)}
|
|
87
93
|
</StaticRouter>
|
|
88
94
|
</Provider>
|
|
89
95
|
);
|
|
@@ -157,10 +163,16 @@ function setupServer(req, res, next) {
|
|
|
157
163
|
const store = configureStore(initialState, history, api);
|
|
158
164
|
|
|
159
165
|
function errorHandler(error) {
|
|
166
|
+
const ErrorComponent =
|
|
167
|
+
config.getComponent('ErrorBoundary').component || null;
|
|
160
168
|
const errorPage = (
|
|
161
169
|
<Provider store={store} onError={reactIntlErrorHandler}>
|
|
162
170
|
<StaticRouter context={{}} location={req.url}>
|
|
163
|
-
|
|
171
|
+
{ErrorComponent ? (
|
|
172
|
+
<ErrorComponent error={error} />
|
|
173
|
+
) : (
|
|
174
|
+
<ErrorPage message={error.message} />
|
|
175
|
+
)}
|
|
164
176
|
</StaticRouter>
|
|
165
177
|
</Provider>
|
|
166
178
|
);
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { ErrorBoundary } from '@plone/volto/components';
|
|
3
|
+
|
|
4
|
+
export default function withErrorBoundary(WrappedComponent, options = {}) {
|
|
5
|
+
// Handle backward compatibility - if second param is a component, treat as fallback
|
|
6
|
+
const config =
|
|
7
|
+
React.isValidElement(options) || typeof options === 'function'
|
|
8
|
+
? { fallback: options }
|
|
9
|
+
: {
|
|
10
|
+
fallback: null,
|
|
11
|
+
onError: null,
|
|
12
|
+
...options,
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
const ErrorBoundaryWrapper = React.memo(function ErrorBoundaryWrapper(props) {
|
|
16
|
+
const { fallback, onError } = config;
|
|
17
|
+
|
|
18
|
+
return (
|
|
19
|
+
<ErrorBoundary fallback={fallback} onError={onError}>
|
|
20
|
+
<WrappedComponent {...props} />
|
|
21
|
+
</ErrorBoundary>
|
|
22
|
+
);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
const wrappedComponentName = WrappedComponent.displayName || 'Component';
|
|
26
|
+
ErrorBoundaryWrapper.displayName = `withErrorBoundary(${wrappedComponentName})`;
|
|
27
|
+
|
|
28
|
+
return ErrorBoundaryWrapper;
|
|
29
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { render, screen } from '@testing-library/react';
|
|
2
|
+
import '@testing-library/jest-dom';
|
|
3
|
+
import { ErrorBoundary } from '@plone/volto/components';
|
|
4
|
+
import withErrorBoundary from './withErrorBoundary';
|
|
5
|
+
|
|
6
|
+
// Mock the ErrorBoundary component from Volto
|
|
7
|
+
jest.mock('@plone/volto/components', () => ({
|
|
8
|
+
ErrorBoundary: jest.fn(({ children, fallback, onError }) => {
|
|
9
|
+
try {
|
|
10
|
+
return children;
|
|
11
|
+
} catch (error) {
|
|
12
|
+
if (onError) onError(error, { componentStack: 'test-stack' });
|
|
13
|
+
return fallback || <div>Error occurred</div>;
|
|
14
|
+
}
|
|
15
|
+
}),
|
|
16
|
+
}));
|
|
17
|
+
|
|
18
|
+
// Test components
|
|
19
|
+
const TestComponent = ({ shouldThrow, message = 'Hello World' }) => {
|
|
20
|
+
if (shouldThrow) {
|
|
21
|
+
throw new Error('Test error');
|
|
22
|
+
}
|
|
23
|
+
return <div>{message}</div>;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const CustomFallback = () => <div>Custom error fallback</div>;
|
|
27
|
+
|
|
28
|
+
describe('withErrorBoundary HOC', () => {
|
|
29
|
+
beforeEach(() => {
|
|
30
|
+
jest.clearAllMocks();
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
describe('Basic functionality', () => {
|
|
34
|
+
it('should render the wrapped component normally', () => {
|
|
35
|
+
const WrappedComponent = withErrorBoundary(TestComponent);
|
|
36
|
+
render(<WrappedComponent message="Test message" />);
|
|
37
|
+
|
|
38
|
+
expect(screen.getByText('Test message')).toBeInTheDocument();
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it('should pass through all props to the wrapped component', () => {
|
|
42
|
+
const WrappedComponent = withErrorBoundary(TestComponent);
|
|
43
|
+
render(<WrappedComponent message="Test props" data-testid="test" />);
|
|
44
|
+
|
|
45
|
+
expect(screen.getByText('Test props')).toBeInTheDocument();
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
describe('Error boundary configuration', () => {
|
|
50
|
+
it('should use default ErrorBoundary when no fallback is provided', () => {
|
|
51
|
+
const WrappedComponent = withErrorBoundary(TestComponent);
|
|
52
|
+
render(<WrappedComponent />);
|
|
53
|
+
|
|
54
|
+
expect(ErrorBoundary).toHaveBeenCalledWith(
|
|
55
|
+
expect.objectContaining({
|
|
56
|
+
fallback: null,
|
|
57
|
+
onError: null,
|
|
58
|
+
}),
|
|
59
|
+
expect.any(Object),
|
|
60
|
+
);
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
it('should accept a custom fallback component', () => {
|
|
64
|
+
const WrappedComponent = withErrorBoundary(TestComponent, {
|
|
65
|
+
fallback: CustomFallback,
|
|
66
|
+
});
|
|
67
|
+
render(<WrappedComponent />);
|
|
68
|
+
|
|
69
|
+
expect(ErrorBoundary).toHaveBeenCalledWith(
|
|
70
|
+
expect.objectContaining({
|
|
71
|
+
fallback: CustomFallback,
|
|
72
|
+
}),
|
|
73
|
+
expect.any(Object),
|
|
74
|
+
);
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
it('should handle backward compatibility with fallback as second parameter', () => {
|
|
78
|
+
const WrappedComponent = withErrorBoundary(TestComponent, CustomFallback);
|
|
79
|
+
render(<WrappedComponent />);
|
|
80
|
+
|
|
81
|
+
expect(ErrorBoundary).toHaveBeenCalledWith(
|
|
82
|
+
expect.objectContaining({
|
|
83
|
+
fallback: CustomFallback,
|
|
84
|
+
}),
|
|
85
|
+
expect.any(Object),
|
|
86
|
+
);
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
it('should call onError callback when provided', () => {
|
|
90
|
+
const onErrorMock = jest.fn();
|
|
91
|
+
const WrappedComponent = withErrorBoundary(TestComponent, {
|
|
92
|
+
onError: onErrorMock,
|
|
93
|
+
});
|
|
94
|
+
render(<WrappedComponent />);
|
|
95
|
+
|
|
96
|
+
expect(ErrorBoundary).toHaveBeenCalledWith(
|
|
97
|
+
expect.objectContaining({
|
|
98
|
+
onError: onErrorMock,
|
|
99
|
+
}),
|
|
100
|
+
expect.any(Object),
|
|
101
|
+
);
|
|
102
|
+
});
|
|
103
|
+
});
|
|
104
|
+
});
|