@eeacms/volto-eea-website-theme 1.34.0 → 2.0.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.
Files changed (54) hide show
  1. package/.eslintrc.js +7 -2
  2. package/CHANGELOG.md +44 -20
  3. package/docker-compose.yml +1 -1
  4. package/jest-addon.config.js +3 -0
  5. package/package.json +2 -1
  6. package/src/components/manage/Blocks/LayoutSettings/index.js +3 -1
  7. package/src/components/manage/Blocks/Title/index.js +3 -1
  8. package/src/components/manage/Blocks/Title/schema.js +3 -1
  9. package/src/components/theme/Banner/View.jsx +12 -5
  10. package/src/components/theme/DraftBackground/DraftBackground.jsx +1 -0
  11. package/src/components/theme/DraftBackground/DraftBackground.test.jsx +85 -0
  12. package/src/config.js +2 -0
  13. package/src/customizations/@plone/volto-slate/blocks/Text/TextBlockView.jsx +32 -0
  14. package/src/customizations/@plone/volto-slate/editor/render.jsx +75 -0
  15. package/src/customizations/@plone/volto-slate/elementEditor/utils.js +76 -75
  16. package/src/customizations/volto/components/manage/Blocks/Grid/Edit.jsx +70 -0
  17. package/src/customizations/volto/components/manage/Blocks/Grid/View.jsx +61 -0
  18. package/src/customizations/volto/components/manage/Blocks/Grid/readme.md +1 -0
  19. package/src/customizations/volto/components/manage/Blocks/Image/Edit.jsx +82 -23
  20. package/src/customizations/volto/components/manage/Blocks/Image/Edit.test.jsx +10 -3
  21. package/src/customizations/volto/components/manage/Blocks/Image/View.jsx +110 -111
  22. package/src/customizations/volto/components/manage/Blocks/Image/schema.js +17 -2
  23. package/src/customizations/volto/components/manage/Blocks/LeadImage/Edit.jsx +35 -14
  24. package/src/customizations/volto/components/manage/Blocks/LeadImage/View.jsx +65 -79
  25. package/src/customizations/volto/components/manage/Display/Display.jsx +306 -0
  26. package/src/customizations/volto/components/manage/Display/Readme.md +1 -0
  27. package/src/customizations/volto/components/manage/Sidebar/SidebarPopup copy.jsx +82 -0
  28. package/src/customizations/volto/components/manage/Toolbar/More.jsx +541 -0
  29. package/src/customizations/volto/components/manage/UniversalLink/UniversalLink.jsx +3 -1
  30. package/src/customizations/volto/components/manage/Widgets/ObjectBrowserWidget.jsx +24 -14
  31. package/src/customizations/volto/components/manage/Widgets/README.md +1 -0
  32. package/src/customizations/volto/components/manage/Workflow/README.txt +1 -0
  33. package/src/customizations/volto/components/manage/Workflow/Workflow.jsx +324 -0
  34. package/src/customizations/volto/components/manage/Workflow/Workflow.test.jsx +81 -0
  35. package/src/customizations/volto/components/theme/Comments/Comments.jsx +1 -2
  36. package/src/customizations/volto/components/theme/ContactForm/ContactForm.jsx +1 -1
  37. package/src/customizations/volto/components/theme/EventDetails/EventDetails.jsx +1 -0
  38. package/src/index.js +21 -16
  39. package/src/middleware/ok.js +4 -2
  40. package/src/middleware/voltoCustom.js +4 -2
  41. package/src/slate.js +10 -8
  42. package/src/customizations/@plone/volto-slate/editor/plugins/StyleMenu/README.txt +0 -1
  43. package/src/customizations/@plone/volto-slate/editor/plugins/StyleMenu/StyleMenu.jsx +0 -157
  44. package/src/customizations/@plone/volto-slate/editor/plugins/StyleMenu/utils.js +0 -168
  45. package/src/customizations/volto/components/manage/Add/Add.jsx +0 -498
  46. package/src/customizations/volto/components/manage/Add/readme.md +0 -1
  47. package/src/customizations/volto/components/manage/Contents/ContentsPropertiesModal.jsx +0 -232
  48. package/src/customizations/volto/components/manage/Form/Form.jsx +0 -810
  49. package/src/customizations/volto/components/manage/Form/Form.test.jsx +0 -1124
  50. package/src/customizations/volto/components/manage/Form/ModalForm.jsx +0 -326
  51. package/src/customizations/volto/components/manage/Sharing/Sharing.jsx +0 -528
  52. package/src/customizations/volto/components/manage/Sharing/Sharing.test.jsx +0 -72
  53. package/src/customizations/volto/components/manage/Widgets/ObjectBrowserWidget.test.jsx +0 -193
  54. package/src/customizations/volto/components/theme/AppExtras/AppExtras.jsx +0 -27
@@ -1,498 +0,0 @@
1
- /**
2
- * Add container.
3
- * @module components/manage/Add/Add
4
- */
5
-
6
- import React, { Component } from 'react';
7
- import PropTypes from 'prop-types';
8
- import { BodyClass, Helmet } from '@plone/volto/helpers';
9
- import { connect } from 'react-redux';
10
- import { compose } from 'redux';
11
- import { keys, isEmpty } from 'lodash';
12
- import { defineMessages, injectIntl } from 'react-intl';
13
- import { Button, Grid, Menu } from 'semantic-ui-react';
14
- import { Portal } from 'react-portal';
15
- import { v4 as uuid } from 'uuid';
16
- import qs from 'query-string';
17
- import { toast } from 'react-toastify';
18
-
19
- import { createContent, getSchema, changeLanguage } from '@plone/volto/actions';
20
- import {
21
- Form,
22
- Icon,
23
- Toolbar,
24
- Sidebar,
25
- Toast,
26
- TranslationObject,
27
- } from '@plone/volto/components';
28
- import {
29
- getBaseUrl,
30
- hasBlocksData,
31
- flattenToAppURL,
32
- getBlocksFieldname,
33
- getBlocksLayoutFieldname,
34
- getLanguageIndependentFields,
35
- langmap,
36
- toGettextLang,
37
- } from '@plone/volto/helpers';
38
-
39
- import { preloadLazyLibs } from '@plone/volto/helpers/Loadable';
40
- import { tryParseJSON } from '@plone/volto/helpers';
41
-
42
- import config from '@plone/volto/registry';
43
-
44
- import saveSVG from '@plone/volto/icons/save.svg';
45
- import clearSVG from '@plone/volto/icons/clear.svg';
46
-
47
- const messages = defineMessages({
48
- add: {
49
- id: 'Add {type}',
50
- defaultMessage: 'Add {type}',
51
- },
52
- save: {
53
- id: 'Save',
54
- defaultMessage: 'Save',
55
- },
56
- cancel: {
57
- id: 'Cancel',
58
- defaultMessage: 'Cancel',
59
- },
60
- error: {
61
- id: 'Error',
62
- defaultMessage: 'Error',
63
- },
64
- translateTo: {
65
- id: 'Translate to {lang}',
66
- defaultMessage: 'Translate to {lang}',
67
- },
68
- someErrors: {
69
- id: 'There are some errors.',
70
- defaultMessage: 'There are some errors.',
71
- },
72
- });
73
-
74
- /**
75
- * Add class.
76
- * @class Add
77
- * @extends Component
78
- */
79
- class Add extends Component {
80
- /**
81
- * Property types.
82
- * @property {Object} propTypes Property types.
83
- * @static
84
- */
85
- static propTypes = {
86
- createContent: PropTypes.func.isRequired,
87
- getSchema: PropTypes.func.isRequired,
88
- pathname: PropTypes.string.isRequired,
89
- schema: PropTypes.objectOf(PropTypes.any),
90
- content: PropTypes.shape({
91
- // eslint-disable-line react/no-unused-prop-types
92
- '@id': PropTypes.string,
93
- '@type': PropTypes.string,
94
- }),
95
- returnUrl: PropTypes.string,
96
- createRequest: PropTypes.shape({
97
- loading: PropTypes.bool,
98
- loaded: PropTypes.bool,
99
- }).isRequired,
100
- schemaRequest: PropTypes.shape({
101
- loading: PropTypes.bool,
102
- loaded: PropTypes.bool,
103
- }).isRequired,
104
- type: PropTypes.string,
105
- location: PropTypes.objectOf(PropTypes.any),
106
- };
107
-
108
- /**
109
- * Default properties
110
- * @property {Object} defaultProps Default properties.
111
- * @static
112
- */
113
- static defaultProps = {
114
- schema: null,
115
- content: null,
116
- returnUrl: null,
117
- type: 'Default',
118
- };
119
-
120
- /**
121
- * Constructor
122
- * @method constructor
123
- * @param {Object} props Component properties
124
- * @constructs WysiwygEditor
125
- */
126
- constructor(props) {
127
- super(props);
128
- this.onCancel = this.onCancel.bind(this);
129
- this.onSubmit = this.onSubmit.bind(this);
130
-
131
- if (config.blocks?.initialBlocks[props.type]) {
132
- this.initialBlocksLayout = config.blocks.initialBlocks[
133
- props.type
134
- ].map((item) => uuid());
135
- this.initialBlocks = this.initialBlocksLayout.reduce(
136
- (acc, value, index) => ({
137
- ...acc,
138
- [value]: { '@type': config.blocks.initialBlocks[props.type][index] },
139
- }),
140
- {},
141
- );
142
- }
143
- this.state = {
144
- isClient: false,
145
- error: null,
146
- formSelected: 'addForm',
147
- };
148
- }
149
-
150
- /**
151
- * Component did mount
152
- * @method componentDidMount
153
- * @returns {undefined}
154
- */
155
- componentDidMount() {
156
- this.props.getSchema(this.props.type, getBaseUrl(this.props.pathname));
157
- this.setState({ isClient: true });
158
- }
159
-
160
- /**
161
- * Component will receive props
162
- * @method componentWillReceiveProps
163
- * @param {Object} nextProps Next properties
164
- * @returns {undefined}
165
- */
166
- UNSAFE_componentWillReceiveProps(nextProps) {
167
- if (
168
- this.props.createRequest.loading &&
169
- nextProps.createRequest.loaded &&
170
- nextProps.content['@type'] === this.props.type
171
- ) {
172
- this.props.history.push(
173
- this.props.returnUrl || flattenToAppURL(nextProps.content['@id']),
174
- );
175
- }
176
-
177
- if (this.props.createRequest.loading && nextProps.createRequest.error) {
178
- const message =
179
- nextProps.createRequest.error.response?.body?.message ||
180
- nextProps.createRequest.error.response?.text;
181
-
182
- const error =
183
- new DOMParser().parseFromString(message, 'text/html')?.all[0]
184
- ?.textContent || message;
185
-
186
- const errorsList = tryParseJSON(error);
187
- let erroMessage;
188
- if (Array.isArray(errorsList)) {
189
- const invariantErrors = errorsList
190
- .filter((errorItem) => !('field' in errorItem))
191
- .map((errorItem) => errorItem['message']);
192
- if (invariantErrors.length > 0) {
193
- // Plone invariant validation message.
194
- erroMessage = invariantErrors.join(' - ');
195
- } else {
196
- // Error in specific field.
197
- erroMessage = this.props.intl.formatMessage(messages.someErrors);
198
- }
199
- } else {
200
- erroMessage = errorsList.error?.message || error;
201
- }
202
-
203
- this.setState({ error: error });
204
-
205
- if (
206
- document?.querySelector('.sidebar-container .tabs-wrapper a')?.click
207
- ) {
208
- document.querySelector('.sidebar-container .tabs-wrapper a').click();
209
- }
210
- toast.error(
211
- <Toast
212
- error
213
- title={this.props.intl.formatMessage(messages.error)}
214
- content={erroMessage}
215
- />,
216
- );
217
- }
218
- }
219
-
220
- /**
221
- * Submit handler
222
- * @method onSubmit
223
- * @param {object} data Form data.
224
- * @returns {undefined}
225
- */
226
- onSubmit(data) {
227
- this.props.createContent(getBaseUrl(this.props.pathname), {
228
- ...data,
229
- '@static_behaviors': this.props.schema.definitions
230
- ? keys(this.props.schema.definitions)
231
- : null,
232
- '@type': this.props.type,
233
- ...(config.settings.isMultilingual &&
234
- this.props.location?.state?.translationOf && {
235
- translation_of: this.props.location.state.translationOf,
236
- language: this.props.location.state.language,
237
- }),
238
- });
239
- }
240
-
241
- /**
242
- * Cancel handler
243
- * @method onCancel
244
- * @returns {undefined}
245
- */
246
- onCancel() {
247
- if (this.props.location?.state?.translationOf) {
248
- const language = this.props.location.state.languageFrom;
249
- const langFileName = toGettextLang(language);
250
- import('@root/../locales/' + langFileName + '.json').then((locale) => {
251
- this.props.changeLanguage(language, locale.default);
252
- });
253
- this.props.history.push(this.props.location?.state?.translationOf);
254
- } else {
255
- this.props.history.push(getBaseUrl(this.props.pathname));
256
- }
257
- }
258
-
259
- form = React.createRef();
260
-
261
- /**
262
- * Render method.
263
- * @method render
264
- * @returns {string} Markup for the component.
265
- */
266
- render() {
267
- if (this.props.schemaRequest.loaded) {
268
- const visual = hasBlocksData(this.props.schema.properties);
269
- const blocksFieldname = getBlocksFieldname(this.props.schema.properties);
270
- const blocksLayoutFieldname = getBlocksLayoutFieldname(
271
- this.props.schema.properties,
272
- );
273
- const translationObject = this.props.location?.state?.translationObject;
274
-
275
- const translateTo = translationObject
276
- ? langmap?.[this.props.location?.state?.language]?.nativeName
277
- : null;
278
-
279
- // Lookup initialBlocks and initialBlocksLayout within schema
280
- const schemaBlocks = this.props.schema.properties[blocksFieldname]
281
- ?.default;
282
- const schemaBlocksLayout = this.props.schema.properties[
283
- blocksLayoutFieldname
284
- ]?.default?.items;
285
- let initialBlocks = this.initialBlocks;
286
- let initialBlocksLayout = this.initialBlocksLayout;
287
-
288
- if (!isEmpty(schemaBlocksLayout) && !isEmpty(schemaBlocks)) {
289
- initialBlocks = {};
290
- initialBlocksLayout = [];
291
- schemaBlocksLayout.forEach((value) => {
292
- if (!isEmpty(schemaBlocks[value])) {
293
- let newUid = uuid();
294
- initialBlocksLayout.push(newUid);
295
- initialBlocks[newUid] = schemaBlocks[value];
296
- initialBlocks[newUid].block = newUid;
297
-
298
- // Layout ID - keep a reference to the original block id within layout
299
- initialBlocks[newUid]['@layout'] = value;
300
- }
301
- });
302
- }
303
- //copy blocks from translationObject
304
- if (translationObject && blocksFieldname && blocksLayoutFieldname) {
305
- initialBlocks = {};
306
- initialBlocksLayout = [];
307
- const originalBlocks = JSON.parse(
308
- JSON.stringify(translationObject[blocksFieldname]),
309
- );
310
- const originalBlocksLayout =
311
- translationObject[blocksLayoutFieldname].items;
312
-
313
- originalBlocksLayout.forEach((value) => {
314
- if (!isEmpty(originalBlocks[value])) {
315
- let newUid = uuid();
316
- initialBlocksLayout.push(newUid);
317
- initialBlocks[newUid] = originalBlocks[value];
318
- initialBlocks[newUid].block = newUid;
319
-
320
- // Layout ID - keep a reference to the original block id within layout
321
- initialBlocks[newUid]['@canonical'] = value;
322
- }
323
- });
324
- }
325
-
326
- const lifData = () => {
327
- const data = {};
328
- if (translationObject) {
329
- getLanguageIndependentFields(this.props.schema).forEach(
330
- (lif) => (data[lif] = translationObject[lif]),
331
- );
332
- }
333
- return data;
334
- };
335
-
336
- const pageAdd = (
337
- <div id="page-add">
338
- <Helmet
339
- title={this.props.intl.formatMessage(messages.add, {
340
- type: this.props.type,
341
- })}
342
- />
343
- <Form
344
- ref={this.form}
345
- key="translated-or-new-content-form"
346
- navRoot={
347
- this.props.content?.['@components']?.navroot?.navroot || {}
348
- }
349
- schema={this.props.schema}
350
- type={this.props.type}
351
- formData={{
352
- ...(blocksFieldname && {
353
- [blocksFieldname]:
354
- initialBlocks ||
355
- this.props.schema.properties[blocksFieldname]?.default,
356
- }),
357
- ...(blocksLayoutFieldname && {
358
- [blocksLayoutFieldname]: {
359
- items:
360
- initialBlocksLayout ||
361
- this.props.schema.properties[blocksLayoutFieldname]?.default
362
- ?.items,
363
- },
364
- }),
365
- // Copy the Language Independent Fields values from the to-be translated content
366
- // into the default values of the translated content Add form.
367
- ...lifData(),
368
- parent: {
369
- '@id': this.props.content?.['@id'] || '',
370
- },
371
- }}
372
- requestError={this.state.error}
373
- onSubmit={this.onSubmit}
374
- hideActions
375
- pathname={this.props.pathname}
376
- visual={visual}
377
- title={
378
- this.props?.schema?.title
379
- ? this.props.intl.formatMessage(messages.add, {
380
- type: this.props.schema.title,
381
- })
382
- : null
383
- }
384
- loading={this.props.createRequest.loading}
385
- isFormSelected={this.state.formSelected === 'addForm'}
386
- onSelectForm={() => {
387
- this.setState({ formSelected: 'addForm' });
388
- }}
389
- global
390
- />
391
- {this.state.isClient && (
392
- <Portal node={document.getElementById('toolbar')}>
393
- <Toolbar
394
- pathname={this.props.pathname}
395
- hideDefaultViewButtons
396
- inner={
397
- <>
398
- <Button
399
- id="toolbar-save"
400
- className="save"
401
- aria-label={this.props.intl.formatMessage(messages.save)}
402
- onClick={() => this.form.current.onSubmit()}
403
- loading={this.props.createRequest.loading}
404
- >
405
- <Icon
406
- name={saveSVG}
407
- className="circled"
408
- size="30px"
409
- title={this.props.intl.formatMessage(messages.save)}
410
- />
411
- </Button>
412
- <Button className="cancel" onClick={() => this.onCancel()}>
413
- <Icon
414
- name={clearSVG}
415
- className="circled"
416
- aria-label={this.props.intl.formatMessage(
417
- messages.cancel,
418
- )}
419
- size="30px"
420
- title={this.props.intl.formatMessage(messages.cancel)}
421
- />
422
- </Button>
423
- </>
424
- }
425
- />
426
- </Portal>
427
- )}
428
- {visual && this.state.isClient && (
429
- <Portal node={document.getElementById('sidebar')}>
430
- <Sidebar />
431
- </Portal>
432
- )}
433
- </div>
434
- );
435
-
436
- return translationObject ? (
437
- <>
438
- <BodyClass className="babel-view" />
439
- <Grid
440
- celled="internally"
441
- stackable
442
- columns={2}
443
- id="page-add-translation"
444
- >
445
- <Grid.Column className="source-object">
446
- <TranslationObject
447
- translationObject={translationObject}
448
- schema={this.props.schema}
449
- pathname={this.props.pathname}
450
- visual={visual}
451
- isFormSelected={
452
- this.state.formSelected === 'translationObjectForm'
453
- }
454
- onSelectForm={() => {
455
- this.setState({
456
- formSelected: 'translationObjectForm',
457
- });
458
- }}
459
- />
460
- </Grid.Column>
461
- <Grid.Column>
462
- <div className="new-translation">
463
- <Menu pointing secondary attached tabular>
464
- <Menu.Item name={translateTo.toUpperCase()} active={true}>
465
- {`${this.props.intl.formatMessage(messages.translateTo, {
466
- lang: translateTo,
467
- })}`}
468
- </Menu.Item>
469
- </Menu>
470
- {pageAdd}
471
- </div>
472
- </Grid.Column>
473
- </Grid>
474
- </>
475
- ) : (
476
- pageAdd
477
- );
478
- }
479
- return <div />;
480
- }
481
- }
482
-
483
- export default compose(
484
- injectIntl,
485
- connect(
486
- (state, props) => ({
487
- createRequest: state.content.create,
488
- schemaRequest: state.schema,
489
- content: state.content.data,
490
- schema: state.schema.schema,
491
- pathname: props.location.pathname,
492
- returnUrl: qs.parse(props.location.search).return_url,
493
- type: qs.parse(props.location.search).type,
494
- }),
495
- { createContent, getSchema, changeLanguage },
496
- ),
497
- preloadLazyLibs('cms'),
498
- )(Add);
@@ -1 +0,0 @@
1
- This customization aims to resolve the issue of adding a page with an empty title. It is a temporary solution and should be removed upon upgrading to Volto 17. Please check this for more information: https://github.com/plone/volto/pull/5842