@plone/volto 19.0.0-alpha.26 → 19.0.0-alpha.28
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/.eslintignore +1 -0
- package/.eslintrc +0 -3
- package/CHANGELOG.md +69 -0
- package/README.md +0 -1
- package/babel.js +0 -6
- package/locales/af/LC_MESSAGES/volto.po +5455 -0
- package/locales/af.json +1 -1
- package/locales/ar/LC_MESSAGES/volto.po +5455 -0
- package/locales/ar.json +1 -1
- package/locales/bg/LC_MESSAGES/volto.po +5455 -0
- package/locales/bg.json +1 -1
- package/locales/bn/LC_MESSAGES/volto.po +5455 -0
- package/locales/bn.json +1 -1
- package/locales/ca/LC_MESSAGES/volto.po +406 -345
- package/locales/ca.json +1 -1
- package/locales/cs/LC_MESSAGES/volto.po +5455 -0
- package/locales/cs.json +1 -1
- package/locales/cy/LC_MESSAGES/volto.po +5455 -0
- package/locales/cy.json +1 -1
- package/locales/da/LC_MESSAGES/volto.po +5455 -0
- package/locales/da.json +1 -1
- package/locales/de/LC_MESSAGES/volto.po +70 -8
- package/locales/de.json +1 -1
- package/locales/el/LC_MESSAGES/volto.po +5455 -0
- package/locales/el.json +1 -1
- package/locales/en/LC_MESSAGES/volto.po +66 -0
- package/locales/en.json +1 -1
- package/locales/en_AU/LC_MESSAGES/volto.po +5455 -0
- package/locales/en_AU.json +1 -1
- package/locales/en_GB/LC_MESSAGES/volto.po +5455 -0
- package/locales/en_GB.json +1 -1
- package/locales/eo/LC_MESSAGES/volto.po +5455 -0
- package/locales/eo.json +1 -1
- package/locales/es/LC_MESSAGES/volto.po +173 -112
- package/locales/es.json +1 -1
- package/locales/et/LC_MESSAGES/volto.po +5455 -0
- package/locales/et.json +1 -1
- package/locales/eu/LC_MESSAGES/volto.po +256 -195
- package/locales/eu.json +1 -1
- package/locales/fa/LC_MESSAGES/volto.po +5455 -0
- package/locales/fa.json +1 -1
- package/locales/fi/LC_MESSAGES/volto.po +62 -1
- package/locales/fi.json +1 -1
- package/locales/fr/LC_MESSAGES/volto.po +61 -0
- package/locales/fr.json +1 -1
- package/locales/fu/LC_MESSAGES/volto.po +5455 -0
- package/locales/fu.json +1 -1
- package/locales/gl/LC_MESSAGES/volto.po +5456 -0
- package/locales/gl.json +1 -1
- package/locales/he/LC_MESSAGES/volto.po +5455 -0
- package/locales/he.json +1 -1
- package/locales/hi/LC_MESSAGES/volto.po +66 -0
- package/locales/hi.json +1 -1
- package/locales/hr/LC_MESSAGES/volto.po +5455 -0
- package/locales/hr.json +1 -1
- package/locales/hu/LC_MESSAGES/volto.po +5455 -0
- package/locales/hu.json +1 -1
- package/locales/hy/LC_MESSAGES/volto.po +5455 -0
- package/locales/hy.json +1 -1
- package/locales/id/LC_MESSAGES/volto.po +5455 -0
- package/locales/id.json +1 -1
- package/locales/it/LC_MESSAGES/volto.po +90 -24
- package/locales/it.json +1 -1
- package/locales/ja/LC_MESSAGES/volto.po +105 -43
- package/locales/ja.json +1 -1
- package/locales/ka/LC_MESSAGES/volto.po +5455 -0
- package/locales/ka.json +1 -1
- package/locales/kn/LC_MESSAGES/volto.po +5455 -0
- package/locales/kn.json +1 -1
- package/locales/ko/LC_MESSAGES/volto.po +5455 -0
- package/locales/ko.json +1 -1
- package/locales/lt/LC_MESSAGES/volto.po +5455 -0
- package/locales/lt.json +1 -1
- package/locales/lv/LC_MESSAGES/volto.po +5455 -0
- package/locales/lv.json +1 -1
- package/locales/mi/LC_MESSAGES/volto.po +5455 -0
- package/locales/mi.json +1 -1
- package/locales/mk/LC_MESSAGES/volto.po +5455 -0
- package/locales/mk.json +1 -1
- package/locales/my/LC_MESSAGES/volto.po +5455 -0
- package/locales/my.json +1 -1
- package/locales/nb_NO/LC_MESSAGES/volto.po +5455 -0
- package/locales/nb_NO.json +1 -1
- package/locales/nl/LC_MESSAGES/volto.po +93 -31
- package/locales/nl.json +1 -1
- package/locales/nn/LC_MESSAGES/volto.po +5455 -0
- package/locales/nn.json +1 -1
- package/locales/pl/LC_MESSAGES/volto.po +5455 -0
- package/locales/pl.json +1 -1
- package/locales/pt/LC_MESSAGES/volto.po +723 -662
- package/locales/pt.json +1 -1
- package/locales/pt_BR/LC_MESSAGES/volto.po +61 -0
- package/locales/pt_BR.json +1 -1
- package/locales/rm/LC_MESSAGES/volto.po +5455 -0
- package/locales/rm.json +1 -1
- package/locales/ro/LC_MESSAGES/volto.po +61 -0
- package/locales/ro.json +1 -1
- package/locales/ru/LC_MESSAGES/volto.po +61 -0
- package/locales/ru.json +1 -1
- package/locales/sk/LC_MESSAGES/volto.po +5455 -0
- package/locales/sk.json +1 -1
- package/locales/sl/LC_MESSAGES/volto.po +5455 -0
- package/locales/sl.json +1 -1
- package/locales/sm/LC_MESSAGES/volto.po +5455 -0
- package/locales/sm.json +1 -1
- package/locales/sq/LC_MESSAGES/volto.po +5455 -0
- package/locales/sq.json +1 -1
- package/locales/sr/LC_MESSAGES/volto.po +5455 -0
- package/locales/sr.json +1 -1
- package/locales/sr@cyrl/LC_MESSAGES/volto.po +5455 -0
- package/locales/sr@cyrl.json +1 -1
- package/locales/sr@latn/LC_MESSAGES/volto.po +5455 -0
- package/locales/sr@latn.json +1 -1
- package/locales/sv/LC_MESSAGES/volto.po +5455 -0
- package/locales/sv.json +1 -1
- package/locales/ta/LC_MESSAGES/volto.po +5456 -0
- package/locales/ta.json +1 -1
- package/locales/te/LC_MESSAGES/volto.po +5455 -0
- package/locales/te.json +1 -1
- package/locales/th/LC_MESSAGES/volto.po +5455 -0
- package/locales/th.json +1 -1
- package/locales/to/LC_MESSAGES/volto.po +5455 -0
- package/locales/to.json +1 -1
- package/locales/tr/LC_MESSAGES/volto.po +5456 -0
- package/locales/tr.json +1 -1
- package/locales/uk/LC_MESSAGES/volto.po +5455 -0
- package/locales/uk.json +1 -1
- package/locales/vi/LC_MESSAGES/volto.po +5455 -0
- package/locales/vi.json +1 -1
- package/locales/volto.pot +62 -1
- package/locales/zh_CN/LC_MESSAGES/volto.po +62 -0
- package/locales/zh_CN.json +1 -1
- package/locales/zh_Hant/LC_MESSAGES/volto.po +5455 -0
- package/locales/zh_Hant.json +1 -1
- package/locales/zh_Hant_HK/LC_MESSAGES/volto.po +5455 -0
- package/locales/zh_Hant_HK.json +1 -1
- package/package.json +19 -35
- package/razzle.config.js +12 -5
- package/src/actions/blockTypes/blockTypes.ts +24 -0
- package/src/components/manage/Add/Add.jsx +7 -6
- package/src/components/manage/Blocks/Block/Order/Item.jsx +9 -3
- package/src/components/manage/Blocks/Block/Order/Order.jsx +116 -67
- package/src/components/manage/Blocks/Block/Order/utilities.js +28 -11
- package/src/components/manage/Blocks/Listing/Edit.jsx +1 -0
- package/src/components/manage/Blocks/Title/Edit.jsx +5 -0
- package/src/components/manage/Controlpanels/AddonsControlpanel.jsx +7 -0
- package/src/components/manage/Controlpanels/BlockType.tsx +166 -0
- package/src/components/manage/Controlpanels/BlockTypes.tsx +145 -0
- package/src/components/manage/Controlpanels/Controlpanels.jsx +28 -5
- package/src/components/manage/Controlpanels/Controlpanels.test.jsx +10 -0
- package/src/components/manage/Controlpanels/DatabaseInformation.jsx +9 -0
- package/src/components/manage/Controlpanels/ModerateComments.jsx +8 -0
- package/src/components/manage/Controlpanels/Users/UsersControlpanel.jsx +4 -5
- package/src/components/manage/Controlpanels/Users/UsersControlpanel.test.jsx +57 -11
- package/src/components/manage/Diff/Diff.jsx +201 -298
- package/src/components/manage/Multilingual/CreateTranslation.jsx +8 -5
- package/src/components/manage/Multilingual/ManageTranslations.jsx +1 -1
- package/src/components/manage/Multilingual/TranslationObject.jsx +9 -6
- package/src/components/manage/Preferences/PersonalPreferences.jsx +8 -5
- package/src/components/manage/Sidebar/ObjectBrowserBody.jsx +5 -1
- package/src/components/manage/Toolbar/Types.crash.test.jsx +48 -0
- package/src/components/manage/Widgets/FileWidget.jsx +7 -0
- package/src/components/manage/Widgets/RegistryImageWidget.jsx +1 -1
- package/src/components/theme/PasswordReset/PasswordReset.jsx +108 -191
- package/src/config/ControlPanels.js +2 -0
- package/src/config/index.js +1 -1
- package/src/config/validation.ts +8 -0
- package/src/constants/ActionTypes.js +1 -0
- package/src/express-middleware/devproxy.js +3 -1
- package/src/helpers/Blocks/Blocks.js +81 -18
- package/src/helpers/FormValidation/FormValidation.test.js +31 -0
- package/src/helpers/FormValidation/validators.ts +21 -0
- package/src/helpers/MessageLabels/MessageLabels.js +5 -0
- package/src/helpers/Utils/Utils.jsx +17 -0
- package/src/helpers/Utils/Utils.test.jsx +39 -0
- package/src/middleware/api.js +7 -3
- package/src/reducers/blockTypes/blockTypes.js +38 -0
- package/src/reducers/index.js +2 -0
- package/src/reducers/users/users.js +1 -1
- package/src/routes.js +10 -0
- package/src/server.jsx +7 -5
- package/test-setup-globals.js +26 -0
- package/theme/themes/pastanaga/extras/block-types.less +17 -0
- package/theme/themes/pastanaga/extras/main.less +1 -2
- package/types/actions/blockTypes/blockTypes.d.ts +7 -0
- package/types/components/index.d.ts +1 -1
- package/types/components/manage/Blocks/Block/Order/utilities.d.ts +2 -1
- package/types/components/manage/Controlpanels/BlockType.d.ts +7 -0
- package/types/components/manage/Controlpanels/BlockTypes.d.ts +7 -0
- package/types/components/manage/Diff/Diff.d.ts +7 -2
- package/types/components/manage/Toolbar/Types.crash.test.d.ts +1 -0
- package/types/components/theme/PasswordReset/PasswordReset.d.ts +6 -2
- package/types/config/ControlPanels.d.ts +1 -0
- package/types/constants/ActionTypes.d.ts +1 -0
- package/types/helpers/Blocks/Blocks.d.ts +3 -0
- package/types/helpers/FormValidation/validators.d.ts +7 -0
- package/types/helpers/MessageLabels/MessageLabels.d.ts +100 -94
- package/types/helpers/Utils/Utils.d.ts +1 -0
- package/types/reducers/blockTypes/blockTypes.d.ts +16 -0
- package/types/reducers/index.d.ts +2 -0
- package/types/routes.d.ts +7 -5
- package/vitest.config.mjs +84 -42
- package/webpack-plugins/webpack-less-plugin.js +1 -1
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import Toolbar from '@plone/volto/components/manage/Toolbar/Toolbar';
|
|
2
|
+
import Icon from '@plone/volto/components/theme/Icon/Icon';
|
|
3
|
+
import { getParentUrl } from '@plone/volto/helpers/Url/Url';
|
|
4
|
+
import { useClient } from '@plone/volto/hooks';
|
|
5
|
+
import config from '@plone/volto/registry';
|
|
6
|
+
import { createPortal } from 'react-dom';
|
|
7
|
+
import { defineMessages, useIntl, FormattedMessage } from 'react-intl';
|
|
8
|
+
import { Link } from 'react-router-dom';
|
|
9
|
+
import { useEffect } from 'react';
|
|
10
|
+
import { getBlockTypes } from '@plone/volto/actions/blockTypes/blockTypes';
|
|
11
|
+
import { useDispatch, useSelector } from 'react-redux';
|
|
12
|
+
import Error from '@plone/volto/components/theme/Error/Error';
|
|
13
|
+
import { Spinner, Table } from '@plone/components';
|
|
14
|
+
import UniversalLink from '@plone/volto/components/manage/UniversalLink/UniversalLink';
|
|
15
|
+
|
|
16
|
+
import backSVG from '@plone/volto/icons/back.svg';
|
|
17
|
+
import type { Location } from 'history';
|
|
18
|
+
|
|
19
|
+
const messages = defineMessages({
|
|
20
|
+
back: {
|
|
21
|
+
id: 'Back',
|
|
22
|
+
defaultMessage: 'Back',
|
|
23
|
+
},
|
|
24
|
+
loading: {
|
|
25
|
+
id: 'loading',
|
|
26
|
+
defaultMessage: 'Loading',
|
|
27
|
+
},
|
|
28
|
+
blockType: {
|
|
29
|
+
id: 'Block Type',
|
|
30
|
+
defaultMessage: 'Block Type',
|
|
31
|
+
},
|
|
32
|
+
occurrences: {
|
|
33
|
+
id: 'Occurrences',
|
|
34
|
+
defaultMessage: 'Occurrences',
|
|
35
|
+
},
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
type RouteProps = {
|
|
39
|
+
history: History;
|
|
40
|
+
location: Location;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
type BlockTypesState = {
|
|
44
|
+
error: {
|
|
45
|
+
status?: number;
|
|
46
|
+
} | null;
|
|
47
|
+
items: Record<string, number> | unknown[];
|
|
48
|
+
loaded: boolean;
|
|
49
|
+
loading: boolean;
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
type SelectorState = {
|
|
53
|
+
blockTypes: BlockTypesState;
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
const BlockTypesControlpanel = (props: RouteProps) => {
|
|
57
|
+
const { location } = props;
|
|
58
|
+
const intl = useIntl();
|
|
59
|
+
const blockTypes = useSelector((state: SelectorState) => state.blockTypes);
|
|
60
|
+
const blocksConfig = config.blocks.blocksConfig;
|
|
61
|
+
const dispatch = useDispatch();
|
|
62
|
+
const pathname = location.pathname;
|
|
63
|
+
const isClient = useClient();
|
|
64
|
+
|
|
65
|
+
const blocks = Object.values(blocksConfig)
|
|
66
|
+
.map((blockConfig) => ({
|
|
67
|
+
...blockConfig,
|
|
68
|
+
title: blockConfig.title
|
|
69
|
+
? intl.formatMessage({
|
|
70
|
+
id: blockConfig.title,
|
|
71
|
+
defaultMessage: blockConfig.title,
|
|
72
|
+
})
|
|
73
|
+
: blockConfig.id,
|
|
74
|
+
}))
|
|
75
|
+
.sort((a, b) => (a.title === b.title ? 0 : a.title > b.title ? 1 : -1));
|
|
76
|
+
|
|
77
|
+
useEffect(() => {
|
|
78
|
+
dispatch(getBlockTypes());
|
|
79
|
+
}, [dispatch]);
|
|
80
|
+
|
|
81
|
+
if (blockTypes.loading) {
|
|
82
|
+
return <Spinner label={intl.formatMessage(messages.loading)} />;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
if (blockTypes?.error?.status) {
|
|
86
|
+
return <Error error={blockTypes.error} />;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return (
|
|
90
|
+
blockTypes.loaded && (
|
|
91
|
+
<div
|
|
92
|
+
id="page-block_types"
|
|
93
|
+
className="ui container controlpanel-block-types"
|
|
94
|
+
>
|
|
95
|
+
<h1>
|
|
96
|
+
<FormattedMessage id="Block Types" defaultMessage="Block Types" />
|
|
97
|
+
</h1>
|
|
98
|
+
<Table
|
|
99
|
+
className="react-aria-Table cmsui-table"
|
|
100
|
+
columns={[
|
|
101
|
+
{
|
|
102
|
+
id: 'blockType',
|
|
103
|
+
name: intl.formatMessage(messages.blockType),
|
|
104
|
+
isRowHeader: true,
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
id: 'occurrences',
|
|
108
|
+
name: intl.formatMessage(messages.occurrences),
|
|
109
|
+
},
|
|
110
|
+
]}
|
|
111
|
+
rows={blocks.map((block) => ({
|
|
112
|
+
id: block.id,
|
|
113
|
+
textValue: block.title,
|
|
114
|
+
blockType: (
|
|
115
|
+
<UniversalLink href={`${pathname}/${block.id}`}>
|
|
116
|
+
{block.title}
|
|
117
|
+
</UniversalLink>
|
|
118
|
+
),
|
|
119
|
+
occurrences: blockTypes.items?.[block.id] || 0,
|
|
120
|
+
}))}
|
|
121
|
+
/>
|
|
122
|
+
{isClient &&
|
|
123
|
+
createPortal(
|
|
124
|
+
<Toolbar
|
|
125
|
+
pathname={pathname}
|
|
126
|
+
hideDefaultViewButtons
|
|
127
|
+
inner={
|
|
128
|
+
<Link to={getParentUrl(pathname)} className="item">
|
|
129
|
+
<Icon
|
|
130
|
+
name={backSVG}
|
|
131
|
+
className="contents circled"
|
|
132
|
+
size="30px"
|
|
133
|
+
title={intl.formatMessage(messages.back)}
|
|
134
|
+
/>
|
|
135
|
+
</Link>
|
|
136
|
+
}
|
|
137
|
+
/>,
|
|
138
|
+
document.getElementById('toolbar') as HTMLElement,
|
|
139
|
+
)}
|
|
140
|
+
</div>
|
|
141
|
+
)
|
|
142
|
+
);
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
export default BlockTypesControlpanel;
|
|
@@ -75,6 +75,10 @@ const messages = defineMessages({
|
|
|
75
75
|
id: 'Add-Ons',
|
|
76
76
|
defaultMessage: 'Add-Ons',
|
|
77
77
|
},
|
|
78
|
+
blockTypes: {
|
|
79
|
+
id: 'Block Types',
|
|
80
|
+
defaultMessage: 'Block Types',
|
|
81
|
+
},
|
|
78
82
|
database: {
|
|
79
83
|
id: 'Database',
|
|
80
84
|
defaultMessage: 'Database',
|
|
@@ -127,6 +131,15 @@ export default function Controlpanels({ location }) {
|
|
|
127
131
|
return <Error error={error} />;
|
|
128
132
|
}
|
|
129
133
|
|
|
134
|
+
/**
|
|
135
|
+
* Determine whether the backend exposes the Discussion control panel.
|
|
136
|
+
* The Moderate Comments view should only be shown if the Discussion
|
|
137
|
+
* control panel is available to the current user.
|
|
138
|
+
*/
|
|
139
|
+
const hasDiscussionControlPanel = controlpanels?.some((panel) =>
|
|
140
|
+
panel['@id']?.endsWith('/discussion'),
|
|
141
|
+
);
|
|
142
|
+
|
|
130
143
|
let customcontrolpanels = config.settings.controlpanels
|
|
131
144
|
? config.settings.controlpanels.map((el) => {
|
|
132
145
|
el.group =
|
|
@@ -146,6 +159,11 @@ export default function Controlpanels({ location }) {
|
|
|
146
159
|
group: intl.formatMessage(messages.general),
|
|
147
160
|
title: intl.formatMessage(messages.addons),
|
|
148
161
|
},
|
|
162
|
+
{
|
|
163
|
+
'@id': '/block-types',
|
|
164
|
+
group: intl.formatMessage(messages.content),
|
|
165
|
+
title: intl.formatMessage(messages.blockTypes),
|
|
166
|
+
},
|
|
149
167
|
{
|
|
150
168
|
'@id': '/database',
|
|
151
169
|
group: intl.formatMessage(messages.general),
|
|
@@ -171,11 +189,16 @@ export default function Controlpanels({ location }) {
|
|
|
171
189
|
group: intl.formatMessage(messages.content),
|
|
172
190
|
title: intl.formatMessage(messages.relations),
|
|
173
191
|
},
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
192
|
+
// only shown if Discussion support addon is available from the backend.
|
|
193
|
+
...(hasDiscussionControlPanel
|
|
194
|
+
? [
|
|
195
|
+
{
|
|
196
|
+
'@id': '/moderate-comments',
|
|
197
|
+
group: intl.formatMessage(messages.content),
|
|
198
|
+
title: intl.formatMessage(messages.moderatecomments),
|
|
199
|
+
},
|
|
200
|
+
]
|
|
201
|
+
: []),
|
|
179
202
|
{
|
|
180
203
|
'@id': '/users',
|
|
181
204
|
group: intl.formatMessage(messages.usersControlPanelCategory),
|
|
@@ -22,6 +22,11 @@ describe('Controlpanels', () => {
|
|
|
22
22
|
const store = mockStore({
|
|
23
23
|
controlpanels: {
|
|
24
24
|
controlpanels: [
|
|
25
|
+
{
|
|
26
|
+
'@id': 'http://localhost:8080/Plone/@controlpanels/discussion',
|
|
27
|
+
group: 'Content',
|
|
28
|
+
title: 'Discussion',
|
|
29
|
+
},
|
|
25
30
|
{
|
|
26
31
|
'@id': 'http://localhost:8080/Plone/@controlpanels/date-and-time',
|
|
27
32
|
group: 'General',
|
|
@@ -47,6 +52,11 @@ describe('Controlpanels', () => {
|
|
|
47
52
|
reduxAsyncConnect: {
|
|
48
53
|
// Mocked in redux async connect as it isn't fetch client-side.
|
|
49
54
|
controlpanels: [
|
|
55
|
+
{
|
|
56
|
+
'@id': 'http://localhost:8080/Plone/@controlpanels/discussion',
|
|
57
|
+
group: 'Content',
|
|
58
|
+
title: 'Discussion',
|
|
59
|
+
},
|
|
50
60
|
{
|
|
51
61
|
'@id': 'http://localhost:8080/Plone/@controlpanels/date-and-time',
|
|
52
62
|
group: 'General',
|
|
@@ -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
|
),
|
|
@@ -25,6 +25,7 @@ import { Link } from 'react-router-dom';
|
|
|
25
25
|
import Helmet from '@plone/volto/helpers/Helmet/Helmet';
|
|
26
26
|
import { messages } from '@plone/volto/helpers/MessageLabels/MessageLabels';
|
|
27
27
|
import { isManager, canAssignGroup } from '@plone/volto/helpers/User/User';
|
|
28
|
+
import { getErrorMessage } from '@plone/volto/helpers/Utils/Utils';
|
|
28
29
|
import clearSVG from '@plone/volto/icons/clear.svg';
|
|
29
30
|
import addUserSvg from '@plone/volto/icons/add-user.svg';
|
|
30
31
|
import saveSVG from '@plone/volto/icons/save.svg';
|
|
@@ -351,9 +352,7 @@ const UsersControlpanel = () => {
|
|
|
351
352
|
})
|
|
352
353
|
.catch((error) => {
|
|
353
354
|
// Handle error
|
|
354
|
-
setAddUserError(
|
|
355
|
-
error.response?.body?.error?.message || 'Error creating user',
|
|
356
|
-
);
|
|
355
|
+
setAddUserError(getErrorMessage(error));
|
|
357
356
|
});
|
|
358
357
|
}
|
|
359
358
|
},
|
|
@@ -417,11 +416,11 @@ const UsersControlpanel = () => {
|
|
|
417
416
|
/**
|
|
418
417
|
* Handle Errors after createUser()
|
|
419
418
|
*
|
|
420
|
-
* @param {object} error object
|
|
419
|
+
* @param {object} error object
|
|
421
420
|
* @returns {undefined}
|
|
422
421
|
*/
|
|
423
422
|
const onAddUserError = useCallback((error) => {
|
|
424
|
-
setAddUserError(error
|
|
423
|
+
setAddUserError(getErrorMessage(error));
|
|
425
424
|
}, []);
|
|
426
425
|
|
|
427
426
|
/**
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { render,
|
|
2
|
+
import { render, waitFor } from '@testing-library/react';
|
|
3
3
|
import configureStore from 'redux-mock-store';
|
|
4
4
|
import { Provider } from 'react-intl-redux';
|
|
5
5
|
import { MemoryRouter } from 'react-router-dom';
|
|
@@ -39,17 +39,63 @@ describe('UsersControlpanel', () => {
|
|
|
39
39
|
messages: {},
|
|
40
40
|
},
|
|
41
41
|
});
|
|
42
|
-
const { container } =
|
|
43
|
-
|
|
44
|
-
<
|
|
45
|
-
<
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
});
|
|
42
|
+
const { container } = render(
|
|
43
|
+
<Provider store={store}>
|
|
44
|
+
<MemoryRouter initialEntries={['/controlpanel/users']}>
|
|
45
|
+
<UsersControlpanel />
|
|
46
|
+
<div id="toolbar"></div>
|
|
47
|
+
</MemoryRouter>
|
|
48
|
+
</Provider>,
|
|
49
|
+
);
|
|
50
|
+
await waitFor(() => {});
|
|
52
51
|
|
|
53
52
|
expect(container).toMatchSnapshot();
|
|
54
53
|
});
|
|
54
|
+
|
|
55
|
+
it('handles createRequest error when response body has only message', async () => {
|
|
56
|
+
const store = mockStore({
|
|
57
|
+
userSession: {
|
|
58
|
+
token: jwt.sign({ sub: 'john' }, 'secret'),
|
|
59
|
+
},
|
|
60
|
+
roles: { roles: [] },
|
|
61
|
+
users: {
|
|
62
|
+
users: [],
|
|
63
|
+
create: {
|
|
64
|
+
loading: false,
|
|
65
|
+
error: {
|
|
66
|
+
response: { body: { message: 'SMTP relay access denied' } },
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
user: {
|
|
70
|
+
roles: ['Manager'],
|
|
71
|
+
'@id': 'admin',
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
groups: {
|
|
75
|
+
groups: [],
|
|
76
|
+
create: { loading: false },
|
|
77
|
+
},
|
|
78
|
+
authRole: {
|
|
79
|
+
authenticatedRole: [],
|
|
80
|
+
},
|
|
81
|
+
intl: {
|
|
82
|
+
locale: 'en',
|
|
83
|
+
messages: {},
|
|
84
|
+
},
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
render(
|
|
88
|
+
<Provider store={store}>
|
|
89
|
+
<MemoryRouter initialEntries={['/controlpanel/users']}>
|
|
90
|
+
<UsersControlpanel />
|
|
91
|
+
<div id="toolbar"></div>
|
|
92
|
+
</MemoryRouter>
|
|
93
|
+
</Provider>,
|
|
94
|
+
);
|
|
95
|
+
await waitFor(() => {});
|
|
96
|
+
|
|
97
|
+
// If the component attempted to read a missing property it would throw.
|
|
98
|
+
// Reaching this line means the error shape was handled without exceptions.
|
|
99
|
+
expect(true).toBe(true);
|
|
100
|
+
});
|
|
55
101
|
});
|