@plone/volto 18.0.0-alpha.18 → 18.0.0-alpha.19
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 +31 -1
- package/locales/ca/LC_MESSAGES/volto.po +17 -42
- package/locales/ca.json +1 -1
- package/locales/de/LC_MESSAGES/volto.po +15 -40
- package/locales/de.json +1 -1
- package/locales/en/LC_MESSAGES/volto.po +14 -39
- package/locales/en.json +1 -1
- package/locales/es/LC_MESSAGES/volto.po +15 -40
- package/locales/es.json +1 -1
- package/locales/eu/LC_MESSAGES/volto.po +15 -40
- package/locales/eu.json +1 -1
- package/locales/fi/LC_MESSAGES/volto.po +15 -40
- package/locales/fi.json +1 -1
- package/locales/fr/LC_MESSAGES/volto.po +15 -40
- package/locales/fr.json +1 -1
- package/locales/it/LC_MESSAGES/volto.po +15 -40
- package/locales/it.json +1 -1
- package/locales/ja/LC_MESSAGES/volto.po +15 -40
- package/locales/ja.json +1 -1
- package/locales/nl/LC_MESSAGES/volto.po +14 -39
- package/locales/nl.json +1 -1
- package/locales/pt/LC_MESSAGES/volto.po +15 -40
- package/locales/pt.json +1 -1
- package/locales/pt_BR/LC_MESSAGES/volto.po +15 -40
- package/locales/pt_BR.json +1 -1
- package/locales/ro/LC_MESSAGES/volto.po +15 -40
- package/locales/ro.json +1 -1
- package/locales/volto.pot +15 -40
- package/locales/zh_CN/LC_MESSAGES/volto.po +15 -40
- package/locales/zh_CN.json +1 -1
- package/package.json +10 -20
- package/src/components/index.js +0 -6
- package/src/components/manage/Blocks/Search/SearchBlockEdit.jsx +8 -2
- package/src/components/manage/Blocks/Search/hocs/withSearch.jsx +2 -2
- package/src/components/manage/Controlpanels/Groups/GroupsControlpanel.jsx +33 -5
- package/src/components/manage/Controlpanels/Groups/GroupsControlpanel.test.jsx +12 -0
- package/src/components/manage/Controlpanels/Groups/RenderGroups.jsx +22 -11
- package/src/components/manage/Controlpanels/Groups/RenderGroups.test.jsx +21 -0
- package/src/components/manage/Controlpanels/Users/RenderUsers.jsx +30 -21
- package/src/components/manage/Controlpanels/Users/RenderUsers.test.jsx +27 -1
- package/src/components/manage/Controlpanels/Users/UserGroupMembershipListing.jsx +29 -7
- package/src/components/manage/Controlpanels/Users/UsersControlpanel.jsx +51 -3
- package/src/components/manage/Controlpanels/Users/UsersControlpanel.test.jsx +8 -0
- package/src/config/Blocks.jsx +63 -67
- package/src/config/Loadables.jsx +0 -22
- package/src/config/Widgets.jsx +0 -2
- package/src/config/index.js +0 -13
- package/src/helpers/User/User.js +29 -0
- package/src/helpers/index.js +6 -1
- package/test-setup-config.js +0 -30
- package/types/components/index.d.ts +0 -6
- package/types/config/Blocks.d.ts +0 -51
- package/types/config/Loadables.d.ts +0 -10
- package/types/config/Widgets.d.ts +0 -2
- package/types/helpers/User/User.d.ts +18 -0
- package/types/helpers/index.d.ts +1 -1
- package/webpack-plugins/webpack-bundle-analyze-plugin.js +1 -1
- package/src/components/manage/AnchorPlugin/components/Link/index.jsx +0 -37
- package/src/components/manage/AnchorPlugin/components/LinkButton/index.jsx +0 -126
- package/src/components/manage/AnchorPlugin/index.jsx +0 -82
- package/src/components/manage/AnchorPlugin/linkStrategy.js +0 -21
- package/src/components/manage/AnchorPlugin/utils/EditorUtils.js +0 -47
- package/src/components/manage/Blocks/HeroImageLeft/Data.jsx +0 -29
- package/src/components/manage/Blocks/HeroImageLeft/Edit.jsx +0 -493
- package/src/components/manage/Blocks/HeroImageLeft/Edit.test.jsx +0 -58
- package/src/components/manage/Blocks/HeroImageLeft/View.jsx +0 -37
- package/src/components/manage/Blocks/HeroImageLeft/View.test.jsx +0 -9
- package/src/components/manage/Blocks/HeroImageLeft/schema.js +0 -43
- package/src/components/manage/Blocks/Table/Cell.jsx +0 -206
- package/src/components/manage/Blocks/Table/Cell.test.jsx +0 -19
- package/src/components/manage/Blocks/Table/Edit.jsx +0 -748
- package/src/components/manage/Blocks/Table/Edit.test.jsx +0 -44
- package/src/components/manage/Blocks/Table/Readme.md +0 -5
- package/src/components/manage/Blocks/Table/View.jsx +0 -51
- package/src/components/manage/Blocks/Table/View.test.jsx +0 -41
- package/src/components/manage/Blocks/Text/Edit.jsx +0 -372
- package/src/components/manage/Blocks/Text/Edit.test.jsx +0 -46
- package/src/components/manage/Blocks/Text/Readme.md +0 -5
- package/src/components/manage/Blocks/Text/Schema.jsx +0 -31
- package/src/components/manage/Blocks/Text/View.jsx +0 -26
- package/src/components/manage/Blocks/Text/View.test.jsx +0 -28
- package/src/components/manage/LinkDetectionPlugin/link-detection-plugin.jsx +0 -227
- package/src/components/manage/LinkDetectionPlugin/utils.js +0 -12
- package/src/components/manage/Widgets/WysiwygWidget.jsx +0 -350
- package/src/components/manage/Widgets/WysiwygWidget.stories.jsx +0 -24
- package/src/components/manage/Widgets/WysiwygWidget.test.jsx +0 -37
- package/src/config/RichTextEditor/Blocks.jsx +0 -29
- package/src/config/RichTextEditor/FromHTML.jsx +0 -8
- package/src/config/RichTextEditor/Plugins.jsx +0 -59
- package/src/config/RichTextEditor/Styles.jsx +0 -69
- package/src/config/RichTextEditor/ToHTML.jsx +0 -262
- package/src/config/RichTextEditor/index.js +0 -25
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import renderer from 'react-test-renderer';
|
|
3
|
-
import configureStore from 'redux-mock-store';
|
|
4
|
-
import { Provider } from 'react-intl-redux';
|
|
5
|
-
|
|
6
|
-
import Edit from './Edit';
|
|
7
|
-
|
|
8
|
-
jest.mock('@plone/volto/helpers/Loadable/Loadable');
|
|
9
|
-
beforeAll(
|
|
10
|
-
async () =>
|
|
11
|
-
await require('@plone/volto/helpers/Loadable/Loadable').__setLoadables(),
|
|
12
|
-
);
|
|
13
|
-
|
|
14
|
-
const mockStore = configureStore();
|
|
15
|
-
|
|
16
|
-
test('renders an edit table block component', () => {
|
|
17
|
-
const store = mockStore({
|
|
18
|
-
intl: {
|
|
19
|
-
locale: 'en',
|
|
20
|
-
messages: {},
|
|
21
|
-
},
|
|
22
|
-
});
|
|
23
|
-
const component = renderer.create(
|
|
24
|
-
<Provider store={store}>
|
|
25
|
-
<Edit
|
|
26
|
-
data={{ table: { rows: [] } }}
|
|
27
|
-
selected={false}
|
|
28
|
-
block="1234"
|
|
29
|
-
onAddBlock={() => {}}
|
|
30
|
-
onInsertBlock={() => {}}
|
|
31
|
-
onChangeBlock={() => {}}
|
|
32
|
-
onSelectBlock={() => {}}
|
|
33
|
-
onDeleteBlock={() => {}}
|
|
34
|
-
onFocusPreviousBlock={() => {}}
|
|
35
|
-
onFocusNextBlock={() => {}}
|
|
36
|
-
handleKeyDown={() => {}}
|
|
37
|
-
onMutateBlock={() => {}}
|
|
38
|
-
index={1}
|
|
39
|
-
/>
|
|
40
|
-
</Provider>,
|
|
41
|
-
);
|
|
42
|
-
const json = component.toJSON();
|
|
43
|
-
expect(json).toMatchSnapshot();
|
|
44
|
-
});
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import PropTypes from 'prop-types';
|
|
3
|
-
import { Table } from 'semantic-ui-react';
|
|
4
|
-
import { map } from 'lodash';
|
|
5
|
-
import redraft from 'redraft';
|
|
6
|
-
import config from '@plone/volto/registry';
|
|
7
|
-
|
|
8
|
-
const View = ({ data }) =>
|
|
9
|
-
data &&
|
|
10
|
-
data.table && (
|
|
11
|
-
<Table
|
|
12
|
-
fixed={data.table.fixed}
|
|
13
|
-
compact={data.table.compact}
|
|
14
|
-
basic={data.table.basic ? 'very' : false}
|
|
15
|
-
celled={data.table.celled}
|
|
16
|
-
inverted={data.table.inverted}
|
|
17
|
-
striped={data.table.striped}
|
|
18
|
-
>
|
|
19
|
-
<Table.Body>
|
|
20
|
-
{map(data.table.rows, (row) => (
|
|
21
|
-
<Table.Row key={row.key}>
|
|
22
|
-
{map(row.cells, (cell) => (
|
|
23
|
-
<Table.Cell
|
|
24
|
-
key={cell.key}
|
|
25
|
-
as={cell.type === 'header' ? 'th' : 'td'}
|
|
26
|
-
>
|
|
27
|
-
{cell.value && cell.value.blocks && cell.value.blocks[0].text
|
|
28
|
-
? redraft(
|
|
29
|
-
cell.value,
|
|
30
|
-
config.settings.richtextViewSettings.ToHTMLRenderers,
|
|
31
|
-
config.settings.richtextViewSettings.ToHTMLOptions,
|
|
32
|
-
)
|
|
33
|
-
: '\u00A0'}
|
|
34
|
-
</Table.Cell>
|
|
35
|
-
))}
|
|
36
|
-
</Table.Row>
|
|
37
|
-
))}
|
|
38
|
-
</Table.Body>
|
|
39
|
-
</Table>
|
|
40
|
-
);
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Property types.
|
|
44
|
-
* @property {Object} propTypes Property types.
|
|
45
|
-
* @static
|
|
46
|
-
*/
|
|
47
|
-
View.propTypes = {
|
|
48
|
-
data: PropTypes.objectOf(PropTypes.any).isRequired,
|
|
49
|
-
};
|
|
50
|
-
|
|
51
|
-
export default View;
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import renderer from 'react-test-renderer';
|
|
3
|
-
import View from './View';
|
|
4
|
-
|
|
5
|
-
test('renders a view table component', () => {
|
|
6
|
-
const component = renderer.create(
|
|
7
|
-
<View
|
|
8
|
-
data={{
|
|
9
|
-
table: {
|
|
10
|
-
rows: [
|
|
11
|
-
{
|
|
12
|
-
key: 'a',
|
|
13
|
-
cells: [
|
|
14
|
-
{
|
|
15
|
-
type: 'data',
|
|
16
|
-
key: 'b',
|
|
17
|
-
value: {
|
|
18
|
-
blocks: [
|
|
19
|
-
{
|
|
20
|
-
data: {},
|
|
21
|
-
depth: 0,
|
|
22
|
-
entityRanges: [],
|
|
23
|
-
inlineStyleRanges: [],
|
|
24
|
-
key: 'fgm98',
|
|
25
|
-
text: 'My header',
|
|
26
|
-
type: 'header-two',
|
|
27
|
-
},
|
|
28
|
-
],
|
|
29
|
-
entityMap: {},
|
|
30
|
-
},
|
|
31
|
-
},
|
|
32
|
-
],
|
|
33
|
-
},
|
|
34
|
-
],
|
|
35
|
-
},
|
|
36
|
-
}}
|
|
37
|
-
/>,
|
|
38
|
-
);
|
|
39
|
-
const json = component.toJSON();
|
|
40
|
-
expect(json).toMatchSnapshot();
|
|
41
|
-
});
|
|
@@ -1,372 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Edit text block.
|
|
3
|
-
* @module components/manage/Blocks/Title/Edit
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import React, { Component } from 'react';
|
|
7
|
-
import PropTypes from 'prop-types';
|
|
8
|
-
import { compose } from 'redux';
|
|
9
|
-
|
|
10
|
-
import { defineMessages, injectIntl } from 'react-intl';
|
|
11
|
-
import { includes, isEqual } from 'lodash';
|
|
12
|
-
import config from '@plone/volto/registry';
|
|
13
|
-
|
|
14
|
-
import { injectLazyLibs } from '@plone/volto/helpers/Loadable/Loadable';
|
|
15
|
-
import { BlockChooserButton } from '@plone/volto/components';
|
|
16
|
-
|
|
17
|
-
import loadable from '@loadable/component';
|
|
18
|
-
|
|
19
|
-
const Editor = loadable(() => import('draft-js-plugins-editor'));
|
|
20
|
-
|
|
21
|
-
const messages = defineMessages({
|
|
22
|
-
text: {
|
|
23
|
-
id: 'Type text…',
|
|
24
|
-
defaultMessage: 'Type text…',
|
|
25
|
-
},
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Edit text block class.
|
|
30
|
-
* @class Edit
|
|
31
|
-
* @extends Component
|
|
32
|
-
*/
|
|
33
|
-
export class EditComponent extends Component {
|
|
34
|
-
/**
|
|
35
|
-
* Property types.
|
|
36
|
-
* @property {Object} propTypes Property types.
|
|
37
|
-
* @static
|
|
38
|
-
*/
|
|
39
|
-
static propTypes = {
|
|
40
|
-
data: PropTypes.objectOf(PropTypes.any).isRequired,
|
|
41
|
-
detached: PropTypes.bool,
|
|
42
|
-
index: PropTypes.number.isRequired,
|
|
43
|
-
selected: PropTypes.bool.isRequired,
|
|
44
|
-
block: PropTypes.string.isRequired,
|
|
45
|
-
onAddBlock: PropTypes.func.isRequired,
|
|
46
|
-
onInsertBlock: PropTypes.func.isRequired,
|
|
47
|
-
onChangeBlock: PropTypes.func.isRequired,
|
|
48
|
-
onDeleteBlock: PropTypes.func.isRequired,
|
|
49
|
-
onMutateBlock: PropTypes.func.isRequired,
|
|
50
|
-
onFocusPreviousBlock: PropTypes.func.isRequired,
|
|
51
|
-
onFocusNextBlock: PropTypes.func.isRequired,
|
|
52
|
-
onSelectBlock: PropTypes.func.isRequired,
|
|
53
|
-
editable: PropTypes.bool,
|
|
54
|
-
allowedBlocks: PropTypes.arrayOf(PropTypes.string),
|
|
55
|
-
showRestricted: PropTypes.bool,
|
|
56
|
-
formTitle: PropTypes.string,
|
|
57
|
-
formDescription: PropTypes.string,
|
|
58
|
-
blocksConfig: PropTypes.objectOf(PropTypes.any),
|
|
59
|
-
properties: PropTypes.objectOf(PropTypes.any),
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* Default properties
|
|
64
|
-
* @property {Object} defaultProps Default properties.
|
|
65
|
-
* @static
|
|
66
|
-
*/
|
|
67
|
-
static defaultProps = {
|
|
68
|
-
detached: false,
|
|
69
|
-
editable: true,
|
|
70
|
-
};
|
|
71
|
-
|
|
72
|
-
/**
|
|
73
|
-
* Constructor
|
|
74
|
-
* @method constructor
|
|
75
|
-
* @param {Object} props Component properties
|
|
76
|
-
* @constructs WysiwygEditor
|
|
77
|
-
*/
|
|
78
|
-
constructor(props) {
|
|
79
|
-
super(props);
|
|
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
|
-
|
|
88
|
-
if (!__SERVER__) {
|
|
89
|
-
let editorState;
|
|
90
|
-
if (props.data && props.data.text) {
|
|
91
|
-
editorState = EditorState.createWithContent(
|
|
92
|
-
convertFromRaw(props.data.text),
|
|
93
|
-
);
|
|
94
|
-
} else {
|
|
95
|
-
editorState = EditorState.createEmpty();
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
const inlineToolbarPlugin = createInlineToolbarPlugin({
|
|
99
|
-
structure: this.draftConfig.richTextEditorInlineToolbarButtons,
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
this.state = {
|
|
103
|
-
editorState,
|
|
104
|
-
inlineToolbarPlugin,
|
|
105
|
-
};
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
this.onChange = this.onChange.bind(this);
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
/**
|
|
112
|
-
* Component will receive props
|
|
113
|
-
* @method componentDidMount
|
|
114
|
-
* @returns {undefined}
|
|
115
|
-
*/
|
|
116
|
-
componentDidMount() {
|
|
117
|
-
if (this.props.selected) {
|
|
118
|
-
// See https://github.com/draft-js-plugins/draft-js-plugins/issues/800
|
|
119
|
-
setTimeout(this.node.focus, 0);
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
/**
|
|
124
|
-
* Component will receive props
|
|
125
|
-
* @method componentWillReceiveProps
|
|
126
|
-
* @param {Object} nextProps Next properties
|
|
127
|
-
* @returns {undefined}
|
|
128
|
-
*/
|
|
129
|
-
UNSAFE_componentWillReceiveProps(nextProps) {
|
|
130
|
-
if (!this.props.selected && nextProps.selected) {
|
|
131
|
-
const selectionState = this.state.editorState.getSelection();
|
|
132
|
-
|
|
133
|
-
if (selectionState.getStartOffset() < selectionState.getEndOffset()) {
|
|
134
|
-
//keep selection
|
|
135
|
-
} else {
|
|
136
|
-
//nothing is selected, move focus to end
|
|
137
|
-
// See https://github.com/draft-js-plugins/draft-js-plugins/issues/800
|
|
138
|
-
setTimeout(this.node.focus, 0);
|
|
139
|
-
const { EditorState } = this.props.draftJs;
|
|
140
|
-
|
|
141
|
-
this.setState({
|
|
142
|
-
editorState: EditorState.moveFocusToEnd(this.state.editorState),
|
|
143
|
-
});
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
componentDidUpdate(prevProps) {
|
|
149
|
-
const { convertToRaw, EditorState, convertFromRaw } = this.props.draftJs;
|
|
150
|
-
if (
|
|
151
|
-
!isEqual(this.props.data, prevProps.data) &&
|
|
152
|
-
!isEqual(
|
|
153
|
-
convertToRaw(this.state.editorState.getCurrentContent()),
|
|
154
|
-
this.props.data.text,
|
|
155
|
-
)
|
|
156
|
-
) {
|
|
157
|
-
const editorState =
|
|
158
|
-
this.props.data && this.props.data.text
|
|
159
|
-
? EditorState.createWithContent(convertFromRaw(this.props.data.text))
|
|
160
|
-
: EditorState.createEmpty();
|
|
161
|
-
|
|
162
|
-
this.setState({
|
|
163
|
-
editorState: editorState,
|
|
164
|
-
});
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
/**
|
|
169
|
-
* @param {*} nextProps
|
|
170
|
-
* @param {*} nextState
|
|
171
|
-
* @returns {boolean}
|
|
172
|
-
* @memberof Edit
|
|
173
|
-
*/
|
|
174
|
-
shouldComponentUpdate(nextProps, nextState) {
|
|
175
|
-
return (
|
|
176
|
-
this.props.selected ||
|
|
177
|
-
!isEqual(this.props.data, nextProps.data) ||
|
|
178
|
-
!isEqual(this.state.editorState, nextState.editorState)
|
|
179
|
-
);
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
/**
|
|
183
|
-
* Change handler
|
|
184
|
-
* @method onChange
|
|
185
|
-
* @param {object} editorState Editor state.
|
|
186
|
-
* @returns {undefined}
|
|
187
|
-
*/
|
|
188
|
-
onChange(editorState) {
|
|
189
|
-
const shouldFilterPaste =
|
|
190
|
-
editorState.getLastChangeType() === 'insert-fragment';
|
|
191
|
-
|
|
192
|
-
const { convertToRaw } = this.props.draftJs;
|
|
193
|
-
const { filterEditorState } = this.props.draftJsFilters;
|
|
194
|
-
|
|
195
|
-
if (
|
|
196
|
-
!isEqual(
|
|
197
|
-
convertToRaw(editorState.getCurrentContent()),
|
|
198
|
-
convertToRaw(this.state.editorState.getCurrentContent()),
|
|
199
|
-
)
|
|
200
|
-
) {
|
|
201
|
-
if (shouldFilterPaste) {
|
|
202
|
-
let filteredState = editorState;
|
|
203
|
-
filteredState = filterEditorState(
|
|
204
|
-
{
|
|
205
|
-
blocks: ['unordered-list-item', 'ordered-list-item'],
|
|
206
|
-
styles: ['BOLD', 'ITALIC'],
|
|
207
|
-
entities: [
|
|
208
|
-
{
|
|
209
|
-
type: 'LINK',
|
|
210
|
-
attributes: ['url'],
|
|
211
|
-
},
|
|
212
|
-
],
|
|
213
|
-
whitespacedCharacters: [],
|
|
214
|
-
},
|
|
215
|
-
filteredState,
|
|
216
|
-
);
|
|
217
|
-
editorState = filteredState;
|
|
218
|
-
}
|
|
219
|
-
this.props.onChangeBlock(this.props.block, {
|
|
220
|
-
...this.props.data,
|
|
221
|
-
text: convertToRaw(editorState.getCurrentContent()),
|
|
222
|
-
});
|
|
223
|
-
}
|
|
224
|
-
this.setState({ editorState });
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
/**
|
|
228
|
-
* Render method.
|
|
229
|
-
* @method render
|
|
230
|
-
* @returns {string} Markup for the component.
|
|
231
|
-
*/
|
|
232
|
-
render() {
|
|
233
|
-
// console.log('draft config', this.draftConfig);
|
|
234
|
-
|
|
235
|
-
if (__SERVER__) {
|
|
236
|
-
return <div />;
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
const placeholder =
|
|
240
|
-
this.props.data.placeholder ||
|
|
241
|
-
this.props.formTitle ||
|
|
242
|
-
this.props.intl.formatMessage(messages.text);
|
|
243
|
-
|
|
244
|
-
const disableNewBlocks =
|
|
245
|
-
this.props.data?.disableNewBlocks || this.props.detached;
|
|
246
|
-
const { InlineToolbar } = this.state.inlineToolbarPlugin;
|
|
247
|
-
// const { settings } = config;
|
|
248
|
-
|
|
249
|
-
const isSoftNewlineEvent = this.props.draftJsLibIsSoftNewlineEvent.default;
|
|
250
|
-
const { RichUtils } = this.props.draftJs;
|
|
251
|
-
|
|
252
|
-
return (
|
|
253
|
-
<>
|
|
254
|
-
<Editor
|
|
255
|
-
readOnly={!this.props.editable}
|
|
256
|
-
onChange={this.onChange}
|
|
257
|
-
editorState={this.state.editorState}
|
|
258
|
-
plugins={[
|
|
259
|
-
this.state.inlineToolbarPlugin,
|
|
260
|
-
// ...settings.richTextEditorPlugins,
|
|
261
|
-
...this.draftConfig.richTextEditorPlugins,
|
|
262
|
-
]}
|
|
263
|
-
blockRenderMap={this.draftConfig.extendedBlockRenderMap}
|
|
264
|
-
blockStyleFn={this.draftConfig.blockStyleFn}
|
|
265
|
-
customStyleMap={this.draftConfig.customStyleMap}
|
|
266
|
-
placeholder={placeholder}
|
|
267
|
-
handleReturn={(e) => {
|
|
268
|
-
if (isSoftNewlineEvent(e)) {
|
|
269
|
-
this.onChange(
|
|
270
|
-
RichUtils.insertSoftNewline(this.state.editorState),
|
|
271
|
-
);
|
|
272
|
-
return 'handled';
|
|
273
|
-
}
|
|
274
|
-
if (!disableNewBlocks) {
|
|
275
|
-
const selectionState = this.state.editorState.getSelection();
|
|
276
|
-
const anchorKey = selectionState.getAnchorKey();
|
|
277
|
-
const currentContent = this.state.editorState.getCurrentContent();
|
|
278
|
-
const currentContentBlock =
|
|
279
|
-
currentContent.getBlockForKey(anchorKey);
|
|
280
|
-
const blockType = currentContentBlock.getType();
|
|
281
|
-
if (!includes(this.draftConfig.listBlockTypes, blockType)) {
|
|
282
|
-
this.props.onSelectBlock(
|
|
283
|
-
this.props.onAddBlock(
|
|
284
|
-
config.settings.defaultBlockType,
|
|
285
|
-
this.props.index + 1,
|
|
286
|
-
),
|
|
287
|
-
);
|
|
288
|
-
return 'handled';
|
|
289
|
-
}
|
|
290
|
-
return 'un-handled';
|
|
291
|
-
}
|
|
292
|
-
return {};
|
|
293
|
-
}}
|
|
294
|
-
handleKeyCommand={(command, editorState) => {
|
|
295
|
-
if (this.props.data.required) {
|
|
296
|
-
return;
|
|
297
|
-
}
|
|
298
|
-
if (
|
|
299
|
-
command === 'backspace' &&
|
|
300
|
-
editorState.getCurrentContent().getPlainText().length === 0
|
|
301
|
-
) {
|
|
302
|
-
this.props.onDeleteBlock(this.props.block, true);
|
|
303
|
-
}
|
|
304
|
-
}}
|
|
305
|
-
onUpArrow={() => {
|
|
306
|
-
const selectionState = this.state.editorState.getSelection();
|
|
307
|
-
const currentCursorPosition = selectionState.getStartOffset();
|
|
308
|
-
|
|
309
|
-
if (currentCursorPosition === 0) {
|
|
310
|
-
this.props.onFocusPreviousBlock(this.props.block, this.node);
|
|
311
|
-
}
|
|
312
|
-
}}
|
|
313
|
-
onDownArrow={() => {
|
|
314
|
-
const selectionState = this.state.editorState.getSelection();
|
|
315
|
-
const { editorState } = this.state;
|
|
316
|
-
const currentCursorPosition = selectionState.getStartOffset();
|
|
317
|
-
const blockLength = editorState
|
|
318
|
-
.getCurrentContent()
|
|
319
|
-
.getFirstBlock()
|
|
320
|
-
.getLength();
|
|
321
|
-
|
|
322
|
-
if (currentCursorPosition === blockLength) {
|
|
323
|
-
this.props.onFocusNextBlock(this.props.block, this.node);
|
|
324
|
-
}
|
|
325
|
-
}}
|
|
326
|
-
ref={(node) => {
|
|
327
|
-
this.node = node;
|
|
328
|
-
}}
|
|
329
|
-
/>
|
|
330
|
-
<InlineToolbar />
|
|
331
|
-
{!config.experimental.addBlockButton.enabled && this.props.selected && (
|
|
332
|
-
<BlockChooserButton
|
|
333
|
-
data={this.props.data}
|
|
334
|
-
block={this.props.block}
|
|
335
|
-
onInsertBlock={(id, value) => {
|
|
336
|
-
this.props.onSelectBlock(this.props.onInsertBlock(id, value));
|
|
337
|
-
}}
|
|
338
|
-
allowedBlocks={this.props.allowedBlocks}
|
|
339
|
-
blocksConfig={this.props.blocksConfig}
|
|
340
|
-
size="24px"
|
|
341
|
-
properties={this.props.properties}
|
|
342
|
-
/>
|
|
343
|
-
)}
|
|
344
|
-
</>
|
|
345
|
-
);
|
|
346
|
-
}
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
export const Edit = compose(
|
|
350
|
-
injectIntl,
|
|
351
|
-
injectLazyLibs([
|
|
352
|
-
'draftJs',
|
|
353
|
-
'draftJsLibIsSoftNewlineEvent',
|
|
354
|
-
'draftJsFilters',
|
|
355
|
-
'draftJsInlineToolbarPlugin',
|
|
356
|
-
'draftJsBlockBreakoutPlugin',
|
|
357
|
-
'draftJsCreateInlineStyleButton',
|
|
358
|
-
'draftJsCreateBlockStyleButton',
|
|
359
|
-
'immutableLib',
|
|
360
|
-
// TODO: add all plugin dependencies, also in Wysiwyg and Cell
|
|
361
|
-
]),
|
|
362
|
-
)(EditComponent);
|
|
363
|
-
|
|
364
|
-
const Preloader = (props) => {
|
|
365
|
-
const [loaded, setLoaded] = React.useState(false);
|
|
366
|
-
React.useEffect(() => {
|
|
367
|
-
Editor.load().then(() => setLoaded(true));
|
|
368
|
-
}, []);
|
|
369
|
-
return loaded ? <Edit {...props} /> : null;
|
|
370
|
-
};
|
|
371
|
-
|
|
372
|
-
export default Preloader;
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import renderer from 'react-test-renderer';
|
|
3
|
-
import configureStore from 'redux-mock-store';
|
|
4
|
-
import { Provider } from 'react-intl-redux';
|
|
5
|
-
|
|
6
|
-
import { Edit } from './Edit';
|
|
7
|
-
|
|
8
|
-
const mockStore = configureStore();
|
|
9
|
-
|
|
10
|
-
global.__SERVER__ = true; // eslint-disable-line no-underscore-dangle
|
|
11
|
-
|
|
12
|
-
jest.mock('@plone/volto/helpers/Loadable/Loadable');
|
|
13
|
-
beforeAll(
|
|
14
|
-
async () =>
|
|
15
|
-
await require('@plone/volto/helpers/Loadable/Loadable').__setLoadables(),
|
|
16
|
-
);
|
|
17
|
-
|
|
18
|
-
test('renders an edit text block component', () => {
|
|
19
|
-
const store = mockStore({
|
|
20
|
-
intl: {
|
|
21
|
-
locale: 'en',
|
|
22
|
-
messages: {},
|
|
23
|
-
},
|
|
24
|
-
});
|
|
25
|
-
const component = renderer.create(
|
|
26
|
-
<Provider store={store}>
|
|
27
|
-
<Edit
|
|
28
|
-
data={{ text: '<p>body text</p>' }}
|
|
29
|
-
selected={false}
|
|
30
|
-
block="1234"
|
|
31
|
-
onAddBlock={() => {}}
|
|
32
|
-
onInsertBlock={() => {}}
|
|
33
|
-
onChangeBlock={() => {}}
|
|
34
|
-
onSelectBlock={() => {}}
|
|
35
|
-
onDeleteBlock={() => {}}
|
|
36
|
-
onFocusPreviousBlock={() => {}}
|
|
37
|
-
onFocusNextBlock={() => {}}
|
|
38
|
-
handleKeyDown={() => {}}
|
|
39
|
-
onMutateBlock={() => {}}
|
|
40
|
-
index={1}
|
|
41
|
-
/>
|
|
42
|
-
</Provider>,
|
|
43
|
-
);
|
|
44
|
-
const json = component.toJSON();
|
|
45
|
-
expect(json).toMatchSnapshot();
|
|
46
|
-
});
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import BlockSettingsSchema from '@plone/volto/components/manage/Blocks/Block/Schema';
|
|
2
|
-
|
|
3
|
-
const Schema = {
|
|
4
|
-
...BlockSettingsSchema,
|
|
5
|
-
fieldsets: [
|
|
6
|
-
{
|
|
7
|
-
...BlockSettingsSchema.fieldsets[0],
|
|
8
|
-
// fields: [
|
|
9
|
-
// ...BlockSettingsSchema.fieldsets[0].fields,
|
|
10
|
-
// 'minLength',
|
|
11
|
-
// 'maxLength',
|
|
12
|
-
// ],
|
|
13
|
-
},
|
|
14
|
-
],
|
|
15
|
-
properties: {
|
|
16
|
-
...BlockSettingsSchema.properties,
|
|
17
|
-
/* TODO Enable when we have block validation inplace */
|
|
18
|
-
// minLength: {
|
|
19
|
-
// title: 'Min length',
|
|
20
|
-
// description: 'Minimum number of characters',
|
|
21
|
-
// type: 'integer',
|
|
22
|
-
// },
|
|
23
|
-
// maxLength: {
|
|
24
|
-
// title: 'Max length',
|
|
25
|
-
// description: 'Maximum number of characters',
|
|
26
|
-
// type: 'integer',
|
|
27
|
-
// },
|
|
28
|
-
},
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
export default Schema;
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import PropTypes from 'prop-types';
|
|
2
|
-
import redraft from 'redraft';
|
|
3
|
-
import React from 'react';
|
|
4
|
-
import config from '@plone/volto/registry';
|
|
5
|
-
|
|
6
|
-
const View = ({ data }) =>
|
|
7
|
-
data.text ? (
|
|
8
|
-
redraft(
|
|
9
|
-
data.text,
|
|
10
|
-
config.settings.richtextViewSettings.ToHTMLRenderers,
|
|
11
|
-
config.settings.richtextViewSettings.ToHTMLOptions,
|
|
12
|
-
)
|
|
13
|
-
) : (
|
|
14
|
-
<br />
|
|
15
|
-
);
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Property types.
|
|
19
|
-
* @property {Object} propTypes Property types.
|
|
20
|
-
* @static
|
|
21
|
-
*/
|
|
22
|
-
View.propTypes = {
|
|
23
|
-
data: PropTypes.objectOf(PropTypes.any).isRequired,
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
export default View;
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import renderer from 'react-test-renderer';
|
|
3
|
-
import View from './View';
|
|
4
|
-
|
|
5
|
-
test('renders a view text component', () => {
|
|
6
|
-
const component = renderer.create(
|
|
7
|
-
<View
|
|
8
|
-
data={{
|
|
9
|
-
text: {
|
|
10
|
-
blocks: [
|
|
11
|
-
{
|
|
12
|
-
data: {},
|
|
13
|
-
depth: 0,
|
|
14
|
-
entityRanges: [],
|
|
15
|
-
inlineStyleRanges: [],
|
|
16
|
-
key: 'fgm98',
|
|
17
|
-
text: 'My header',
|
|
18
|
-
type: 'header-two',
|
|
19
|
-
},
|
|
20
|
-
],
|
|
21
|
-
entityMap: {},
|
|
22
|
-
},
|
|
23
|
-
}}
|
|
24
|
-
/>,
|
|
25
|
-
);
|
|
26
|
-
const json = component.toJSON();
|
|
27
|
-
expect(json).toMatchSnapshot();
|
|
28
|
-
});
|