@plone/volto 18.0.0-alpha.40 → 18.0.0-alpha.42
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 +61 -0
- package/locales/ca/LC_MESSAGES/volto.po +31 -1
- package/locales/ca.json +1 -1
- package/locales/de/LC_MESSAGES/volto.po +31 -1
- package/locales/de.json +1 -1
- package/locales/en/LC_MESSAGES/volto.po +31 -1
- package/locales/en.json +1 -1
- package/locales/es/LC_MESSAGES/volto.po +31 -1
- package/locales/es.json +1 -1
- package/locales/eu/LC_MESSAGES/volto.po +31 -1
- package/locales/eu.json +1 -1
- package/locales/fi/LC_MESSAGES/volto.po +31 -1
- package/locales/fi.json +1 -1
- package/locales/fr/LC_MESSAGES/volto.po +31 -1
- package/locales/fr.json +1 -1
- package/locales/hi/LC_MESSAGES/volto.po +31 -1
- package/locales/hi.json +1 -1
- package/locales/it/LC_MESSAGES/volto.po +31 -1
- package/locales/it.json +1 -1
- package/locales/ja/LC_MESSAGES/volto.po +31 -1
- package/locales/ja.json +1 -1
- package/locales/nl/LC_MESSAGES/volto.po +31 -1
- package/locales/nl.json +1 -1
- package/locales/pt/LC_MESSAGES/volto.po +31 -1
- package/locales/pt.json +1 -1
- package/locales/pt_BR/LC_MESSAGES/volto.po +31 -1
- package/locales/pt_BR.json +1 -1
- package/locales/ro/LC_MESSAGES/volto.po +31 -1
- package/locales/ro.json +1 -1
- package/locales/volto.pot +32 -2
- package/locales/zh_CN/LC_MESSAGES/volto.po +31 -1
- package/locales/zh_CN.json +1 -1
- package/package.json +4 -5
- package/razzle.config.js +2 -2
- package/src/components/index.js +0 -1
- package/src/components/manage/AnchorPlugin/components/LinkButton/AddLinkForm.jsx +1 -1
- package/src/components/manage/AnchorPlugin/useLinkEditor.jsx +21 -21
- package/src/components/manage/Blocks/Block/BlocksForm.jsx +5 -0
- package/src/components/manage/Blocks/Block/Order/Item.jsx +6 -2
- package/src/components/manage/Blocks/Block/Order/Order.jsx +2 -0
- package/src/components/manage/Blocks/Container/Data.jsx +10 -2
- package/src/components/manage/Blocks/Image/ImageSidebar.jsx +10 -2
- package/src/components/manage/Blocks/Listing/ListingData.jsx +10 -2
- package/src/components/manage/Blocks/Maps/MapsSidebar.jsx +3 -1
- package/src/components/manage/Blocks/Search/SearchBlockEdit.jsx +2 -0
- package/src/components/manage/Blocks/Search/SearchBlockView.jsx +18 -2
- package/src/components/manage/Blocks/Search/hocs/withSearch.jsx +1 -1
- package/src/components/manage/Blocks/Teaser/Data.jsx +10 -2
- package/src/components/manage/Blocks/ToC/Edit.jsx +1 -0
- package/src/components/manage/Blocks/Video/Edit.jsx +1 -1
- package/src/components/manage/Blocks/Video/VideoSidebar.jsx +3 -1
- package/src/components/manage/Contents/Contents.jsx +1 -1
- package/src/components/manage/Controlpanels/ContentTypeSchema.jsx +1 -0
- package/src/components/manage/Controlpanels/UndoControlpanel.jsx +3 -3
- package/src/components/manage/Controlpanels/Users/UserGroupMembershipListing.jsx +28 -12
- package/src/components/manage/Controlpanels/Users/UserGroupMembershipMatrix.jsx +12 -4
- package/src/components/manage/Form/Form.jsx +85 -20
- package/src/components/manage/Form/InlineForm.jsx +4 -6
- package/src/components/manage/Form/ModalForm.jsx +1 -1
- package/src/components/manage/History/History.jsx +1 -1
- package/src/components/manage/Pluggable/Pluggable.test.js +1 -1
- package/src/components/manage/Toolbar/Toolbar.jsx +1 -1
- package/src/components/manage/Widgets/ArrayWidget.jsx +2 -2
- package/src/components/manage/Widgets/ImageWidget.jsx +34 -10
- package/src/components/manage/Widgets/RecurrenceWidget/EndField.jsx +7 -1
- package/src/components/manage/Widgets/RecurrenceWidget/RecurrenceWidget.jsx +80 -31
- package/src/components/theme/Login/Login.jsx +25 -4
- package/src/components/theme/Logout/Logout.jsx +2 -2
- package/src/components/theme/Search/Search.jsx +13 -5
- package/src/components/theme/View/View.jsx +0 -7
- package/src/components/theme/View/View.test.jsx +0 -3
- package/src/config/Widgets.jsx +1 -1
- package/src/config/index.js +7 -2
- package/src/config/validation.ts +155 -0
- package/src/helpers/Extensions/withBlockExtensions.jsx +1 -1
- package/src/helpers/FormValidation/FormValidation.jsx +109 -170
- package/src/helpers/FormValidation/FormValidation.test.js +836 -8
- package/src/helpers/FormValidation/validators.ts +203 -0
- package/src/helpers/MessageLabels/MessageLabels.js +28 -0
- package/src/helpers/Url/Url.test.js +4 -4
- package/src/helpers/User/User.js +1 -1
- package/src/hooks/client/useClient.js +1 -1
- package/test-setup-config.jsx +7 -0
- package/theme/themes/default/modules/embed.variables +1 -1
- package/theme/themes/pastanaga/collections/form.overrides +36 -2
- package/theme/themes/pastanaga/extras/blocks.less +14 -5
- package/theme/themes/pastanaga/extras/sidebar.less +4 -0
- package/theme/themes/pastanaga/extras/toolbar.less +10 -3
- package/tsconfig.declarations.json +3 -2
- package/types/components/index.d.ts +0 -1
- package/types/components/manage/Blocks/Block/Order/Order.d.ts +2 -1
- package/types/components/theme/Logout/Logout.d.ts +1 -1
- package/types/config/RichTextEditor/ToHTML.d.ts +1 -1
- package/types/config/Widgets.d.ts +2 -2
- package/types/config/validation.d.ts +3 -0
- package/types/helpers/Extensions/withBlockExtensions.d.ts +1 -1
- package/types/helpers/FormValidation/FormValidation.d.ts +1 -0
- package/types/helpers/FormValidation/validators.d.ts +29 -0
- package/types/helpers/MessageLabels/MessageLabels.d.ts +36 -0
- package/types/helpers/User/User.d.ts +1 -1
- package/src/components/theme/SocialSharing/SocialSharing.jsx +0 -48
- package/src/components/theme/SocialSharing/SocialSharing.test.jsx +0 -14
|
@@ -37,7 +37,6 @@ import {
|
|
|
37
37
|
FREQUENCES,
|
|
38
38
|
WEEKLY_DAYS,
|
|
39
39
|
MONDAYFRIDAY_DAYS,
|
|
40
|
-
toISOString,
|
|
41
40
|
rrulei18n,
|
|
42
41
|
} from './Utils';
|
|
43
42
|
|
|
@@ -219,26 +218,40 @@ class RecurrenceWidget extends Component {
|
|
|
219
218
|
|
|
220
219
|
componentDidUpdate(prevProps) {
|
|
221
220
|
if (this.props.value) {
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
this.
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
rruleSet
|
|
240
|
-
|
|
241
|
-
|
|
221
|
+
const changedStart =
|
|
222
|
+
prevProps.formData?.start !== this.props.formData?.start;
|
|
223
|
+
const changedEnd = prevProps.formData?.end !== this.props.formData?.end;
|
|
224
|
+
|
|
225
|
+
if (changedStart || changedEnd) {
|
|
226
|
+
let start = this.getUTCDate(this.props.formData?.start).toDate();
|
|
227
|
+
|
|
228
|
+
let changeFormValues = {};
|
|
229
|
+
if (changedEnd) {
|
|
230
|
+
changeFormValues.until = this.getUTCDate(
|
|
231
|
+
this.props.formData?.end,
|
|
232
|
+
).toDate();
|
|
233
|
+
}
|
|
234
|
+
this.setState(
|
|
235
|
+
(prevState) => {
|
|
236
|
+
let rruleSet = prevState.rruleSet;
|
|
237
|
+
|
|
238
|
+
rruleSet = this.updateRruleSet(
|
|
239
|
+
rruleSet,
|
|
240
|
+
{ ...prevState.formValues, ...changeFormValues },
|
|
241
|
+
'dtstart',
|
|
242
|
+
start,
|
|
243
|
+
);
|
|
244
|
+
|
|
245
|
+
return {
|
|
246
|
+
...prevState,
|
|
247
|
+
rruleSet,
|
|
248
|
+
};
|
|
249
|
+
},
|
|
250
|
+
() => {
|
|
251
|
+
//then, after set state, set recurrence rrule value
|
|
252
|
+
this.saveRrule();
|
|
253
|
+
},
|
|
254
|
+
);
|
|
242
255
|
}
|
|
243
256
|
}
|
|
244
257
|
}
|
|
@@ -250,7 +263,8 @@ class RecurrenceWidget extends Component {
|
|
|
250
263
|
setRecurrenceStartEnd = () => {
|
|
251
264
|
const start = this.props.formData?.start;
|
|
252
265
|
|
|
253
|
-
|
|
266
|
+
// The `start` date from Plone is in UTC
|
|
267
|
+
const _start = new Date(start);
|
|
254
268
|
|
|
255
269
|
this.setState((prevState) => {
|
|
256
270
|
let rruleSet = prevState.rruleSet;
|
|
@@ -339,7 +353,7 @@ class RecurrenceWidget extends Component {
|
|
|
339
353
|
case 'until':
|
|
340
354
|
if (value != null) {
|
|
341
355
|
formValues['recurrenceEnds'] = option;
|
|
342
|
-
formValues[option] =
|
|
356
|
+
formValues[option] = value;
|
|
343
357
|
}
|
|
344
358
|
break;
|
|
345
359
|
case 'byweekday':
|
|
@@ -422,7 +436,24 @@ class RecurrenceWidget extends Component {
|
|
|
422
436
|
}
|
|
423
437
|
break;
|
|
424
438
|
case 'until':
|
|
425
|
-
|
|
439
|
+
let mDate = null;
|
|
440
|
+
if (value) {
|
|
441
|
+
mDate = this.moment(new Date(value));
|
|
442
|
+
if (typeof value === 'string') {
|
|
443
|
+
mDate = this.moment(new Date(value));
|
|
444
|
+
} else {
|
|
445
|
+
//object-->Date()
|
|
446
|
+
mDate = this.moment(value);
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
if (this.props.formData.end) {
|
|
450
|
+
//set time from formData.end
|
|
451
|
+
const mEnd = this.moment(new Date(this.props.formData.end));
|
|
452
|
+
mDate.set('hour', mEnd.get('hour'));
|
|
453
|
+
mDate.set('minute', mEnd.get('minute'));
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
value = value ? mDate.toDate() : null;
|
|
426
457
|
break;
|
|
427
458
|
default:
|
|
428
459
|
break;
|
|
@@ -447,7 +478,7 @@ class RecurrenceWidget extends Component {
|
|
|
447
478
|
? value
|
|
448
479
|
: rruleSet.dtstart()
|
|
449
480
|
? rruleSet.dtstart()
|
|
450
|
-
:
|
|
481
|
+
: new Date();
|
|
451
482
|
var exdates =
|
|
452
483
|
field === 'exdates' ? value : Object.assign([], rruleSet.exdates());
|
|
453
484
|
|
|
@@ -470,13 +501,14 @@ class RecurrenceWidget extends Component {
|
|
|
470
501
|
|
|
471
502
|
getDefaultUntil = (freq) => {
|
|
472
503
|
const moment = this.moment;
|
|
504
|
+
|
|
473
505
|
var end = this.props.formData?.end
|
|
474
|
-
?
|
|
506
|
+
? moment(new Date(this.props.formData.end))
|
|
475
507
|
: null;
|
|
476
|
-
var tomorrow =
|
|
477
|
-
var nextWeek =
|
|
478
|
-
var nextMonth =
|
|
479
|
-
var nextYear =
|
|
508
|
+
var tomorrow = moment().add(1, 'days');
|
|
509
|
+
var nextWeek = moment().add(7, 'days');
|
|
510
|
+
var nextMonth = moment().add(1, 'months');
|
|
511
|
+
var nextYear = moment().add(1, 'years');
|
|
480
512
|
|
|
481
513
|
var until = end;
|
|
482
514
|
switch (freq) {
|
|
@@ -502,6 +534,19 @@ class RecurrenceWidget extends Component {
|
|
|
502
534
|
break;
|
|
503
535
|
}
|
|
504
536
|
|
|
537
|
+
if (this.props.formData.end) {
|
|
538
|
+
//set default end time
|
|
539
|
+
until.set('hour', end.get('hour'));
|
|
540
|
+
until.set('minute', end.get('minute'));
|
|
541
|
+
}
|
|
542
|
+
until = new Date(
|
|
543
|
+
until.get('year'),
|
|
544
|
+
until.get('month'),
|
|
545
|
+
until.get('date'),
|
|
546
|
+
until.get('hour'),
|
|
547
|
+
until.get('minute'),
|
|
548
|
+
);
|
|
549
|
+
|
|
505
550
|
return until;
|
|
506
551
|
};
|
|
507
552
|
|
|
@@ -716,9 +761,13 @@ class RecurrenceWidget extends Component {
|
|
|
716
761
|
}
|
|
717
762
|
};
|
|
718
763
|
|
|
719
|
-
|
|
764
|
+
saveRrule = () => {
|
|
720
765
|
var value = this.state.rruleSet.toString();
|
|
721
766
|
this.props.onChange(this.props.id, value);
|
|
767
|
+
};
|
|
768
|
+
|
|
769
|
+
save = () => {
|
|
770
|
+
this.saveRrule();
|
|
722
771
|
this.close();
|
|
723
772
|
};
|
|
724
773
|
|
|
@@ -12,10 +12,15 @@ import {
|
|
|
12
12
|
import { FormattedMessage, defineMessages, useIntl } from 'react-intl';
|
|
13
13
|
import qs from 'query-string';
|
|
14
14
|
|
|
15
|
-
import { Helmet } from '@plone/volto/helpers';
|
|
15
|
+
import { Helmet, usePrevious } from '@plone/volto/helpers';
|
|
16
16
|
import config from '@plone/volto/registry';
|
|
17
17
|
import { Icon } from '@plone/volto/components';
|
|
18
|
-
import {
|
|
18
|
+
import {
|
|
19
|
+
login,
|
|
20
|
+
logout,
|
|
21
|
+
resetLoginRequest,
|
|
22
|
+
purgeMessages,
|
|
23
|
+
} from '@plone/volto/actions';
|
|
19
24
|
import { toast } from 'react-toastify';
|
|
20
25
|
import { Toast } from '@plone/volto/components';
|
|
21
26
|
import aheadSVG from '@plone/volto/icons/ahead.svg';
|
|
@@ -78,8 +83,22 @@ const Login = (props) => {
|
|
|
78
83
|
location.pathname.replace(/\/login\/?$/, '').replace(/\/logout\/?$/, '') ||
|
|
79
84
|
'/';
|
|
80
85
|
|
|
86
|
+
const previousToken = usePrevious(token);
|
|
87
|
+
|
|
81
88
|
useEffect(() => {
|
|
82
|
-
if (
|
|
89
|
+
if (location?.state?.isLogout) {
|
|
90
|
+
// Execute a true Logout action
|
|
91
|
+
// This is needed to cover the use case of being logged in in
|
|
92
|
+
// another backend (eg. in development), having a token for
|
|
93
|
+
// localhost and try to use it, the login route has to know that
|
|
94
|
+
// it's the same as it comes from a logout
|
|
95
|
+
// See also Unauthorized.jsx
|
|
96
|
+
dispatch(logout());
|
|
97
|
+
dispatch(purgeMessages());
|
|
98
|
+
// Reset the location state
|
|
99
|
+
history.push(`${location.pathname}${location.search}`);
|
|
100
|
+
} else if (token && token !== previousToken) {
|
|
101
|
+
// We just did a true login action
|
|
83
102
|
history.push(returnUrl || '/');
|
|
84
103
|
if (toast.isActive('loggedOut')) {
|
|
85
104
|
toast.dismiss('loggedOut');
|
|
@@ -116,8 +135,10 @@ const Login = (props) => {
|
|
|
116
135
|
intl,
|
|
117
136
|
history,
|
|
118
137
|
returnUrl,
|
|
119
|
-
|
|
138
|
+
location.search,
|
|
139
|
+
location.pathname,
|
|
120
140
|
location?.state?.isLogout,
|
|
141
|
+
previousToken,
|
|
121
142
|
]);
|
|
122
143
|
|
|
123
144
|
const onLogin = (event) => {
|
|
@@ -3,7 +3,7 @@ import { useDispatch, useSelector, shallowEqual } from 'react-redux';
|
|
|
3
3
|
import { useHistory } from 'react-router-dom';
|
|
4
4
|
import { defineMessages, useIntl } from 'react-intl';
|
|
5
5
|
import qs from 'query-string';
|
|
6
|
-
import {
|
|
6
|
+
import { Toast } from '@plone/volto/components';
|
|
7
7
|
import { logout, purgeMessages } from '@plone/volto/actions';
|
|
8
8
|
import { toast } from 'react-toastify';
|
|
9
9
|
|
|
@@ -55,7 +55,7 @@ const Logout = ({ location }) => {
|
|
|
55
55
|
}
|
|
56
56
|
}, [history, returnUrl, intl, token]);
|
|
57
57
|
|
|
58
|
-
return
|
|
58
|
+
return '';
|
|
59
59
|
};
|
|
60
60
|
|
|
61
61
|
export default Logout;
|
|
@@ -71,6 +71,7 @@ class Search extends Component {
|
|
|
71
71
|
|
|
72
72
|
constructor(props) {
|
|
73
73
|
super(props);
|
|
74
|
+
this.defaultPageSize = config.settings.defaultPageSize;
|
|
74
75
|
this.state = { currentPage: 1, isClient: false, active: 'relevance' };
|
|
75
76
|
}
|
|
76
77
|
|
|
@@ -109,19 +110,24 @@ class Search extends Component {
|
|
|
109
110
|
const options = qs.parse(this.props.history.location.search);
|
|
110
111
|
this.setState({ currentPage: 1 });
|
|
111
112
|
options['use_site_search_settings'] = 1;
|
|
112
|
-
this.props.searchContent('',
|
|
113
|
+
this.props.searchContent('', {
|
|
114
|
+
b_size: this.defaultPageSize,
|
|
115
|
+
...options,
|
|
116
|
+
});
|
|
113
117
|
};
|
|
114
118
|
|
|
115
119
|
handleQueryPaginationChange = (e, { activePage }) => {
|
|
116
|
-
const { settings } = config;
|
|
117
120
|
window.scrollTo(0, 0);
|
|
118
121
|
let options = qs.parse(this.props.history.location.search);
|
|
119
122
|
options['use_site_search_settings'] = 1;
|
|
120
123
|
|
|
121
124
|
this.setState({ currentPage: activePage }, () => {
|
|
122
125
|
this.props.searchContent('', {
|
|
126
|
+
b_size: this.defaultPageSize,
|
|
123
127
|
...options,
|
|
124
|
-
b_start:
|
|
128
|
+
b_start:
|
|
129
|
+
(this.state.currentPage - 1) *
|
|
130
|
+
(options.b_size || this.defaultPageSize),
|
|
125
131
|
});
|
|
126
132
|
});
|
|
127
133
|
};
|
|
@@ -149,7 +155,8 @@ class Search extends Component {
|
|
|
149
155
|
* @returns {string} Markup for the component.
|
|
150
156
|
*/
|
|
151
157
|
render() {
|
|
152
|
-
const
|
|
158
|
+
const options = qs.parse(this.props.history.location.search);
|
|
159
|
+
|
|
153
160
|
return (
|
|
154
161
|
<Container id="page-search">
|
|
155
162
|
<Helmet title={this.props.intl.formatMessage(messages.Search)} />
|
|
@@ -282,7 +289,8 @@ class Search extends Component {
|
|
|
282
289
|
<Pagination
|
|
283
290
|
activePage={this.state.currentPage}
|
|
284
291
|
totalPages={Math.ceil(
|
|
285
|
-
this.props.search.items_total /
|
|
292
|
+
this.props.search.items_total /
|
|
293
|
+
(options.b_size || this.defaultPageSize),
|
|
286
294
|
)}
|
|
287
295
|
onPageChange={this.handleQueryPaginationChange}
|
|
288
296
|
firstItem={null}
|
|
@@ -261,13 +261,6 @@ class View extends Component {
|
|
|
261
261
|
this.props.content.subjects.length > 0 && (
|
|
262
262
|
<Tags tags={this.props.content.subjects} />
|
|
263
263
|
)}
|
|
264
|
-
{/* Add opt-in social sharing if required, disabled by default */}
|
|
265
|
-
{/* In the future this might be parameterized from the app config */}
|
|
266
|
-
{/* <SocialSharing
|
|
267
|
-
url={typeof window === 'undefined' ? '' : window.location.href}
|
|
268
|
-
title={this.props.content.title}
|
|
269
|
-
description={this.props.content.description || ''}
|
|
270
|
-
/> */}
|
|
271
264
|
{this.props.content.allow_discussion && (
|
|
272
265
|
<Comments pathname={this.props.pathname} />
|
|
273
266
|
)}
|
|
@@ -30,9 +30,6 @@ jest.mock('../../manage/Toolbar/Toolbar', () =>
|
|
|
30
30
|
jest.fn(() => <div id="Portal" />),
|
|
31
31
|
);
|
|
32
32
|
|
|
33
|
-
jest.mock('../SocialSharing/SocialSharing', () =>
|
|
34
|
-
jest.fn(() => <div id="SocialSharing" />),
|
|
35
|
-
);
|
|
36
33
|
jest.mock('../Comments/Comments', () => jest.fn(() => <div id="Comments" />));
|
|
37
34
|
jest.mock('../Tags/Tags', () => jest.fn(() => <div id="Tags" />));
|
|
38
35
|
jest.mock('../SlotRenderer/SlotRenderer', () =>
|
package/src/config/Widgets.jsx
CHANGED
|
@@ -55,7 +55,6 @@ import ImageWidget from '@plone/volto/components/manage/Widgets/ImageWidget';
|
|
|
55
55
|
// Widgets mapping
|
|
56
56
|
export const widgetMapping = {
|
|
57
57
|
id: {
|
|
58
|
-
schema: SchemaWidget,
|
|
59
58
|
subjects: TokenWidget,
|
|
60
59
|
query: QuerystringWidget,
|
|
61
60
|
recurrence: RecurrenceWidget,
|
|
@@ -89,6 +88,7 @@ export const widgetMapping = {
|
|
|
89
88
|
autocomplete: SelectAutoComplete,
|
|
90
89
|
color_picker: ColorPickerWidget,
|
|
91
90
|
select: SelectWidget,
|
|
91
|
+
schema: SchemaWidget,
|
|
92
92
|
},
|
|
93
93
|
vocabulary: {
|
|
94
94
|
'plone.app.vocabularies.Catalog': ObjectBrowserWidget,
|
package/src/config/index.js
CHANGED
|
@@ -32,6 +32,7 @@ import applyAddonConfiguration, { addonsInfo } from 'load-volto-addons';
|
|
|
32
32
|
import ConfigRegistry from '@plone/volto/registry';
|
|
33
33
|
|
|
34
34
|
import { getSiteAsyncPropExtender } from '@plone/volto/helpers';
|
|
35
|
+
import { registerValidators } from './validation';
|
|
35
36
|
|
|
36
37
|
const host = process.env.HOST || 'localhost';
|
|
37
38
|
const port = process.env.PORT || '3000';
|
|
@@ -97,7 +98,7 @@ let config = {
|
|
|
97
98
|
process.env.RAZZLE_INTERNAL_API_PATH ||
|
|
98
99
|
process.env.RAZZLE_API_PATH ||
|
|
99
100
|
'http://localhost:8080/Plone', // Set it to '' for disabling the proxy
|
|
100
|
-
// proxyRewriteTarget Set it for set a custom target for the proxy or
|
|
101
|
+
// proxyRewriteTarget Set it for set a custom target for the proxy or override the internal VHM rewrite
|
|
101
102
|
// proxyRewriteTarget: '/VirtualHostBase/http/localhost:8080/Plone/VirtualHostRoot/_vh_api'
|
|
102
103
|
// proxyRewriteTarget: 'https://myvoltositeinproduction.com'
|
|
103
104
|
proxyRewriteTarget: process.env.RAZZLE_PROXY_REWRITE_TARGET || undefined,
|
|
@@ -209,8 +210,9 @@ let config = {
|
|
|
209
210
|
},
|
|
210
211
|
addonRoutes: [],
|
|
211
212
|
addonReducers: {},
|
|
212
|
-
slots: {},
|
|
213
213
|
components,
|
|
214
|
+
slots: {},
|
|
215
|
+
utilities: {},
|
|
214
216
|
};
|
|
215
217
|
|
|
216
218
|
// The apiExpanders depends on a config of the object, so it's done here
|
|
@@ -238,5 +240,8 @@ ConfigRegistry.addonRoutes = config.addonRoutes;
|
|
|
238
240
|
ConfigRegistry.addonReducers = config.addonReducers;
|
|
239
241
|
ConfigRegistry.components = config.components;
|
|
240
242
|
ConfigRegistry.slots = config.slots;
|
|
243
|
+
ConfigRegistry.utilities = config.utilities;
|
|
244
|
+
|
|
245
|
+
registerValidators(ConfigRegistry);
|
|
241
246
|
|
|
242
247
|
applyAddonConfiguration(ConfigRegistry);
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import { ConfigType } from '@plone/registry';
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
minLengthValidator,
|
|
5
|
+
maxLengthValidator,
|
|
6
|
+
urlValidator,
|
|
7
|
+
emailValidator,
|
|
8
|
+
isNumberValidator,
|
|
9
|
+
maximumValidator,
|
|
10
|
+
minimumValidator,
|
|
11
|
+
isIntegerValidator,
|
|
12
|
+
maxItemsValidator,
|
|
13
|
+
minItemsValidator,
|
|
14
|
+
hasUniqueItemsValidator,
|
|
15
|
+
startEventDateRangeValidator,
|
|
16
|
+
endEventDateRangeValidator,
|
|
17
|
+
patternValidator,
|
|
18
|
+
} from '@plone/volto/helpers/FormValidation/validators';
|
|
19
|
+
|
|
20
|
+
const registerValidators = (config: ConfigType) => {
|
|
21
|
+
config.registerUtility({
|
|
22
|
+
name: 'minLength',
|
|
23
|
+
type: 'validator',
|
|
24
|
+
dependencies: { fieldType: 'string' },
|
|
25
|
+
method: minLengthValidator,
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
config.registerUtility({
|
|
29
|
+
name: 'maxLength',
|
|
30
|
+
type: 'validator',
|
|
31
|
+
dependencies: { fieldType: 'string' },
|
|
32
|
+
method: maxLengthValidator,
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
config.registerUtility({
|
|
36
|
+
name: 'pattern',
|
|
37
|
+
type: 'validator',
|
|
38
|
+
dependencies: { fieldType: 'string' },
|
|
39
|
+
method: patternValidator,
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
config.registerUtility({
|
|
43
|
+
name: 'minLength',
|
|
44
|
+
type: 'validator',
|
|
45
|
+
dependencies: { fieldType: 'password' },
|
|
46
|
+
method: minLengthValidator,
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
config.registerUtility({
|
|
50
|
+
name: 'maxLength',
|
|
51
|
+
type: 'validator',
|
|
52
|
+
dependencies: { fieldType: 'password' },
|
|
53
|
+
method: maxLengthValidator,
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
config.registerUtility({
|
|
57
|
+
name: 'pattern',
|
|
58
|
+
type: 'validator',
|
|
59
|
+
dependencies: { fieldType: 'password' },
|
|
60
|
+
method: patternValidator,
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
config.registerUtility({
|
|
64
|
+
name: 'email',
|
|
65
|
+
type: 'validator',
|
|
66
|
+
dependencies: { widget: 'email' },
|
|
67
|
+
method: emailValidator,
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
config.registerUtility({
|
|
71
|
+
name: 'url',
|
|
72
|
+
type: 'validator',
|
|
73
|
+
dependencies: { widget: 'url' },
|
|
74
|
+
method: urlValidator,
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
config.registerUtility({
|
|
78
|
+
name: 'number',
|
|
79
|
+
type: 'validator',
|
|
80
|
+
dependencies: { fieldType: 'number' },
|
|
81
|
+
method: isNumberValidator,
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
config.registerUtility({
|
|
85
|
+
name: 'minimum',
|
|
86
|
+
type: 'validator',
|
|
87
|
+
dependencies: { fieldType: 'number' },
|
|
88
|
+
method: minimumValidator,
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
config.registerUtility({
|
|
92
|
+
name: 'maximum',
|
|
93
|
+
type: 'validator',
|
|
94
|
+
dependencies: { fieldType: 'number' },
|
|
95
|
+
method: maximumValidator,
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
config.registerUtility({
|
|
99
|
+
name: 'integer',
|
|
100
|
+
type: 'validator',
|
|
101
|
+
dependencies: { fieldType: 'integer' },
|
|
102
|
+
method: isIntegerValidator,
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
config.registerUtility({
|
|
106
|
+
name: 'minimum',
|
|
107
|
+
type: 'validator',
|
|
108
|
+
dependencies: { fieldType: 'integer' },
|
|
109
|
+
method: minimumValidator,
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
config.registerUtility({
|
|
113
|
+
name: 'maximum',
|
|
114
|
+
type: 'validator',
|
|
115
|
+
dependencies: { fieldType: 'integer' },
|
|
116
|
+
method: maximumValidator,
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
config.registerUtility({
|
|
120
|
+
name: 'maxItems',
|
|
121
|
+
type: 'validator',
|
|
122
|
+
dependencies: { fieldType: 'array' },
|
|
123
|
+
method: maxItemsValidator,
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
config.registerUtility({
|
|
127
|
+
name: 'minItems',
|
|
128
|
+
type: 'validator',
|
|
129
|
+
dependencies: { fieldType: 'array' },
|
|
130
|
+
method: minItemsValidator,
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
config.registerUtility({
|
|
134
|
+
name: 'uniqueItems',
|
|
135
|
+
type: 'validator',
|
|
136
|
+
dependencies: { fieldType: 'array' },
|
|
137
|
+
method: hasUniqueItemsValidator,
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
config.registerUtility({
|
|
141
|
+
name: 'dateRangeValidator',
|
|
142
|
+
type: 'validator',
|
|
143
|
+
dependencies: { behaviorName: 'plone.eventbasic', fieldName: 'start' },
|
|
144
|
+
method: startEventDateRangeValidator,
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
config.registerUtility({
|
|
148
|
+
name: 'dateRangeValidator',
|
|
149
|
+
type: 'validator',
|
|
150
|
+
dependencies: { behaviorName: 'plone.eventbasic', fieldName: 'end' },
|
|
151
|
+
method: endEventDateRangeValidator,
|
|
152
|
+
});
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
export { registerValidators };
|
|
@@ -51,7 +51,7 @@ export function resolveExtension(name, extensions, data) {
|
|
|
51
51
|
* - extensions is the blocksConfig extensions object for that block
|
|
52
52
|
* - resolvedExtensions is an object with
|
|
53
53
|
* `{ variation, <someExtensionA>, <someExtensionB> }` and each of these
|
|
54
|
-
* fields hold the
|
|
54
|
+
* fields hold the corresponding definition object from the block's
|
|
55
55
|
* configuration.
|
|
56
56
|
*/
|
|
57
57
|
export function resolveBlockExtensions(data, blocksConfig) {
|