@plone/volto 15.0.0-alpha.4 → 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.
- package/CHANGELOG.md +11 -0
- package/package.json +1 -1
- package/src/actions/language/language.js +7 -2
- package/src/components/manage/AnchorPlugin/components/LinkButton/AddLinkForm.jsx +1 -2
- package/src/components/manage/AnchorPlugin/components/LinkButton/index.jsx +15 -6
- package/src/components/manage/AnchorPlugin/index.jsx +12 -5
- package/src/components/manage/AnchorPlugin/utils/EditorUtils.js +8 -7
- package/src/components/manage/Blocks/Description/Edit.jsx +33 -19
- package/src/components/manage/Blocks/Description/Edit.test.jsx +6 -0
- package/src/components/manage/Blocks/HeroImageLeft/Edit.jsx +37 -26
- package/src/components/manage/Blocks/HeroImageLeft/Edit.test.jsx +6 -0
- package/src/components/manage/Blocks/Table/Cell.jsx +40 -14
- package/src/components/manage/Blocks/Table/Cell.test.jsx +7 -1
- package/src/components/manage/Blocks/Table/Edit.jsx +7 -3
- package/src/components/manage/Blocks/Table/Edit.test.jsx +6 -0
- package/src/components/manage/Blocks/Table/View.jsx +2 -2
- package/src/components/manage/Blocks/Text/Edit.jsx +56 -14
- package/src/components/manage/Blocks/Text/Edit.test.jsx +7 -1
- package/src/components/manage/Blocks/Text/View.jsx +2 -2
- package/src/components/manage/Blocks/Title/Edit.jsx +25 -13
- package/src/components/manage/Blocks/Title/Edit.test.jsx +6 -0
- package/src/components/manage/Sidebar/Sidebar.jsx +5 -1
- package/src/components/manage/Toolbar/Toolbar.jsx +3 -1
- package/src/components/manage/UniversalLink/UniversalLink.jsx +5 -2
- package/src/components/manage/Widgets/UrlWidget.jsx +1 -1
- package/src/components/manage/Widgets/WysiwygWidget.jsx +45 -19
- package/src/components/manage/Widgets/WysiwygWidget.test.jsx +7 -1
- package/src/components/theme/View/LinkView.jsx +1 -1
- package/src/config/Loadables.jsx +22 -0
- package/src/config/RichTextEditor/Blocks.jsx +25 -20
- package/src/config/RichTextEditor/Plugins.jsx +38 -31
- package/src/config/RichTextEditor/Styles.jsx +48 -44
- package/src/config/RichTextEditor/index.js +25 -0
- package/src/config/index.js +14 -18
- package/src/helpers/Url/Url.js +32 -1
- package/src/helpers/Url/urlRegex.js +7 -1
- package/src/helpers/index.js +1 -0
- package/src/middleware/api.js +1 -1
- package/test-setup-config.js +22 -7
- package/src/components/manage/AnchorPlugin/utils/URLUtils.js +0 -36
- package/src/components/manage/AnchorPlugin/utils/mailRegex.js +0 -2
- package/src/components/manage/AnchorPlugin/utils/telRegex.js +0 -1
- package/src/components/manage/AnchorPlugin/utils/urlRegex.js +0 -54
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
# Change Log
|
|
2
2
|
|
|
3
|
+
## 15.0.0-alpha.5 (2022-02-16)
|
|
4
|
+
|
|
5
|
+
### Breaking
|
|
6
|
+
|
|
7
|
+
- Lazyload draftjs library. See the upgrade guide on how that impacts you, in case you have extended the rich text editor configuration @tiberiuichim @kreafox
|
|
8
|
+
See https://docs.voltocms.com/upgrade-guide/ for more information.
|
|
9
|
+
|
|
10
|
+
### Feature
|
|
11
|
+
|
|
12
|
+
- Add `cookiesExpire` value to config to control the cookie expiration @giuliaghisini
|
|
13
|
+
|
|
3
14
|
## 15.0.0-alpha.4 (2022-02-16)
|
|
4
15
|
|
|
5
16
|
### Breaking
|
package/package.json
CHANGED
|
@@ -1,16 +1,21 @@
|
|
|
1
1
|
import { updateIntl } from 'react-intl-redux';
|
|
2
2
|
import { normalizeLanguageName } from '@plone/volto/helpers';
|
|
3
3
|
import Cookies from 'universal-cookie';
|
|
4
|
+
import config from '@plone/volto/registry';
|
|
4
5
|
|
|
5
6
|
export function changeLanguageCookies(language) {
|
|
6
7
|
const cookies = new Cookies();
|
|
7
8
|
|
|
8
9
|
cookies.set('lang', normalizeLanguageName(language), {
|
|
9
|
-
expires: new Date(
|
|
10
|
+
expires: new Date(
|
|
11
|
+
new Date().getTime() + config.settings.cookieExpires * 1000,
|
|
12
|
+
),
|
|
10
13
|
path: '/',
|
|
11
14
|
});
|
|
12
15
|
cookies.set('I18N_LANGUAGE', normalizeLanguageName(language) || '', {
|
|
13
|
-
expires: new Date(
|
|
16
|
+
expires: new Date(
|
|
17
|
+
new Date().getTime() + config.settings.cookieExpires * 1000,
|
|
18
|
+
),
|
|
14
19
|
path: '/',
|
|
15
20
|
});
|
|
16
21
|
}
|
|
@@ -13,14 +13,13 @@ import {
|
|
|
13
13
|
addAppURL,
|
|
14
14
|
isInternalURL,
|
|
15
15
|
flattenToAppURL,
|
|
16
|
+
URLUtils,
|
|
16
17
|
} from '@plone/volto/helpers';
|
|
17
18
|
|
|
18
19
|
import { doesNodeContainClick } from 'semantic-ui-react/dist/commonjs/lib';
|
|
19
20
|
import { Input, Form, Button } from 'semantic-ui-react';
|
|
20
21
|
import { defineMessages, injectIntl } from 'react-intl';
|
|
21
22
|
|
|
22
|
-
import URLUtils from '@plone/volto/components/manage/AnchorPlugin/utils/URLUtils';
|
|
23
|
-
|
|
24
23
|
import clearSVG from '@plone/volto/icons/clear.svg';
|
|
25
24
|
import navTreeSVG from '@plone/volto/icons/nav.svg';
|
|
26
25
|
import aheadSVG from '@plone/volto/icons/ahead.svg';
|
|
@@ -2,7 +2,7 @@ import React, { Component } from 'react';
|
|
|
2
2
|
import PropTypes from 'prop-types';
|
|
3
3
|
import cx from 'classnames';
|
|
4
4
|
import EditorUtils from '../../utils/EditorUtils';
|
|
5
|
-
import
|
|
5
|
+
import { injectLazyLibs } from '@plone/volto/helpers/Loadable/Loadable';
|
|
6
6
|
import AddLinkForm from '@plone/volto/components/manage/AnchorPlugin/components/LinkButton/AddLinkForm';
|
|
7
7
|
import Icon from '@plone/volto/components/theme/Icon/Icon';
|
|
8
8
|
|
|
@@ -26,6 +26,13 @@ class LinkButton extends Component {
|
|
|
26
26
|
onOverrideContent: PropTypes.func.isRequired,
|
|
27
27
|
};
|
|
28
28
|
|
|
29
|
+
constructor(props) {
|
|
30
|
+
super(props);
|
|
31
|
+
|
|
32
|
+
this.DraftEditorUtils = props.draftJsPluginsUtils.default;
|
|
33
|
+
this.EditorUtils = EditorUtils(props);
|
|
34
|
+
}
|
|
35
|
+
|
|
29
36
|
static defaultProps = {
|
|
30
37
|
placeholder: '',
|
|
31
38
|
};
|
|
@@ -38,7 +45,7 @@ class LinkButton extends Component {
|
|
|
38
45
|
e.preventDefault();
|
|
39
46
|
e.stopPropagation();
|
|
40
47
|
const { ownTheme, placeholder, onOverrideContent } = this.props;
|
|
41
|
-
const link = EditorUtils.getCurrentEntity(
|
|
48
|
+
const link = this.EditorUtils.getCurrentEntity(
|
|
42
49
|
this.props.getEditorState(),
|
|
43
50
|
)?.getData()?.url;
|
|
44
51
|
|
|
@@ -52,12 +59,14 @@ class LinkButton extends Component {
|
|
|
52
59
|
onChangeBlock={() => {}}
|
|
53
60
|
onClear={() => {
|
|
54
61
|
this.props.setEditorState(
|
|
55
|
-
DraftEditorUtils.removeLinkAtSelection(
|
|
62
|
+
this.DraftEditorUtils.removeLinkAtSelection(
|
|
63
|
+
this.props.getEditorState(),
|
|
64
|
+
),
|
|
56
65
|
);
|
|
57
66
|
}}
|
|
58
67
|
onChangeValue={(url) => {
|
|
59
68
|
this.props.setEditorState(
|
|
60
|
-
DraftEditorUtils.createLinkAtSelection(
|
|
69
|
+
this.DraftEditorUtils.createLinkAtSelection(
|
|
61
70
|
this.props.getEditorState(),
|
|
62
71
|
url,
|
|
63
72
|
),
|
|
@@ -75,7 +84,7 @@ class LinkButton extends Component {
|
|
|
75
84
|
*/
|
|
76
85
|
render() {
|
|
77
86
|
const { theme } = this.props;
|
|
78
|
-
const hasLinkSelected = EditorUtils.hasEntity(
|
|
87
|
+
const hasLinkSelected = this.EditorUtils.hasEntity(
|
|
79
88
|
this.props.getEditorState(),
|
|
80
89
|
'LINK',
|
|
81
90
|
);
|
|
@@ -114,4 +123,4 @@ class LinkButton extends Component {
|
|
|
114
123
|
}
|
|
115
124
|
}
|
|
116
125
|
|
|
117
|
-
export default LinkButton;
|
|
126
|
+
export default injectLazyLibs(['draftJs', 'draftJsPluginsUtils'])(LinkButton);
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import decorateComponentWithProps from 'decorate-component-with-props';
|
|
2
|
-
import { EditorState, Modifier } from 'draft-js';
|
|
3
2
|
|
|
4
3
|
import DefaultLink from './components/Link';
|
|
5
4
|
import LinkButton from './components/LinkButton';
|
|
6
5
|
import linkStrategy, { matchesEntityType } from './linkStrategy';
|
|
7
6
|
|
|
8
|
-
function
|
|
7
|
+
function unboundRemoveEntity(editorState) {
|
|
9
8
|
const contentState = editorState.getCurrentContent();
|
|
10
9
|
const selectionState = editorState.getSelection();
|
|
11
10
|
const startKey = selectionState.getStartKey();
|
|
@@ -30,13 +29,13 @@ function removeEntity(editorState) {
|
|
|
30
29
|
},
|
|
31
30
|
);
|
|
32
31
|
|
|
33
|
-
const newContentState = Modifier.applyEntity(
|
|
32
|
+
const newContentState = this.Modifier.applyEntity(
|
|
34
33
|
contentState,
|
|
35
34
|
entitySelection,
|
|
36
35
|
null,
|
|
37
36
|
);
|
|
38
37
|
|
|
39
|
-
const newEditorState = EditorState.push(
|
|
38
|
+
const newEditorState = this.EditorState.push(
|
|
40
39
|
editorState,
|
|
41
40
|
newContentState,
|
|
42
41
|
'apply-entity',
|
|
@@ -49,7 +48,15 @@ export default (config = {}) => {
|
|
|
49
48
|
// ToDo: Get rif of the remainings of having the original CSS modules
|
|
50
49
|
const defaultTheme = {};
|
|
51
50
|
|
|
52
|
-
const {
|
|
51
|
+
const {
|
|
52
|
+
theme = defaultTheme,
|
|
53
|
+
placeholder,
|
|
54
|
+
Link,
|
|
55
|
+
linkTarget,
|
|
56
|
+
libraries,
|
|
57
|
+
} = config;
|
|
58
|
+
|
|
59
|
+
const removeEntity = unboundRemoveEntity.bind(libraries);
|
|
53
60
|
|
|
54
61
|
return {
|
|
55
62
|
decorators: [
|
|
@@ -1,22 +1,23 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
export default {
|
|
1
|
+
export default ({ draftJs }) => ({
|
|
4
2
|
createLinkAtSelection(editorState, url) {
|
|
5
3
|
const contentState = editorState
|
|
6
4
|
.getCurrentContent()
|
|
7
5
|
.createEntity('LINK', 'MUTABLE', { url });
|
|
8
6
|
const entityKey = contentState.getLastCreatedEntityKey();
|
|
9
|
-
const withLink = RichUtils.toggleLink(
|
|
7
|
+
const withLink = draftJs.RichUtils.toggleLink(
|
|
10
8
|
editorState,
|
|
11
9
|
editorState.getSelection(),
|
|
12
10
|
entityKey,
|
|
13
11
|
);
|
|
14
|
-
return EditorState.forceSelection(
|
|
12
|
+
return draftJs.EditorState.forceSelection(
|
|
13
|
+
withLink,
|
|
14
|
+
editorState.getSelection(),
|
|
15
|
+
);
|
|
15
16
|
},
|
|
16
17
|
|
|
17
18
|
removeLinkAtSelection(editorState) {
|
|
18
19
|
const selection = editorState.getSelection();
|
|
19
|
-
return RichUtils.toggleLink(editorState, selection, null);
|
|
20
|
+
return draftJs.RichUtils.toggleLink(editorState, selection, null);
|
|
20
21
|
},
|
|
21
22
|
|
|
22
23
|
getCurrentEntityKey(editorState) {
|
|
@@ -41,4 +42,4 @@ export default {
|
|
|
41
42
|
const entity = this.getCurrentEntity(editorState);
|
|
42
43
|
return entity && entity.getType() === entityType;
|
|
43
44
|
},
|
|
44
|
-
};
|
|
45
|
+
});
|
|
@@ -4,13 +4,12 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import React, { Component } from 'react';
|
|
7
|
-
import {
|
|
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';
|
|
13
11
|
import cx from 'classnames';
|
|
12
|
+
import { injectLazyLibs } from '@plone/volto/helpers/Loadable/Loadable';
|
|
14
13
|
import config from '@plone/volto/registry';
|
|
15
14
|
|
|
16
15
|
const messages = defineMessages({
|
|
@@ -20,14 +19,6 @@ const messages = defineMessages({
|
|
|
20
19
|
},
|
|
21
20
|
});
|
|
22
21
|
|
|
23
|
-
const blockRenderMap = Map({
|
|
24
|
-
unstyled: {
|
|
25
|
-
element: 'div',
|
|
26
|
-
},
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
const extendedBlockRenderMap = DefaultDraftBlockRenderMap.merge(blockRenderMap);
|
|
30
|
-
|
|
31
22
|
/**
|
|
32
23
|
* Edit description block class.
|
|
33
24
|
* @class Edit
|
|
@@ -72,12 +63,29 @@ class Edit extends Component {
|
|
|
72
63
|
super(props);
|
|
73
64
|
|
|
74
65
|
if (!__SERVER__) {
|
|
66
|
+
const { Editor, EditorState, DefaultDraftBlockRenderMap } = props.draftJs;
|
|
67
|
+
const { Map } = props.immutableLib;
|
|
68
|
+
|
|
69
|
+
this.Editor = Editor;
|
|
70
|
+
this.EditorState = EditorState;
|
|
71
|
+
this.stateFromHTML = props.draftJsImportHtml.stateFromHTML;
|
|
72
|
+
|
|
73
|
+
const blockRenderMap = Map({
|
|
74
|
+
unstyled: {
|
|
75
|
+
element: 'div',
|
|
76
|
+
},
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
this.extendedBlockRenderMap = DefaultDraftBlockRenderMap.merge(
|
|
80
|
+
blockRenderMap,
|
|
81
|
+
);
|
|
82
|
+
|
|
75
83
|
let editorState;
|
|
76
84
|
if (props.properties && props.properties.description) {
|
|
77
|
-
const contentState = stateFromHTML(props.properties.description);
|
|
78
|
-
editorState = EditorState.createWithContent(contentState);
|
|
85
|
+
const contentState = this.stateFromHTML(props.properties.description);
|
|
86
|
+
editorState = this.EditorState.createWithContent(contentState);
|
|
79
87
|
} else {
|
|
80
|
-
editorState = EditorState.createEmpty();
|
|
88
|
+
editorState = this.EditorState.createEmpty();
|
|
81
89
|
}
|
|
82
90
|
this.state = { editorState, focus: false };
|
|
83
91
|
}
|
|
@@ -109,11 +117,11 @@ class Edit extends Component {
|
|
|
109
117
|
this.props.properties.description !== nextProps.properties.description &&
|
|
110
118
|
!this.state.focus
|
|
111
119
|
) {
|
|
112
|
-
const contentState = stateFromHTML(nextProps.properties.description);
|
|
120
|
+
const contentState = this.stateFromHTML(nextProps.properties.description);
|
|
113
121
|
this.setState({
|
|
114
122
|
editorState: nextProps.properties.description
|
|
115
|
-
? EditorState.createWithContent(contentState)
|
|
116
|
-
: EditorState.createEmpty(),
|
|
123
|
+
? this.EditorState.createWithContent(contentState)
|
|
124
|
+
: this.EditorState.createEmpty(),
|
|
117
125
|
});
|
|
118
126
|
}
|
|
119
127
|
|
|
@@ -163,6 +171,9 @@ class Edit extends Component {
|
|
|
163
171
|
if (__SERVER__) {
|
|
164
172
|
return <div />;
|
|
165
173
|
}
|
|
174
|
+
|
|
175
|
+
const Editor = this.Editor;
|
|
176
|
+
|
|
166
177
|
return (
|
|
167
178
|
<div
|
|
168
179
|
className={cx('block description', { selected: this.props.selected })}
|
|
@@ -171,7 +182,7 @@ class Edit extends Component {
|
|
|
171
182
|
onChange={this.onChange}
|
|
172
183
|
editorState={this.state.editorState}
|
|
173
184
|
readOnly={!this.props.editable}
|
|
174
|
-
blockRenderMap={extendedBlockRenderMap}
|
|
185
|
+
blockRenderMap={this.extendedBlockRenderMap}
|
|
175
186
|
handleReturn={() => {
|
|
176
187
|
if (this.props.data?.disableNewBlocks) {
|
|
177
188
|
return 'handled';
|
|
@@ -223,4 +234,7 @@ class Edit extends Component {
|
|
|
223
234
|
}
|
|
224
235
|
}
|
|
225
236
|
|
|
226
|
-
export default
|
|
237
|
+
export default compose(
|
|
238
|
+
injectLazyLibs(['draftJs', 'immutableLib', 'draftJsImportHtml']),
|
|
239
|
+
injectIntl,
|
|
240
|
+
)(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
|
|
@@ -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
|
|
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();
|
|
@@ -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
|
|
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:
|
|
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
|
|
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
|
-
...
|
|
144
|
+
...this.draftConfig.richTextEditorPlugins,
|
|
139
145
|
]}
|
|
140
|
-
blockRenderMap={
|
|
141
|
-
blockStyleFn={
|
|
142
|
-
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(
|
|
164
|
+
if (!includes(this.draftConfig.listBlockTypes, blockType)) {
|
|
159
165
|
this.props.onSelectBlock(
|
|
160
166
|
this.props.onAddBlock(
|
|
161
|
-
|
|
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
|
|
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>
|