@eeacms/volto-group-block 8.1.1 → 10.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.
@@ -1,197 +0,0 @@
1
- import React from 'react';
2
- import { Icon, BlockChooser } from '@plone/volto/components';
3
- import {
4
- blockHasValue,
5
- buildStyleClassNamesFromData,
6
- } from '@plone/volto/helpers';
7
- import { Button } from 'semantic-ui-react';
8
- import includes from 'lodash/includes';
9
- import isBoolean from 'lodash/isBoolean';
10
- import { defineMessages, injectIntl } from 'react-intl';
11
- import cx from 'classnames';
12
- import config from '@plone/volto/registry';
13
- import { doesNodeContainClick } from 'semantic-ui-react/dist/commonjs/lib';
14
-
15
- import dragSVG from '@plone/volto/icons/drag.svg';
16
- import addSVG from '@plone/volto/icons/circle-plus.svg';
17
- import trashSVG from '@plone/volto/icons/delete.svg';
18
-
19
- const messages = defineMessages({
20
- unknownBlock: {
21
- id: 'Unknown Block',
22
- defaultMessage: 'Unknown Block {block}',
23
- },
24
- delete: {
25
- id: 'delete',
26
- defaultMessage: 'delete',
27
- },
28
- addBlock: {
29
- id: 'addBlock',
30
- defaultMessage: 'Add block',
31
- },
32
- removeBlock: {
33
- id: 'removeBlock',
34
- defaultMessage: 'Remove block',
35
- },
36
- });
37
-
38
- class EditBlockWrapper extends React.Component {
39
- constructor(props) {
40
- super(props);
41
- this.state = {
42
- addNewBlockOpened: false,
43
- };
44
- }
45
-
46
- componentDidMount() {
47
- document.addEventListener('mousedown', this.handleClickOutside, false);
48
- }
49
-
50
- componentWillUnmount() {
51
- document.removeEventListener('mousedown', this.handleClickOutside);
52
- }
53
-
54
- handleClickOutside = (e) => {
55
- if (
56
- this.blockNode.current &&
57
- doesNodeContainClick(this.blockNode.current, e)
58
- )
59
- return;
60
-
61
- if (this.state.addNewBlockOpened) {
62
- this.setState({
63
- addNewBlockOpened: false,
64
- });
65
- return true;
66
- }
67
- };
68
-
69
- blockNode = React.createRef();
70
-
71
- render() {
72
- const { intl, blockProps, draginfo, extraControls, disabled, children } =
73
- this.props;
74
-
75
- const {
76
- allowedBlocks,
77
- block,
78
- data,
79
- onSelectBlock,
80
- onDeleteBlock,
81
- onMutateBlock,
82
- onInsertBlock,
83
- selected,
84
- } = blockProps;
85
- const type = data['@type'];
86
- const { disableNewBlocks } = data;
87
- const dragVisible = !data.fixed;
88
- const visible = selected;
89
-
90
- const required = isBoolean(data.required)
91
- ? data.required
92
- : includes(config.blocks.requiredBlocks, type);
93
-
94
- const styles = buildStyleClassNamesFromData(data.styles);
95
-
96
- // Get editing instructions from block settings or props
97
- let instructions = data?.instructions?.data || data?.instructions;
98
- if (!instructions || instructions === '<p><br/></p>') {
99
- instructions = '';
100
- }
101
-
102
- return (
103
- <div ref={this.blockNode}>
104
- <div
105
- ref={draginfo?.innerRef}
106
- {...(selected ? draginfo?.draggableProps : null)}
107
- className={cx(`block-editor-${data['@type']}`, styles, {
108
- [data.align]: data.align,
109
- })}
110
- >
111
- {(!selected || !visible || disabled) && (
112
- <div
113
- style={{
114
- display: 'none',
115
- // keep react-beautiful-dnd happy
116
- }}
117
- {...draginfo.dragHandleProps}
118
- ></div>
119
- )}
120
- {visible && (
121
- <div className="block-toolbar">
122
- {instructions ? extraControls : ''}
123
-
124
- {!disabled && (
125
- <>
126
- <div
127
- style={{
128
- display: dragVisible ? 'inline-block' : 'none',
129
- }}
130
- {...draginfo.dragHandleProps}
131
- className="drag handle wrapper-group-block"
132
- >
133
- <Button icon basic title="Drag and drop">
134
- <Icon name={dragSVG} size="19px" />
135
- </Button>
136
- </div>
137
-
138
- {!disableNewBlocks && !blockHasValue(data) && (
139
- <Button
140
- icon
141
- basic
142
- title={intl.formatMessage(messages.addBlock)}
143
- onClick={() => {
144
- this.setState((prevState) => ({
145
- addNewBlockOpened: !prevState.addNewBlockOpened,
146
- }));
147
- }}
148
- className="group-block-add-button"
149
- >
150
- <Icon name={addSVG} className="" size="19px" />
151
- </Button>
152
- )}
153
- {!required && (
154
- <Button
155
- icon
156
- basic
157
- title={intl.formatMessage(messages.removeBlock)}
158
- onClick={() => onDeleteBlock(block)}
159
- className="delete-button-group-block"
160
- aria-label={intl.formatMessage(messages.delete)}
161
- >
162
- <Icon name={trashSVG} size="19px" />
163
- </Button>
164
- )}
165
- {this.state.addNewBlockOpened && (
166
- <BlockChooser
167
- onMutateBlock={(id, value) => {
168
- onMutateBlock(id, value);
169
- this.setState({ addNewBlockOpened: false });
170
- }}
171
- onInsertBlock={(id, value) => {
172
- onSelectBlock(onInsertBlock(id, value));
173
- this.setState({ addNewBlockOpened: false });
174
- }}
175
- currentBlock={block}
176
- allowedBlocks={allowedBlocks}
177
- />
178
- )}
179
- </>
180
- )}
181
- </div>
182
- )}
183
-
184
- <div
185
- className={cx('ui drag block wrapper inner', type, {
186
- multiSelected: this.props.multiSelected,
187
- })}
188
- >
189
- {children}
190
- </div>
191
- </div>
192
- </div>
193
- );
194
- }
195
- }
196
-
197
- export default injectIntl(EditBlockWrapper);
@@ -1,58 +0,0 @@
1
- import React from 'react';
2
- import { fireEvent, render } from '@testing-library/react';
3
- import { Provider } from 'react-intl-redux';
4
- import EditBlockWrapper from './EditBlockWrapper';
5
- import configureStore from 'redux-mock-store';
6
- import '@testing-library/jest-dom/extend-expect';
7
-
8
- const mockDragInfo = {
9
- innerRef: {
10
- current: {
11
- childMethod: jest.fn(),
12
- },
13
- },
14
- draggableProps: {},
15
- dragHandleProps: {},
16
- };
17
-
18
- const mockStore = configureStore();
19
- const store = mockStore({
20
- intl: {
21
- locale: 'en',
22
- messages: {},
23
- },
24
- });
25
-
26
- describe('EditBlockWrapper', () => {
27
- const mockBlockProps = {
28
- allowedBlocks: [],
29
- block: 'mockBlock',
30
- data: {},
31
- onSelectBlock: jest.fn(),
32
- onDeleteBlock: jest.fn(),
33
- onMutateBlock: jest.fn(),
34
- onInsertBlock: jest.fn(),
35
- selected: true,
36
- };
37
-
38
- it('renders children', () => {
39
- const { getByText } = render(
40
- <Provider store={store}>
41
- <EditBlockWrapper blockProps={mockBlockProps} draginfo={mockDragInfo}>
42
- <div>Test child</div>
43
- </EditBlockWrapper>
44
- </Provider>,
45
- );
46
- expect(getByText('Test child')).toBeInTheDocument();
47
- });
48
-
49
- it('calls onDeleteBlock when delete button is clicked', () => {
50
- const { getByTitle } = render(
51
- <Provider store={store}>
52
- <EditBlockWrapper blockProps={mockBlockProps} draginfo={mockDragInfo} />
53
- </Provider>,
54
- );
55
- fireEvent.click(getByTitle('Remove block'));
56
- expect(mockBlockProps.onDeleteBlock).toHaveBeenCalledWith('mockBlock');
57
- });
58
- });