@contentful/field-editor-reference 5.16.3 → 5.17.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/dist/cjs/assets/MultipleMediaEditor.js +3 -3
- package/dist/cjs/common/MultipleReferenceEditor.js +14 -18
- package/dist/cjs/common/SortableLinkList.js +96 -68
- package/dist/cjs/entries/MultipleEntryReferenceEditor.js +2 -2
- package/dist/cjs/resources/MultipleResourceReferenceEditor.js +7 -4
- package/dist/cjs/utils/useSortIDs.js +84 -0
- package/dist/esm/assets/MultipleMediaEditor.js +3 -3
- package/dist/esm/common/MultipleReferenceEditor.js +12 -11
- package/dist/esm/common/SortableLinkList.js +96 -29
- package/dist/esm/entries/MultipleEntryReferenceEditor.js +2 -2
- package/dist/esm/resources/MultipleResourceReferenceEditor.js +5 -2
- package/dist/esm/utils/useSortIDs.js +35 -0
- package/dist/types/common/MultipleReferenceEditor.d.ts +6 -3
- package/dist/types/common/SortableLinkList.d.ts +15 -7
- package/dist/types/utils/useSortIDs.d.ts +9 -0
- package/package.json +5 -4
|
@@ -9,6 +9,7 @@ Object.defineProperty(exports, "MultipleMediaEditor", {
|
|
|
9
9
|
}
|
|
10
10
|
});
|
|
11
11
|
const _react = _interop_require_wildcard(require("react"));
|
|
12
|
+
const _sortable = require("@dnd-kit/sortable");
|
|
12
13
|
const _emotion = require("emotion");
|
|
13
14
|
const _MultipleReferenceEditor = require("../common/MultipleReferenceEditor");
|
|
14
15
|
const _SortableLinkList = require("../common/SortableLinkList");
|
|
@@ -65,11 +66,10 @@ function MultipleMediaEditor(props) {
|
|
|
65
66
|
entityType: "Asset"
|
|
66
67
|
}, (childrenProps)=>_react.createElement(_SortableLinkList.SortableLinkList, {
|
|
67
68
|
...childrenProps,
|
|
69
|
+
sortingStrategy: childrenProps.viewType === 'card' ? _sortable.rectSortingStrategy : _sortable.verticalListSortingStrategy,
|
|
68
70
|
className: (0, _emotion.cx)({
|
|
69
71
|
[styles.gridContainer]: childrenProps.viewType === 'card'
|
|
70
|
-
})
|
|
71
|
-
axis: childrenProps.viewType === 'card' ? 'xy' : 'y',
|
|
72
|
-
useDragHandle: true
|
|
72
|
+
})
|
|
73
73
|
}, ({ items , item , index , isDisabled , DragHandle })=>_react.createElement(_FetchingWrappedAssetCard.FetchingWrappedAssetCard, {
|
|
74
74
|
...childrenProps,
|
|
75
75
|
isDisabled: isDisabled,
|
|
@@ -9,16 +9,12 @@ Object.defineProperty(exports, "MultipleReferenceEditor", {
|
|
|
9
9
|
}
|
|
10
10
|
});
|
|
11
11
|
const _react = _interop_require_wildcard(require("react"));
|
|
12
|
-
const
|
|
12
|
+
const _sortable = require("@dnd-kit/sortable");
|
|
13
13
|
const _components = require("../components");
|
|
14
14
|
const _LinkEntityActions = require("../components/LinkActions/LinkEntityActions");
|
|
15
|
+
const _useSortIDs = require("../utils/useSortIDs");
|
|
15
16
|
const _ReferenceEditor = require("./ReferenceEditor");
|
|
16
17
|
const _useEditorPermissions = require("./useEditorPermissions");
|
|
17
|
-
function _interop_require_default(obj) {
|
|
18
|
-
return obj && obj.__esModule ? obj : {
|
|
19
|
-
default: obj
|
|
20
|
-
};
|
|
21
|
-
}
|
|
22
18
|
function _getRequireWildcardCache(nodeInterop) {
|
|
23
19
|
if (typeof WeakMap !== "function") return null;
|
|
24
20
|
var cacheBabelInterop = new WeakMap();
|
|
@@ -77,39 +73,39 @@ const nullableValue = {
|
|
|
77
73
|
}
|
|
78
74
|
};
|
|
79
75
|
function Editor(props) {
|
|
80
|
-
const { setValue , entityType , setIndexToUpdate } = props;
|
|
76
|
+
const { setValue , entityType , onSortingEnd , setIndexToUpdate } = props;
|
|
81
77
|
const editorPermissions = (0, _useEditorPermissions.useEditorPermissions)(props);
|
|
82
78
|
const items = _react.useMemo(()=>{
|
|
83
79
|
return (props.items || []).map((link)=>link || nullableValue);
|
|
84
80
|
}, [
|
|
85
81
|
props.items
|
|
86
82
|
]);
|
|
87
|
-
const
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
}
|
|
91
|
-
event.preventDefault();
|
|
83
|
+
const { rearrangeSortIDs } = (0, _useSortIDs.useSortIDs)(items);
|
|
84
|
+
const onSortStart = (0, _react.useCallback)(()=>{
|
|
85
|
+
document.body.classList.add('grabbing');
|
|
92
86
|
}, []);
|
|
93
87
|
const onSortEnd = (0, _react.useCallback)(({ oldIndex , newIndex })=>{
|
|
94
|
-
|
|
88
|
+
onSortingEnd && onSortingEnd({
|
|
95
89
|
oldIndex,
|
|
96
90
|
newIndex
|
|
97
91
|
});
|
|
98
|
-
const newItems = (0,
|
|
92
|
+
const newItems = (0, _sortable.arrayMove)(items, oldIndex, newIndex);
|
|
99
93
|
setValue(newItems);
|
|
100
94
|
setIndexToUpdate && setIndexToUpdate(undefined);
|
|
101
95
|
document.body.classList.remove('grabbing');
|
|
102
96
|
}, [
|
|
103
97
|
items,
|
|
104
|
-
|
|
98
|
+
onSortingEnd,
|
|
105
99
|
setIndexToUpdate,
|
|
106
100
|
setValue
|
|
107
101
|
]);
|
|
108
102
|
const onMove = (0, _react.useCallback)((oldIndex, newIndex)=>{
|
|
109
|
-
const newItems = (0,
|
|
103
|
+
const newItems = (0, _sortable.arrayMove)(items, oldIndex, newIndex);
|
|
104
|
+
rearrangeSortIDs(oldIndex, newIndex);
|
|
110
105
|
setValue(newItems);
|
|
111
106
|
}, [
|
|
112
107
|
items,
|
|
108
|
+
rearrangeSortIDs,
|
|
113
109
|
setValue
|
|
114
110
|
]);
|
|
115
111
|
const onCreate = (0, _react.useCallback)((id, index)=>onLinkOrCreate(setValue, entityType, items, [
|
|
@@ -137,8 +133,8 @@ function Editor(props) {
|
|
|
137
133
|
]);
|
|
138
134
|
return _react.createElement(_react.Fragment, null, props.children({
|
|
139
135
|
...props,
|
|
140
|
-
onSortStart
|
|
141
|
-
onSortEnd
|
|
136
|
+
onSortStart,
|
|
137
|
+
onSortEnd,
|
|
142
138
|
onMove,
|
|
143
139
|
renderCustomCard: props.renderCustomCard && customCardRenderer
|
|
144
140
|
}), _react.createElement(_components.LinkEntityActions, {
|
|
@@ -8,88 +8,116 @@ Object.defineProperty(exports, "SortableLinkList", {
|
|
|
8
8
|
return SortableLinkList;
|
|
9
9
|
}
|
|
10
10
|
});
|
|
11
|
-
const _react =
|
|
12
|
-
const _reactsortablehoc = require("react-sortable-hoc");
|
|
11
|
+
const _react = _interop_require_default(require("react"));
|
|
13
12
|
const _f36tokens = _interop_require_default(require("@contentful/f36-tokens"));
|
|
13
|
+
const _core = require("@dnd-kit/core");
|
|
14
|
+
const _sortable = require("@dnd-kit/sortable");
|
|
15
|
+
const _utilities = require("@dnd-kit/utilities");
|
|
14
16
|
const _emotion = require("emotion");
|
|
17
|
+
const _useSortIDs = require("../utils/useSortIDs");
|
|
15
18
|
function _interop_require_default(obj) {
|
|
16
19
|
return obj && obj.__esModule ? obj : {
|
|
17
20
|
default: obj
|
|
18
21
|
};
|
|
19
22
|
}
|
|
20
|
-
function _getRequireWildcardCache(nodeInterop) {
|
|
21
|
-
if (typeof WeakMap !== "function") return null;
|
|
22
|
-
var cacheBabelInterop = new WeakMap();
|
|
23
|
-
var cacheNodeInterop = new WeakMap();
|
|
24
|
-
return (_getRequireWildcardCache = function(nodeInterop) {
|
|
25
|
-
return nodeInterop ? cacheNodeInterop : cacheBabelInterop;
|
|
26
|
-
})(nodeInterop);
|
|
27
|
-
}
|
|
28
|
-
function _interop_require_wildcard(obj, nodeInterop) {
|
|
29
|
-
if (!nodeInterop && obj && obj.__esModule) {
|
|
30
|
-
return obj;
|
|
31
|
-
}
|
|
32
|
-
if (obj === null || typeof obj !== "object" && typeof obj !== "function") {
|
|
33
|
-
return {
|
|
34
|
-
default: obj
|
|
35
|
-
};
|
|
36
|
-
}
|
|
37
|
-
var cache = _getRequireWildcardCache(nodeInterop);
|
|
38
|
-
if (cache && cache.has(obj)) {
|
|
39
|
-
return cache.get(obj);
|
|
40
|
-
}
|
|
41
|
-
var newObj = {};
|
|
42
|
-
var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor;
|
|
43
|
-
for(var key in obj){
|
|
44
|
-
if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) {
|
|
45
|
-
var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null;
|
|
46
|
-
if (desc && (desc.get || desc.set)) {
|
|
47
|
-
Object.defineProperty(newObj, key, desc);
|
|
48
|
-
} else {
|
|
49
|
-
newObj[key] = obj[key];
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
newObj.default = obj;
|
|
54
|
-
if (cache) {
|
|
55
|
-
cache.set(obj, newObj);
|
|
56
|
-
}
|
|
57
|
-
return newObj;
|
|
58
|
-
}
|
|
59
23
|
const styles = {
|
|
60
24
|
container: (0, _emotion.css)({
|
|
61
25
|
position: 'relative'
|
|
62
26
|
}),
|
|
63
27
|
item: (0, _emotion.css)({
|
|
64
|
-
|
|
28
|
+
position: 'relative',
|
|
29
|
+
marginBottom: _f36tokens.default.spacingM
|
|
30
|
+
}),
|
|
31
|
+
isDragging: (0, _emotion.css)({
|
|
65
32
|
zIndex: _f36tokens.default.zIndexModal
|
|
33
|
+
}),
|
|
34
|
+
dragHandle: (0, _emotion.css)({
|
|
35
|
+
display: 'flex'
|
|
66
36
|
})
|
|
67
37
|
};
|
|
68
|
-
const
|
|
69
|
-
const
|
|
70
|
-
|
|
38
|
+
const SortableLink = ({ id , items , item , isDisabled =false , index , children })=>{
|
|
39
|
+
const { listeners , setNodeRef , setActivatorNodeRef , transform , transition , isDragging } = (0, _sortable.useSortable)({
|
|
40
|
+
id
|
|
41
|
+
});
|
|
42
|
+
const style = {
|
|
43
|
+
transform: transform ? _utilities.CSS.Transform.toString({
|
|
44
|
+
...transform,
|
|
45
|
+
scaleX: 1,
|
|
46
|
+
scaleY: 1
|
|
47
|
+
}) : '',
|
|
48
|
+
transition
|
|
49
|
+
};
|
|
50
|
+
const DragHandle = _react.default.useCallback((props)=>{
|
|
51
|
+
const SortableDragHandle = ()=>props.drag;
|
|
52
|
+
return _react.default.createElement("div", {
|
|
53
|
+
ref: setActivatorNodeRef,
|
|
54
|
+
className: styles.dragHandle,
|
|
55
|
+
...listeners
|
|
56
|
+
}, _react.default.createElement(SortableDragHandle, null));
|
|
57
|
+
}, [
|
|
58
|
+
listeners,
|
|
59
|
+
setActivatorNodeRef
|
|
60
|
+
]);
|
|
61
|
+
return _react.default.createElement("div", {
|
|
62
|
+
ref: setNodeRef,
|
|
63
|
+
style: style,
|
|
64
|
+
className: (0, _emotion.cx)(styles.item, {
|
|
65
|
+
[styles.isDragging]: isDragging
|
|
66
|
+
})
|
|
67
|
+
}, children({
|
|
68
|
+
items,
|
|
69
|
+
isDisabled,
|
|
70
|
+
item,
|
|
71
|
+
index,
|
|
72
|
+
DragHandle: isDisabled ? undefined : DragHandle
|
|
73
|
+
}));
|
|
71
74
|
};
|
|
72
|
-
const
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
const
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
75
|
+
const SortableLinkList = ({ items , isDisabled , className , children , onSortStart , onSortEnd , updateBeforeSortStart , sortingStrategy })=>{
|
|
76
|
+
const { sortIDs , rearrangeSortIDs } = (0, _useSortIDs.useSortIDs)(items);
|
|
77
|
+
const onSortStartHandler = _react.default.useCallback((event)=>{
|
|
78
|
+
const index = sortIDs.findIndex((item)=>item.id === event.active.id);
|
|
79
|
+
updateBeforeSortStart?.({
|
|
80
|
+
index
|
|
81
|
+
});
|
|
82
|
+
onSortStart?.(event);
|
|
83
|
+
}, [
|
|
84
|
+
updateBeforeSortStart,
|
|
85
|
+
onSortStart,
|
|
86
|
+
sortIDs
|
|
87
|
+
]);
|
|
88
|
+
const onSortEndHandler = _react.default.useCallback((event)=>{
|
|
89
|
+
const { active , over } = event;
|
|
90
|
+
if (active && over && active.id !== over.id) {
|
|
91
|
+
const oldIndex = sortIDs.findIndex((item)=>item.id === active.id);
|
|
92
|
+
const newIndex = sortIDs.findIndex((item)=>item.id === over.id);
|
|
93
|
+
rearrangeSortIDs(oldIndex, newIndex);
|
|
94
|
+
onSortEnd?.({
|
|
95
|
+
oldIndex,
|
|
96
|
+
newIndex
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
}, [
|
|
100
|
+
onSortEnd,
|
|
101
|
+
sortIDs,
|
|
102
|
+
rearrangeSortIDs
|
|
103
|
+
]);
|
|
104
|
+
return _react.default.createElement(_core.DndContext, {
|
|
105
|
+
onDragStart: onSortStartHandler,
|
|
106
|
+
onDragEnd: onSortEndHandler
|
|
107
|
+
}, _react.default.createElement(_sortable.SortableContext, {
|
|
108
|
+
items: sortIDs,
|
|
109
|
+
strategy: sortingStrategy
|
|
110
|
+
}, _react.default.createElement("div", {
|
|
111
|
+
className: (0, _emotion.cx)(styles.container, className)
|
|
112
|
+
}, items.map((item, index)=>{
|
|
113
|
+
const id = sortIDs[index]?.id;
|
|
114
|
+
return _react.default.createElement(SortableLink, {
|
|
115
|
+
key: id,
|
|
116
|
+
id: id,
|
|
117
|
+
items: items,
|
|
118
|
+
item: item,
|
|
119
|
+
isDisabled: isDisabled,
|
|
81
120
|
index: index
|
|
82
|
-
},
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
item,
|
|
86
|
-
index,
|
|
87
|
-
DragHandle: props.isDisabled ? undefined : DragHandle
|
|
88
|
-
}))));
|
|
89
|
-
});
|
|
90
|
-
function SortableLinkList(props) {
|
|
91
|
-
return _react.createElement(SortableLinkListInternal, {
|
|
92
|
-
distance: 1,
|
|
93
|
-
...props
|
|
94
|
-
}, props.children);
|
|
95
|
-
}
|
|
121
|
+
}, children);
|
|
122
|
+
}))));
|
|
123
|
+
};
|
|
@@ -9,6 +9,7 @@ Object.defineProperty(exports, "MultipleEntryReferenceEditor", {
|
|
|
9
9
|
}
|
|
10
10
|
});
|
|
11
11
|
const _react = _interop_require_wildcard(require("react"));
|
|
12
|
+
const _sortable = require("@dnd-kit/sortable");
|
|
12
13
|
const _MultipleReferenceEditor = require("../common/MultipleReferenceEditor");
|
|
13
14
|
const _SortableLinkList = require("../common/SortableLinkList");
|
|
14
15
|
const _FetchingWrappedEntryCard = require("./WrappedEntryCard/FetchingWrappedEntryCard");
|
|
@@ -62,8 +63,7 @@ function MultipleEntryReferenceEditor(props) {
|
|
|
62
63
|
setIndexToUpdate: setIndexToUpdate
|
|
63
64
|
}, (childrenProps)=>_react.createElement(_SortableLinkList.SortableLinkList, {
|
|
64
65
|
...childrenProps,
|
|
65
|
-
|
|
66
|
-
useDragHandle: true,
|
|
66
|
+
sortingStrategy: _sortable.verticalListSortingStrategy,
|
|
67
67
|
updateBeforeSortStart: updateBeforeSortStart
|
|
68
68
|
}, ({ items , item , index , isDisabled , DragHandle })=>{
|
|
69
69
|
const lastIndex = items.length - 1;
|
|
@@ -10,8 +10,9 @@ Object.defineProperty(exports, "MultipleResourceReferenceEditor", {
|
|
|
10
10
|
});
|
|
11
11
|
const _react = _interop_require_wildcard(require("react"));
|
|
12
12
|
const _fieldeditorshared = require("@contentful/field-editor-shared");
|
|
13
|
-
const
|
|
13
|
+
const _sortable = require("@dnd-kit/sortable");
|
|
14
14
|
const _deepequal = _interop_require_default(require("deep-equal"));
|
|
15
|
+
const _noop = _interop_require_default(require("lodash/noop"));
|
|
15
16
|
const _EntityStore = require("../common/EntityStore");
|
|
16
17
|
const _SortableLinkList = require("../common/SortableLinkList");
|
|
17
18
|
const _LinkEntityActions = require("../components/LinkActions/LinkEntityActions");
|
|
@@ -63,16 +64,16 @@ function _interop_require_wildcard(obj, nodeInterop) {
|
|
|
63
64
|
}
|
|
64
65
|
function ResourceEditor(props) {
|
|
65
66
|
const { setValue , items , apiUrl } = props;
|
|
66
|
-
const onSortStart = (0,
|
|
67
|
+
const onSortStart = ()=>(0, _noop.default)();
|
|
67
68
|
const onSortEnd = (0, _react.useCallback)(({ oldIndex , newIndex })=>{
|
|
68
|
-
const newItems = (0,
|
|
69
|
+
const newItems = (0, _sortable.arrayMove)(items, oldIndex, newIndex);
|
|
69
70
|
setValue(newItems);
|
|
70
71
|
}, [
|
|
71
72
|
items,
|
|
72
73
|
setValue
|
|
73
74
|
]);
|
|
74
75
|
const onMove = (0, _react.useCallback)((oldIndex, newIndex)=>{
|
|
75
|
-
const newItems = (0,
|
|
76
|
+
const newItems = (0, _sortable.arrayMove)(items, oldIndex, newIndex);
|
|
76
77
|
setValue(newItems);
|
|
77
78
|
}, [
|
|
78
79
|
items,
|
|
@@ -139,11 +140,13 @@ function MultipleResourceReferenceEditor(props) {
|
|
|
139
140
|
renderCustomActions: props.renderCustomActions,
|
|
140
141
|
key: `${externalReset}-list`
|
|
141
142
|
}, (editorProps)=>_react.createElement(_SortableLinkList.SortableLinkList, editorProps, ({ item , isDisabled , DragHandle , index })=>_react.createElement(WithPerItemCallbacks, {
|
|
143
|
+
key: index,
|
|
142
144
|
index: index,
|
|
143
145
|
onMove: editorProps.onMove,
|
|
144
146
|
onRemoteItemAtIndex: editorProps.onRemoteItemAtIndex,
|
|
145
147
|
listLength: value?.length || 0
|
|
146
148
|
}, ({ onMoveBottom , onMoveTop , onRemove })=>_react.createElement(_ResourceCard.ResourceCard, {
|
|
149
|
+
key: index,
|
|
147
150
|
index: index,
|
|
148
151
|
resourceLink: item,
|
|
149
152
|
isDisabled: isDisabled,
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
Object.defineProperty(exports, "useSortIDs", {
|
|
6
|
+
enumerable: true,
|
|
7
|
+
get: function() {
|
|
8
|
+
return useSortIDs;
|
|
9
|
+
}
|
|
10
|
+
});
|
|
11
|
+
const _react = _interop_require_wildcard(require("react"));
|
|
12
|
+
const _sortable = require("@dnd-kit/sortable");
|
|
13
|
+
function _getRequireWildcardCache(nodeInterop) {
|
|
14
|
+
if (typeof WeakMap !== "function") return null;
|
|
15
|
+
var cacheBabelInterop = new WeakMap();
|
|
16
|
+
var cacheNodeInterop = new WeakMap();
|
|
17
|
+
return (_getRequireWildcardCache = function(nodeInterop) {
|
|
18
|
+
return nodeInterop ? cacheNodeInterop : cacheBabelInterop;
|
|
19
|
+
})(nodeInterop);
|
|
20
|
+
}
|
|
21
|
+
function _interop_require_wildcard(obj, nodeInterop) {
|
|
22
|
+
if (!nodeInterop && obj && obj.__esModule) {
|
|
23
|
+
return obj;
|
|
24
|
+
}
|
|
25
|
+
if (obj === null || typeof obj !== "object" && typeof obj !== "function") {
|
|
26
|
+
return {
|
|
27
|
+
default: obj
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
var cache = _getRequireWildcardCache(nodeInterop);
|
|
31
|
+
if (cache && cache.has(obj)) {
|
|
32
|
+
return cache.get(obj);
|
|
33
|
+
}
|
|
34
|
+
var newObj = {};
|
|
35
|
+
var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor;
|
|
36
|
+
for(var key in obj){
|
|
37
|
+
if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) {
|
|
38
|
+
var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null;
|
|
39
|
+
if (desc && (desc.get || desc.set)) {
|
|
40
|
+
Object.defineProperty(newObj, key, desc);
|
|
41
|
+
} else {
|
|
42
|
+
newObj[key] = obj[key];
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
newObj.default = obj;
|
|
47
|
+
if (cache) {
|
|
48
|
+
cache.set(obj, newObj);
|
|
49
|
+
}
|
|
50
|
+
return newObj;
|
|
51
|
+
}
|
|
52
|
+
const useSortIDs = (items)=>{
|
|
53
|
+
const ids = (items || []).map((item, index)=>{
|
|
54
|
+
const { type } = item.sys;
|
|
55
|
+
return {
|
|
56
|
+
id: type === 'ResourceLink' ? `${item.sys.urn}-${index}` : `${item.sys.id}-${index}`
|
|
57
|
+
};
|
|
58
|
+
});
|
|
59
|
+
const [sortIDs, setSortIDs] = (0, _react.useState)(ids);
|
|
60
|
+
_react.default.useEffect(()=>{
|
|
61
|
+
if (items.length !== sortIDs.length) {
|
|
62
|
+
const ids = items.map((item, index)=>{
|
|
63
|
+
const { type } = item.sys;
|
|
64
|
+
return {
|
|
65
|
+
id: type === 'ResourceLink' ? `${item.sys.urn}-${index}` : `${item.sys.id}-${index}`
|
|
66
|
+
};
|
|
67
|
+
});
|
|
68
|
+
setSortIDs(ids);
|
|
69
|
+
}
|
|
70
|
+
}, [
|
|
71
|
+
items,
|
|
72
|
+
sortIDs.length
|
|
73
|
+
]);
|
|
74
|
+
const rearrangeSortIDs = (0, _react.useCallback)((oldIndex, newIndex)=>{
|
|
75
|
+
const newSortIDs = (0, _sortable.arrayMove)(sortIDs, oldIndex, newIndex);
|
|
76
|
+
setSortIDs(newSortIDs);
|
|
77
|
+
}, [
|
|
78
|
+
sortIDs
|
|
79
|
+
]);
|
|
80
|
+
return {
|
|
81
|
+
sortIDs,
|
|
82
|
+
rearrangeSortIDs
|
|
83
|
+
};
|
|
84
|
+
};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
+
import { rectSortingStrategy, verticalListSortingStrategy } from '@dnd-kit/sortable';
|
|
2
3
|
import { css, cx } from 'emotion';
|
|
3
4
|
import { MultipleReferenceEditor } from '../common/MultipleReferenceEditor';
|
|
4
5
|
import { SortableLinkList } from '../common/SortableLinkList';
|
|
@@ -16,11 +17,10 @@ export function MultipleMediaEditor(props) {
|
|
|
16
17
|
entityType: "Asset"
|
|
17
18
|
}, (childrenProps)=>React.createElement(SortableLinkList, {
|
|
18
19
|
...childrenProps,
|
|
20
|
+
sortingStrategy: childrenProps.viewType === 'card' ? rectSortingStrategy : verticalListSortingStrategy,
|
|
19
21
|
className: cx({
|
|
20
22
|
[styles.gridContainer]: childrenProps.viewType === 'card'
|
|
21
|
-
})
|
|
22
|
-
axis: childrenProps.viewType === 'card' ? 'xy' : 'y',
|
|
23
|
-
useDragHandle: true
|
|
23
|
+
})
|
|
24
24
|
}, ({ items , item , index , isDisabled , DragHandle })=>React.createElement(FetchingWrappedAssetCard, {
|
|
25
25
|
...childrenProps,
|
|
26
26
|
isDisabled: isDisabled,
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { useCallback } from 'react';
|
|
3
|
-
import arrayMove from '
|
|
3
|
+
import { arrayMove } from '@dnd-kit/sortable';
|
|
4
4
|
import { LinkEntityActions } from '../components';
|
|
5
5
|
import { useLinkActionsProps } from '../components/LinkActions/LinkEntityActions';
|
|
6
|
+
import { useSortIDs } from '../utils/useSortIDs';
|
|
6
7
|
import { ReferenceEditor } from './ReferenceEditor';
|
|
7
8
|
import { useEditorPermissions } from './useEditorPermissions';
|
|
8
9
|
function onLinkOrCreate(setValue, entityType, items, ids, index = items.length) {
|
|
@@ -24,21 +25,19 @@ const nullableValue = {
|
|
|
24
25
|
}
|
|
25
26
|
};
|
|
26
27
|
function Editor(props) {
|
|
27
|
-
const { setValue , entityType , setIndexToUpdate } = props;
|
|
28
|
+
const { setValue , entityType , onSortingEnd , setIndexToUpdate } = props;
|
|
28
29
|
const editorPermissions = useEditorPermissions(props);
|
|
29
30
|
const items = React.useMemo(()=>{
|
|
30
31
|
return (props.items || []).map((link)=>link || nullableValue);
|
|
31
32
|
}, [
|
|
32
33
|
props.items
|
|
33
34
|
]);
|
|
34
|
-
const
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
}
|
|
38
|
-
event.preventDefault();
|
|
35
|
+
const { rearrangeSortIDs } = useSortIDs(items);
|
|
36
|
+
const onSortStart = useCallback(()=>{
|
|
37
|
+
document.body.classList.add('grabbing');
|
|
39
38
|
}, []);
|
|
40
39
|
const onSortEnd = useCallback(({ oldIndex , newIndex })=>{
|
|
41
|
-
|
|
40
|
+
onSortingEnd && onSortingEnd({
|
|
42
41
|
oldIndex,
|
|
43
42
|
newIndex
|
|
44
43
|
});
|
|
@@ -48,15 +47,17 @@ function Editor(props) {
|
|
|
48
47
|
document.body.classList.remove('grabbing');
|
|
49
48
|
}, [
|
|
50
49
|
items,
|
|
51
|
-
|
|
50
|
+
onSortingEnd,
|
|
52
51
|
setIndexToUpdate,
|
|
53
52
|
setValue
|
|
54
53
|
]);
|
|
55
54
|
const onMove = useCallback((oldIndex, newIndex)=>{
|
|
56
55
|
const newItems = arrayMove(items, oldIndex, newIndex);
|
|
56
|
+
rearrangeSortIDs(oldIndex, newIndex);
|
|
57
57
|
setValue(newItems);
|
|
58
58
|
}, [
|
|
59
59
|
items,
|
|
60
|
+
rearrangeSortIDs,
|
|
60
61
|
setValue
|
|
61
62
|
]);
|
|
62
63
|
const onCreate = useCallback((id, index)=>onLinkOrCreate(setValue, entityType, items, [
|
|
@@ -84,8 +85,8 @@ function Editor(props) {
|
|
|
84
85
|
]);
|
|
85
86
|
return React.createElement(React.Fragment, null, props.children({
|
|
86
87
|
...props,
|
|
87
|
-
onSortStart
|
|
88
|
-
onSortEnd
|
|
88
|
+
onSortStart,
|
|
89
|
+
onSortEnd,
|
|
89
90
|
onMove,
|
|
90
91
|
renderCustomCard: props.renderCustomCard && customCardRenderer
|
|
91
92
|
}), React.createElement(LinkEntityActions, {
|
|
@@ -1,41 +1,108 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { SortableContainer, SortableElement, SortableHandle } from 'react-sortable-hoc';
|
|
1
|
+
import React from 'react';
|
|
3
2
|
import tokens from '@contentful/f36-tokens';
|
|
3
|
+
import { DndContext } from '@dnd-kit/core';
|
|
4
|
+
import { SortableContext, useSortable } from '@dnd-kit/sortable';
|
|
5
|
+
import { CSS } from '@dnd-kit/utilities';
|
|
4
6
|
import { css, cx } from 'emotion';
|
|
7
|
+
import { useSortIDs } from '../utils/useSortIDs';
|
|
5
8
|
const styles = {
|
|
6
9
|
container: css({
|
|
7
10
|
position: 'relative'
|
|
8
11
|
}),
|
|
9
12
|
item: css({
|
|
10
|
-
|
|
13
|
+
position: 'relative',
|
|
14
|
+
marginBottom: tokens.spacingM
|
|
15
|
+
}),
|
|
16
|
+
isDragging: css({
|
|
11
17
|
zIndex: tokens.zIndexModal
|
|
18
|
+
}),
|
|
19
|
+
dragHandle: css({
|
|
20
|
+
display: 'flex'
|
|
12
21
|
})
|
|
13
22
|
};
|
|
14
|
-
const
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
};
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
23
|
+
const SortableLink = ({ id , items , item , isDisabled =false , index , children })=>{
|
|
24
|
+
const { listeners , setNodeRef , setActivatorNodeRef , transform , transition , isDragging } = useSortable({
|
|
25
|
+
id
|
|
26
|
+
});
|
|
27
|
+
const style = {
|
|
28
|
+
transform: transform ? CSS.Transform.toString({
|
|
29
|
+
...transform,
|
|
30
|
+
scaleX: 1,
|
|
31
|
+
scaleY: 1
|
|
32
|
+
}) : '',
|
|
33
|
+
transition
|
|
34
|
+
};
|
|
35
|
+
const DragHandle = React.useCallback((props)=>{
|
|
36
|
+
const SortableDragHandle = ()=>props.drag;
|
|
37
|
+
return React.createElement("div", {
|
|
38
|
+
ref: setActivatorNodeRef,
|
|
39
|
+
className: styles.dragHandle,
|
|
40
|
+
...listeners
|
|
41
|
+
}, React.createElement(SortableDragHandle, null));
|
|
42
|
+
}, [
|
|
43
|
+
listeners,
|
|
44
|
+
setActivatorNodeRef
|
|
45
|
+
]);
|
|
22
46
|
return React.createElement("div", {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
47
|
+
ref: setNodeRef,
|
|
48
|
+
style: style,
|
|
49
|
+
className: cx(styles.item, {
|
|
50
|
+
[styles.isDragging]: isDragging
|
|
51
|
+
})
|
|
52
|
+
}, children({
|
|
53
|
+
items,
|
|
54
|
+
isDisabled,
|
|
55
|
+
item,
|
|
56
|
+
index,
|
|
57
|
+
DragHandle: isDisabled ? undefined : DragHandle
|
|
58
|
+
}));
|
|
59
|
+
};
|
|
60
|
+
export const SortableLinkList = ({ items , isDisabled , className , children , onSortStart , onSortEnd , updateBeforeSortStart , sortingStrategy })=>{
|
|
61
|
+
const { sortIDs , rearrangeSortIDs } = useSortIDs(items);
|
|
62
|
+
const onSortStartHandler = React.useCallback((event)=>{
|
|
63
|
+
const index = sortIDs.findIndex((item)=>item.id === event.active.id);
|
|
64
|
+
updateBeforeSortStart?.({
|
|
65
|
+
index
|
|
66
|
+
});
|
|
67
|
+
onSortStart?.(event);
|
|
68
|
+
}, [
|
|
69
|
+
updateBeforeSortStart,
|
|
70
|
+
onSortStart,
|
|
71
|
+
sortIDs
|
|
72
|
+
]);
|
|
73
|
+
const onSortEndHandler = React.useCallback((event)=>{
|
|
74
|
+
const { active , over } = event;
|
|
75
|
+
if (active && over && active.id !== over.id) {
|
|
76
|
+
const oldIndex = sortIDs.findIndex((item)=>item.id === active.id);
|
|
77
|
+
const newIndex = sortIDs.findIndex((item)=>item.id === over.id);
|
|
78
|
+
rearrangeSortIDs(oldIndex, newIndex);
|
|
79
|
+
onSortEnd?.({
|
|
80
|
+
oldIndex,
|
|
81
|
+
newIndex
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
}, [
|
|
85
|
+
onSortEnd,
|
|
86
|
+
sortIDs,
|
|
87
|
+
rearrangeSortIDs
|
|
88
|
+
]);
|
|
89
|
+
return React.createElement(DndContext, {
|
|
90
|
+
onDragStart: onSortStartHandler,
|
|
91
|
+
onDragEnd: onSortEndHandler
|
|
92
|
+
}, React.createElement(SortableContext, {
|
|
93
|
+
items: sortIDs,
|
|
94
|
+
strategy: sortingStrategy
|
|
95
|
+
}, React.createElement("div", {
|
|
96
|
+
className: cx(styles.container, className)
|
|
97
|
+
}, items.map((item, index)=>{
|
|
98
|
+
const id = sortIDs[index]?.id;
|
|
99
|
+
return React.createElement(SortableLink, {
|
|
100
|
+
key: id,
|
|
101
|
+
id: id,
|
|
102
|
+
items: items,
|
|
103
|
+
item: item,
|
|
104
|
+
isDisabled: isDisabled,
|
|
27
105
|
index: index
|
|
28
|
-
},
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
item,
|
|
32
|
-
index,
|
|
33
|
-
DragHandle: props.isDisabled ? undefined : DragHandle
|
|
34
|
-
}))));
|
|
35
|
-
});
|
|
36
|
-
export function SortableLinkList(props) {
|
|
37
|
-
return React.createElement(SortableLinkListInternal, {
|
|
38
|
-
distance: 1,
|
|
39
|
-
...props
|
|
40
|
-
}, props.children);
|
|
41
|
-
}
|
|
106
|
+
}, children);
|
|
107
|
+
}))));
|
|
108
|
+
};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
+
import { verticalListSortingStrategy } from '@dnd-kit/sortable';
|
|
2
3
|
import { MultipleReferenceEditor } from '../common/MultipleReferenceEditor';
|
|
3
4
|
import { SortableLinkList } from '../common/SortableLinkList';
|
|
4
5
|
import { FetchingWrappedEntryCard } from './WrappedEntryCard/FetchingWrappedEntryCard';
|
|
@@ -13,8 +14,7 @@ export function MultipleEntryReferenceEditor(props) {
|
|
|
13
14
|
setIndexToUpdate: setIndexToUpdate
|
|
14
15
|
}, (childrenProps)=>React.createElement(SortableLinkList, {
|
|
15
16
|
...childrenProps,
|
|
16
|
-
|
|
17
|
-
useDragHandle: true,
|
|
17
|
+
sortingStrategy: verticalListSortingStrategy,
|
|
18
18
|
updateBeforeSortStart: updateBeforeSortStart
|
|
19
19
|
}, ({ items , item , index , isDisabled , DragHandle })=>{
|
|
20
20
|
const lastIndex = items.length - 1;
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { useCallback } from 'react';
|
|
3
3
|
import { FieldConnector } from '@contentful/field-editor-shared';
|
|
4
|
-
import arrayMove from '
|
|
4
|
+
import { arrayMove } from '@dnd-kit/sortable';
|
|
5
5
|
import deepEqual from 'deep-equal';
|
|
6
|
+
import noop from 'lodash/noop';
|
|
6
7
|
import { EntityProvider } from '../common/EntityStore';
|
|
7
8
|
import { SortableLinkList } from '../common/SortableLinkList';
|
|
8
9
|
import { CombinedLinkEntityActions } from '../components/LinkActions/LinkEntityActions';
|
|
@@ -10,7 +11,7 @@ import { ResourceCard } from './Cards/ResourceCard';
|
|
|
10
11
|
import { useResourceLinkActions } from './useResourceLinkActions';
|
|
11
12
|
function ResourceEditor(props) {
|
|
12
13
|
const { setValue , items , apiUrl } = props;
|
|
13
|
-
const onSortStart =
|
|
14
|
+
const onSortStart = ()=>noop();
|
|
14
15
|
const onSortEnd = useCallback(({ oldIndex , newIndex })=>{
|
|
15
16
|
const newItems = arrayMove(items, oldIndex, newIndex);
|
|
16
17
|
setValue(newItems);
|
|
@@ -86,11 +87,13 @@ export function MultipleResourceReferenceEditor(props) {
|
|
|
86
87
|
renderCustomActions: props.renderCustomActions,
|
|
87
88
|
key: `${externalReset}-list`
|
|
88
89
|
}, (editorProps)=>React.createElement(SortableLinkList, editorProps, ({ item , isDisabled , DragHandle , index })=>React.createElement(WithPerItemCallbacks, {
|
|
90
|
+
key: index,
|
|
89
91
|
index: index,
|
|
90
92
|
onMove: editorProps.onMove,
|
|
91
93
|
onRemoteItemAtIndex: editorProps.onRemoteItemAtIndex,
|
|
92
94
|
listLength: value?.length || 0
|
|
93
95
|
}, ({ onMoveBottom , onMoveTop , onRemove })=>React.createElement(ResourceCard, {
|
|
96
|
+
key: index,
|
|
94
97
|
index: index,
|
|
95
98
|
resourceLink: item,
|
|
96
99
|
isDisabled: isDisabled,
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import React, { useCallback, useState } from 'react';
|
|
2
|
+
import { arrayMove } from '@dnd-kit/sortable';
|
|
3
|
+
export const useSortIDs = (items)=>{
|
|
4
|
+
const ids = (items || []).map((item, index)=>{
|
|
5
|
+
const { type } = item.sys;
|
|
6
|
+
return {
|
|
7
|
+
id: type === 'ResourceLink' ? `${item.sys.urn}-${index}` : `${item.sys.id}-${index}`
|
|
8
|
+
};
|
|
9
|
+
});
|
|
10
|
+
const [sortIDs, setSortIDs] = useState(ids);
|
|
11
|
+
React.useEffect(()=>{
|
|
12
|
+
if (items.length !== sortIDs.length) {
|
|
13
|
+
const ids = items.map((item, index)=>{
|
|
14
|
+
const { type } = item.sys;
|
|
15
|
+
return {
|
|
16
|
+
id: type === 'ResourceLink' ? `${item.sys.urn}-${index}` : `${item.sys.id}-${index}`
|
|
17
|
+
};
|
|
18
|
+
});
|
|
19
|
+
setSortIDs(ids);
|
|
20
|
+
}
|
|
21
|
+
}, [
|
|
22
|
+
items,
|
|
23
|
+
sortIDs.length
|
|
24
|
+
]);
|
|
25
|
+
const rearrangeSortIDs = useCallback((oldIndex, newIndex)=>{
|
|
26
|
+
const newSortIDs = arrayMove(sortIDs, oldIndex, newIndex);
|
|
27
|
+
setSortIDs(newSortIDs);
|
|
28
|
+
}, [
|
|
29
|
+
sortIDs
|
|
30
|
+
]);
|
|
31
|
+
return {
|
|
32
|
+
sortIDs,
|
|
33
|
+
rearrangeSortIDs
|
|
34
|
+
};
|
|
35
|
+
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import {
|
|
2
|
+
import { DragStartEvent } from '@dnd-kit/core';
|
|
3
3
|
import { ReferenceValue, ContentEntityType, ContentType } from '../types';
|
|
4
4
|
import { ReferenceEditorProps } from './ReferenceEditor';
|
|
5
5
|
type ChildProps = {
|
|
@@ -8,8 +8,11 @@ type ChildProps = {
|
|
|
8
8
|
isDisabled: boolean;
|
|
9
9
|
setValue: (value: ReferenceValue[]) => void;
|
|
10
10
|
allContentTypes: ContentType[];
|
|
11
|
-
onSortStart:
|
|
12
|
-
onSortEnd:
|
|
11
|
+
onSortStart: (event: DragStartEvent) => void;
|
|
12
|
+
onSortEnd: ({ oldIndex, newIndex }: {
|
|
13
|
+
oldIndex: number;
|
|
14
|
+
newIndex: number;
|
|
15
|
+
}) => void;
|
|
13
16
|
onMove: (oldIndex: number, newIndex: number) => void;
|
|
14
17
|
};
|
|
15
18
|
export declare function MultipleReferenceEditor(props: ReferenceEditorProps & {
|
|
@@ -1,19 +1,27 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { DragStartEvent } from '@dnd-kit/core';
|
|
3
|
+
import { SortingStrategy } from '@dnd-kit/sortable';
|
|
3
4
|
import { ReferenceEditorProps } from './ReferenceEditor';
|
|
4
5
|
type SortableContainerChildProps<IType> = Pick<SortableLinkListProps<IType>, 'items' | 'isDisabled'> & {
|
|
5
6
|
item: IType;
|
|
6
7
|
index: number;
|
|
7
|
-
DragHandle?:
|
|
8
|
+
DragHandle?: (props: {
|
|
9
|
+
drag: React.ReactElement;
|
|
10
|
+
}) => React.ReactElement;
|
|
8
11
|
};
|
|
9
12
|
type SortableLinkListProps<T> = ReferenceEditorProps & {
|
|
10
13
|
items: T[];
|
|
11
14
|
isDisabled: boolean;
|
|
12
15
|
children: (props: SortableContainerChildProps<T>) => React.ReactElement;
|
|
16
|
+
sortingStrategy?: SortingStrategy;
|
|
17
|
+
onSortStart?: (event: DragStartEvent) => void;
|
|
18
|
+
onSortEnd?: ({ oldIndex, newIndex }: {
|
|
19
|
+
oldIndex: number;
|
|
20
|
+
newIndex: number;
|
|
21
|
+
}) => void;
|
|
13
22
|
className?: string;
|
|
14
23
|
};
|
|
15
|
-
declare const
|
|
16
|
-
|
|
17
|
-
}) => React.JSX.Element;
|
|
18
|
-
export declare function SortableLinkList<T>(props: SortableLinkListProps<T> & SortableContainerProps): React.JSX.Element;
|
|
24
|
+
export declare const SortableLinkList: <T extends {
|
|
25
|
+
sys: any;
|
|
26
|
+
}>({ items, isDisabled, className, children, onSortStart, onSortEnd, updateBeforeSortStart, sortingStrategy, }: SortableLinkListProps<T>) => React.JSX.Element;
|
|
19
27
|
export {};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { ReferenceValue, ResourceLink } from '../types';
|
|
2
|
+
type Items = (ResourceLink | ReferenceValue)[];
|
|
3
|
+
export declare const useSortIDs: (items: Items) => {
|
|
4
|
+
sortIDs: {
|
|
5
|
+
id: string;
|
|
6
|
+
}[];
|
|
7
|
+
rearrangeSortIDs: (oldIndex: number, newIndex: number) => void;
|
|
8
|
+
};
|
|
9
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@contentful/field-editor-reference",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.17.0",
|
|
4
4
|
"main": "dist/cjs/index.js",
|
|
5
5
|
"module": "dist/esm/index.js",
|
|
6
6
|
"types": "dist/types/index.d.ts",
|
|
@@ -40,9 +40,11 @@
|
|
|
40
40
|
"@contentful/f36-tokens": "^4.0.0",
|
|
41
41
|
"@contentful/field-editor-shared": "^1.4.2",
|
|
42
42
|
"@contentful/mimetype": "^1.4.0",
|
|
43
|
+
"@dnd-kit/core": "^6.0.8",
|
|
44
|
+
"@dnd-kit/modifiers": "^6.0.1",
|
|
45
|
+
"@dnd-kit/sortable": "^7.0.2",
|
|
43
46
|
"@tanstack/react-query": "^4.3.9",
|
|
44
47
|
"@types/deep-equal": "^1.0.1",
|
|
45
|
-
"array-move": "^3.0.0",
|
|
46
48
|
"constate": "3.2.0",
|
|
47
49
|
"contentful-management": "^10.14.0",
|
|
48
50
|
"deep-equal": "2.2.2",
|
|
@@ -51,7 +53,6 @@
|
|
|
51
53
|
"moment": "^2.20.0",
|
|
52
54
|
"p-queue": "^4.0.0",
|
|
53
55
|
"react-intersection-observer": "9.4.0",
|
|
54
|
-
"react-sortable-hoc": "^2.0.0",
|
|
55
56
|
"type-fest": "2.17.0"
|
|
56
57
|
},
|
|
57
58
|
"devDependencies": {
|
|
@@ -63,5 +64,5 @@
|
|
|
63
64
|
"@contentful/app-sdk": "^4.17.1",
|
|
64
65
|
"react": ">=16.8.0"
|
|
65
66
|
},
|
|
66
|
-
"gitHead": "
|
|
67
|
+
"gitHead": "ff0704c0aa9e0f0cdbb4fc70de7ac4ca337529e4"
|
|
67
68
|
}
|