@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.
- package/.changelog.draft +21 -18
- package/.yarn/install-state.gz +0 -0
- package/CHANGELOG.md +62 -1
- package/README.md +4 -4
- package/cypress/support/commands.js +25 -0
- package/locales/ca/LC_MESSAGES/volto.po +5 -0
- package/locales/ca.json +1 -1
- package/locales/de/LC_MESSAGES/volto.po +5 -0
- package/locales/de.json +1 -1
- package/locales/en/LC_MESSAGES/volto.po +5 -0
- package/locales/en.json +1 -1
- package/locales/es/LC_MESSAGES/volto.po +5 -0
- package/locales/es.json +1 -1
- package/locales/eu/LC_MESSAGES/volto.po +5 -0
- package/locales/eu.json +1 -1
- package/locales/fi.json +1 -1
- package/locales/fr/LC_MESSAGES/volto.po +5 -0
- package/locales/fr.json +1 -1
- package/locales/it/LC_MESSAGES/volto.po +5 -0
- package/locales/it.json +1 -1
- package/locales/ja/LC_MESSAGES/volto.po +5 -0
- package/locales/ja.json +1 -1
- package/locales/nl/LC_MESSAGES/volto.po +5 -0
- package/locales/nl.json +1 -1
- package/locales/pt/LC_MESSAGES/volto.po +5 -0
- package/locales/pt.json +1 -1
- package/locales/pt_BR/LC_MESSAGES/volto.po +5 -0
- package/locales/pt_BR.json +1 -1
- package/locales/ro/LC_MESSAGES/volto.po +5 -0
- package/locales/ro.json +1 -1
- package/locales/volto.pot +5 -0
- package/locales/zh_CN/LC_MESSAGES/volto.po +5 -0
- package/locales/zh_CN.json +1 -1
- package/package-why.json +0 -1
- package/package.json +7 -7
- package/packages/volto-slate/package.json +1 -1
- package/packages/volto-slate/src/blocks/Table/index.js +2 -0
- package/src/components/manage/Blocks/Listing/Edit.jsx +0 -5
- package/src/components/manage/Blocks/Listing/ListingBody.jsx +77 -61
- package/src/components/manage/Blocks/Listing/View.jsx +0 -4
- package/src/components/manage/Blocks/ToC/Edit.jsx +1 -0
- package/src/components/manage/Contents/Contents.jsx +35 -8
- package/src/components/manage/Controlpanels/Controlpanels.jsx +1 -1
- package/src/components/manage/DragDropList/DragDropList.jsx +63 -42
- package/src/components/manage/Form/BlocksToolbar.jsx +5 -1
- package/src/components/manage/Form/Form.jsx +6 -2
- package/theme/themes/pastanaga/extras/contents.less +1 -0
- 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.
|
|
1192
|
-
)}
|
|
1199
|
+
messages.deleteItemCountMessage,
|
|
1200
|
+
) + ` ${this.state.itemsToDelete.length}`}
|
|
1193
1201
|
</h3>
|
|
1194
1202
|
<ul className="content">
|
|
1195
|
-
{map(
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
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
|
|
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 =
|
|
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(
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
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(
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
(
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
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
|
|
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
|
|
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.
|
|
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={
|
|
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}
|
|
@@ -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 {
|