@plone/volto 18.0.0-alpha.41 → 18.0.0-alpha.43
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 +114 -0
- package/finalreleasechangelog.py +48 -0
- package/locales/ca/LC_MESSAGES/volto.po +39 -13
- package/locales/ca.json +1 -1
- package/locales/de/LC_MESSAGES/volto.po +40 -14
- package/locales/de.json +1 -1
- package/locales/en/LC_MESSAGES/volto.po +39 -13
- package/locales/en.json +1 -1
- package/locales/es/LC_MESSAGES/volto.po +40 -14
- package/locales/es.json +1 -1
- package/locales/eu/LC_MESSAGES/volto.po +40 -14
- package/locales/eu.json +1 -1
- package/locales/fi/LC_MESSAGES/volto.po +40 -14
- package/locales/fi.json +1 -1
- package/locales/fr/LC_MESSAGES/volto.po +40 -14
- package/locales/fr.json +1 -1
- package/locales/hi/LC_MESSAGES/volto.po +40 -14
- package/locales/hi.json +1 -1
- package/locales/it/LC_MESSAGES/volto.po +40 -14
- package/locales/it.json +1 -1
- package/locales/ja/LC_MESSAGES/volto.po +39 -13
- package/locales/ja.json +1 -1
- package/locales/nl/LC_MESSAGES/volto.po +39 -13
- package/locales/nl.json +1 -1
- package/locales/pt/LC_MESSAGES/volto.po +39 -13
- package/locales/pt.json +1 -1
- package/locales/pt_BR/LC_MESSAGES/volto.po +40 -14
- package/locales/pt_BR.json +1 -1
- package/locales/ro/LC_MESSAGES/volto.po +39 -13
- package/locales/ro.json +1 -1
- package/locales/volto.pot +40 -14
- package/locales/zh_CN/LC_MESSAGES/volto.po +40 -14
- package/locales/zh_CN.json +1 -1
- package/package.json +5 -6
- package/razzle.config.js +3 -3
- package/src/components/index.js +0 -1
- package/src/components/manage/Actions/Actions.stories.jsx +138 -0
- package/src/components/manage/Add/Add.jsx +7 -4
- package/src/components/manage/BlockChooser/BlockChooser.jsx +9 -1
- package/src/components/manage/Blocks/Block/BlocksForm.jsx +5 -0
- package/src/components/manage/Blocks/Block/Edit.jsx +24 -8
- package/src/components/manage/Blocks/Block/EditBlockWrapper.jsx +17 -1
- package/src/components/manage/Blocks/Block/Order/Item.jsx +8 -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/Grid/View.jsx +3 -0
- package/src/components/manage/Blocks/Image/ImageSidebar.jsx +10 -2
- package/src/components/manage/Blocks/LeadImage/Edit.jsx +74 -126
- 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/components/SortOn.jsx +82 -55
- package/src/components/manage/Blocks/Search/hocs/withSearch.jsx +1 -1
- package/src/components/manage/Blocks/Search/widgets/SelectMetadataField.jsx +107 -176
- package/src/components/manage/Blocks/Teaser/Data.jsx +10 -2
- package/src/components/manage/Blocks/Teaser/DefaultBody.jsx +15 -8
- package/src/components/manage/Blocks/ToC/Edit.jsx +36 -28
- package/src/components/manage/Blocks/Video/Edit.jsx +105 -172
- package/src/components/manage/Blocks/Video/Edit.stories.jsx +57 -0
- package/src/components/manage/Blocks/Video/VideoSidebar.jsx +3 -1
- package/src/components/manage/Contents/Contents.jsx +4 -1
- package/src/components/manage/Contents/ContentsBreadcrumbs.stories.jsx +46 -0
- package/src/components/manage/Contents/ContentsPropertiesModal.jsx +85 -52
- package/src/components/manage/Contents/ContentsUploadModal.jsx +230 -323
- package/src/components/manage/Contents/ContentsUploadModal.stories.jsx +56 -0
- package/src/components/manage/Controlpanels/AddonsControlpanel.jsx +323 -441
- package/src/components/manage/Controlpanels/Aliases.jsx +452 -580
- package/src/components/manage/Controlpanels/Aliases.stories.jsx +74 -0
- package/src/components/manage/Controlpanels/ContentTypeSchema.jsx +1 -0
- package/src/components/manage/Controlpanels/Controlpanel.jsx +41 -2
- package/src/components/manage/Controlpanels/Controlpanel.test.jsx +55 -24
- package/src/components/manage/Controlpanels/DatabaseInformation.jsx +162 -229
- package/src/components/manage/Controlpanels/Groups/RenderGroups.jsx +74 -122
- 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/Display/Display.jsx +92 -148
- package/src/components/manage/Display/Display.stories.jsx +46 -0
- package/src/components/manage/Edit/Edit.jsx +2 -4
- package/src/components/manage/Form/Form.jsx +85 -20
- package/src/components/manage/Form/InlineForm.jsx +2 -4
- 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/Preferences/ChangePassword.jsx +94 -172
- package/src/components/manage/Preferences/ChangePassword.stories.jsx +41 -0
- package/src/components/manage/Preferences/PersonalInformation.jsx +50 -115
- package/src/components/manage/Preferences/PersonalPreferences.jsx +46 -100
- package/src/components/manage/Preferences/PersonalPreferences.stories.jsx +48 -0
- package/src/components/manage/Toolbar/More.jsx +308 -399
- package/src/components/manage/Toolbar/Toolbar.jsx +1 -1
- package/src/components/manage/Widgets/ArrayWidget.jsx +2 -2
- package/src/components/manage/Widgets/DatetimeWidget.jsx +121 -175
- package/src/components/manage/Widgets/ImageWidget.jsx +6 -5
- package/src/components/manage/Widgets/RecurrenceWidget/EndField.jsx +7 -1
- package/src/components/manage/Widgets/RecurrenceWidget/RecurrenceWidget.jsx +80 -31
- package/src/components/manage/Widgets/ReferenceWidget.jsx +134 -210
- package/src/components/theme/Register/Register.jsx +70 -142
- package/src/components/theme/Register/Register.stories.jsx +49 -0
- package/src/components/theme/Search/Search.jsx +13 -5
- package/src/components/theme/Tags/Tags.jsx +19 -10
- package/src/components/theme/Tags/Tags.test.jsx +9 -11
- package/src/components/theme/View/AlbumView.jsx +122 -167
- package/src/components/theme/View/LinkView.jsx +4 -0
- package/src/components/theme/View/LinkView.test.jsx +2 -0
- package/src/components/theme/View/View.jsx +0 -13
- package/src/components/theme/View/View.test.jsx +0 -3
- package/src/config/ControlPanels.js +49 -43
- package/src/config/Widgets.jsx +1 -1
- package/src/config/config.test.js +1 -0
- package/src/config/index.js +23 -2
- package/src/config/slots.js +12 -0
- package/src/config/validation.ts +155 -0
- package/src/helpers/Blocks/Blocks.js +12 -7
- package/src/helpers/Blocks/Blocks.test.js +15 -0
- package/src/helpers/Blocks/cloneBlocks.ts +1 -1
- package/src/helpers/Extensions/withBlockExtensions.jsx +1 -1
- package/src/helpers/FormValidation/FormValidation.jsx +128 -172
- 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 +19 -6
- package/src/helpers/Url/urlRegex.js +1 -1
- package/src/helpers/User/User.js +1 -1
- package/src/helpers/index.js +2 -0
- package/src/hooks/client/useClient.js +1 -1
- package/src/middleware/api.js +4 -2
- package/src/middleware/index.js +1 -0
- package/src/middleware/userSessionReset.js +46 -0
- package/src/store.js +2 -0
- package/test-setup-config.jsx +10 -0
- package/theme/themes/default/modules/embed.variables +1 -1
- package/theme/themes/pastanaga/collections/form.overrides +34 -0
- package/theme/themes/pastanaga/extras/blocks.less +6 -0
- 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/Actions/Actions.stories.d.ts +8 -0
- package/types/components/manage/Blocks/Block/Order/Order.d.ts +2 -1
- package/types/components/manage/Blocks/LeadImage/Edit.d.ts +14 -5
- package/types/components/manage/Blocks/Search/widgets/SelectMetadataField.d.ts +0 -5
- package/types/components/manage/Blocks/ToC/Edit.d.ts +1 -6
- package/types/components/manage/Blocks/Video/Edit.d.ts +1 -1
- package/types/components/manage/Blocks/Video/Edit.stories.d.ts +8 -0
- package/types/components/manage/Contents/ContentsBreadcrumbs.stories.d.ts +8 -0
- package/types/components/manage/Contents/ContentsUploadModal.d.ts +14 -2
- package/types/components/manage/Contents/ContentsUploadModal.stories.d.ts +8 -0
- package/types/components/manage/Contents/index.d.ts +1 -1
- package/types/components/manage/Controlpanels/AddonsControlpanel.d.ts +2 -2
- package/types/components/manage/Controlpanels/Aliases.d.ts +2 -2
- package/types/components/manage/Controlpanels/Aliases.stories.d.ts +8 -0
- package/types/components/manage/Controlpanels/DatabaseInformation.d.ts +2 -2
- package/types/components/manage/Controlpanels/Groups/RenderGroups.d.ts +10 -5
- package/types/components/manage/Controlpanels/index.d.ts +4 -4
- package/types/components/manage/Display/Display.stories.d.ts +8 -0
- package/types/components/manage/Preferences/ChangePassword.d.ts +2 -2
- package/types/components/manage/Preferences/ChangePassword.stories.d.ts +8 -0
- package/types/components/manage/Preferences/PersonalInformation.d.ts +7 -2
- package/types/components/manage/Preferences/PersonalPreferences.d.ts +5 -1
- package/types/components/manage/Preferences/PersonalPreferences.stories.d.ts +8 -0
- package/types/components/manage/Toolbar/More.d.ts +8 -5
- package/types/components/manage/Widgets/DatetimeWidget.d.ts +0 -85
- package/types/components/manage/Widgets/DatetimeWidget.stories.d.ts +0 -1
- package/types/components/manage/Widgets/ReferenceWidget.d.ts +27 -2
- package/types/components/manage/Widgets/index.d.ts +1 -1
- package/types/components/theme/Register/Register.d.ts +2 -2
- package/types/components/theme/Register/Register.stories.d.ts +9 -0
- package/types/components/theme/Tags/Tags.d.ts +15 -7
- package/types/components/theme/View/AlbumView.d.ts +3 -17
- package/types/config/ControlPanels.d.ts +8 -0
- package/types/config/RichTextEditor/ToHTML.d.ts +1 -1
- package/types/config/Widgets.d.ts +3 -3
- package/types/config/slots.d.ts +21 -0
- package/types/config/validation.d.ts +3 -0
- package/types/helpers/Blocks/Blocks.d.ts +6 -0
- package/types/helpers/Extensions/withBlockExtensions.d.ts +1 -1
- package/types/helpers/FormValidation/FormValidation.d.ts +2 -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/types/helpers/index.d.ts +2 -2
- package/types/middleware/index.d.ts +1 -0
- package/types/middleware/userSessionReset.d.ts +5 -0
- package/src/components/theme/SocialSharing/SocialSharing.jsx +0 -48
- package/src/components/theme/SocialSharing/SocialSharing.test.jsx +0 -14
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
import { validationMessage } from '@plone/volto/helpers/FormValidation/FormValidation';
|
|
2
|
+
import { messages } from '@plone/volto/helpers/MessageLabels/MessageLabels';
|
|
3
|
+
|
|
4
|
+
type MinMaxValidator = {
|
|
5
|
+
value: string | number;
|
|
6
|
+
fieldSpec: string | number;
|
|
7
|
+
criterion: string;
|
|
8
|
+
formatMessage: Function;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
type Validator = {
|
|
12
|
+
value: string;
|
|
13
|
+
field: Record<string, any>;
|
|
14
|
+
formData: any;
|
|
15
|
+
formatMessage: Function;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export const isMaxPropertyValid = ({
|
|
19
|
+
value,
|
|
20
|
+
fieldSpec,
|
|
21
|
+
criterion,
|
|
22
|
+
formatMessage,
|
|
23
|
+
}: MinMaxValidator) => {
|
|
24
|
+
const isValid = fieldSpec !== undefined ? value <= fieldSpec : true;
|
|
25
|
+
return validationMessage(isValid, criterion, fieldSpec, formatMessage);
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export const isMinPropertyValid = ({
|
|
29
|
+
value,
|
|
30
|
+
fieldSpec,
|
|
31
|
+
criterion,
|
|
32
|
+
formatMessage,
|
|
33
|
+
}: MinMaxValidator) => {
|
|
34
|
+
const isValid = fieldSpec !== undefined ? value >= fieldSpec : true;
|
|
35
|
+
return validationMessage(isValid, criterion, fieldSpec, formatMessage);
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export const minLengthValidator = ({
|
|
39
|
+
value,
|
|
40
|
+
field,
|
|
41
|
+
formatMessage,
|
|
42
|
+
}: Validator) =>
|
|
43
|
+
isMinPropertyValid({
|
|
44
|
+
value: value.length,
|
|
45
|
+
fieldSpec: field.minLength,
|
|
46
|
+
criterion: 'minLength',
|
|
47
|
+
formatMessage,
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
export const maxLengthValidator = ({
|
|
51
|
+
value,
|
|
52
|
+
field,
|
|
53
|
+
formatMessage,
|
|
54
|
+
}: Validator) =>
|
|
55
|
+
isMaxPropertyValid({
|
|
56
|
+
value: value.length,
|
|
57
|
+
fieldSpec: field.maxLength,
|
|
58
|
+
criterion: 'maxLength',
|
|
59
|
+
formatMessage,
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
export const urlValidator = ({ value, formatMessage }: Validator) => {
|
|
63
|
+
const urlRegex = new RegExp(
|
|
64
|
+
'^(https?:\\/\\/)?' + // validate protocol
|
|
65
|
+
'((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|' + // validate domain name
|
|
66
|
+
'((\\d{1,3}\\.){3}\\d{1,3}))|' + // validate OR ip (v4) address
|
|
67
|
+
'(localhost)' + // validate OR localhost address
|
|
68
|
+
'(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*' + // validate port and path
|
|
69
|
+
'(\\?[;&a-z\\d%_.~+=-]*)?' + // validate query string
|
|
70
|
+
'(\\#[-a-z\\d_]*)?$', // validate fragment locator
|
|
71
|
+
'i',
|
|
72
|
+
);
|
|
73
|
+
const isValid = urlRegex.test(value);
|
|
74
|
+
return !isValid ? formatMessage(messages.isValidURL) : null;
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
export const emailValidator = ({ value, formatMessage }: Validator): string => {
|
|
78
|
+
// Email Regex taken from from WHATWG living standard:
|
|
79
|
+
// https://html.spec.whatwg.org/multipage/input.html#e-mail-state-(type=email)
|
|
80
|
+
const emailRegex =
|
|
81
|
+
/^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/;
|
|
82
|
+
const isValid = emailRegex.test(value);
|
|
83
|
+
return !isValid ? formatMessage(messages.isValidEmail) : null;
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
export const isNumberValidator = ({ value, formatMessage }: Validator) => {
|
|
87
|
+
const isNumeric = (string: string | number) => Number.isFinite(+string);
|
|
88
|
+
const floatRegex = /^[+-]?\d+(\.\d+)?$/;
|
|
89
|
+
const isValid = isNumeric(value) && floatRegex.test(value);
|
|
90
|
+
// const isValid =
|
|
91
|
+
// typeof value === 'string' && !isNaN(+value) && floatRegex.test(value);
|
|
92
|
+
return !isValid ? formatMessage(messages.isNumber) : null;
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
export const minimumValidator = ({ value, field, formatMessage }: Validator) =>
|
|
96
|
+
isMinPropertyValid({
|
|
97
|
+
value,
|
|
98
|
+
fieldSpec: field.minimum,
|
|
99
|
+
criterion: 'minimum',
|
|
100
|
+
formatMessage,
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
export const maximumValidator = ({ value, field, formatMessage }: Validator) =>
|
|
104
|
+
isMaxPropertyValid({
|
|
105
|
+
value,
|
|
106
|
+
fieldSpec: field.maximum,
|
|
107
|
+
criterion: 'maximum',
|
|
108
|
+
formatMessage,
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
export const isIntegerValidator = ({ value, formatMessage }: Validator) => {
|
|
112
|
+
const isNumeric = (string: string | number) => Number.isFinite(+string);
|
|
113
|
+
const intRegex = /^-?[0-9]+$/;
|
|
114
|
+
const isValid = isNumeric(value) && intRegex.test(value);
|
|
115
|
+
return !isValid ? formatMessage(messages.isInteger) : null;
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
export const hasUniqueItemsValidator = ({
|
|
119
|
+
value,
|
|
120
|
+
field,
|
|
121
|
+
formatMessage,
|
|
122
|
+
}: Validator) => {
|
|
123
|
+
if (!field.uniqueItems) {
|
|
124
|
+
return null;
|
|
125
|
+
}
|
|
126
|
+
const isValid =
|
|
127
|
+
field.uniqueItems &&
|
|
128
|
+
value &&
|
|
129
|
+
// unique items
|
|
130
|
+
[...new Set(value)].length === value.length;
|
|
131
|
+
return !isValid ? formatMessage(messages.uniqueItems) : null;
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
export const startEventDateRangeValidator = ({
|
|
135
|
+
value,
|
|
136
|
+
field,
|
|
137
|
+
formData,
|
|
138
|
+
formatMessage,
|
|
139
|
+
}: Validator) => {
|
|
140
|
+
const isValid =
|
|
141
|
+
value && formData.end && new Date(value) < new Date(formData.end);
|
|
142
|
+
return !isValid
|
|
143
|
+
? formatMessage(messages.startEventRange, {
|
|
144
|
+
endDateValueOrEndFieldName: formData.end || 'end',
|
|
145
|
+
})
|
|
146
|
+
: null;
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
export const endEventDateRangeValidator = ({
|
|
150
|
+
value,
|
|
151
|
+
field,
|
|
152
|
+
formData,
|
|
153
|
+
formatMessage,
|
|
154
|
+
}: Validator) => {
|
|
155
|
+
const isValid =
|
|
156
|
+
value && formData.start && new Date(value) > new Date(formData.start);
|
|
157
|
+
return !isValid
|
|
158
|
+
? formatMessage(messages.endEventRange, {
|
|
159
|
+
startDateValueOrStartFieldName: formData.start || 'start',
|
|
160
|
+
})
|
|
161
|
+
: null;
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
export const patternValidator = ({
|
|
165
|
+
value,
|
|
166
|
+
field,
|
|
167
|
+
formatMessage,
|
|
168
|
+
}: Validator) => {
|
|
169
|
+
if (!field.pattern) {
|
|
170
|
+
return null;
|
|
171
|
+
}
|
|
172
|
+
const regex = new RegExp(field.pattern);
|
|
173
|
+
const isValid = regex.test(value);
|
|
174
|
+
return !isValid ? formatMessage(messages.pattern) : null;
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
export const maxItemsValidator = ({
|
|
178
|
+
value,
|
|
179
|
+
field,
|
|
180
|
+
formatMessage,
|
|
181
|
+
}: Validator) => {
|
|
182
|
+
if (!field.maxItems) {
|
|
183
|
+
return null;
|
|
184
|
+
}
|
|
185
|
+
const isValid = Array.isArray(value) && value.length <= field.maxItems;
|
|
186
|
+
return !isValid
|
|
187
|
+
? formatMessage(messages.maxItems, { maxItems: field.maxItems })
|
|
188
|
+
: null;
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
export const minItemsValidator = ({
|
|
192
|
+
value,
|
|
193
|
+
field,
|
|
194
|
+
formatMessage,
|
|
195
|
+
}: Validator) => {
|
|
196
|
+
if (!field.minItems) {
|
|
197
|
+
return null;
|
|
198
|
+
}
|
|
199
|
+
const isValid = Array.isArray(value) && value.length >= field.minItems;
|
|
200
|
+
return !isValid
|
|
201
|
+
? formatMessage(messages.minItems, { minItems: field.minItems })
|
|
202
|
+
: null;
|
|
203
|
+
};
|
|
@@ -375,4 +375,32 @@ export const messages = defineMessages({
|
|
|
375
375
|
id: 'fileTooLarge',
|
|
376
376
|
defaultMessage: 'This website does not accept files larger than {limit}',
|
|
377
377
|
},
|
|
378
|
+
blocksFieldsErrorTitle: {
|
|
379
|
+
id: 'blocksFieldsErrorTitle',
|
|
380
|
+
defaultMessage: 'Error in the block field {errorField}.',
|
|
381
|
+
},
|
|
382
|
+
startEventRange: {
|
|
383
|
+
id: 'Event start date must be on or before {endDateValueOrEndFieldName}',
|
|
384
|
+
defaultMessage:
|
|
385
|
+
'Event start date must be on or before {endDateValueOrEndFieldName}',
|
|
386
|
+
},
|
|
387
|
+
endEventRange: {
|
|
388
|
+
id: 'Event end date must be on or after {startDateValueOrStartFieldName}',
|
|
389
|
+
defaultMessage:
|
|
390
|
+
'Event end date must be on or after {startDateValueOrStartFieldName}',
|
|
391
|
+
},
|
|
392
|
+
pattern: {
|
|
393
|
+
id: 'The value does not match the pattern {pattern}',
|
|
394
|
+
defaultMessage: 'The value does not match the pattern {pattern}',
|
|
395
|
+
},
|
|
396
|
+
maxItems: {
|
|
397
|
+
id: 'The number of items must be less than or equal to {maxItems}',
|
|
398
|
+
defaultMessage:
|
|
399
|
+
'The number of items must be less than or equal to {maxItems}',
|
|
400
|
+
},
|
|
401
|
+
minItems: {
|
|
402
|
+
id: 'The number of items must be greater than or equal to {minItems}',
|
|
403
|
+
defaultMessage:
|
|
404
|
+
'The number of items must be greater than or equal to {minItems}',
|
|
405
|
+
},
|
|
378
406
|
});
|
|
@@ -66,7 +66,7 @@ describe('Url', () => {
|
|
|
66
66
|
it('return empty string if no url is empty string', () => {
|
|
67
67
|
expect(getBaseUrl('')).toBe('');
|
|
68
68
|
});
|
|
69
|
-
it('return a null/undefined mailto
|
|
69
|
+
it('return a null/undefined mailto address ', () => {
|
|
70
70
|
expect(normaliseMail(null)).toBe('mailto:null');
|
|
71
71
|
expect(normaliseMail(undefined)).toBe('mailto:undefined');
|
|
72
72
|
});
|
|
@@ -163,14 +163,14 @@ describe('Url', () => {
|
|
|
163
163
|
});
|
|
164
164
|
|
|
165
165
|
describe('flattenHTMLToAppURL', () => {
|
|
166
|
-
it('flattens all
|
|
166
|
+
it('flattens all occurrences of the api URL from an html snippet', () => {
|
|
167
167
|
const html = `<a href="${settings.apiPath}/foo/bar">An internal link</a><a href="${settings.apiPath}/foo/baz">second link</a>`;
|
|
168
168
|
expect(flattenHTMLToAppURL(html)).toBe(
|
|
169
169
|
'<a href="/foo/bar">An internal link</a><a href="/foo/baz">second link</a>',
|
|
170
170
|
);
|
|
171
171
|
});
|
|
172
172
|
|
|
173
|
-
it('flattens all
|
|
173
|
+
it('flattens all occurrences of the api URL from an html snippet, with settings.internalApiPath', () => {
|
|
174
174
|
const html = `<a href="http://plone:8080/Plone/foo/bar">An internal link</a><a href="http://plone:8080/Plone/foo/baz">second link</a>`;
|
|
175
175
|
const saved = settings.internalApiPath;
|
|
176
176
|
settings.internalApiPath = 'http://plone:8080/Plone';
|
|
@@ -228,7 +228,7 @@ describe('Url', () => {
|
|
|
228
228
|
const href = undefined;
|
|
229
229
|
expect(isInternalURL(href)).toBe(undefined);
|
|
230
230
|
});
|
|
231
|
-
it('tells if an URL is external if settings.externalroutes is
|
|
231
|
+
it('tells if an URL is external if settings.externalroutes is present.', () => {
|
|
232
232
|
const url = `https://localhost:3000/fb/my-page/contents`;
|
|
233
233
|
const blacklistedurl = '/blacklisted';
|
|
234
234
|
settings.externalRoutes = [
|
|
@@ -255,11 +255,24 @@ describe('Url', () => {
|
|
|
255
255
|
});
|
|
256
256
|
it('isUrl test 4', () => {
|
|
257
257
|
const href = `https://www`;
|
|
258
|
-
expect(isUrl(href)).toBe(
|
|
258
|
+
expect(isUrl(href)).toBe(true);
|
|
259
259
|
});
|
|
260
260
|
it('isUrl test 5', () => {
|
|
261
|
+
const href = `https://www/foo/bar`;
|
|
262
|
+
expect(isUrl(href)).toBe(true);
|
|
263
|
+
});
|
|
264
|
+
it('isUrl test 6', () => {
|
|
265
|
+
// at the end of the day, this is a strange, but valid, URL
|
|
261
266
|
const href = `www.e`;
|
|
262
|
-
expect(isUrl(href)).toBe(
|
|
267
|
+
expect(isUrl(href)).toBe(true);
|
|
268
|
+
});
|
|
269
|
+
it('isUrl test 7', () => {
|
|
270
|
+
const href = `file://server/folder/file.txt`;
|
|
271
|
+
expect(isUrl(href)).toBe(true);
|
|
272
|
+
});
|
|
273
|
+
it('isUrl test 8', () => {
|
|
274
|
+
const href = `file://server.dir.internal/folder/file.txt`;
|
|
275
|
+
expect(isUrl(href)).toBe(true);
|
|
263
276
|
});
|
|
264
277
|
});
|
|
265
278
|
describe('getFieldURL', () => {
|
|
@@ -52,7 +52,7 @@ export const urlRegex = (_opts) => {
|
|
|
52
52
|
})\\.?`;
|
|
53
53
|
const port = '(?::\\d{2,5})?';
|
|
54
54
|
const path = '(?:[/?#][^\\s"]*)?';
|
|
55
|
-
const regex = `(?:${protocol}|www\\.)${auth}(?:localhost|${ip}|${host}${domain}${tld})${port}${path}`;
|
|
55
|
+
const regex = `(?:${protocol}|www\\.)${auth}(?:localhost|${ip}|${host}${domain}${tld}|${host})${port}${path}`;
|
|
56
56
|
|
|
57
57
|
return opts.exact
|
|
58
58
|
? new RegExp(`(?:^${regex}$)`, 'i')
|
package/src/helpers/User/User.js
CHANGED
package/src/helpers/index.js
CHANGED
|
@@ -40,6 +40,7 @@ export {
|
|
|
40
40
|
getLanguageIndependentFields,
|
|
41
41
|
} from '@plone/volto/helpers/Content/Content';
|
|
42
42
|
export {
|
|
43
|
+
applyBlockInitialValue,
|
|
43
44
|
addBlock,
|
|
44
45
|
insertBlock,
|
|
45
46
|
blockHasValue,
|
|
@@ -85,6 +86,7 @@ export { default as Helmet } from './Helmet/Helmet';
|
|
|
85
86
|
export { default as FormValidation } from './FormValidation/FormValidation';
|
|
86
87
|
export { validateFileUploadSize } from './FormValidation/FormValidation';
|
|
87
88
|
export { tryParseJSON } from './FormValidation/FormValidation';
|
|
89
|
+
export { extractInvariantErrors } from './FormValidation/FormValidation';
|
|
88
90
|
export {
|
|
89
91
|
difference,
|
|
90
92
|
getColor,
|
package/src/middleware/api.js
CHANGED
|
@@ -222,7 +222,8 @@ const apiMiddlewareFactory =
|
|
|
222
222
|
}
|
|
223
223
|
|
|
224
224
|
const { settings } = config;
|
|
225
|
-
|
|
225
|
+
const state = getState();
|
|
226
|
+
if (state.apierror.connectionRefused) {
|
|
226
227
|
next({
|
|
227
228
|
...rest,
|
|
228
229
|
type: RESET_APIERROR,
|
|
@@ -232,7 +233,7 @@ const apiMiddlewareFactory =
|
|
|
232
233
|
const lang = result?.language?.token;
|
|
233
234
|
if (
|
|
234
235
|
lang &&
|
|
235
|
-
|
|
236
|
+
state.intl.locale !== toReactIntlLang(lang) &&
|
|
236
237
|
!subrequest &&
|
|
237
238
|
config.settings.supportedLanguages.includes(lang)
|
|
238
239
|
) {
|
|
@@ -244,6 +245,7 @@ const apiMiddlewareFactory =
|
|
|
244
245
|
});
|
|
245
246
|
}
|
|
246
247
|
}
|
|
248
|
+
|
|
247
249
|
if (type === LOGIN && settings.websockets) {
|
|
248
250
|
const cookies = new Cookies();
|
|
249
251
|
cookies.set(
|
package/src/middleware/index.js
CHANGED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import Cookies from 'universal-cookie';
|
|
2
|
+
|
|
3
|
+
const LOCATION_CHANGE = '@@router/LOCATION_CHANGE';
|
|
4
|
+
|
|
5
|
+
const userSessionReset =
|
|
6
|
+
({ dispatch, getState }) =>
|
|
7
|
+
(next) =>
|
|
8
|
+
(action) => {
|
|
9
|
+
if (typeof action === 'function') {
|
|
10
|
+
return next(action);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
switch (action.type) {
|
|
14
|
+
case LOCATION_CHANGE:
|
|
15
|
+
if (action.request?.subrequest || __SERVER__) {
|
|
16
|
+
return next(action);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const cookies = new Cookies();
|
|
20
|
+
const token = cookies.get('auth_token');
|
|
21
|
+
const state = getState();
|
|
22
|
+
|
|
23
|
+
if (token && !state.userSession?.token) {
|
|
24
|
+
const loginAction = {
|
|
25
|
+
type: 'LOGIN_SUCCESS',
|
|
26
|
+
result: {
|
|
27
|
+
token,
|
|
28
|
+
},
|
|
29
|
+
};
|
|
30
|
+
dispatch(loginAction);
|
|
31
|
+
} else if (!token && state.userSession?.token) {
|
|
32
|
+
const logoutAction = {
|
|
33
|
+
type: 'LOGOUT_SUCCESS',
|
|
34
|
+
result: {
|
|
35
|
+
token,
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
dispatch(logoutAction);
|
|
39
|
+
}
|
|
40
|
+
return next(action);
|
|
41
|
+
default:
|
|
42
|
+
return next(action);
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
export default userSessionReset;
|
package/src/store.js
CHANGED
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
protectLoadStart,
|
|
14
14
|
protectLoadEnd,
|
|
15
15
|
loadProtector,
|
|
16
|
+
userSessionReset,
|
|
16
17
|
} from '@plone/volto/middleware';
|
|
17
18
|
|
|
18
19
|
const configureStore = (initialState, history, apiHelper) => {
|
|
@@ -22,6 +23,7 @@ const configureStore = (initialState, history, apiHelper) => {
|
|
|
22
23
|
routerMiddleware(history),
|
|
23
24
|
thunk,
|
|
24
25
|
...(apiHelper ? [api(apiHelper)] : []),
|
|
26
|
+
userSessionReset,
|
|
25
27
|
protectLoadEnd,
|
|
26
28
|
...(__CLIENT__
|
|
27
29
|
? [save({ states: config.settings.persistentReducers, debounce: 500 })]
|
package/test-setup-config.jsx
CHANGED
|
@@ -20,9 +20,11 @@ import {
|
|
|
20
20
|
controlPanelsIcons,
|
|
21
21
|
filterControlPanels,
|
|
22
22
|
filterControlPanelsSchema,
|
|
23
|
+
unwantedControlPanelsFields,
|
|
23
24
|
} from '@plone/volto/config/ControlPanels';
|
|
24
25
|
|
|
25
26
|
import ListingBlockSchema from '@plone/volto/components/manage/Blocks/Listing/schema';
|
|
27
|
+
import { registerValidators } from '@plone/volto/config/validation';
|
|
26
28
|
|
|
27
29
|
config.set('settings', {
|
|
28
30
|
apiPath: 'http://localhost:8080/Plone',
|
|
@@ -30,6 +32,7 @@ config.set('settings', {
|
|
|
30
32
|
defaultLanguage: 'en',
|
|
31
33
|
supportedLanguages: ['en'],
|
|
32
34
|
defaultPageSize: 25,
|
|
35
|
+
showTags: true,
|
|
33
36
|
isMultilingual: false,
|
|
34
37
|
nonContentRoutes,
|
|
35
38
|
contentIcons: contentIcons,
|
|
@@ -48,6 +51,7 @@ config.set('settings', {
|
|
|
48
51
|
controlPanelsIcons,
|
|
49
52
|
filterControlPanels,
|
|
50
53
|
filterControlPanelsSchema,
|
|
54
|
+
unwantedControlPanelsFields,
|
|
51
55
|
apiExpanders: [],
|
|
52
56
|
downloadableObjects: ['File'],
|
|
53
57
|
viewableInBrowserObjects: [],
|
|
@@ -153,9 +157,15 @@ config.set('components', {
|
|
|
153
157
|
component: (props) => <img alt="Image component mock" {...props} />,
|
|
154
158
|
},
|
|
155
159
|
});
|
|
160
|
+
|
|
161
|
+
config.set('utilities', {});
|
|
162
|
+
|
|
156
163
|
config.set('experimental', {
|
|
157
164
|
addBlockButton: {
|
|
158
165
|
enabled: false,
|
|
159
166
|
},
|
|
160
167
|
});
|
|
168
|
+
|
|
161
169
|
config.set('slots', {});
|
|
170
|
+
|
|
171
|
+
registerValidators(config);
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
/* Placeholder */
|
|
15
15
|
@placeholderUnderlay: @background;
|
|
16
16
|
|
|
17
|
-
/* Placeholder
|
|
17
|
+
/* Placeholder Overlaid Background */
|
|
18
18
|
@placeholderBackground: radial-gradient(transparent 45%, rgba(0, 0, 0, 0.3));
|
|
19
19
|
@placeholderBackgroundOpacity: 0.5;
|
|
20
20
|
@placeholderBackgroundTransition: opacity @transitionDuration @transitionEasing;
|
|
@@ -123,16 +123,50 @@
|
|
|
123
123
|
z-index: 1;
|
|
124
124
|
top: 0;
|
|
125
125
|
right: 0;
|
|
126
|
+
left: auto;
|
|
126
127
|
display: flex;
|
|
127
128
|
height: 60px;
|
|
128
129
|
align-items: center;
|
|
129
130
|
margin-right: 1rem;
|
|
131
|
+
background: transparent;
|
|
132
|
+
box-shadow: none;
|
|
133
|
+
transform: none;
|
|
130
134
|
|
|
131
135
|
.item {
|
|
132
136
|
cursor: pointer;
|
|
133
137
|
}
|
|
134
138
|
}
|
|
135
139
|
|
|
140
|
+
.block.form {
|
|
141
|
+
[data-rbd-draggable-context-id] {
|
|
142
|
+
margin-bottom: 0;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
.ui.menu .item > i.icon {
|
|
146
|
+
margin-left: -2px;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
.square.icon {
|
|
150
|
+
margin-top: -2px;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
.ui.segments > div {
|
|
154
|
+
background: white !important;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
.drag.handle {
|
|
158
|
+
cursor: grab;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
.tabular.menu > .item {
|
|
162
|
+
height: 66px;
|
|
163
|
+
|
|
164
|
+
button {
|
|
165
|
+
border-bottom-width: 5px;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
136
170
|
.ui.form .field .ui.basic.button.delete-button {
|
|
137
171
|
padding: 0;
|
|
138
172
|
border: none;
|
|
@@ -1120,6 +1120,12 @@ div.image-upload-widget-image {
|
|
|
1120
1120
|
flex-direction: row;
|
|
1121
1121
|
align-items: center;
|
|
1122
1122
|
margin-right: 0.5em;
|
|
1123
|
+
|
|
1124
|
+
.sorted-label-value {
|
|
1125
|
+
margin-right: 0.5em;
|
|
1126
|
+
margin-left: 0.7em;
|
|
1127
|
+
color: @lightGrey;
|
|
1128
|
+
}
|
|
1123
1129
|
}
|
|
1124
1130
|
|
|
1125
1131
|
.sort-label {
|
|
@@ -129,7 +129,7 @@ body:not(.has-sidebar):not(.has-sidebar-collapsed) {
|
|
|
129
129
|
}
|
|
130
130
|
|
|
131
131
|
.toolbar-handler {
|
|
132
|
-
button {
|
|
132
|
+
.toolbar-handler-button {
|
|
133
133
|
opacity: 0.3;
|
|
134
134
|
}
|
|
135
135
|
|
|
@@ -243,7 +243,7 @@ body:not(.has-sidebar):not(.has-sidebar-collapsed) {
|
|
|
243
243
|
width: 100%;
|
|
244
244
|
justify-content: center;
|
|
245
245
|
|
|
246
|
-
button {
|
|
246
|
+
.toolbar-handler-button {
|
|
247
247
|
width: @toolbarWidth;
|
|
248
248
|
height: 20px;
|
|
249
249
|
padding: 0;
|
|
@@ -428,7 +428,7 @@ body:not(.has-sidebar):not(.has-sidebar-collapsed) {
|
|
|
428
428
|
flex-direction: column;
|
|
429
429
|
justify-content: center;
|
|
430
430
|
|
|
431
|
-
button {
|
|
431
|
+
.toolbar-handler-button {
|
|
432
432
|
width: @toolbarWidthMin;
|
|
433
433
|
height: @toolbarWidth;
|
|
434
434
|
|
|
@@ -752,3 +752,10 @@ body:not(.has-sidebar):not(.has-sidebar-collapsed) {
|
|
|
752
752
|
}
|
|
753
753
|
}
|
|
754
754
|
// End Orphaned CSS
|
|
755
|
+
|
|
756
|
+
// Toolbar handler color in homepage
|
|
757
|
+
.contenttype-plone-site {
|
|
758
|
+
#toolbar .toolbar-handler .toolbar-handler-button:before {
|
|
759
|
+
background: @teal-blue;
|
|
760
|
+
}
|
|
761
|
+
}
|
|
@@ -9,9 +9,10 @@
|
|
|
9
9
|
"esModuleInterop": true,
|
|
10
10
|
"jsx": "react-jsx",
|
|
11
11
|
"preserveSymlinks": true,
|
|
12
|
+
"downlevelIteration": true,
|
|
12
13
|
"paths": {
|
|
13
|
-
"@plone/volto/*": ["./src/*"]
|
|
14
|
+
"@plone/volto/*": ["./src/*"]
|
|
14
15
|
}
|
|
15
16
|
},
|
|
16
|
-
"include": ["src/**/*.js", "src/**/*.jsx", "src/**/*.tsx"]
|
|
17
|
+
"include": ["src/**/*.js", "src/**/*.jsx", "src/**/*.tsx"]
|
|
17
18
|
}
|
|
@@ -33,7 +33,6 @@ export { default as Logout } from "@plone/volto/components/theme/Logout/Logout";
|
|
|
33
33
|
export { default as Sitemap } from "@plone/volto/components/theme/Sitemap/Sitemap";
|
|
34
34
|
export { default as Search } from "@plone/volto/components/theme/Search/Search";
|
|
35
35
|
export { default as Comments } from "@plone/volto/components/theme/Comments/Comments";
|
|
36
|
-
export { default as SocialSharing } from "@plone/volto/components/theme/SocialSharing/SocialSharing";
|
|
37
36
|
export { default as Register } from "@plone/volto/components/theme/Register/Register";
|
|
38
37
|
export { default as PasswordReset } from "@plone/volto/components/theme/PasswordReset/PasswordReset";
|
|
39
38
|
export { default as RequestPasswordReset } from "@plone/volto/components/theme/PasswordReset/RequestPasswordReset";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export function Order({ items, onMoveBlock, onDeleteBlock, onSelectBlock, indentationWidth, removable, dndKitCore, dndKitSortable, dndKitUtilities, }: {
|
|
1
|
+
export function Order({ items, onMoveBlock, onDeleteBlock, onSelectBlock, indentationWidth, removable, dndKitCore, dndKitSortable, dndKitUtilities, errors, }: {
|
|
2
2
|
items?: any[];
|
|
3
3
|
onMoveBlock: any;
|
|
4
4
|
onDeleteBlock: any;
|
|
@@ -8,6 +8,7 @@ export function Order({ items, onMoveBlock, onDeleteBlock, onSelectBlock, indent
|
|
|
8
8
|
dndKitCore: any;
|
|
9
9
|
dndKitSortable: any;
|
|
10
10
|
dndKitUtilities: any;
|
|
11
|
+
errors: any;
|
|
11
12
|
}): import("react/jsx-runtime").JSX.Element;
|
|
12
13
|
declare const _default: any;
|
|
13
14
|
export default _default;
|
|
@@ -1,5 +1,14 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
export default Edit;
|
|
2
|
+
declare function Edit(props: any): import("react/jsx-runtime").JSX.Element;
|
|
3
|
+
declare namespace Edit {
|
|
4
|
+
namespace propTypes {
|
|
5
|
+
let properties: any;
|
|
6
|
+
let selected: any;
|
|
7
|
+
let block: any;
|
|
8
|
+
let index: any;
|
|
9
|
+
let data: any;
|
|
10
|
+
let pathname: any;
|
|
11
|
+
let onChangeBlock: any;
|
|
12
|
+
let openObjectBrowser: any;
|
|
13
|
+
}
|
|
14
|
+
}
|