@plone/volto 18.33.1 → 18.35.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/.release-it.json +3 -0
- package/CHANGELOG.md +52 -0
- package/README.md +0 -1
- package/locales/af/LC_MESSAGES/volto.po +55 -0
- package/locales/af.json +1 -1
- package/locales/ar/LC_MESSAGES/volto.po +55 -0
- package/locales/ar.json +1 -1
- package/locales/bg/LC_MESSAGES/volto.po +55 -0
- package/locales/bg.json +1 -1
- package/locales/bn/LC_MESSAGES/volto.po +55 -0
- package/locales/bn.json +1 -1
- package/locales/ca/LC_MESSAGES/volto.po +57 -2
- package/locales/ca.json +1 -1
- package/locales/cs/LC_MESSAGES/volto.po +55 -0
- package/locales/cs.json +1 -1
- package/locales/cy/LC_MESSAGES/volto.po +55 -0
- package/locales/cy.json +1 -1
- package/locales/da/LC_MESSAGES/volto.po +55 -0
- package/locales/da.json +1 -1
- package/locales/de/LC_MESSAGES/volto.po +59 -4
- package/locales/de.json +1 -1
- package/locales/el/LC_MESSAGES/volto.po +55 -0
- package/locales/el.json +1 -1
- package/locales/en/LC_MESSAGES/volto.po +55 -0
- package/locales/en.json +1 -1
- package/locales/en_AU/LC_MESSAGES/volto.po +55 -0
- package/locales/en_AU.json +1 -1
- package/locales/en_GB/LC_MESSAGES/volto.po +55 -0
- package/locales/en_GB.json +1 -1
- package/locales/eo/LC_MESSAGES/volto.po +55 -0
- package/locales/eo.json +1 -1
- package/locales/es/LC_MESSAGES/volto.po +73 -18
- package/locales/es.json +1 -1
- package/locales/et/LC_MESSAGES/volto.po +55 -0
- package/locales/et.json +1 -1
- package/locales/eu/LC_MESSAGES/volto.po +58 -3
- package/locales/eu.json +1 -1
- package/locales/fa/LC_MESSAGES/volto.po +55 -0
- package/locales/fa.json +1 -1
- package/locales/fi/LC_MESSAGES/volto.po +55 -0
- package/locales/fi.json +1 -1
- package/locales/fr/LC_MESSAGES/volto.po +56 -1
- package/locales/fr.json +1 -1
- package/locales/fu/LC_MESSAGES/volto.po +55 -0
- package/locales/fu.json +1 -1
- package/locales/gl/LC_MESSAGES/volto.po +60 -5
- package/locales/gl.json +1 -1
- package/locales/he/LC_MESSAGES/volto.po +55 -0
- package/locales/he.json +1 -1
- package/locales/hi/LC_MESSAGES/volto.po +58 -3
- package/locales/hi.json +1 -1
- package/locales/hr/LC_MESSAGES/volto.po +55 -0
- package/locales/hr.json +1 -1
- package/locales/hu/LC_MESSAGES/volto.po +55 -0
- package/locales/hu.json +1 -1
- package/locales/hy/LC_MESSAGES/volto.po +55 -0
- package/locales/hy.json +1 -1
- package/locales/id/LC_MESSAGES/volto.po +55 -0
- package/locales/id.json +1 -1
- package/locales/it/LC_MESSAGES/volto.po +56 -1
- package/locales/it.json +1 -1
- package/locales/ja/LC_MESSAGES/volto.po +55 -0
- package/locales/ja.json +1 -1
- package/locales/ka/LC_MESSAGES/volto.po +55 -0
- package/locales/ka.json +1 -1
- package/locales/kn/LC_MESSAGES/volto.po +55 -0
- package/locales/kn.json +1 -1
- package/locales/ko/LC_MESSAGES/volto.po +55 -0
- package/locales/ko.json +1 -1
- package/locales/lt/LC_MESSAGES/volto.po +55 -0
- package/locales/lt.json +1 -1
- package/locales/lv/LC_MESSAGES/volto.po +55 -0
- package/locales/lv.json +1 -1
- package/locales/mi/LC_MESSAGES/volto.po +55 -0
- package/locales/mi.json +1 -1
- package/locales/mk/LC_MESSAGES/volto.po +55 -0
- package/locales/mk.json +1 -1
- package/locales/my/LC_MESSAGES/volto.po +55 -0
- package/locales/my.json +1 -1
- package/locales/nb_NO/LC_MESSAGES/volto.po +55 -0
- package/locales/nb_NO.json +1 -1
- package/locales/nl/LC_MESSAGES/volto.po +56 -1
- package/locales/nl.json +1 -1
- package/locales/nn/LC_MESSAGES/volto.po +55 -0
- package/locales/nn.json +1 -1
- package/locales/pl/LC_MESSAGES/volto.po +55 -0
- package/locales/pl.json +1 -1
- package/locales/pt/LC_MESSAGES/volto.po +55 -0
- package/locales/pt.json +1 -1
- package/locales/pt_BR/LC_MESSAGES/volto.po +69 -14
- package/locales/pt_BR.json +1 -1
- package/locales/rm/LC_MESSAGES/volto.po +55 -0
- package/locales/rm.json +1 -1
- package/locales/ro/LC_MESSAGES/volto.po +56 -1
- package/locales/ro.json +1 -1
- package/locales/ru/LC_MESSAGES/volto.po +56 -1
- package/locales/ru.json +1 -1
- package/locales/sk/LC_MESSAGES/volto.po +55 -0
- package/locales/sk.json +1 -1
- package/locales/sl/LC_MESSAGES/volto.po +55 -0
- package/locales/sl.json +1 -1
- package/locales/sm/LC_MESSAGES/volto.po +55 -0
- package/locales/sm.json +1 -1
- package/locales/sq/LC_MESSAGES/volto.po +55 -0
- package/locales/sq.json +1 -1
- package/locales/sr/LC_MESSAGES/volto.po +55 -0
- package/locales/sr.json +1 -1
- package/locales/sr@cyrl/LC_MESSAGES/volto.po +55 -0
- package/locales/sr@cyrl.json +1 -1
- package/locales/sr@latn/LC_MESSAGES/volto.po +55 -0
- package/locales/sr@latn.json +1 -1
- package/locales/sv/LC_MESSAGES/volto.po +55 -0
- package/locales/sv.json +1 -1
- package/locales/ta/LC_MESSAGES/volto.po +56 -1
- package/locales/ta.json +1 -1
- package/locales/te/LC_MESSAGES/volto.po +55 -0
- package/locales/te.json +1 -1
- package/locales/th/LC_MESSAGES/volto.po +55 -0
- package/locales/th.json +1 -1
- package/locales/to/LC_MESSAGES/volto.po +55 -0
- package/locales/to.json +1 -1
- package/locales/tr/LC_MESSAGES/volto.po +55 -0
- package/locales/tr.json +1 -1
- package/locales/uk/LC_MESSAGES/volto.po +55 -0
- package/locales/uk.json +1 -1
- package/locales/vi/LC_MESSAGES/volto.po +55 -0
- package/locales/vi.json +1 -1
- package/locales/volto.pot +56 -1
- package/locales/zh_CN/LC_MESSAGES/volto.po +55 -0
- package/locales/zh_CN.json +1 -1
- package/locales/zh_Hant/LC_MESSAGES/volto.po +55 -0
- package/locales/zh_Hant.json +1 -1
- package/locales/zh_Hant_HK/LC_MESSAGES/volto.po +55 -0
- package/locales/zh_Hant_HK.json +1 -1
- package/news/7308.fix +1 -0
- package/news/8084.fix +1 -0
- package/package.json +19 -19
- package/razzle.config.js +1 -0
- package/src/actions/users/users.js +2 -2
- package/src/components/manage/Blocks/Block/Order/Item.jsx +18 -10
- package/src/components/manage/Blocks/Block/Order/Item.test.jsx +90 -0
- package/src/components/manage/Controlpanels/AddonsControlpanel.jsx +7 -0
- package/src/components/manage/Controlpanels/ContentTypes.jsx +9 -2
- package/src/components/manage/Controlpanels/DatabaseInformation.jsx +9 -0
- package/src/components/manage/Controlpanels/ModerateComments.jsx +8 -0
- package/src/components/manage/Controlpanels/Users/UserGroupMembershipControlPanel.test.jsx +3 -0
- package/src/components/manage/Controlpanels/Users/UsersControlpanel.jsx +58 -5
- package/src/components/manage/Controlpanels/Users/UsersControlpanel.ssr.test.jsx +624 -0
- package/src/components/manage/Controlpanels/Users/UsersControlpanel.test.jsx +8 -0
- package/src/components/manage/Form/Form.jsx +6 -1
- package/src/components/manage/Form/ModalForm.jsx +165 -87
- package/src/components/manage/Sidebar/Sidebar.jsx +1 -0
- package/src/components/manage/Toast/Toast.jsx +35 -1
- package/src/components/manage/Toast/Toast.test.jsx +8 -5
- package/src/components/manage/Widgets/DatetimeWidget.jsx +92 -58
- package/src/components/manage/Widgets/DatetimeWidget.test.jsx +55 -0
- package/src/components/manage/Widgets/FormFieldWrapper.jsx +7 -5
- package/src/components/manage/Widgets/TextWidget.jsx +4 -0
- package/src/components/manage/Widgets/UrlWidget.jsx +51 -6
- package/src/components/theme/Search/Search.jsx +24 -1
- package/src/components/theme/Unauthorized/Unauthorized.jsx +30 -22
- package/src/components/theme/Unauthorized/Unauthorized.test.jsx +28 -1
- package/src/helpers/FormValidation/validators.ts +15 -2
- package/theme/themes/default/globals/site.variables +2 -2
- package/theme/themes/pastanaga/collections/form.overrides +21 -0
- package/theme/themes/pastanaga/elements/button.overrides +30 -3
- package/theme/themes/pastanaga/extras/main.less +16 -0
- package/theme/themes/pastanaga/globals/site.variables +0 -2
- package/types/components/manage/Blocks/Block/Order/Item.test.d.ts +1 -0
- package/types/components/manage/Controlpanels/Users/UsersControlpanel.d.ts +2 -6
- package/types/components/manage/Controlpanels/Users/UsersControlpanel.ssr.test.d.ts +1 -0
- package/types/components/manage/Controlpanels/index.d.ts +1 -1
- package/webpack-plugins/webpack-less-plugin.js +1 -1
package/package.json
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
}
|
|
10
10
|
],
|
|
11
11
|
"license": "MIT",
|
|
12
|
-
"version": "18.
|
|
12
|
+
"version": "18.35.0",
|
|
13
13
|
"repository": {
|
|
14
14
|
"type": "git",
|
|
15
15
|
"url": "git@github.com:plone/volto.git"
|
|
@@ -142,17 +142,17 @@
|
|
|
142
142
|
"@dnd-kit/core": "6.0.8",
|
|
143
143
|
"@dnd-kit/sortable": "7.0.2",
|
|
144
144
|
"@dnd-kit/utilities": "3.2.2",
|
|
145
|
-
"@loadable/component": "5.
|
|
146
|
-
"@loadable/server": "5.
|
|
145
|
+
"@loadable/component": "5.16.7",
|
|
146
|
+
"@loadable/server": "5.16.7",
|
|
147
147
|
"@redux-devtools/extension": "^3.3.0",
|
|
148
148
|
"classnames": "2.5.1",
|
|
149
149
|
"connected-react-router": "6.8.0",
|
|
150
|
-
"debug": "4.3.
|
|
150
|
+
"debug": "4.3.4",
|
|
151
151
|
"decorate-component-with-props": "1.2.1",
|
|
152
152
|
"dependency-graph": "0.10.0",
|
|
153
153
|
"detect-browser": "5.1.0",
|
|
154
|
-
"diff": "3.5.
|
|
155
|
-
"express": "4.
|
|
154
|
+
"diff": "3.5.1",
|
|
155
|
+
"express": "4.22.1",
|
|
156
156
|
"filesize": "6",
|
|
157
157
|
"full-icu": "1.4.0",
|
|
158
158
|
"github-slugger": "1.4.0",
|
|
@@ -166,7 +166,7 @@
|
|
|
166
166
|
"jwt-decode": "2.2.0",
|
|
167
167
|
"linkify-it": "3.0.2",
|
|
168
168
|
"locale": "0.1.0",
|
|
169
|
-
"lodash": "4.
|
|
169
|
+
"lodash": "4.18.1",
|
|
170
170
|
"lodash-move": "1.1.1",
|
|
171
171
|
"moment": "2.29.4",
|
|
172
172
|
"object-assign": "4.1.1",
|
|
@@ -177,7 +177,7 @@
|
|
|
177
177
|
"process": "^0.11.10",
|
|
178
178
|
"promise-file-reader": "1.0.2",
|
|
179
179
|
"prop-types": "15.7.2",
|
|
180
|
-
"query-string": "7.1.
|
|
180
|
+
"query-string": "7.1.3",
|
|
181
181
|
"rc-time-picker": "3.7.3",
|
|
182
182
|
"react": "18.2.0",
|
|
183
183
|
"react-anchor-link-smooth-scroll": "1.0.12",
|
|
@@ -220,7 +220,7 @@
|
|
|
220
220
|
"rrule": "2.7.1",
|
|
221
221
|
"semantic-ui-less": "2.4.1",
|
|
222
222
|
"semantic-ui-react": "2.1.5",
|
|
223
|
-
"serialize-javascript": "7.0.
|
|
223
|
+
"serialize-javascript": "7.0.5",
|
|
224
224
|
"slate": "0.100.0",
|
|
225
225
|
"slate-hyperscript": "0.100.0",
|
|
226
226
|
"slate-react": "0.98.4",
|
|
@@ -232,9 +232,9 @@
|
|
|
232
232
|
"url": "^0.11.3",
|
|
233
233
|
"use-deep-compare-effect": "1.8.1",
|
|
234
234
|
"uuid": "^8.3.2",
|
|
235
|
-
"@plone/
|
|
236
|
-
"@plone/
|
|
237
|
-
"@plone/volto-slate": "18.
|
|
235
|
+
"@plone/scripts": "3.10.6",
|
|
236
|
+
"@plone/registry": "2.7.2",
|
|
237
|
+
"@plone/volto-slate": "18.10.0"
|
|
238
238
|
},
|
|
239
239
|
"devDependencies": {
|
|
240
240
|
"@babel/core": "^7.0.0",
|
|
@@ -249,7 +249,7 @@
|
|
|
249
249
|
"@babel/types": "7.20.5",
|
|
250
250
|
"@fiverr/afterbuild-webpack-plugin": "^1.0.0",
|
|
251
251
|
"@jest/globals": "^29.7.0",
|
|
252
|
-
"@loadable/babel-plugin": "5.
|
|
252
|
+
"@loadable/babel-plugin": "5.16.1",
|
|
253
253
|
"@loadable/webpack-plugin": "5.15.2",
|
|
254
254
|
"@sinonjs/fake-timers": "^6.0.1",
|
|
255
255
|
"@storybook/addon-actions": "^8.0.4",
|
|
@@ -268,7 +268,7 @@
|
|
|
268
268
|
"@testing-library/react-hooks": "8.0.1",
|
|
269
269
|
"@types/history": "^4.7.11",
|
|
270
270
|
"@types/jest": "^29.5.8",
|
|
271
|
-
"@types/loadable__component": "^5.13.
|
|
271
|
+
"@types/loadable__component": "^5.13.10",
|
|
272
272
|
"@types/lodash": "^4.14.201",
|
|
273
273
|
"@types/node": "^22",
|
|
274
274
|
"@types/react": "^18",
|
|
@@ -308,7 +308,7 @@
|
|
|
308
308
|
"eslint-plugin-prettier": "^5.1.3",
|
|
309
309
|
"eslint-plugin-react": "^7.34.1",
|
|
310
310
|
"eslint-plugin-react-hooks": "^4.6.0",
|
|
311
|
-
"html-webpack-plugin": "5.
|
|
311
|
+
"html-webpack-plugin": "5.6.7",
|
|
312
312
|
"identity-obj-proxy": "3.0.0",
|
|
313
313
|
"jest": "26.6.3",
|
|
314
314
|
"jest-environment-jsdom": "^26",
|
|
@@ -319,7 +319,7 @@
|
|
|
319
319
|
"less": "3.13.1",
|
|
320
320
|
"less-loader": "11.1.0",
|
|
321
321
|
"lodash-webpack-plugin": "0.11.6",
|
|
322
|
-
"mini-css-extract-plugin": "2.
|
|
322
|
+
"mini-css-extract-plugin": "2.10.2",
|
|
323
323
|
"moment-locales-webpack-plugin": "1.2.0",
|
|
324
324
|
"postcss": "8.4.31",
|
|
325
325
|
"postcss-flexbugs-fixes": "5.0.2",
|
|
@@ -331,7 +331,7 @@
|
|
|
331
331
|
"razzle": "4.2.18",
|
|
332
332
|
"razzle-dev-utils": "4.2.18",
|
|
333
333
|
"razzle-plugin-scss": "4.2.18",
|
|
334
|
-
"react-docgen-typescript-plugin": "^1.0.
|
|
334
|
+
"react-docgen-typescript-plugin": "^1.0.8",
|
|
335
335
|
"react-error-overlay": "6.0.9",
|
|
336
336
|
"react-is": "^18.2.0",
|
|
337
337
|
"release-it": "^19.0.5",
|
|
@@ -345,7 +345,7 @@
|
|
|
345
345
|
"svg-loader": "0.0.2",
|
|
346
346
|
"svgo": "^3.0.0",
|
|
347
347
|
"svgo-loader": "3.0.3",
|
|
348
|
-
"terser-webpack-plugin": "5.
|
|
348
|
+
"terser-webpack-plugin": "5.4.0",
|
|
349
349
|
"ts-jest": "^26.4.2",
|
|
350
350
|
"ts-loader": "9.4.4",
|
|
351
351
|
"typescript": "^5.7.3",
|
|
@@ -357,7 +357,7 @@
|
|
|
357
357
|
"webpack-dev-server": "4.11.1",
|
|
358
358
|
"webpack-node-externals": "3.0.0",
|
|
359
359
|
"why": "0.6.2",
|
|
360
|
-
"@plone/types": "1.6.
|
|
360
|
+
"@plone/types": "1.6.2",
|
|
361
361
|
"@plone/volto-coresandbox": "1.0.0"
|
|
362
362
|
},
|
|
363
363
|
"scripts": {
|
package/razzle.config.js
CHANGED
|
@@ -310,6 +310,7 @@ const defaultModify = ({
|
|
|
310
310
|
'load-volto-addons': addonsLoaderPath,
|
|
311
311
|
...registry.getResolveAliases(),
|
|
312
312
|
'@plone/volto': `${registry.voltoPath}/src`,
|
|
313
|
+
'@plone/volto-slate': `${registry.voltoPath}/../volto-slate/src`,
|
|
313
314
|
// to be able to reference path uncustomized by webpack
|
|
314
315
|
'@plone/volto-original': `${registry.voltoPath}/src`,
|
|
315
316
|
// be able to reference current package from customized package
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* @module actions/users/users
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import
|
|
6
|
+
import qs from 'query-string';
|
|
7
7
|
|
|
8
8
|
import {
|
|
9
9
|
CREATE_USER,
|
|
@@ -92,7 +92,7 @@ export function listUsers(options = {}) {
|
|
|
92
92
|
|
|
93
93
|
let filterarg =
|
|
94
94
|
groups_filter.length > 0
|
|
95
|
-
? stringify(
|
|
95
|
+
? qs.stringify(
|
|
96
96
|
{ 'groups-filter': groups_filter },
|
|
97
97
|
{ arrayFormat: 'colon-list-separator' },
|
|
98
98
|
)
|
|
@@ -44,6 +44,12 @@ export const Item = forwardRef(
|
|
|
44
44
|
config.blocks.blocksConfig[data?.['@type']]?.icon ||
|
|
45
45
|
config.blocks.blocksConfig.title?.icon;
|
|
46
46
|
|
|
47
|
+
const required =
|
|
48
|
+
typeof data?.required === 'boolean'
|
|
49
|
+
? data.required
|
|
50
|
+
: includes(config.blocks.requiredBlocks, data?.['@type']);
|
|
51
|
+
const fixed = !!data?.fixed;
|
|
52
|
+
|
|
47
53
|
return (
|
|
48
54
|
<li
|
|
49
55
|
className={classNames(
|
|
@@ -93,15 +99,17 @@ export const Item = forwardRef(
|
|
|
93
99
|
ref={ref}
|
|
94
100
|
style={style}
|
|
95
101
|
>
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
102
|
+
{!fixed && (
|
|
103
|
+
<button
|
|
104
|
+
ref={ref}
|
|
105
|
+
{...handleProps}
|
|
106
|
+
className={classNames('action', 'drag')}
|
|
107
|
+
tabIndex={0}
|
|
108
|
+
data-cypress="draggable-handle"
|
|
109
|
+
>
|
|
110
|
+
<Icon name={dragSVG} size="16px" />
|
|
111
|
+
</button>
|
|
112
|
+
)}
|
|
105
113
|
<span
|
|
106
114
|
className={cx('text', {
|
|
107
115
|
errored: errors && Object.keys(errors).length > 0,
|
|
@@ -118,7 +126,7 @@ export const Item = forwardRef(
|
|
|
118
126
|
config.blocks.blocksConfig[data?.['@type']]?.title ||
|
|
119
127
|
data?.title}
|
|
120
128
|
</span>
|
|
121
|
-
{!clone && onRemove && (
|
|
129
|
+
{!clone && onRemove && !required && (
|
|
122
130
|
<button
|
|
123
131
|
onClick={onRemove}
|
|
124
132
|
className={classNames('action', 'delete')}
|
|
@@ -0,0 +1,90 @@
|
|
|
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 config from '@plone/volto/registry';
|
|
6
|
+
|
|
7
|
+
import { Item } from './Item';
|
|
8
|
+
|
|
9
|
+
const mockStore = configureStore();
|
|
10
|
+
|
|
11
|
+
const defaultStoreState = {
|
|
12
|
+
intl: {
|
|
13
|
+
locale: 'en',
|
|
14
|
+
messages: {},
|
|
15
|
+
},
|
|
16
|
+
form: {
|
|
17
|
+
ui: {
|
|
18
|
+
selected: null,
|
|
19
|
+
hovered: null,
|
|
20
|
+
multiSelected: [],
|
|
21
|
+
gridSelected: null,
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const renderItem = (data = {}) => {
|
|
27
|
+
const store = mockStore(defaultStoreState);
|
|
28
|
+
|
|
29
|
+
return render(
|
|
30
|
+
<Provider store={store}>
|
|
31
|
+
<Item
|
|
32
|
+
id="title-block-id"
|
|
33
|
+
data={{ '@type': 'title', ...data }}
|
|
34
|
+
depth={0}
|
|
35
|
+
indentationWidth={25}
|
|
36
|
+
onRemove={() => {}}
|
|
37
|
+
onSelectBlock={() => {}}
|
|
38
|
+
handleProps={{}}
|
|
39
|
+
/>
|
|
40
|
+
</Provider>,
|
|
41
|
+
);
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
describe('Order Item', () => {
|
|
45
|
+
let requiredBlocks;
|
|
46
|
+
|
|
47
|
+
beforeEach(() => {
|
|
48
|
+
requiredBlocks = [...(config.blocks.requiredBlocks || [])];
|
|
49
|
+
config.blocks.requiredBlocks = [];
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
afterEach(() => {
|
|
53
|
+
config.blocks.requiredBlocks = requiredBlocks;
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
test('renders drag and delete actions for movable and removable blocks', () => {
|
|
57
|
+
const { container } = renderItem();
|
|
58
|
+
|
|
59
|
+
expect(container.querySelector('.action.drag')).not.toBeNull();
|
|
60
|
+
expect(container.querySelector('.action.delete')).not.toBeNull();
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
test('hides delete action for required blocks', () => {
|
|
64
|
+
const { container } = renderItem({ required: true });
|
|
65
|
+
|
|
66
|
+
expect(container.querySelector('.action.delete')).toBeNull();
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
test('hides delete action for block types configured as required', () => {
|
|
70
|
+
config.blocks.requiredBlocks = ['title'];
|
|
71
|
+
|
|
72
|
+
const { container } = renderItem();
|
|
73
|
+
|
|
74
|
+
expect(container.querySelector('.action.delete')).toBeNull();
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
test('allows explicit required=false to override required block types', () => {
|
|
78
|
+
config.blocks.requiredBlocks = ['title'];
|
|
79
|
+
|
|
80
|
+
const { container } = renderItem({ required: false });
|
|
81
|
+
|
|
82
|
+
expect(container.querySelector('.action.delete')).not.toBeNull();
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
test('hides drag action for fixed blocks', () => {
|
|
86
|
+
const { container } = renderItem({ fixed: true });
|
|
87
|
+
|
|
88
|
+
expect(container.querySelector('.action.drag')).toBeNull();
|
|
89
|
+
});
|
|
90
|
+
});
|
|
@@ -27,6 +27,7 @@ import Helmet from '@plone/volto/helpers/Helmet/Helmet';
|
|
|
27
27
|
import Icon from '@plone/volto/components/theme/Icon/Icon';
|
|
28
28
|
import Toolbar from '@plone/volto/components/manage/Toolbar/Toolbar';
|
|
29
29
|
import Toast from '@plone/volto/components/manage/Toast/Toast';
|
|
30
|
+
import Error from '@plone/volto/components/theme/Error/Error';
|
|
30
31
|
import circleBottomSVG from '@plone/volto/icons/circle-bottom.svg';
|
|
31
32
|
import circleTopSVG from '@plone/volto/icons/circle-top.svg';
|
|
32
33
|
import backSVG from '@plone/volto/icons/back.svg';
|
|
@@ -148,6 +149,7 @@ const AddonsControlpanel = (props) => {
|
|
|
148
149
|
shallowEqual,
|
|
149
150
|
);
|
|
150
151
|
const loadingAddons = useSelector((state) => state.addons.loading);
|
|
152
|
+
const addonsError = useSelector((state) => state.addons.error);
|
|
151
153
|
|
|
152
154
|
useEffect(() => {
|
|
153
155
|
dispatch(listAddons());
|
|
@@ -245,6 +247,11 @@ const AddonsControlpanel = (props) => {
|
|
|
245
247
|
setactiveIndex(newIndex);
|
|
246
248
|
};
|
|
247
249
|
|
|
250
|
+
// Error handling for unauthorized access
|
|
251
|
+
if (addonsError) {
|
|
252
|
+
return <Error error={addonsError} />;
|
|
253
|
+
}
|
|
254
|
+
|
|
248
255
|
return (
|
|
249
256
|
<Container id="page-addons" className="controlpanel-addons">
|
|
250
257
|
<Helmet title={intl.formatMessage(messages.addOns)} />
|
|
@@ -227,6 +227,7 @@ class ContentTypes extends Component {
|
|
|
227
227
|
addTypeError: undefined,
|
|
228
228
|
addTypeSetFormDataCallback: undefined,
|
|
229
229
|
});
|
|
230
|
+
this._addTypeTrigger?.focus();
|
|
230
231
|
toast.success(
|
|
231
232
|
<Toast
|
|
232
233
|
success
|
|
@@ -369,10 +370,13 @@ class ContentTypes extends Component {
|
|
|
369
370
|
/>
|
|
370
371
|
<ModalForm
|
|
371
372
|
open={this.state.showAddType}
|
|
372
|
-
className="modal"
|
|
373
|
+
className="modal add-content-type"
|
|
373
374
|
onSubmit={this.onAddTypeSubmit}
|
|
374
375
|
submitError={this.state.addTypeError}
|
|
375
|
-
onCancel={() =>
|
|
376
|
+
onCancel={() => {
|
|
377
|
+
this.setState({ showAddType: false });
|
|
378
|
+
this._addTypeTrigger?.focus();
|
|
379
|
+
}}
|
|
376
380
|
title={this.props.intl.formatMessage(messages.addTypeFormTitle)}
|
|
377
381
|
loading={this.props.cpanelRequest.post.loading}
|
|
378
382
|
schema={{
|
|
@@ -474,6 +478,9 @@ class ContentTypes extends Component {
|
|
|
474
478
|
aria-label={this.props.intl.formatMessage(messages.add)}
|
|
475
479
|
tabIndex={0}
|
|
476
480
|
id="toolbar-add"
|
|
481
|
+
ref={(el) => {
|
|
482
|
+
this._addTypeTrigger = el;
|
|
483
|
+
}}
|
|
477
484
|
onClick={() => {
|
|
478
485
|
this.setState({ showAddType: true });
|
|
479
486
|
}}
|
|
@@ -10,6 +10,7 @@ import Helmet from '@plone/volto/helpers/Helmet/Helmet';
|
|
|
10
10
|
import { useClient } from '@plone/volto/hooks/client/useClient';
|
|
11
11
|
import Icon from '@plone/volto/components/theme/Icon/Icon';
|
|
12
12
|
import Toolbar from '@plone/volto/components/manage/Toolbar/Toolbar';
|
|
13
|
+
import Error from '@plone/volto/components/theme/Error/Error';
|
|
13
14
|
import backSVG from '@plone/volto/icons/back.svg';
|
|
14
15
|
|
|
15
16
|
const messages = defineMessages({
|
|
@@ -31,11 +32,19 @@ const DatabaseInformation = () => {
|
|
|
31
32
|
const databaseInformation = useSelector(
|
|
32
33
|
(state) => state.controlpanels.databaseinformation,
|
|
33
34
|
);
|
|
35
|
+
const databaseError = useSelector(
|
|
36
|
+
(state) => state.controlpanels.database?.error,
|
|
37
|
+
);
|
|
34
38
|
|
|
35
39
|
useEffect(() => {
|
|
36
40
|
dispatch(getDatabaseInformation());
|
|
37
41
|
}, [dispatch]);
|
|
38
42
|
|
|
43
|
+
// Error handling for unauthorized access
|
|
44
|
+
if (databaseError) {
|
|
45
|
+
return <Error error={databaseError} />;
|
|
46
|
+
}
|
|
47
|
+
|
|
39
48
|
return databaseInformation ? (
|
|
40
49
|
<Container id="database-page" className="controlpanel-database">
|
|
41
50
|
<Helmet title={intl.formatMessage(messages.databaseInformation)} />
|
|
@@ -19,6 +19,7 @@ import { searchContent } from '@plone/volto/actions/search/search';
|
|
|
19
19
|
import FormattedRelativeDate from '@plone/volto/components/theme/FormattedDate/FormattedRelativeDate';
|
|
20
20
|
import Icon from '@plone/volto/components/theme/Icon/Icon';
|
|
21
21
|
import Toolbar from '@plone/volto/components/manage/Toolbar/Toolbar';
|
|
22
|
+
import Error from '@plone/volto/components/theme/Error/Error';
|
|
22
23
|
import { CommentEditModal } from '@plone/volto/components/theme/Comments';
|
|
23
24
|
|
|
24
25
|
import backSVG from '@plone/volto/icons/back.svg';
|
|
@@ -65,6 +66,7 @@ class ModerateComments extends Component {
|
|
|
65
66
|
loaded: PropTypes.bool,
|
|
66
67
|
}).isRequired,
|
|
67
68
|
pathname: PropTypes.string.isRequired,
|
|
69
|
+
searchError: PropTypes.object,
|
|
68
70
|
};
|
|
69
71
|
|
|
70
72
|
/**
|
|
@@ -186,6 +188,11 @@ class ModerateComments extends Component {
|
|
|
186
188
|
* @returns {string} Markup for the component.
|
|
187
189
|
*/
|
|
188
190
|
render() {
|
|
191
|
+
// Error handling for unauthorized access
|
|
192
|
+
if (this.props.searchError) {
|
|
193
|
+
return <Error error={this.props.searchError} />;
|
|
194
|
+
}
|
|
195
|
+
|
|
189
196
|
return (
|
|
190
197
|
<div id="page-moderate-comments">
|
|
191
198
|
<CommentEditModal
|
|
@@ -297,6 +304,7 @@ export default compose(
|
|
|
297
304
|
items: state.search.items,
|
|
298
305
|
deleteRequest: state.comments.delete,
|
|
299
306
|
pathname: props.location.pathname,
|
|
307
|
+
searchError: state.search.error,
|
|
300
308
|
}),
|
|
301
309
|
{ deleteComment, searchContent },
|
|
302
310
|
),
|
|
@@ -14,6 +14,9 @@ vi.mock('../../Toolbar/Toolbar', () => ({
|
|
|
14
14
|
describe('UserGroupMembershipControlPanel', () => {
|
|
15
15
|
it('renders a user group membership control component', () => {
|
|
16
16
|
const store = mockStore({
|
|
17
|
+
userSession: {
|
|
18
|
+
token: '1234',
|
|
19
|
+
},
|
|
17
20
|
controlpanels: {
|
|
18
21
|
controlpanel: {
|
|
19
22
|
data: {
|
|
@@ -13,6 +13,7 @@ import { listRoles } from '@plone/volto/actions/roles/roles';
|
|
|
13
13
|
import { listGroups, updateGroup } from '@plone/volto/actions/groups/groups';
|
|
14
14
|
import { getControlpanel } from '@plone/volto/actions/controlpanels/controlpanels';
|
|
15
15
|
import { getUserSchema } from '@plone/volto/actions/userschema/userschema';
|
|
16
|
+
import { asyncConnect } from '@plone/volto/helpers/AsyncConnect';
|
|
16
17
|
import jwtDecode from 'jwt-decode';
|
|
17
18
|
import Icon from '@plone/volto/components/theme/Icon/Icon';
|
|
18
19
|
import Toast from '@plone/volto/components/manage/Toast/Toast';
|
|
@@ -57,7 +58,8 @@ import {
|
|
|
57
58
|
* UsersControlpanel functional component.
|
|
58
59
|
* @function UsersControlpanel
|
|
59
60
|
*/
|
|
60
|
-
const UsersControlpanel = () => {
|
|
61
|
+
const UsersControlpanel = (props) => {
|
|
62
|
+
const { staticContext } = props;
|
|
61
63
|
const intl = useIntl();
|
|
62
64
|
const dispatch = useDispatch();
|
|
63
65
|
|
|
@@ -143,7 +145,10 @@ const UsersControlpanel = () => {
|
|
|
143
145
|
await listUsersAction();
|
|
144
146
|
setEntries(users);
|
|
145
147
|
}
|
|
146
|
-
|
|
148
|
+
// Only fetch user schema if it hasn't been loaded yet (e.g. by asyncConnect SSR)
|
|
149
|
+
if (!userschema?.loaded) {
|
|
150
|
+
await getUserSchemaAction();
|
|
151
|
+
}
|
|
147
152
|
await getUserAction(userId);
|
|
148
153
|
}, [
|
|
149
154
|
getControlpanelAction,
|
|
@@ -152,6 +157,7 @@ const UsersControlpanel = () => {
|
|
|
152
157
|
listGroupsAction,
|
|
153
158
|
listUsersAction,
|
|
154
159
|
users,
|
|
160
|
+
userschema,
|
|
155
161
|
getUserSchemaAction,
|
|
156
162
|
getUserAction,
|
|
157
163
|
userId,
|
|
@@ -451,6 +457,8 @@ const UsersControlpanel = () => {
|
|
|
451
457
|
|
|
452
458
|
useEffect(() => {
|
|
453
459
|
setIsClient(true);
|
|
460
|
+
// Skip fetching if the store already has an error.
|
|
461
|
+
if (loadRolesRequest?.error) return;
|
|
454
462
|
fetchData();
|
|
455
463
|
checkLoginUsingEmailStatus();
|
|
456
464
|
}, []); // eslint-disable-line react-hooks/exhaustive-deps
|
|
@@ -471,8 +479,14 @@ const UsersControlpanel = () => {
|
|
|
471
479
|
}
|
|
472
480
|
}, [loadRolesRequest?.error, loadRolesRequest?.loading]);
|
|
473
481
|
|
|
474
|
-
|
|
475
|
-
|
|
482
|
+
const effectiveError =
|
|
483
|
+
error ||
|
|
484
|
+
(loadRolesRequest?.error && !loadRolesRequest?.loading
|
|
485
|
+
? loadRolesRequest.error
|
|
486
|
+
: null);
|
|
487
|
+
|
|
488
|
+
if (effectiveError) {
|
|
489
|
+
return <Error error={effectiveError} staticContext={staticContext} />;
|
|
476
490
|
}
|
|
477
491
|
|
|
478
492
|
const usernameToDelete = userToDelete ? userToDelete.username : '';
|
|
@@ -729,4 +743,43 @@ const UsersControlpanel = () => {
|
|
|
729
743
|
);
|
|
730
744
|
};
|
|
731
745
|
|
|
732
|
-
export default
|
|
746
|
+
export default asyncConnect([
|
|
747
|
+
{
|
|
748
|
+
key: 'controlpanels',
|
|
749
|
+
promise: ({ store: { dispatch, getState } }) => {
|
|
750
|
+
return dispatch(getControlpanel('usergroup')).then(() => {
|
|
751
|
+
const state = getState();
|
|
752
|
+
const many_users = state.controlpanels?.controlpanel?.data?.many_users;
|
|
753
|
+
if (!many_users) {
|
|
754
|
+
dispatch(listUsers());
|
|
755
|
+
dispatch(listGroups());
|
|
756
|
+
}
|
|
757
|
+
});
|
|
758
|
+
},
|
|
759
|
+
},
|
|
760
|
+
{
|
|
761
|
+
key: 'roles',
|
|
762
|
+
promise: ({ store: { dispatch } }) => {
|
|
763
|
+
return dispatch(listRoles());
|
|
764
|
+
},
|
|
765
|
+
},
|
|
766
|
+
{
|
|
767
|
+
key: 'userschema',
|
|
768
|
+
promise: ({ store: { dispatch } }) => {
|
|
769
|
+
return dispatch(getUserSchema());
|
|
770
|
+
},
|
|
771
|
+
},
|
|
772
|
+
{
|
|
773
|
+
key: 'user',
|
|
774
|
+
promise: ({ store: { dispatch, getState } }) => {
|
|
775
|
+
const state = getState();
|
|
776
|
+
const token = state.userSession.token;
|
|
777
|
+
if (token) {
|
|
778
|
+
const userId = jwtDecode(token).sub;
|
|
779
|
+
if (userId) {
|
|
780
|
+
return dispatch(getUser(userId));
|
|
781
|
+
}
|
|
782
|
+
}
|
|
783
|
+
},
|
|
784
|
+
},
|
|
785
|
+
])(UsersControlpanel);
|