@plone/volto 14.4.0 → 14.5.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,23 @@
1
1
  # Change Log
2
2
 
3
+ ## 14.5.0 (2022-01-26)
4
+
5
+ ### Feature
6
+
7
+ - VocabularyTermsWidget: Token is now on creation of term editable, but stays ineditable afterwards. @ksuess
8
+
9
+ ### Bugfix
10
+
11
+ - Fix A11Y violations in Navigation @iRohitSingh
12
+ - Fix `language-independent-field` CSS class styling @sneridagh
13
+
14
+ ### Internal
15
+
16
+ - Lazyload react-beautiful-dnd @tiberiuichim
17
+ - Lazyload react-dnd @tiberiuichim
18
+ - Improve docs on environment variables, add recipes @sneridagh
19
+ - Update p.restapi to 8.20.0 and plone.volto to 4.0.0a1 and plone.rest to 2.0.0a2 @sneridagh
20
+
3
21
  ## 14.4.0 (2022-01-21)
4
22
 
5
23
  ### Feature
@@ -16,6 +34,7 @@
16
34
 
17
35
  ### Bugfix
18
36
 
37
+ - Fix ListingBlock to add "No results" message when there are no messages @erral
19
38
  - Fix overflow table in Content view @giuliaghisini
20
39
  - Fixed url validation in FormValidation to admit ip addresses. @giuliaghisini
21
40
  - Upgrade to plone.restapi 8.19.0 (to support the language independent fields serialization) @sneridagh
package/package.json CHANGED
@@ -9,7 +9,7 @@
9
9
  }
10
10
  ],
11
11
  "license": "MIT",
12
- "version": "14.4.0",
12
+ "version": "14.5.0",
13
13
  "repository": {
14
14
  "type": "git",
15
15
  "url": "git@github.com:plone/volto.git"
@@ -12,8 +12,6 @@ import { keys, isEmpty } from 'lodash';
12
12
  import { defineMessages, injectIntl } from 'react-intl';
13
13
  import { Button, Grid, Menu } from 'semantic-ui-react';
14
14
  import { Portal } from 'react-portal';
15
- import { DragDropContext } from 'react-dnd';
16
- import HTML5Backend from 'react-dnd-html5-backend';
17
15
  import { v4 as uuid } from 'uuid';
18
16
  import qs from 'query-string';
19
17
  import { toast } from 'react-toastify';
@@ -446,7 +444,6 @@ class Add extends Component {
446
444
  }
447
445
 
448
446
  export default compose(
449
- DragDropContext(HTML5Backend),
450
447
  injectIntl,
451
448
  connect(
452
449
  (state, props) => ({
@@ -6,6 +6,12 @@ import { render } from '@testing-library/react';
6
6
 
7
7
  import config from '@plone/volto/registry';
8
8
 
9
+ jest.mock('@plone/volto/helpers/Loadable/Loadable');
10
+ beforeAll(
11
+ async () =>
12
+ await require('@plone/volto/helpers/Loadable/Loadable').__setLoadables(),
13
+ );
14
+
9
15
  let mockSerial = 0;
10
16
 
11
17
  jest.mock('uuid', () => {
@@ -97,6 +97,12 @@ const ListingBody = withQuerystringResults((props) => {
97
97
  </div>
98
98
  ) : (
99
99
  <div>
100
+ {hasLoaded && (
101
+ <FormattedMessage
102
+ id="No results found."
103
+ defaultMessage="No results found."
104
+ />
105
+ )}
100
106
  <Dimmer active={!hasLoaded} inverted>
101
107
  <Loader indeterminate size="small">
102
108
  <FormattedMessage id="loading" defaultMessage="Loading" />
@@ -33,8 +33,6 @@ import {
33
33
  pull,
34
34
  } from 'lodash';
35
35
  import move from 'lodash-move';
36
- import { DragDropContext } from 'react-dnd';
37
- import HTML5Backend from 'react-dnd-html5-backend';
38
36
  import { FormattedMessage, defineMessages, injectIntl } from 'react-intl';
39
37
  import { asyncConnect } from '@plone/volto/helpers';
40
38
 
@@ -1780,9 +1778,21 @@ class Contents extends Component {
1780
1778
  }
1781
1779
  }
1782
1780
 
1781
+ const DragDropConnector = (props) => {
1782
+ const { DragDropContext } = props.reactDnd;
1783
+ const HTML5Backend = props.reactDndHtml5Backend.default;
1784
+
1785
+ const DndConnectedContents = React.useMemo(
1786
+ () => DragDropContext(HTML5Backend)(Contents),
1787
+ [DragDropContext, HTML5Backend],
1788
+ );
1789
+
1790
+ return <DndConnectedContents {...props} />;
1791
+ };
1792
+
1783
1793
  export const __test__ = compose(
1784
1794
  injectIntl,
1785
- injectLazyLibs(['toastify']),
1795
+ injectLazyLibs(['toastify', 'reactDnd']),
1786
1796
  connect(
1787
1797
  (store, props) => {
1788
1798
  return {
@@ -1822,7 +1832,6 @@ export const __test__ = compose(
1822
1832
  )(Contents);
1823
1833
 
1824
1834
  export default compose(
1825
- DragDropContext(HTML5Backend),
1826
1835
  injectIntl,
1827
1836
  connect(
1828
1837
  (store, props) => {
@@ -1869,5 +1878,5 @@ export default compose(
1869
1878
  await dispatch(listActions(getBaseUrl(location.pathname))),
1870
1879
  },
1871
1880
  ]),
1872
- injectLazyLibs(['toastify']),
1873
- )(Contents);
1881
+ injectLazyLibs(['toastify', 'reactDnd', 'reactDndHtml5Backend']),
1882
+ )(DragDropConnector);
@@ -5,8 +5,8 @@
5
5
 
6
6
  import React from 'react';
7
7
  import PropTypes from 'prop-types';
8
- import { DragSource, DropTarget } from 'react-dnd';
9
8
  import { injectIntl } from 'react-intl';
9
+ import { injectLazyLibs } from '@plone/volto/helpers/Loadable/Loadable';
10
10
 
11
11
  const widthValues = [
12
12
  'one',
@@ -69,39 +69,51 @@ ContentsIndexHeaderComponent.propTypes = {
69
69
  onOrderIndex: PropTypes.func.isRequired,
70
70
  };
71
71
 
72
- export default DropTarget(
73
- 'index',
74
- {
75
- hover(props, monitor) {
76
- const dragOrder = monitor.getItem().order;
77
- const hoverOrder = props.order;
72
+ const DragDropConnector = (props) => {
73
+ const { DropTarget, DragSource } = props.reactDnd;
78
74
 
79
- if (dragOrder === hoverOrder) {
80
- return;
81
- }
75
+ const DndConnectedContentsIndexHeader = React.useMemo(
76
+ () =>
77
+ DropTarget(
78
+ 'index',
79
+ {
80
+ hover(props, monitor) {
81
+ const dragOrder = monitor.getItem().order;
82
+ const hoverOrder = props.order;
82
83
 
83
- props.onOrderIndex(dragOrder, hoverOrder - dragOrder);
84
+ if (dragOrder === hoverOrder) {
85
+ return;
86
+ }
84
87
 
85
- monitor.getItem().order = hoverOrder;
86
- },
87
- },
88
- (connect) => ({
89
- connectDropTarget: connect.dropTarget(),
90
- }),
91
- )(
92
- DragSource(
93
- 'index',
94
- {
95
- beginDrag(props) {
96
- return {
97
- id: props.label,
98
- order: props.order,
99
- };
100
- },
101
- },
102
- (connect, monitor) => ({
103
- connectDragSource: connect.dragSource(),
104
- isDragging: monitor.isDragging(),
105
- }),
106
- )(injectIntl(ContentsIndexHeaderComponent)),
107
- );
88
+ props.onOrderIndex(dragOrder, hoverOrder - dragOrder);
89
+
90
+ monitor.getItem().order = hoverOrder;
91
+ },
92
+ },
93
+ (connect) => ({
94
+ connectDropTarget: connect.dropTarget(),
95
+ }),
96
+ )(
97
+ DragSource(
98
+ 'index',
99
+ {
100
+ beginDrag(props) {
101
+ return {
102
+ id: props.label,
103
+ order: props.order,
104
+ };
105
+ },
106
+ },
107
+ (connect, monitor) => ({
108
+ connectDragSource: connect.dragSource(),
109
+ isDragging: monitor.isDragging(),
110
+ }),
111
+ )(injectIntl(ContentsIndexHeaderComponent)),
112
+ ),
113
+ [DragSource, DropTarget],
114
+ );
115
+
116
+ return <DndConnectedContentsIndexHeader {...props} />;
117
+ };
118
+
119
+ export default injectLazyLibs('reactDnd')(DragDropConnector);
@@ -9,7 +9,6 @@ import { Link } from 'react-router-dom';
9
9
  import PropTypes from 'prop-types';
10
10
  import { map } from 'lodash';
11
11
  import moment from 'moment';
12
- import { DragSource, DropTarget } from 'react-dnd';
13
12
  import { useIntl, defineMessages, FormattedMessage } from 'react-intl';
14
13
  import { Icon, Circle } from '@plone/volto/components';
15
14
  import { getContentIcon } from '@plone/volto/helpers';
@@ -26,6 +25,8 @@ import editingSVG from '@plone/volto/icons/editing.svg';
26
25
  import dragSVG from '@plone/volto/icons/drag.svg';
27
26
  import cx from 'classnames';
28
27
 
28
+ import { injectLazyLibs } from '@plone/volto/helpers/Loadable/Loadable';
29
+
29
30
  const messages = defineMessages({
30
31
  private: {
31
32
  id: 'private',
@@ -313,55 +314,67 @@ ContentsItemComponent.propTypes = {
313
314
  onOrderItem: PropTypes.func.isRequired,
314
315
  };
315
316
 
316
- export default DropTarget(
317
- 'item',
318
- {
319
- hover(props, monitor) {
320
- const id = monitor.getItem().id;
321
- const dragOrder = monitor.getItem().order;
322
- const hoverOrder = props.order;
317
+ const DragDropConnector = (props) => {
318
+ const { DropTarget, DragSource } = props.reactDnd;
323
319
 
324
- if (dragOrder === hoverOrder) {
325
- return;
326
- }
320
+ const DndConnectedContentsItem = React.useMemo(
321
+ () =>
322
+ DropTarget(
323
+ 'item',
324
+ {
325
+ hover(props, monitor) {
326
+ const id = monitor.getItem().id;
327
+ const dragOrder = monitor.getItem().order;
328
+ const hoverOrder = props.order;
327
329
 
328
- props.onOrderItem(id, dragOrder, hoverOrder - dragOrder, false);
330
+ if (dragOrder === hoverOrder) {
331
+ return;
332
+ }
329
333
 
330
- monitor.getItem().order = hoverOrder;
331
- },
332
- drop(props, monitor) {
333
- const id = monitor.getItem().id;
334
- const dragOrder = monitor.getItem().startOrder;
335
- const dropOrder = props.order;
334
+ props.onOrderItem(id, dragOrder, hoverOrder - dragOrder, false);
336
335
 
337
- if (dragOrder === dropOrder) {
338
- return;
339
- }
336
+ monitor.getItem().order = hoverOrder;
337
+ },
338
+ drop(props, monitor) {
339
+ const id = monitor.getItem().id;
340
+ const dragOrder = monitor.getItem().startOrder;
341
+ const dropOrder = props.order;
340
342
 
341
- props.onOrderItem(id, dragOrder, dropOrder - dragOrder, true);
343
+ if (dragOrder === dropOrder) {
344
+ return;
345
+ }
342
346
 
343
- monitor.getItem().order = dropOrder;
344
- },
345
- },
346
- (connect) => ({
347
- connectDropTarget: connect.dropTarget(),
348
- }),
349
- )(
350
- DragSource(
351
- 'item',
352
- {
353
- beginDrag(props) {
354
- return {
355
- id: props.item['@id'],
356
- order: props.order,
357
- startOrder: props.order,
358
- };
359
- },
360
- },
361
- (connect, monitor) => ({
362
- connectDragSource: connect.dragSource(),
363
- connectDragPreview: connect.dragPreview(),
364
- isDragging: monitor.isDragging(),
365
- }),
366
- )(ContentsItemComponent),
367
- );
347
+ props.onOrderItem(id, dragOrder, dropOrder - dragOrder, true);
348
+
349
+ monitor.getItem().order = dropOrder;
350
+ },
351
+ },
352
+ (connect) => ({
353
+ connectDropTarget: connect.dropTarget(),
354
+ }),
355
+ )(
356
+ DragSource(
357
+ 'item',
358
+ {
359
+ beginDrag(props) {
360
+ return {
361
+ id: props.item['@id'],
362
+ order: props.order,
363
+ startOrder: props.order,
364
+ };
365
+ },
366
+ },
367
+ (connect, monitor) => ({
368
+ connectDragSource: connect.dragSource(),
369
+ connectDragPreview: connect.dragPreview(),
370
+ isDragging: monitor.isDragging(),
371
+ }),
372
+ )(ContentsItemComponent),
373
+ ),
374
+ [DragSource, DropTarget],
375
+ );
376
+
377
+ return <DndConnectedContentsItem {...props} />;
378
+ };
379
+
380
+ export default injectLazyLibs('reactDnd')(DragDropConnector);
@@ -1,6 +1,6 @@
1
1
  import React, { useRef } from 'react';
2
2
  import { isEmpty } from 'lodash';
3
- import { DragDropContext, Draggable, Droppable } from 'react-beautiful-dnd';
3
+ import { injectLazyLibs } from '@plone/volto/helpers/Loadable/Loadable';
4
4
  import { v4 as uuid } from 'uuid';
5
5
 
6
6
  const getPlaceholder = (draggedDOM, sourceIndex, destinationIndex) => {
@@ -55,7 +55,9 @@ const DragDropList = (props) => {
55
55
  as = 'div',
56
56
  style,
57
57
  forwardedAriaLabelledBy,
58
+ reactBeautifulDnd,
58
59
  } = props; //renderChild
60
+ const { DragDropContext, Draggable, Droppable } = reactBeautifulDnd;
59
61
  const [placeholderProps, setPlaceholderProps] = React.useState({});
60
62
  const [uid] = React.useState(uuid());
61
63
  // queueing timed action
@@ -157,4 +159,4 @@ const DragDropList = (props) => {
157
159
  );
158
160
  };
159
161
 
160
- export default DragDropList;
162
+ export default injectLazyLibs(['reactBeautifulDnd'])(DragDropList);
@@ -5,9 +5,9 @@
5
5
 
6
6
  import React from 'react';
7
7
  import PropTypes from 'prop-types';
8
- import { DragSource, DropTarget } from 'react-dnd';
9
8
  import { injectIntl } from 'react-intl';
10
9
  import config from '@plone/volto/registry';
10
+ import { injectLazyLibs } from '@plone/volto/helpers/Loadable/Loadable';
11
11
 
12
12
  const MODE_HIDDEN = 'hidden'; //hidden mode. If mode is hidden, field is not rendered
13
13
  /**
@@ -150,7 +150,7 @@ const getWidgetByType = (type) => config.widgets.type[type] || null;
150
150
  * @param {Object} props Properties.
151
151
  * @returns {string} Markup of the component.
152
152
  */
153
- const Field = (props, { intl }) => {
153
+ const UnconnectedField = (props, { intl }) => {
154
154
  const Widget =
155
155
  getWidgetByFieldId(props.id) ||
156
156
  getWidgetFromTaggedValues(props.widgetOptions) ||
@@ -173,6 +173,7 @@ const Field = (props, { intl }) => {
173
173
  };
174
174
 
175
175
  if (props.onOrder) {
176
+ const { DropTarget, DragSource } = props.reactDnd;
176
177
  const WrappedWidget = DropTarget(
177
178
  'field',
178
179
  {
@@ -230,6 +231,15 @@ const Field = (props, { intl }) => {
230
231
  return <Widget {...widgetProps} />;
231
232
  };
232
233
 
234
+ const DndConnectedField = injectLazyLibs(['reactDnd'])(UnconnectedField);
235
+
236
+ const Field = (props) =>
237
+ props.onOrder ? (
238
+ <DndConnectedField {...props} />
239
+ ) : (
240
+ <UnconnectedField {...props} />
241
+ );
242
+
233
243
  /**
234
244
  * Property types.
235
245
  * @property {Object} propTypes Property types.
@@ -5,6 +5,12 @@ import configureStore from 'redux-mock-store';
5
5
  import '@testing-library/jest-dom/extend-expect';
6
6
  import ObjectListWidget from './ObjectListWidget';
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
  let mockSerial = 0;
9
15
  const mockStore = configureStore();
10
16
 
@@ -11,7 +11,7 @@ import { concat, findIndex, isString, map, omit, slice, without } from 'lodash';
11
11
  import move from 'lodash-move';
12
12
  import { Confirm, Form, Grid, Icon, Message, Segment } from 'semantic-ui-react';
13
13
  import { defineMessages, injectIntl } from 'react-intl';
14
- import { DragDropContext, Draggable, Droppable } from 'react-beautiful-dnd';
14
+ import { injectLazyLibs } from '@plone/volto/helpers/Loadable/Loadable';
15
15
 
16
16
  import {
17
17
  Field,
@@ -1078,7 +1078,8 @@ class SchemaWidget extends Component {
1078
1078
  * @returns {string} Markup for the component.
1079
1079
  */
1080
1080
  render() {
1081
- const { error } = this.props;
1081
+ const { error, reactBeautifulDnd } = this.props;
1082
+ const { Draggable, DragDropContext, Droppable } = reactBeautifulDnd;
1082
1083
  if (!this.props.value) {
1083
1084
  return '';
1084
1085
  }
@@ -1427,6 +1428,7 @@ class SchemaWidget extends Component {
1427
1428
 
1428
1429
  export default compose(
1429
1430
  injectIntl,
1431
+ injectLazyLibs(['reactBeautifulDnd']),
1430
1432
  connect(
1431
1433
  (state, props) => ({
1432
1434
  value: isString(props.value) ? JSON.parse(props.value) : props.value,
@@ -5,6 +5,12 @@ import { Provider } from 'react-intl-redux';
5
5
 
6
6
  import SchemaWidget from './SchemaWidget';
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 a schema widget component', () => {
@@ -7,9 +7,10 @@
7
7
 
8
8
  import PropTypes from 'prop-types';
9
9
  import React from 'react';
10
- import { Draggable } from 'react-beautiful-dnd';
11
10
  import { Icon } from 'semantic-ui-react';
12
11
 
12
+ import { injectLazyLibs } from '@plone/volto/helpers/Loadable/Loadable';
13
+
13
14
  /**
14
15
  * Schema widget fieldset component.
15
16
  * @function SchemaWidgetFieldset
@@ -26,8 +27,9 @@ export const SchemaWidgetFieldsetComponent = ({
26
27
  getItemStyle,
27
28
  isDraggable,
28
29
  isDisabled,
30
+ reactBeautifulDnd,
29
31
  }) => (
30
- <Draggable draggableId={title} index={order} key={title}>
32
+ <reactBeautifulDnd.Draggable draggableId={title} index={order} key={title}>
31
33
  {(provided, snapshot) => (
32
34
  <div
33
35
  className={`item${active ? ' active' : ''}`}
@@ -71,7 +73,7 @@ export const SchemaWidgetFieldsetComponent = ({
71
73
  )}
72
74
  </div>
73
75
  )}
74
- </Draggable>
76
+ </reactBeautifulDnd.Draggable>
75
77
  );
76
78
 
77
79
  /**
@@ -91,4 +93,6 @@ SchemaWidgetFieldsetComponent.propTypes = {
91
93
  isDisabled: PropTypes.bool,
92
94
  };
93
95
 
94
- export default SchemaWidgetFieldsetComponent;
96
+ export default injectLazyLibs(['reactBeautifulDnd'])(
97
+ SchemaWidgetFieldsetComponent,
98
+ );
@@ -1,7 +1,13 @@
1
1
  import React from 'react';
2
2
  import { DragDropContext, Droppable } from 'react-beautiful-dnd';
3
3
  import renderer from 'react-test-renderer';
4
- import { SchemaWidgetFieldsetComponent } from './SchemaWidgetFieldset';
4
+ import SchemaWidgetFieldsetComponent from './SchemaWidgetFieldset';
5
+
6
+ jest.mock('@plone/volto/helpers/Loadable/Loadable');
7
+ beforeAll(
8
+ async () =>
9
+ await require('@plone/volto/helpers/Loadable/Loadable').__setLoadables(),
10
+ );
5
11
 
6
12
  test('renders a contents item component', () => {
7
13
  const component = renderer.create(
@@ -84,11 +84,11 @@ def TalkTypesVocabulary(context):
84
84
 
85
85
  import React from 'react';
86
86
  import { useDispatch } from 'react-redux';
87
- import { findIndex, remove } from 'lodash';
87
+ import { find, findIndex, remove } from 'lodash';
88
88
  import { defineMessages, useIntl } from 'react-intl';
89
89
  import { v4 as uuid } from 'uuid';
90
90
 
91
- import { Button, Segment } from 'semantic-ui-react';
91
+ import { Button } from 'semantic-ui-react';
92
92
 
93
93
  import {
94
94
  DragDropList,
@@ -134,6 +134,7 @@ const VocabularyTermsWidget = (props) => {
134
134
  var widgetvalue = value;
135
135
  const dispatch = useDispatch();
136
136
  const [toFocusId, setToFocusId] = React.useState('');
137
+ const [editableToken, setEditableToken] = React.useState('');
137
138
  const intl = useIntl();
138
139
 
139
140
  React.useEffect(() => {
@@ -206,6 +207,7 @@ const VocabularyTermsWidget = (props) => {
206
207
  items: newitems,
207
208
  });
208
209
  setToFocusId(`field-${supportedLanguages[0]}-0-${id}-${newtoken}`);
210
+ setEditableToken(newtoken);
209
211
  }
210
212
 
211
213
  function swap(arr, from, to) {
@@ -217,10 +219,7 @@ const VocabularyTermsWidget = (props) => {
217
219
  });
218
220
 
219
221
  return (
220
- <FormFieldWrapper {...props} className="dictwidget">
221
- <Segment basic>
222
- <h3>{props.title}</h3>
223
- </Segment>
222
+ <FormFieldWrapper {...props} className="vocabularytermswidget dictwidget">
224
223
  <div className="add-item-button-wrapper">
225
224
  <Button
226
225
  aria-label={intl.formatMessage(messages.termtitle)}
@@ -268,7 +267,7 @@ const VocabularyTermsWidget = (props) => {
268
267
  schema={TermSchema}
269
268
  title="Translation of term"
270
269
  />,
271
- termProps,
270
+ { editableToken, setEditableToken, ...termProps },
272
271
  );
273
272
  }}
274
273
  </DragDropList>
@@ -287,6 +286,33 @@ const TermsWrapper = (props) => {
287
286
  const { termProps, draginfo, children } = props;
288
287
  const { id, vocabularyterms, vterm, onChange } = termProps;
289
288
 
289
+ const _updateTermsWithNewToken = (term, newtoken) => {
290
+ let newitems = termProps.vocabularyterms;
291
+ let index = findIndex(newitems, { token: term.token });
292
+ newitems.splice(index, 1, {
293
+ token: newtoken,
294
+ titles: newitems[index].titles,
295
+ });
296
+ onChange(id, {
297
+ items: newitems,
298
+ });
299
+ };
300
+
301
+ function onChangeTokenHandler(event) {
302
+ let value = event.target.value;
303
+ // required token length: 3
304
+ if (value.length > 2) {
305
+ // check if value is different from already used tokens
306
+ if (find(termProps.vocabularyterms, (el) => el.token === value)) {
307
+ // token already token. Stay with uuid.
308
+ } else {
309
+ // `token '${value}' is OK`
310
+ _updateTermsWithNewToken(vterm, value);
311
+ termProps.setEditableToken('');
312
+ }
313
+ }
314
+ }
315
+
290
316
  return (
291
317
  <div
292
318
  ref={draginfo.innerRef}
@@ -299,6 +325,14 @@ const TermsWrapper = (props) => {
299
325
  </div>
300
326
  <div className="ui drag block inner">{children}</div>
301
327
  <div>
328
+ {vterm.token === termProps.editableToken ? (
329
+ <input
330
+ id={`token-${vterm.token}`}
331
+ title="Token"
332
+ placeholder="token"
333
+ onBlur={onChangeTokenHandler}
334
+ />
335
+ ) : null}
302
336
  <Button
303
337
  icon
304
338
  basic
@@ -1,10 +1,9 @@
1
- import VocabularyTermsWidget from './VocabularyTermsWidget';
2
1
  import React from 'react';
3
-
2
+ import VocabularyTermsWidget from './VocabularyTermsWidget';
4
3
  import WidgetStory from './story';
5
4
 
6
- export const JSONField = WidgetStory.bind({
7
- props: { id: 'simplevocabulary', title: 'Vocabulary terms' },
5
+ export const VocabularyTerms = WidgetStory.bind({
6
+ props: { id: 'vocabularyterms', title: 'Vocabulary terms', block: 'block' },
8
7
  widget: VocabularyTermsWidget,
9
8
  customStore: {
10
9
  userSession: { token: '1234' },
@@ -34,26 +33,12 @@ export const JSONField = WidgetStory.bind({
34
33
  ],
35
34
  },
36
35
  });
37
-
38
- export const Simple = WidgetStory.bind({
39
- props: { id: 'simplevocabulary', title: 'Vocabulary terms' },
40
- widget: VocabularyTermsWidget,
41
- customStore: {
42
- userSession: { token: '1234' },
43
- intl: {
44
- locale: 'en',
45
- messages: {},
46
- },
47
- },
48
- initialValue: {
49
- '001': 'manual',
50
- '002': 'questions & answers',
51
- },
52
- });
36
+ VocabularyTerms.args = {};
53
37
 
54
38
  export default {
55
- title: 'Widgets/Vocabulary',
39
+ title: 'Widgets/VocabularyTerms',
56
40
  component: VocabularyTermsWidget,
41
+ argTypes: {},
57
42
  decorators: [
58
43
  (Story) => (
59
44
  <div className="ui segment form attached" style={{ width: '600px' }}>
@@ -5,6 +5,12 @@ import { Provider } from 'react-intl-redux';
5
5
 
6
6
  import VocabularyTermsWidget from './VocabularyTermsWidget';
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
  let mockSerial = 0;
9
15
  const mockStore = configureStore();
10
16
 
@@ -124,7 +124,7 @@ class Navigation extends Component {
124
124
  */
125
125
  render() {
126
126
  return (
127
- <nav className="navigation" id="navigation">
127
+ <nav className="navigation" id="navigation" aria-label="navigation">
128
128
  <div className="hamburger-wrapper mobile tablet only">
129
129
  <button
130
130
  className={cx('hamburger hamburger--spin', {
@@ -29,4 +29,7 @@ export const loadables = {
29
29
  diffLib: loadable.lib(() => import('diff')),
30
30
  moment: loadable.lib(() => import('moment')),
31
31
  reactDates: loadable.lib(() => import('react-dates')),
32
+ reactDnd: loadable.lib(() => import('react-dnd')),
33
+ reactDndHtml5Backend: loadable.lib(() => import('react-dnd-html5-backend')),
34
+ reactBeautifulDnd: loadable.lib(() => import('react-beautiful-dnd')),
32
35
  };
@@ -133,6 +133,7 @@ let config = {
133
133
  'prismCore',
134
134
  'toastify',
135
135
  'reactSelect',
136
+ 'reactBeautifulDnd',
136
137
  // 'diffLib',
137
138
  ],
138
139
  },
@@ -138,7 +138,7 @@
138
138
 
139
139
  // Fake "disabled" field for language independent fields
140
140
  // Only on Add form
141
- #page-add .language-independent-field {
141
+ #page-add-translation #page-add .language-independent-field {
142
142
  pointer-events: none;
143
143
 
144
144
  input,