@plone/volto 15.0.0-alpha.1 → 15.0.0-alpha.5

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 (68) hide show
  1. package/.github/workflows/{core-sandbox.yml → coresandbox.yml} +1 -1
  2. package/.storybook/main.js +3 -9
  3. package/CHANGELOG.md +55 -0
  4. package/README.md +1 -0
  5. package/addon-registry.js +16 -11
  6. package/docker-compose.yml +15 -10
  7. package/locales/volto.pot +1 -1
  8. package/package.json +9 -9
  9. package/pyvenv.cfg +3 -0
  10. package/razzle.config.js +13 -13
  11. package/src/actions/language/language.js +7 -2
  12. package/src/components/manage/AnchorPlugin/components/LinkButton/AddLinkForm.jsx +1 -2
  13. package/src/components/manage/AnchorPlugin/components/LinkButton/index.jsx +15 -6
  14. package/src/components/manage/AnchorPlugin/index.jsx +12 -5
  15. package/src/components/manage/AnchorPlugin/utils/EditorUtils.js +8 -7
  16. package/src/components/manage/Blocks/Description/Edit.jsx +33 -19
  17. package/src/components/manage/Blocks/Description/Edit.test.jsx +6 -0
  18. package/src/components/manage/Blocks/HeroImageLeft/Edit.jsx +37 -26
  19. package/src/components/manage/Blocks/HeroImageLeft/Edit.test.jsx +6 -0
  20. package/src/components/manage/Blocks/Listing/View.jsx +1 -1
  21. package/src/components/manage/Blocks/Table/Cell.jsx +40 -14
  22. package/src/components/manage/Blocks/Table/Cell.test.jsx +7 -1
  23. package/src/components/manage/Blocks/Table/Edit.jsx +7 -3
  24. package/src/components/manage/Blocks/Table/Edit.test.jsx +6 -0
  25. package/src/components/manage/Blocks/Table/View.jsx +2 -2
  26. package/src/components/manage/Blocks/Text/Edit.jsx +56 -14
  27. package/src/components/manage/Blocks/Text/Edit.test.jsx +7 -1
  28. package/src/components/manage/Blocks/Text/View.jsx +2 -2
  29. package/src/components/manage/Blocks/Title/Edit.jsx +25 -13
  30. package/src/components/manage/Blocks/Title/Edit.test.jsx +6 -0
  31. package/src/components/manage/Contents/ContentsUploadModal.jsx +3 -1
  32. package/src/components/manage/Sidebar/Sidebar.jsx +5 -1
  33. package/src/components/manage/Toolbar/Toolbar.jsx +3 -1
  34. package/src/components/manage/UniversalLink/UniversalLink.jsx +5 -2
  35. package/src/components/manage/Widgets/UrlWidget.jsx +1 -1
  36. package/src/components/manage/Widgets/WysiwygWidget.jsx +45 -19
  37. package/src/components/manage/Widgets/WysiwygWidget.test.jsx +7 -1
  38. package/src/components/theme/ContactForm/ContactForm.jsx +1 -1
  39. package/src/components/theme/LanguageSelector/LanguageSelector.js +2 -18
  40. package/src/components/theme/Login/Login.jsx +3 -1
  41. package/src/components/theme/MultilingualRedirector/MultilingualRedirector.jsx +17 -2
  42. package/src/components/theme/View/LinkView.jsx +3 -3
  43. package/src/config/Loadables.jsx +22 -0
  44. package/src/config/RichTextEditor/Blocks.jsx +25 -20
  45. package/src/config/RichTextEditor/Plugins.jsx +38 -31
  46. package/src/config/RichTextEditor/Styles.jsx +48 -44
  47. package/src/config/RichTextEditor/index.js +25 -0
  48. package/src/config/index.js +14 -18
  49. package/src/helpers/Url/Url.js +32 -1
  50. package/src/helpers/Url/urlRegex.js +7 -1
  51. package/src/helpers/index.js +1 -0
  52. package/src/middleware/api.js +1 -1
  53. package/test-setup-config.js +22 -7
  54. package/{webpack-bundle-analyze-plugin.js → webpack-plugins/webpack-bundle-analyze-plugin.js} +0 -0
  55. package/{webpack-less-plugin.js → webpack-plugins/webpack-less-plugin.js} +0 -0
  56. package/{webpack-relative-resolver.js → webpack-plugins/webpack-relative-resolver.js} +0 -0
  57. package/{webpack-root-resolver.js → webpack-plugins/webpack-root-resolver.js} +0 -0
  58. package/{webpack-sentry-plugin.js → webpack-plugins/webpack-sentry-plugin.js} +0 -0
  59. package/{webpack-svg-plugin.js → webpack-plugins/webpack-svg-plugin.js} +0 -0
  60. package/.surgeignore +0 -2
  61. package/Dockerfile.slim +0 -27
  62. package/patches/fixprettier.patch +0 -11
  63. package/patches/fixstylelint.patch +0 -11
  64. package/src/components/manage/AnchorPlugin/utils/URLUtils.js +0 -36
  65. package/src/components/manage/AnchorPlugin/utils/mailRegex.js +0 -2
  66. package/src/components/manage/AnchorPlugin/utils/telRegex.js +0 -1
  67. package/src/components/manage/AnchorPlugin/utils/urlRegex.js +0 -54
  68. package/styleguide.config.js +0 -42
@@ -7,15 +7,13 @@ import React, { Component } from 'react';
7
7
  import PropTypes from 'prop-types';
8
8
  import { connect } from 'react-redux';
9
9
  import { compose } from 'redux';
10
- import { Map } from 'immutable';
11
10
  import { readAsDataURL } from 'promise-file-reader';
12
11
  import { Button, Dimmer, Loader, Message } from 'semantic-ui-react';
13
- import { stateFromHTML } from 'draft-js-import-html';
14
- import { Editor, DefaultDraftBlockRenderMap, EditorState } from 'draft-js';
15
12
  import { isEqual } from 'lodash';
16
13
  import { defineMessages, injectIntl } from 'react-intl';
17
14
  import cx from 'classnames';
18
15
 
16
+ import { injectLazyLibs } from '@plone/volto/helpers/Loadable/Loadable';
19
17
  import { flattenToAppURL, getBaseUrl } from '@plone/volto/helpers';
20
18
  import { createContent } from '@plone/volto/actions';
21
19
  import { Icon, SidebarPortal, LinkMore } from '@plone/volto/components';
@@ -51,32 +49,12 @@ const messages = defineMessages({
51
49
  },
52
50
  });
53
51
 
54
- const blockTitleRenderMap = Map({
55
- unstyled: {
56
- element: 'h1',
57
- },
58
- });
59
-
60
- const blockDescriptionRenderMap = Map({
61
- unstyled: {
62
- element: 'div',
63
- },
64
- });
65
-
66
- const extendedBlockRenderMap = DefaultDraftBlockRenderMap.merge(
67
- blockTitleRenderMap,
68
- );
69
-
70
- const extendedDescripBlockRenderMap = DefaultDraftBlockRenderMap.merge(
71
- blockDescriptionRenderMap,
72
- );
73
-
74
52
  /**
75
53
  * Edit image block class.
76
54
  * @class Edit
77
55
  * @extends Component
78
56
  */
79
- class Edit extends Component {
57
+ class EditComponent extends Component {
80
58
  /**
81
59
  * Property types.
82
60
  * @property {Object} propTypes Property types.
@@ -126,7 +104,32 @@ class Edit extends Component {
126
104
  uploading: false,
127
105
  };
128
106
 
107
+ const { Map } = this.props.immutableLib;
108
+
129
109
  if (!__SERVER__) {
110
+ const { DefaultDraftBlockRenderMap, EditorState } = props.draftJs;
111
+ const { stateFromHTML } = props.draftJsImportHtml;
112
+
113
+ const blockTitleRenderMap = Map({
114
+ unstyled: {
115
+ element: 'h1',
116
+ },
117
+ });
118
+
119
+ const blockDescriptionRenderMap = Map({
120
+ unstyled: {
121
+ element: 'div',
122
+ },
123
+ });
124
+
125
+ this.extendedBlockRenderMap = DefaultDraftBlockRenderMap.merge(
126
+ blockTitleRenderMap,
127
+ );
128
+
129
+ this.extendedDescripBlockRenderMap = DefaultDraftBlockRenderMap.merge(
130
+ blockDescriptionRenderMap,
131
+ );
132
+
130
133
  let titleEditorState;
131
134
  let descriptionEditorState;
132
135
  if (props.data && props.data.title) {
@@ -187,6 +190,9 @@ class Edit extends Component {
187
190
  });
188
191
  }
189
192
 
193
+ const { EditorState } = this.props.draftJs;
194
+ const { stateFromHTML } = this.props.draftJsImportHtml;
195
+
190
196
  if (
191
197
  nextProps.data.title &&
192
198
  this.props.data.title !== nextProps.data.title &&
@@ -299,6 +305,7 @@ class Edit extends Component {
299
305
  if (__SERVER__) {
300
306
  return <div />;
301
307
  }
308
+ const { Editor } = this.props.draftJs;
302
309
  const placeholder =
303
310
  this.props.data.placeholder ||
304
311
  this.props.intl.formatMessage(messages.placeholder);
@@ -374,7 +381,7 @@ class Edit extends Component {
374
381
  readOnly={!this.props.editable}
375
382
  onChange={this.onChangeTitle}
376
383
  editorState={this.state.titleEditorState}
377
- blockRenderMap={extendedBlockRenderMap}
384
+ blockRenderMap={this.extendedBlockRenderMap}
378
385
  handleReturn={() => true}
379
386
  placeholder={this.props.intl.formatMessage(messages.title)}
380
387
  blockStyleFn={() => 'title-editor'}
@@ -416,7 +423,7 @@ class Edit extends Component {
416
423
  readOnly={!this.props.editable}
417
424
  onChange={this.onChangeDescription}
418
425
  editorState={this.state.descriptionEditorState}
419
- blockRenderMap={extendedDescripBlockRenderMap}
426
+ blockRenderMap={this.extendedDescripBlockRenderMap}
420
427
  handleReturn={() => true}
421
428
  placeholder={this.props.intl.formatMessage(
422
429
  messages.description,
@@ -460,6 +467,10 @@ class Edit extends Component {
460
467
  }
461
468
  }
462
469
 
470
+ const Edit = injectLazyLibs(['draftJs', 'immutableLib', 'draftJsImportHtml'])(
471
+ EditComponent,
472
+ );
473
+
463
474
  export default compose(
464
475
  injectIntl,
465
476
  connect(
@@ -5,6 +5,12 @@ import { Provider } from 'react-intl-redux';
5
5
 
6
6
  import Edit from './Edit';
7
7
 
8
+ jest.mock('@plone/volto/helpers/Loadable/Loadable');
9
+ beforeAll(
10
+ async () =>
11
+ await require('@plone/volto/helpers/Loadable/Loadable').__setLoadables(),
12
+ );
13
+
8
14
  global.__SERVER__ = true; // eslint-disable-line no-underscore-dangle
9
15
 
10
16
  const mockStore = configureStore();
@@ -9,7 +9,7 @@ const View = (props) => {
9
9
  const { data, path, pathname } = props;
10
10
 
11
11
  return (
12
- <div className={cx('block listing', data.variation)}>
12
+ <div className={cx('block listing', data.variation || 'default')}>
13
13
  <ListingBody {...props} path={path ?? pathname} />
14
14
  </div>
15
15
  );
@@ -5,19 +5,20 @@
5
5
 
6
6
  import React, { Component } from 'react';
7
7
  import PropTypes from 'prop-types';
8
- import Editor from 'draft-js-plugins-editor';
9
- import { convertFromRaw, EditorState, RichUtils } from 'draft-js';
10
- import createInlineToolbarPlugin from 'draft-js-inline-toolbar-plugin';
11
- import isSoftNewlineEvent from 'draft-js/lib/isSoftNewlineEvent';
12
8
  import { includes } from 'lodash';
13
9
  import config from '@plone/volto/registry';
14
10
 
11
+ import { injectLazyLibs } from '@plone/volto/helpers/Loadable/Loadable';
12
+ import loadable from '@loadable/component';
13
+
14
+ const Editor = loadable(() => import('draft-js-plugins-editor'));
15
+
15
16
  /**
16
17
  * Edit text cell class.
17
18
  * @class Cell
18
19
  * @extends Component
19
20
  */
20
- class Cell extends Component {
21
+ class CellComponent extends Component {
21
22
  /**
22
23
  * Property types.
23
24
  * @property {Object} propTypes Property types.
@@ -54,12 +55,16 @@ class Cell extends Component {
54
55
  constructor(props) {
55
56
  super(props);
56
57
 
58
+ const { EditorState, convertFromRaw } = props.draftJs;
59
+ const createInlineToolbarPlugin = props.draftJsInlineToolbarPlugin.default;
60
+
57
61
  if (!__SERVER__) {
62
+ this.draftConfig = config.settings.richtextEditorSettings(props);
58
63
  let editorState;
59
64
  editorState = EditorState.createWithContent(convertFromRaw(props.value));
60
65
 
61
66
  const inlineToolbarPlugin = createInlineToolbarPlugin({
62
- structure: config.settings.richTextEditorInlineToolbarButtons,
67
+ structure: this.draftConfig.richTextEditorInlineToolbarButtons,
63
68
  });
64
69
 
65
70
  this.state = {
@@ -125,7 +130,8 @@ class Cell extends Component {
125
130
  }
126
131
 
127
132
  const { InlineToolbar } = this.state.inlineToolbarPlugin;
128
- const { settings } = config;
133
+ const isSoftNewlineEvent = this.props.draftJsLibIsSoftNewlineEvent.default;
134
+ const { RichUtils } = this.props.draftJs;
129
135
 
130
136
  return (
131
137
  <div>
@@ -135,11 +141,11 @@ class Cell extends Component {
135
141
  editorState={this.state.editorState}
136
142
  plugins={[
137
143
  this.state.inlineToolbarPlugin,
138
- ...settings.richTextEditorPlugins,
144
+ ...this.draftConfig.richTextEditorPlugins,
139
145
  ]}
140
- blockRenderMap={settings.extendedBlockRenderMap}
141
- blockStyleFn={settings.blockStyleFn}
142
- customStyleMap={settings.customStyleMap}
146
+ blockRenderMap={this.draftConfig.extendedBlockRenderMap}
147
+ blockStyleFn={this.draftConfig.blockStyleFn}
148
+ customStyleMap={this.draftConfig.customStyleMap}
143
149
  handleReturn={(e) => {
144
150
  if (isSoftNewlineEvent(e)) {
145
151
  this.onChange(
@@ -155,10 +161,10 @@ class Cell extends Component {
155
161
  anchorKey,
156
162
  );
157
163
  const blockType = currentContentBlock.getType();
158
- if (!includes(settings.listBlockTypes, blockType)) {
164
+ if (!includes(this.draftConfig.listBlockTypes, blockType)) {
159
165
  this.props.onSelectBlock(
160
166
  this.props.onAddBlock(
161
- settings.defaultBlockType,
167
+ this.draftConfig.defaultBlockType,
162
168
  this.props.index + 1,
163
169
  ),
164
170
  );
@@ -178,4 +184,24 @@ class Cell extends Component {
178
184
  }
179
185
  }
180
186
 
181
- export default Cell;
187
+ export const Cell = injectLazyLibs([
188
+ 'draftJs',
189
+ 'draftJsBlockBreakoutPlugin',
190
+ 'draftJsCreateBlockStyleButton',
191
+ 'draftJsCreateInlineStyleButton',
192
+ 'draftJsFilters',
193
+ 'draftJsImportHtml',
194
+ 'draftJsInlineToolbarPlugin',
195
+ 'draftJsLibIsSoftNewlineEvent',
196
+ 'immutableLib',
197
+ ])(CellComponent);
198
+
199
+ const Preloader = (props) => {
200
+ const [loaded, setLoaded] = React.useState(false);
201
+ React.useEffect(() => {
202
+ Editor.load().then(() => setLoaded(true));
203
+ }, []);
204
+ return loaded ? <Cell {...props} /> : null;
205
+ };
206
+
207
+ export default Preloader;
@@ -1,9 +1,15 @@
1
1
  import React from 'react';
2
2
  import renderer from 'react-test-renderer';
3
- import Cell from './Cell';
3
+ import { Cell } from './Cell';
4
4
 
5
5
  global.__SERVER__ = true; // eslint-disable-line no-underscore-dangle
6
6
 
7
+ jest.mock('@plone/volto/helpers/Loadable/Loadable');
8
+ beforeAll(
9
+ async () =>
10
+ await require('@plone/volto/helpers/Loadable/Loadable').__setLoadables(),
11
+ );
12
+
7
13
  test('renders a cell component', () => {
8
14
  const component = renderer.create(
9
15
  <Cell onChange={() => {}} onSelectCell={() => {}} />,
@@ -5,15 +5,16 @@
5
5
 
6
6
  import React, { Component } from 'react';
7
7
  import PropTypes from 'prop-types';
8
+ import { compose } from 'redux';
8
9
  import { map, remove } from 'lodash';
9
10
  import { Button, Segment, Table, Form } from 'semantic-ui-react';
10
- import { convertToRaw } from 'draft-js';
11
11
  import { Portal } from 'react-portal';
12
12
  import cx from 'classnames';
13
13
  import { FormattedMessage, defineMessages, injectIntl } from 'react-intl';
14
14
 
15
15
  import Cell from '@plone/volto/components/manage/Blocks/Table/Cell';
16
16
  import { Field, Icon } from '@plone/volto/components';
17
+ import { injectLazyLibs } from '@plone/volto/helpers/Loadable/Loadable';
17
18
 
18
19
  import rowBeforeSVG from '@plone/volto/icons/row-before.svg';
19
20
  import rowAfterSVG from '@plone/volto/icons/row-after.svg';
@@ -208,6 +209,9 @@ class Edit extends Component {
208
209
  this.toggleBasic = this.toggleBasic.bind(this);
209
210
  this.toggleCelled = this.toggleCelled.bind(this);
210
211
  this.toggleStriped = this.toggleStriped.bind(this);
212
+
213
+ const { convertToRaw } = props.draftJs;
214
+ this.convertToRaw = convertToRaw;
211
215
  }
212
216
 
213
217
  /**
@@ -261,7 +265,7 @@ class Edit extends Component {
261
265
  */
262
266
  onChangeCell(row, cell, editorState) {
263
267
  const table = { ...this.props.data.table };
264
- table.rows[row].cells[cell].value = convertToRaw(
268
+ table.rows[row].cells[cell].value = this.convertToRaw(
265
269
  editorState.getCurrentContent(),
266
270
  );
267
271
  this.props.onChangeBlock(this.props.block, {
@@ -740,4 +744,4 @@ class Edit extends Component {
740
744
  }
741
745
  }
742
746
 
743
- export default injectIntl(Edit);
747
+ export default compose(injectLazyLibs(['draftJs']), injectIntl)(Edit);
@@ -5,6 +5,12 @@ import { Provider } from 'react-intl-redux';
5
5
 
6
6
  import Edit from './Edit';
7
7
 
8
+ jest.mock('@plone/volto/helpers/Loadable/Loadable');
9
+ beforeAll(
10
+ async () =>
11
+ await require('@plone/volto/helpers/Loadable/Loadable').__setLoadables(),
12
+ );
13
+
8
14
  const mockStore = configureStore();
9
15
 
10
16
  test('renders an edit table block component', () => {
@@ -37,8 +37,8 @@ const View = ({ data }) =>
37
37
  {cell.value && cell.value.blocks && cell.value.blocks[0].text
38
38
  ? redraft(
39
39
  cell.value,
40
- config.settings.ToHTMLRenderers,
41
- config.settings.ToHTMLOptions,
40
+ config.settings.richtextViewSettings.ToHTMLRenderers,
41
+ config.settings.richtextViewSettings.ToHTMLOptions,
42
42
  )
43
43
  : '\u00A0'}
44
44
  </Table.Cell>
@@ -5,18 +5,19 @@
5
5
 
6
6
  import React, { Component } from 'react';
7
7
  import PropTypes from 'prop-types';
8
- import Editor from 'draft-js-plugins-editor';
9
- import { convertFromRaw, convertToRaw, EditorState, RichUtils } from 'draft-js';
10
- import createInlineToolbarPlugin from 'draft-js-inline-toolbar-plugin';
8
+ import { compose } from 'redux';
11
9
 
12
- import isSoftNewlineEvent from 'draft-js/lib/isSoftNewlineEvent';
13
10
  import { defineMessages, injectIntl } from 'react-intl';
14
11
  import { includes, isEqual } from 'lodash';
15
- import { filterEditorState } from 'draftjs-filters';
16
12
  import config from '@plone/volto/registry';
17
13
 
14
+ import { injectLazyLibs } from '@plone/volto/helpers/Loadable/Loadable';
18
15
  import { BlockChooserButton } from '@plone/volto/components';
19
16
 
17
+ import loadable from '@loadable/component';
18
+
19
+ const Editor = loadable(() => import('draft-js-plugins-editor'));
20
+
20
21
  const messages = defineMessages({
21
22
  text: {
22
23
  id: 'Type text…',
@@ -29,7 +30,7 @@ const messages = defineMessages({
29
30
  * @class Edit
30
31
  * @extends Component
31
32
  */
32
- class Edit extends Component {
33
+ export class EditComponent extends Component {
33
34
  /**
34
35
  * Property types.
35
36
  * @property {Object} propTypes Property types.
@@ -77,6 +78,13 @@ class Edit extends Component {
77
78
  constructor(props) {
78
79
  super(props);
79
80
 
81
+ const { settings } = config;
82
+
83
+ this.draftConfig = settings.richtextEditorSettings(props);
84
+
85
+ const { EditorState, convertFromRaw } = props.draftJs;
86
+ const createInlineToolbarPlugin = props.draftJsInlineToolbarPlugin.default;
87
+
80
88
  if (!__SERVER__) {
81
89
  let editorState;
82
90
  if (props.data && props.data.text) {
@@ -88,7 +96,7 @@ class Edit extends Component {
88
96
  }
89
97
 
90
98
  const inlineToolbarPlugin = createInlineToolbarPlugin({
91
- structure: config.settings.richTextEditorInlineToolbarButtons,
99
+ structure: this.draftConfig.richTextEditorInlineToolbarButtons,
92
100
  });
93
101
 
94
102
  this.state = {
@@ -128,6 +136,7 @@ class Edit extends Component {
128
136
  //nothing is selected, move focus to end
129
137
  // See https://github.com/draft-js-plugins/draft-js-plugins/issues/800
130
138
  setTimeout(this.node.focus, 0);
139
+ const { EditorState } = this.props.draftJs;
131
140
 
132
141
  this.setState({
133
142
  editorState: EditorState.moveFocusToEnd(this.state.editorState),
@@ -137,6 +146,7 @@ class Edit extends Component {
137
146
  }
138
147
 
139
148
  componentDidUpdate(prevProps) {
149
+ const { convertToRaw, EditorState, convertFromRaw } = this.props.draftJs;
140
150
  if (
141
151
  !isEqual(this.props.data, prevProps.data) &&
142
152
  !isEqual(
@@ -179,6 +189,9 @@ class Edit extends Component {
179
189
  const shouldFilterPaste =
180
190
  editorState.getLastChangeType() === 'insert-fragment';
181
191
 
192
+ const { convertToRaw } = this.props.draftJs;
193
+ const { filterEditorState } = this.props.draftJsFilters;
194
+
182
195
  if (
183
196
  !isEqual(
184
197
  convertToRaw(editorState.getCurrentContent()),
@@ -217,6 +230,8 @@ class Edit extends Component {
217
230
  * @returns {string} Markup for the component.
218
231
  */
219
232
  render() {
233
+ // console.log('draft config', this.draftConfig);
234
+
220
235
  if (__SERVER__) {
221
236
  return <div />;
222
237
  }
@@ -229,7 +244,10 @@ class Edit extends Component {
229
244
  const disableNewBlocks =
230
245
  this.props.data?.disableNewBlocks || this.props.detached;
231
246
  const { InlineToolbar } = this.state.inlineToolbarPlugin;
232
- const { settings } = config;
247
+ // const { settings } = config;
248
+
249
+ const isSoftNewlineEvent = this.props.draftJsLibIsSoftNewlineEvent.default;
250
+ const { RichUtils } = this.props.draftJs;
233
251
 
234
252
  return (
235
253
  <>
@@ -239,11 +257,12 @@ class Edit extends Component {
239
257
  editorState={this.state.editorState}
240
258
  plugins={[
241
259
  this.state.inlineToolbarPlugin,
242
- ...settings.richTextEditorPlugins,
260
+ // ...settings.richTextEditorPlugins,
261
+ ...this.draftConfig.richTextEditorPlugins,
243
262
  ]}
244
- blockRenderMap={settings.extendedBlockRenderMap}
245
- blockStyleFn={settings.blockStyleFn}
246
- customStyleMap={settings.customStyleMap}
263
+ blockRenderMap={this.draftConfig.extendedBlockRenderMap}
264
+ blockStyleFn={this.draftConfig.blockStyleFn}
265
+ customStyleMap={this.draftConfig.customStyleMap}
247
266
  placeholder={placeholder}
248
267
  handleReturn={(e) => {
249
268
  if (isSoftNewlineEvent(e)) {
@@ -260,7 +279,7 @@ class Edit extends Component {
260
279
  anchorKey,
261
280
  );
262
281
  const blockType = currentContentBlock.getType();
263
- if (!includes(settings.listBlockTypes, blockType)) {
282
+ if (!includes(this.draftConfig.listBlockTypes, blockType)) {
264
283
  this.props.onSelectBlock(
265
284
  this.props.onAddBlock(
266
285
  config.settings.defaultBlockType,
@@ -329,4 +348,27 @@ class Edit extends Component {
329
348
  }
330
349
  }
331
350
 
332
- export default injectIntl(Edit);
351
+ export const Edit = compose(
352
+ injectIntl,
353
+ injectLazyLibs([
354
+ 'draftJs',
355
+ 'draftJsLibIsSoftNewlineEvent',
356
+ 'draftJsFilters',
357
+ 'draftJsInlineToolbarPlugin',
358
+ 'draftJsBlockBreakoutPlugin',
359
+ 'draftJsCreateInlineStyleButton',
360
+ 'draftJsCreateBlockStyleButton',
361
+ 'immutableLib',
362
+ // TODO: add all plugin dependencies, also in Wysiwyg and Cell
363
+ ]),
364
+ )(EditComponent);
365
+
366
+ const Preloader = (props) => {
367
+ const [loaded, setLoaded] = React.useState(false);
368
+ React.useEffect(() => {
369
+ Editor.load().then(() => setLoaded(true));
370
+ }, []);
371
+ return loaded ? <Edit {...props} /> : null;
372
+ };
373
+
374
+ export default Preloader;
@@ -3,12 +3,18 @@ import renderer from 'react-test-renderer';
3
3
  import configureStore from 'redux-mock-store';
4
4
  import { Provider } from 'react-intl-redux';
5
5
 
6
- import Edit from './Edit';
6
+ import { Edit } from './Edit';
7
7
 
8
8
  const mockStore = configureStore();
9
9
 
10
10
  global.__SERVER__ = true; // eslint-disable-line no-underscore-dangle
11
11
 
12
+ jest.mock('@plone/volto/helpers/Loadable/Loadable');
13
+ beforeAll(
14
+ async () =>
15
+ await require('@plone/volto/helpers/Loadable/Loadable').__setLoadables(),
16
+ );
17
+
12
18
  test('renders an edit text block component', () => {
13
19
  const store = mockStore({
14
20
  intl: {
@@ -17,8 +17,8 @@ const View = ({ data }) =>
17
17
  data.text ? (
18
18
  redraft(
19
19
  data.text,
20
- config.settings.ToHTMLRenderers,
21
- config.settings.ToHTMLOptions,
20
+ config.settings.richtextViewSettings.ToHTMLRenderers,
21
+ config.settings.richtextViewSettings.ToHTMLOptions,
22
22
  )
23
23
  ) : (
24
24
  <br />
@@ -4,12 +4,11 @@
4
4
  */
5
5
 
6
6
  import React, { Component } from 'react';
7
- import { Map } from 'immutable';
7
+ import { compose } from 'redux';
8
8
  import PropTypes from 'prop-types';
9
- import { stateFromHTML } from 'draft-js-import-html';
10
9
  import { isEqual } from 'lodash';
11
- import { Editor, DefaultDraftBlockRenderMap, EditorState } from 'draft-js';
12
10
  import { defineMessages, injectIntl } from 'react-intl';
11
+ import { injectLazyLibs } from '@plone/volto/helpers/Loadable/Loadable';
13
12
  import config from '@plone/volto/registry';
14
13
 
15
14
  const messages = defineMessages({
@@ -19,14 +18,6 @@ const messages = defineMessages({
19
18
  },
20
19
  });
21
20
 
22
- const blockRenderMap = Map({
23
- unstyled: {
24
- element: 'h1',
25
- },
26
- });
27
-
28
- const extendedBlockRenderMap = DefaultDraftBlockRenderMap.merge(blockRenderMap);
29
-
30
21
  /**
31
22
  * Edit title block class.
32
23
  * @class Edit
@@ -71,6 +62,19 @@ class Edit extends Component {
71
62
  super(props);
72
63
 
73
64
  if (!__SERVER__) {
65
+ const { Map } = props.immutableLib;
66
+ const { DefaultDraftBlockRenderMap, EditorState } = props.draftJs;
67
+ const { stateFromHTML } = props.draftJsImportHtml;
68
+
69
+ const blockRenderMap = Map({
70
+ unstyled: {
71
+ element: 'h1',
72
+ },
73
+ });
74
+
75
+ this.extendedBlockRenderMap = DefaultDraftBlockRenderMap.merge(
76
+ blockRenderMap,
77
+ );
74
78
  let editorState;
75
79
  if (props.properties && props.properties.title) {
76
80
  const contentState = stateFromHTML(props.properties.title);
@@ -117,6 +121,9 @@ class Edit extends Component {
117
121
  this.props.properties.title !== nextProps.properties.title &&
118
122
  !this.state.focus
119
123
  ) {
124
+ const { stateFromHTML } = this.props.draftJsImportHtml;
125
+ const { EditorState } = this.props.draftJs;
126
+
120
127
  const contentState = stateFromHTML(nextProps.properties.title);
121
128
  this.setState({
122
129
  editorState: nextProps.properties.title
@@ -156,6 +163,8 @@ class Edit extends Component {
156
163
  return <div />;
157
164
  }
158
165
 
166
+ const { Editor } = this.props.draftJs;
167
+
159
168
  const placeholder =
160
169
  this.props.data.placeholder ||
161
170
  this.props.intl.formatMessage(messages.title);
@@ -165,7 +174,7 @@ class Edit extends Component {
165
174
  readOnly={!this.props.editable}
166
175
  onChange={this.onChange}
167
176
  editorState={this.state.editorState}
168
- blockRenderMap={extendedBlockRenderMap}
177
+ blockRenderMap={this.extendedBlockRenderMap}
169
178
  handleReturn={() => {
170
179
  if (this.props.data.disableNewBlocks) {
171
180
  return 'handled';
@@ -208,4 +217,7 @@ class Edit extends Component {
208
217
  }
209
218
  }
210
219
 
211
- export default injectIntl(Edit);
220
+ export default compose(
221
+ injectLazyLibs(['draftJs', 'immutableLib', 'draftJsImportHtml']),
222
+ injectIntl,
223
+ )(Edit);
@@ -5,6 +5,12 @@ import { Provider } from 'react-intl-redux';
5
5
 
6
6
  import Edit from './Edit';
7
7
 
8
+ jest.mock('@plone/volto/helpers/Loadable/Loadable');
9
+ beforeAll(
10
+ async () =>
11
+ await require('@plone/volto/helpers/Loadable/Loadable').__setLoadables(),
12
+ );
13
+
8
14
  const mockStore = configureStore();
9
15
 
10
16
  global.__SERVER__ = true; // eslint-disable-line no-underscore-dangle
@@ -267,7 +267,9 @@ class ContentsUploadModal extends Component {
267
267
  <Table.Row className="upload-row" key={file.name}>
268
268
  <Table.Cell>{file.name}</Table.Cell>
269
269
  <Table.Cell>
270
- <FormattedRelativeDate date={file.lastModifiedDate} />
270
+ {file.lastModifiedDate && (
271
+ <FormattedRelativeDate date={file.lastModifiedDate} />
272
+ )}
271
273
  </Table.Cell>
272
274
  <Table.Cell>
273
275
  {filesize(file.size, { round: 0 })}
@@ -18,6 +18,8 @@ import { setSidebarTab } from '@plone/volto/actions';
18
18
  import expandSVG from '@plone/volto/icons/left-key.svg';
19
19
  import collapseSVG from '@plone/volto/icons/right-key.svg';
20
20
 
21
+ import config from '@plone/volto/registry';
22
+
21
23
  const messages = defineMessages({
22
24
  document: {
23
25
  id: 'Document',
@@ -98,7 +100,9 @@ class Sidebar extends Component {
98
100
  onToggleExpanded() {
99
101
  const { cookies } = this.props;
100
102
  cookies.set('sidebar_expanded', !this.state.expanded, {
101
- expires: new Date((2 ** 31 - 1) * 1000),
103
+ expires: new Date(
104
+ new Date().getTime() + config.settings.cookieExpires * 1000,
105
+ ),
102
106
  path: '/',
103
107
  });
104
108
  this.setState({
@@ -232,7 +232,9 @@ class Toolbar extends Component {
232
232
  handleShrink = () => {
233
233
  const { cookies } = this.props;
234
234
  cookies.set('toolbar_expanded', !this.state.expanded, {
235
- expires: new Date((2 ** 31 - 1) * 1000),
235
+ expires: new Date(
236
+ new Date().getTime() + config.settings.cookieExpires * 1000,
237
+ ),
236
238
  path: '/',
237
239
  });
238
240
  this.setState(