@plone/volto 17.0.0-alpha.1 → 17.0.0-alpha.2

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 (48) hide show
  1. package/.changelog.draft +21 -18
  2. package/.yarn/install-state.gz +0 -0
  3. package/CHANGELOG.md +62 -1
  4. package/README.md +4 -4
  5. package/cypress/support/commands.js +25 -0
  6. package/locales/ca/LC_MESSAGES/volto.po +5 -0
  7. package/locales/ca.json +1 -1
  8. package/locales/de/LC_MESSAGES/volto.po +5 -0
  9. package/locales/de.json +1 -1
  10. package/locales/en/LC_MESSAGES/volto.po +5 -0
  11. package/locales/en.json +1 -1
  12. package/locales/es/LC_MESSAGES/volto.po +5 -0
  13. package/locales/es.json +1 -1
  14. package/locales/eu/LC_MESSAGES/volto.po +5 -0
  15. package/locales/eu.json +1 -1
  16. package/locales/fi.json +1 -1
  17. package/locales/fr/LC_MESSAGES/volto.po +5 -0
  18. package/locales/fr.json +1 -1
  19. package/locales/it/LC_MESSAGES/volto.po +5 -0
  20. package/locales/it.json +1 -1
  21. package/locales/ja/LC_MESSAGES/volto.po +5 -0
  22. package/locales/ja.json +1 -1
  23. package/locales/nl/LC_MESSAGES/volto.po +5 -0
  24. package/locales/nl.json +1 -1
  25. package/locales/pt/LC_MESSAGES/volto.po +5 -0
  26. package/locales/pt.json +1 -1
  27. package/locales/pt_BR/LC_MESSAGES/volto.po +5 -0
  28. package/locales/pt_BR.json +1 -1
  29. package/locales/ro/LC_MESSAGES/volto.po +5 -0
  30. package/locales/ro.json +1 -1
  31. package/locales/volto.pot +5 -0
  32. package/locales/zh_CN/LC_MESSAGES/volto.po +5 -0
  33. package/locales/zh_CN.json +1 -1
  34. package/package-why.json +0 -1
  35. package/package.json +7 -7
  36. package/packages/volto-slate/package.json +1 -1
  37. package/packages/volto-slate/src/blocks/Table/index.js +2 -0
  38. package/src/components/manage/Blocks/Listing/Edit.jsx +0 -5
  39. package/src/components/manage/Blocks/Listing/ListingBody.jsx +77 -61
  40. package/src/components/manage/Blocks/Listing/View.jsx +0 -4
  41. package/src/components/manage/Blocks/ToC/Edit.jsx +1 -0
  42. package/src/components/manage/Contents/Contents.jsx +35 -8
  43. package/src/components/manage/Controlpanels/Controlpanels.jsx +1 -1
  44. package/src/components/manage/DragDropList/DragDropList.jsx +63 -42
  45. package/src/components/manage/Form/BlocksToolbar.jsx +5 -1
  46. package/src/components/manage/Form/Form.jsx +6 -2
  47. package/theme/themes/pastanaga/extras/contents.less +1 -0
  48. package/theme/themes/pastanaga/extras/main.less +80 -1
@@ -290,6 +290,10 @@ const messages = defineMessages({
290
290
  id: 'This Page is referenced by the following items:',
291
291
  defaultMessage: 'This Page is referenced by the following items:',
292
292
  },
293
+ deleteItemCountMessage: {
294
+ id: 'Total items to be deleted:',
295
+ defaultMessage: 'Total items to be deleted:',
296
+ },
293
297
  deleteItemMessage: {
294
298
  id: 'Items to be deleted:',
295
299
  defaultMessage: 'Items to be deleted:',
@@ -418,6 +422,8 @@ class Contents extends Component {
418
422
  this.paste = this.paste.bind(this);
419
423
  this.fetchContents = this.fetchContents.bind(this);
420
424
  this.orderTimeout = null;
425
+ this.deleteItemsToShowThreshold = 10;
426
+
421
427
  this.state = {
422
428
  selected: [],
423
429
  showDelete: false,
@@ -427,6 +433,7 @@ class Contents extends Component {
427
433
  showProperties: false,
428
434
  showWorkflow: false,
429
435
  itemsToDelete: [],
436
+ showAllItemsToDelete: true,
430
437
  items: this.props.items,
431
438
  filter: '',
432
439
  currentPage: 0,
@@ -456,7 +463,6 @@ class Contents extends Component {
456
463
  this.fetchContents();
457
464
  this.setState({ isClient: true });
458
465
  }
459
-
460
466
  async componentDidUpdate(_, prevState) {
461
467
  if (
462
468
  this.state.itemsToDelete !== prevState.itemsToDelete &&
@@ -468,6 +474,8 @@ class Contents extends Component {
468
474
  this.getFieldById(item, 'UID'),
469
475
  ),
470
476
  ),
477
+ showAllItemsToDelete:
478
+ this.state.itemsToDelete.length < this.deleteItemsToShowThreshold,
471
479
  });
472
480
  }
473
481
  }
@@ -1188,16 +1196,35 @@ class Contents extends Component {
1188
1196
  <div className="content">
1189
1197
  <h3>
1190
1198
  {this.props.intl.formatMessage(
1191
- messages.deleteItemMessage,
1192
- )}
1199
+ messages.deleteItemCountMessage,
1200
+ ) + ` ${this.state.itemsToDelete.length}`}
1193
1201
  </h3>
1194
1202
  <ul className="content">
1195
- {map(this.state.itemsToDelete, (item) => (
1196
- <li key={item}>
1197
- {this.getFieldById(item, 'title')}
1198
- </li>
1199
- ))}
1203
+ {map(
1204
+ this.state.showAllItemsToDelete
1205
+ ? this.state.itemsToDelete
1206
+ : this.state.itemsToDelete.slice(
1207
+ 0,
1208
+ this.deleteItemsToShowThreshold,
1209
+ ),
1210
+ (item) => (
1211
+ <li key={item}>
1212
+ {this.getFieldById(item, 'title')}
1213
+ </li>
1214
+ ),
1215
+ )}
1200
1216
  </ul>
1217
+ {!this.state.showAllItemsToDelete && (
1218
+ <Button
1219
+ onClick={() =>
1220
+ this.setState({
1221
+ showAllItemsToDelete: true,
1222
+ })
1223
+ }
1224
+ >
1225
+ Show all items
1226
+ </Button>
1227
+ )}
1201
1228
  {this.state.linkIntegrityBreakages.length > 0 ? (
1202
1229
  <div>
1203
1230
  <h3>
@@ -270,7 +270,7 @@ class Controlpanels extends Component {
270
270
  {group}
271
271
  </Segment>,
272
272
  <Segment key={`body-${group}`} attached>
273
- <Grid columns={6}>
273
+ <Grid doubling columns={6}>
274
274
  <Grid.Row>
275
275
  {map(filter(controlpanels, { group }), (controlpanel) => (
276
276
  <Grid.Column key={controlpanel.id}>
@@ -3,7 +3,7 @@ import { isEmpty } from 'lodash';
3
3
  import { injectLazyLibs } from '@plone/volto/helpers/Loadable/Loadable';
4
4
  import { v4 as uuid } from 'uuid';
5
5
 
6
- const getPlaceholder = (draggedDOM, sourceIndex, destinationIndex) => {
6
+ const getPlaceholder = (draggedDOM, sourceIndex, destinationIndex, uid) => {
7
7
  // Because of the margin rendering rules, there is no easy
8
8
  // way to calculate the offset of the placeholder.
9
9
  //
@@ -13,12 +13,16 @@ const getPlaceholder = (draggedDOM, sourceIndex, destinationIndex) => {
13
13
  //
14
14
  // To get a placeholder that looks good in all cases, we
15
15
  // fill up the space between the previous and the next element.
16
- const childrenArray = [...draggedDOM.parentNode.children];
16
+ const queryAttr = 'data-rbd-droppable-id';
17
+ const domQuery = `[${queryAttr}='${uid}']`;
18
+ const parentDOM = document.querySelector(domQuery);
19
+
20
+ const childrenArray = [...parentDOM.children];
17
21
  // Remove the source element
18
22
  childrenArray.splice(sourceIndex, 1);
19
23
  // Also remove the placeholder that the library always inserts at the end
20
24
  childrenArray.splice(-1, 1);
21
- const parentRect = draggedDOM.parentNode.getBoundingClientRect();
25
+ const parentRect = parentDOM.getBoundingClientRect();
22
26
  const prevNode = childrenArray[destinationIndex - 1];
23
27
  const nextNode = childrenArray[destinationIndex];
24
28
  let top, bottom;
@@ -40,9 +44,7 @@ const getPlaceholder = (draggedDOM, sourceIndex, destinationIndex) => {
40
44
  return {
41
45
  clientY: top,
42
46
  clientHeight: bottom - top,
43
- clientX: parseFloat(
44
- window.getComputedStyle(draggedDOM.parentNode).paddingLeft,
45
- ),
47
+ clientX: parseFloat(window.getComputedStyle(parentDOM).paddingLeft),
46
48
  clientWidth: draggedDOM.clientWidth,
47
49
  };
48
50
  };
@@ -63,17 +65,22 @@ const DragDropList = (props) => {
63
65
  // queueing timed action
64
66
  const timer = useRef(null);
65
67
 
66
- const onDragStart = React.useCallback((event) => {
67
- clearTimeout(timer.current);
68
- const queryAttr = 'data-rbd-draggable-id';
69
- const domQuery = `[${queryAttr}='${event.draggableId}']`;
70
- const draggedDOM = document.querySelector(domQuery);
71
- if (!draggedDOM) {
72
- return;
73
- }
74
- const sourceIndex = event.source.index;
75
- setPlaceholderProps(getPlaceholder(draggedDOM, sourceIndex, sourceIndex));
76
- }, []);
68
+ const onDragStart = React.useCallback(
69
+ (event) => {
70
+ clearTimeout(timer.current);
71
+ const queryAttr = 'data-rbd-draggable-id';
72
+ const domQuery = `[${queryAttr}='${event.draggableId}']`;
73
+ const draggedDOM = document.querySelector(domQuery);
74
+ if (!draggedDOM) {
75
+ return;
76
+ }
77
+ const sourceIndex = event.source.index;
78
+ setPlaceholderProps(
79
+ getPlaceholder(draggedDOM, sourceIndex, sourceIndex, uid),
80
+ );
81
+ },
82
+ [uid],
83
+ );
77
84
 
78
85
  const onDragEnd = React.useCallback(
79
86
  (result) => {
@@ -84,30 +91,33 @@ const DragDropList = (props) => {
84
91
  [onMoveItem],
85
92
  );
86
93
 
87
- const onDragUpdate = React.useCallback((update) => {
88
- clearTimeout(timer.current);
89
- setPlaceholderProps({});
90
- if (!update.destination) {
91
- return;
92
- }
93
- const draggableId = update.draggableId;
94
- const queryAttr = 'data-rbd-draggable-id';
95
- const domQuery = `[${queryAttr}='${draggableId}']`;
96
- const draggedDOM = document.querySelector(domQuery);
97
- if (!draggedDOM) {
98
- return;
99
- }
100
- const sourceIndex = update.source.index;
101
- const destinationIndex = update.destination.index;
102
- // Wait until the animations have finished, to make it look good.
103
- timer.current = setTimeout(
104
- () =>
105
- setPlaceholderProps(
106
- getPlaceholder(draggedDOM, sourceIndex, destinationIndex),
107
- ),
108
- 250,
109
- );
110
- }, []);
94
+ const onDragUpdate = React.useCallback(
95
+ (update) => {
96
+ clearTimeout(timer.current);
97
+ setPlaceholderProps({});
98
+ if (!update.destination) {
99
+ return;
100
+ }
101
+ const draggableId = update.draggableId;
102
+ const queryAttr = 'data-rbd-draggable-id';
103
+ const domQuery = `[${queryAttr}='${draggableId}']`;
104
+ const draggedDOM = document.querySelector(domQuery);
105
+ if (!draggedDOM) {
106
+ return;
107
+ }
108
+ const sourceIndex = update.source.index;
109
+ const destinationIndex = update.destination.index;
110
+ // Wait until the animations have finished, to make it look good.
111
+ timer.current = setTimeout(
112
+ () =>
113
+ setPlaceholderProps(
114
+ getPlaceholder(draggedDOM, sourceIndex, destinationIndex, uid),
115
+ ),
116
+ 250,
117
+ );
118
+ },
119
+ [uid],
120
+ );
111
121
 
112
122
  const AsDomComponent = as;
113
123
  return (
@@ -116,7 +126,18 @@ const DragDropList = (props) => {
116
126
  onDragUpdate={onDragUpdate}
117
127
  onDragEnd={onDragEnd}
118
128
  >
119
- <Droppable droppableId={uid}>
129
+ <Droppable
130
+ droppableId={uid}
131
+ renderClone={(provided, snapshot, rubric) => {
132
+ const index = rubric.source.index;
133
+ return children({
134
+ child: childList[index][1],
135
+ childId: childList[index][0],
136
+ index,
137
+ draginfo: provided,
138
+ });
139
+ }}
140
+ >
120
141
  {(provided, snapshot) => (
121
142
  <AsDomComponent
122
143
  ref={provided.innerRef}
@@ -177,7 +177,11 @@ export class BlocksToolbarComponent extends React.Component {
177
177
  ''
178
178
  )}
179
179
  {selectedBlock && (blocksClipboard?.cut || blocksClipboard?.copy) && (
180
- <Plug pluggable="main.toolbar.bottom" id="block-paste-btn">
180
+ <Plug
181
+ pluggable="main.toolbar.bottom"
182
+ id="block-paste-btn"
183
+ dependencies={[selectedBlock]}
184
+ >
181
185
  <button
182
186
  aria-label={intl.formatMessage(messages.pasteBlocks)}
183
187
  onClick={this.pasteBlocks}
@@ -258,7 +258,11 @@ class Form extends Component {
258
258
  * Tab selection is done only by setting activeIndex in state
259
259
  */
260
260
  onTabChange(e, { activeIndex }) {
261
- this.setState({ activeIndex });
261
+ const defaultFocus = this.props.schema.fieldsets[activeIndex].fields[0];
262
+ this.setState({
263
+ activeIndex,
264
+ ...(defaultFocus ? { inFocus: { [defaultFocus]: true } } : {}),
265
+ });
262
266
  }
263
267
 
264
268
  /**
@@ -686,7 +690,7 @@ class Form extends Component {
686
690
  id={field}
687
691
  formData={this.state.formData}
688
692
  fieldSet={item.title.toLowerCase()}
689
- focus={index === 0}
693
+ focus={this.state.inFocus[field]}
690
694
  value={this.state.formData?.[field]}
691
695
  required={schema.required.indexOf(field) !== -1}
692
696
  onChange={this.onChangeField}
@@ -38,6 +38,7 @@
38
38
  .ui.menu.top-menu {
39
39
  padding: 10px 0;
40
40
  border-bottom: 4px solid #c7d5d8;
41
+ overflow-x: scroll;
41
42
  }
42
43
 
43
44
  .ui.menu .menu.top-menu-menu {
@@ -8,7 +8,6 @@
8
8
  @import (multiple) '../../theme.config';
9
9
 
10
10
  // Extras (third party libs)
11
- @import (less) '~hamburgers/dist/hamburgers.css';
12
11
  @import (less) '~react-toastify/dist/ReactToastify.css';
13
12
 
14
13
  // Mixins
@@ -494,6 +493,86 @@ fieldset.invisible {
494
493
  .hamburger-wrapper {
495
494
  position: relative;
496
495
  z-index: 5;
496
+ width: 70px;
497
+ height: 59px;
498
+ padding: 15px 15px;
499
+
500
+ .hamburger {
501
+ position: relative;
502
+ width: 40px;
503
+ height: 24px;
504
+ padding: 0;
505
+ border: none;
506
+ background-color: transparent;
507
+ cursor: pointer;
508
+ transition: 0.3s ease-in-out;
509
+ }
510
+
511
+ .hamburger::after {
512
+ position: absolute;
513
+ top: 0;
514
+ left: 0;
515
+ display: inline-block;
516
+ width: 100%;
517
+ height: 4px;
518
+ background-color: #000;
519
+ border-radius: 4px;
520
+ content: '';
521
+ transition: 0.3s ease-in-out;
522
+ }
523
+
524
+ .hamburger::before {
525
+ position: absolute;
526
+ top: 20px;
527
+ left: 0;
528
+ display: inline-block;
529
+ width: 100%;
530
+ height: 4px;
531
+ background-color: #000;
532
+ border-radius: 4px;
533
+ content: '';
534
+ transition: 0.3s ease-in-out;
535
+ }
536
+
537
+ .hamburger-inner {
538
+ position: absolute;
539
+ top: 10px;
540
+ left: 0;
541
+ display: inline-block;
542
+ width: 100%;
543
+ height: 4px;
544
+ border-radius: 4px;
545
+ transition: 0.3s ease-in-out;
546
+ }
547
+
548
+ .hamburger.is-active::after,
549
+ .hamburger.is-active::before {
550
+ top: 10px;
551
+ left: 50%;
552
+ width: 0%;
553
+ }
554
+
555
+ .hamburger-inner::after,
556
+ .hamburger-inner::before {
557
+ position: absolute;
558
+ top: 0;
559
+ left: 0;
560
+ display: block;
561
+ width: 100%;
562
+ height: 4px;
563
+ background-color: #000;
564
+ border-radius: 4px;
565
+ content: '';
566
+ transition: 0.3s ease-in-out;
567
+ }
568
+
569
+ .hamburger.is-active .hamburger-inner::after {
570
+ transform: rotate(45deg);
571
+ }
572
+
573
+ .hamburger.is-active .hamburger-inner::before {
574
+ transform: rotate(-45deg);
575
+ }
497
576
  }
498
577
 
499
578
  .mobile-menu {