@strapi/content-manager 5.38.0 → 5.38.1
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/admin/history/components/VersionContent.js +48 -16
- package/dist/admin/history/components/VersionContent.js.map +1 -1
- package/dist/admin/history/components/VersionContent.mjs +48 -16
- package/dist/admin/history/components/VersionContent.mjs.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/Blocks/List.js +51 -0
- package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/Blocks/List.js.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/Blocks/List.mjs +52 -1
- package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/Blocks/List.mjs.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/BlocksContent.js +6 -2
- package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/BlocksContent.js.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/BlocksContent.mjs +6 -2
- package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/BlocksContent.mjs.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/BlocksEditor.js.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/BlocksInput/BlocksEditor.mjs.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/DynamicZone/DynamicComponent.js +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/DynamicZone/DynamicComponent.js.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/DynamicZone/DynamicComponent.mjs +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/DynamicZone/DynamicComponent.mjs.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/Relations/RelationModal.mjs +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/Relations/Relations.js +148 -111
- package/dist/admin/pages/EditView/components/FormInputs/Relations/Relations.js.map +1 -1
- package/dist/admin/pages/EditView/components/FormInputs/Relations/Relations.mjs +152 -115
- package/dist/admin/pages/EditView/components/FormInputs/Relations/Relations.mjs.map +1 -1
- package/dist/admin/pages/EditView/components/InputRenderer.js +15 -5
- package/dist/admin/pages/EditView/components/InputRenderer.js.map +1 -1
- package/dist/admin/pages/EditView/components/InputRenderer.mjs +15 -5
- package/dist/admin/pages/EditView/components/InputRenderer.mjs.map +1 -1
- package/dist/admin/pages/ListView/components/Filters.js +54 -1
- package/dist/admin/pages/ListView/components/Filters.js.map +1 -1
- package/dist/admin/pages/ListView/components/Filters.mjs +54 -1
- package/dist/admin/pages/ListView/components/Filters.mjs.map +1 -1
- package/dist/admin/src/exports.d.ts +1 -1
- package/dist/admin/src/pages/EditView/components/FormInputs/BlocksInput/BlocksEditor.d.ts +1 -0
- package/dist/admin/src/utils/conditionalFields.d.ts +12 -0
- package/dist/admin/translations/en.json.js +5 -0
- package/dist/admin/translations/en.json.js.map +1 -1
- package/dist/admin/translations/en.json.mjs +5 -0
- package/dist/admin/translations/en.json.mjs.map +1 -1
- package/dist/admin/translations/es.json.js +136 -2
- package/dist/admin/translations/es.json.js.map +1 -1
- package/dist/admin/translations/es.json.mjs +136 -2
- package/dist/admin/translations/es.json.mjs.map +1 -1
- package/dist/admin/utils/conditionalFields.js +76 -0
- package/dist/admin/utils/conditionalFields.js.map +1 -0
- package/dist/admin/utils/conditionalFields.mjs +69 -0
- package/dist/admin/utils/conditionalFields.mjs.map +1 -0
- package/dist/server/controllers/collection-types.js +157 -4
- package/dist/server/controllers/collection-types.js.map +1 -1
- package/dist/server/controllers/collection-types.mjs +159 -6
- package/dist/server/controllers/collection-types.mjs.map +1 -1
- package/dist/server/controllers/single-types.js +19 -4
- package/dist/server/controllers/single-types.js.map +1 -1
- package/dist/server/controllers/single-types.mjs +19 -4
- package/dist/server/controllers/single-types.mjs.map +1 -1
- package/dist/server/preview/services/preview.js +2 -1
- package/dist/server/preview/services/preview.js.map +1 -1
- package/dist/server/preview/services/preview.mjs +2 -1
- package/dist/server/preview/services/preview.mjs.map +1 -1
- package/dist/server/src/controllers/collection-types.d.ts.map +1 -1
- package/dist/server/src/controllers/single-types.d.ts.map +1 -1
- package/dist/server/src/preview/services/preview.d.ts.map +1 -1
- package/package.json +13 -8
|
@@ -53,13 +53,13 @@ var React__namespace = /*#__PURE__*/_interopNamespaceDefault(React);
|
|
|
53
53
|
const field = strapiAdmin.useField(fieldName);
|
|
54
54
|
const removeFieldRow = strapiAdmin.useForm(consumerName, (state)=>state.removeFieldRow);
|
|
55
55
|
const addFieldRow = strapiAdmin.useForm(consumerName, (state)=>state.addFieldRow);
|
|
56
|
-
const handleDisconnect = (relation)=>{
|
|
56
|
+
const handleDisconnect = React__namespace.useCallback((relation)=>{
|
|
57
57
|
if (field.value && field.value.connect) {
|
|
58
58
|
/**
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
59
|
+
* A relation will exist in the `connect` array _if_ it has
|
|
60
|
+
* been added without saving. In this case, we just remove it
|
|
61
|
+
* from the connect array
|
|
62
|
+
*/ const indexOfRelationInConnectArray = field.value.connect.findIndex((rel)=>rel.id === relation.id);
|
|
63
63
|
if (indexOfRelationInConnectArray >= 0) {
|
|
64
64
|
removeFieldRow(`${fieldName}.connect`, indexOfRelationInConnectArray);
|
|
65
65
|
return;
|
|
@@ -73,7 +73,12 @@ var React__namespace = /*#__PURE__*/_interopNamespaceDefault(React);
|
|
|
73
73
|
locale: relation.locale
|
|
74
74
|
}
|
|
75
75
|
});
|
|
76
|
-
}
|
|
76
|
+
}, [
|
|
77
|
+
addFieldRow,
|
|
78
|
+
field.value,
|
|
79
|
+
fieldName,
|
|
80
|
+
removeFieldRow
|
|
81
|
+
]);
|
|
77
82
|
return handleDisconnect;
|
|
78
83
|
}
|
|
79
84
|
/* -------------------------------------------------------------------------------------------------
|
|
@@ -86,6 +91,7 @@ const ONE_WAY_RELATIONS = [
|
|
|
86
91
|
'oneToManyMorph',
|
|
87
92
|
'oneToOneMorph'
|
|
88
93
|
];
|
|
94
|
+
const EMPTY_RELATION_RESULTS = [];
|
|
89
95
|
/**
|
|
90
96
|
* TODO: we get a rather ugly flash when we remove a single relation from the list leaving
|
|
91
97
|
* no other relations when we press save. The initial relation re-renders, probably because
|
|
@@ -105,10 +111,10 @@ const ONE_WAY_RELATIONS = [
|
|
|
105
111
|
const { formatMessage } = reactIntl.useIntl();
|
|
106
112
|
const isMorph = props.attribute.relation.toLowerCase().includes('morph');
|
|
107
113
|
const isDisabled = isMorph || disabled;
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
114
|
+
// @ts-expect-error – `targetModel` exists on supported non-morph relations (morph is disabled).
|
|
115
|
+
const targetModel = props.attribute.targetModel;
|
|
116
|
+
const componentId = ComponentContext.useComponent('RelationsField', (state)=>state.id);
|
|
117
|
+
const componentUID = ComponentContext.useComponent('RelationsField', (state)=>state.uid);
|
|
112
118
|
const isSubmitting = strapiAdmin.useForm('RelationsList', (state)=>state.isSubmitting);
|
|
113
119
|
React__namespace.useEffect(()=>{
|
|
114
120
|
setCurrentPage(1);
|
|
@@ -146,27 +152,19 @@ const ONE_WAY_RELATIONS = [
|
|
|
146
152
|
}
|
|
147
153
|
}, {
|
|
148
154
|
refetchOnMountOrArgChange: true,
|
|
149
|
-
skip: !id || !isRelatedToCurrentDocument
|
|
150
|
-
selectFromResult: (result)=>{
|
|
151
|
-
return {
|
|
152
|
-
...result,
|
|
153
|
-
data: {
|
|
154
|
-
...result.data,
|
|
155
|
-
results: result.data?.results ? result.data.results : []
|
|
156
|
-
}
|
|
157
|
-
};
|
|
158
|
-
}
|
|
155
|
+
skip: !id || !isRelatedToCurrentDocument
|
|
159
156
|
});
|
|
160
157
|
const handleLoadMore = ()=>{
|
|
161
158
|
setCurrentPage((prev)=>prev + 1);
|
|
162
159
|
};
|
|
163
160
|
const field = strapiAdmin.useField(props.name);
|
|
161
|
+
const serverData = data?.results ?? EMPTY_RELATION_RESULTS;
|
|
164
162
|
const isFetchingMoreRelations = isLoading || isFetching;
|
|
165
|
-
const realServerRelationsCount =
|
|
163
|
+
const realServerRelationsCount = data?.pagination ? data.pagination.total : 0;
|
|
166
164
|
/**
|
|
167
165
|
* Items that are already connected, but reordered would be in
|
|
168
166
|
* this list, so to get an accurate figure, we remove them.
|
|
169
|
-
*/ const relationsConnected = (field.value?.connect ?? []).filter((rel)=>
|
|
167
|
+
*/ const relationsConnected = (field.value?.connect ?? []).filter((rel)=>serverData.findIndex((relation)=>relation.id === rel.id) === -1).length ?? 0;
|
|
170
168
|
const relationsDisconnected = field.value?.disconnect?.length ?? 0;
|
|
171
169
|
const relationsCount = realServerRelationsCount + relationsConnected - relationsDisconnected;
|
|
172
170
|
/**
|
|
@@ -176,15 +174,14 @@ const ONE_WAY_RELATIONS = [
|
|
|
176
174
|
*/ const relations$2 = React__namespace.useMemo(()=>{
|
|
177
175
|
const ctx = {
|
|
178
176
|
field: field.value,
|
|
179
|
-
|
|
180
|
-
href: `../${collections.COLLECTION_TYPES}/${props.attribute.targetModel}`,
|
|
177
|
+
href: `../${collections.COLLECTION_TYPES}/${targetModel}`,
|
|
181
178
|
mainField: props.mainField
|
|
182
179
|
};
|
|
183
180
|
/**
|
|
184
181
|
* Tidy up our data.
|
|
185
182
|
*/ const transformations = pipe(removeConnected(ctx), removeDisconnected(ctx), addLabelAndHref(ctx));
|
|
186
183
|
const transformedRels = transformations([
|
|
187
|
-
...
|
|
184
|
+
...serverData
|
|
188
185
|
]);
|
|
189
186
|
/**
|
|
190
187
|
* THIS IS CRUCIAL. If you don't sort by the __temp_key__ which comes from fractional indexing
|
|
@@ -198,14 +195,13 @@ const ONE_WAY_RELATIONS = [
|
|
|
198
195
|
return 0;
|
|
199
196
|
});
|
|
200
197
|
}, [
|
|
201
|
-
|
|
198
|
+
serverData,
|
|
202
199
|
field.value,
|
|
203
|
-
|
|
204
|
-
props.attribute.targetModel,
|
|
200
|
+
targetModel,
|
|
205
201
|
props.mainField
|
|
206
202
|
]);
|
|
207
203
|
const handleDisconnect = useHandleDisconnect(props.name, 'RelationsField');
|
|
208
|
-
const handleConnect = (relation)=>{
|
|
204
|
+
const handleConnect = React__namespace.useCallback((relation)=>{
|
|
209
205
|
const [lastItemInList] = relations$2.slice(-1);
|
|
210
206
|
const item = {
|
|
211
207
|
id: relation.id,
|
|
@@ -217,13 +213,12 @@ const ONE_WAY_RELATIONS = [
|
|
|
217
213
|
},
|
|
218
214
|
status: relation.status,
|
|
219
215
|
/**
|
|
220
|
-
|
|
221
|
-
|
|
216
|
+
* If there's a last item, that's the first key we use to generate out next one.
|
|
217
|
+
*/ __temp_key__: fractionalIndexing.generateNKeysBetween(lastItemInList?.__temp_key__ ?? null, null, 1)[0],
|
|
222
218
|
// Fallback to `id` if there is no `mainField` value, which will overwrite the above `id` property with the exact same data.
|
|
223
219
|
[props.mainField?.name ?? 'documentId']: relation[props.mainField?.name ?? 'documentId'],
|
|
224
220
|
label: relations$1.getRelationLabel(relation, props.mainField),
|
|
225
|
-
|
|
226
|
-
href: `../${collections.COLLECTION_TYPES}/${props.attribute.targetModel}/${relation.documentId}?${relation.locale ? `plugins[i18n][locale]=${relation.locale}` : ''}`
|
|
221
|
+
href: `../${collections.COLLECTION_TYPES}/${targetModel}/${relation.documentId}?${relation.locale ? `plugins[i18n][locale]=${relation.locale}` : ''}`
|
|
227
222
|
};
|
|
228
223
|
if (ONE_WAY_RELATIONS.includes(props.attribute.relation)) {
|
|
229
224
|
// Remove any existing relation so they can be replaced with the new one
|
|
@@ -238,7 +233,15 @@ const ONE_WAY_RELATIONS = [
|
|
|
238
233
|
item
|
|
239
234
|
]);
|
|
240
235
|
}
|
|
241
|
-
}
|
|
236
|
+
}, [
|
|
237
|
+
field,
|
|
238
|
+
handleDisconnect,
|
|
239
|
+
props.attribute.relation,
|
|
240
|
+
props.mainField,
|
|
241
|
+
props.name,
|
|
242
|
+
relations$2,
|
|
243
|
+
targetModel
|
|
244
|
+
]);
|
|
242
245
|
return /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Flex, {
|
|
243
246
|
ref: ref,
|
|
244
247
|
direction: "column",
|
|
@@ -253,7 +256,7 @@ const ONE_WAY_RELATIONS = [
|
|
|
253
256
|
gap: 2,
|
|
254
257
|
width: "100%",
|
|
255
258
|
children: [
|
|
256
|
-
/*#__PURE__*/ jsxRuntime.jsx(
|
|
259
|
+
/*#__PURE__*/ jsxRuntime.jsx(MemoizedRelationsComboboxInput, {
|
|
257
260
|
disabled: isDisabled,
|
|
258
261
|
// NOTE: we should not default to using the documentId if the component is being created (componentUID is undefined)
|
|
259
262
|
id: componentUID && component ? componentId ? `${componentId}` : '' : documentId,
|
|
@@ -263,7 +266,7 @@ const ONE_WAY_RELATIONS = [
|
|
|
263
266
|
isRelatedToCurrentDocument: isRelatedToCurrentDocument,
|
|
264
267
|
...props
|
|
265
268
|
}),
|
|
266
|
-
|
|
269
|
+
data?.pagination && data.pagination.pageCount > data.pagination.page ? /*#__PURE__*/ jsxRuntime.jsx(designSystem.TextButton, {
|
|
267
270
|
disabled: isFetchingMoreRelations,
|
|
268
271
|
onClick: handleLoadMore,
|
|
269
272
|
loading: isFetchingMoreRelations,
|
|
@@ -277,15 +280,15 @@ const ONE_WAY_RELATIONS = [
|
|
|
277
280
|
}) : null
|
|
278
281
|
]
|
|
279
282
|
}),
|
|
280
|
-
/*#__PURE__*/ jsxRuntime.jsx(
|
|
283
|
+
/*#__PURE__*/ jsxRuntime.jsx(MemoizedRelationsList, {
|
|
281
284
|
data: relations$2,
|
|
282
|
-
serverData:
|
|
285
|
+
serverData: serverData,
|
|
283
286
|
disabled: isDisabled,
|
|
284
287
|
name: props.name,
|
|
285
288
|
isLoading: isFetchingMoreRelations,
|
|
286
289
|
relationType: props.attribute.relation,
|
|
287
|
-
|
|
288
|
-
|
|
290
|
+
targetModel: targetModel,
|
|
291
|
+
documentParams: currentDocumentMeta.params,
|
|
289
292
|
mainField: props.mainField
|
|
290
293
|
})
|
|
291
294
|
]
|
|
@@ -338,6 +341,8 @@ const ONE_WAY_RELATIONS = [
|
|
|
338
341
|
const { currentDocumentMeta } = useDocumentContext.useDocumentContext('RelationsInput');
|
|
339
342
|
const { formatMessage } = reactIntl.useIntl();
|
|
340
343
|
const field = strapiAdmin.useField(name);
|
|
344
|
+
// @ts-expect-error – `targetModel` exists on supported non-morph relations (morph is disabled).
|
|
345
|
+
const targetModel = props.attribute.targetModel;
|
|
341
346
|
const searchParamsDebounced = useDebounce.useDebounce(searchParams, 300);
|
|
342
347
|
const [searchForTrigger, { data, isLoading }] = relations.useLazySearchRelationsQuery();
|
|
343
348
|
/**
|
|
@@ -379,7 +384,7 @@ const ONE_WAY_RELATIONS = [
|
|
|
379
384
|
]);
|
|
380
385
|
const hasNextPage = data?.pagination ? data.pagination.page < data.pagination.pageCount : false;
|
|
381
386
|
const options = data?.results ?? [];
|
|
382
|
-
const handleChange = (relationId)=>{
|
|
387
|
+
const handleChange = React__namespace.useCallback((relationId)=>{
|
|
383
388
|
if (!relationId) {
|
|
384
389
|
return;
|
|
385
390
|
}
|
|
@@ -397,20 +402,27 @@ const ONE_WAY_RELATIONS = [
|
|
|
397
402
|
return;
|
|
398
403
|
}
|
|
399
404
|
/**
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
}
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
405
|
+
* You need to give this relation a correct _temp_key_ but
|
|
406
|
+
* this component doesn't know about those ones, you can't rely
|
|
407
|
+
* on the connect array because that doesn't hold items that haven't
|
|
408
|
+
* moved. So use a callback to fill in the gaps when connecting.
|
|
409
|
+
*
|
|
410
|
+
*/ onChange(relation);
|
|
411
|
+
}, [
|
|
412
|
+
formatMessage,
|
|
413
|
+
onChange,
|
|
414
|
+
options,
|
|
415
|
+
toggleNotification
|
|
416
|
+
]);
|
|
417
|
+
const relation = React__namespace.useMemo(()=>({
|
|
418
|
+
collectionType: collections.COLLECTION_TYPES,
|
|
419
|
+
model: targetModel,
|
|
420
|
+
documentId: '',
|
|
421
|
+
params: currentDocumentMeta.params
|
|
422
|
+
}), [
|
|
423
|
+
currentDocumentMeta.params,
|
|
424
|
+
targetModel
|
|
425
|
+
]);
|
|
414
426
|
const { permissions = [], isLoading: isLoadingPermissions, error } = strapiAdmin.useRBAC(plugin.PERMISSIONS.map((action)=>({
|
|
415
427
|
action,
|
|
416
428
|
subject: relation.model
|
|
@@ -444,7 +456,7 @@ const ONE_WAY_RELATIONS = [
|
|
|
444
456
|
/*#__PURE__*/ jsxRuntime.jsx(DocumentRBAC.DocumentRBAC, {
|
|
445
457
|
permissions: permissions,
|
|
446
458
|
model: relation.model,
|
|
447
|
-
children: /*#__PURE__*/ jsxRuntime.jsx(
|
|
459
|
+
children: /*#__PURE__*/ jsxRuntime.jsx(MemoizedRelationModalWithContext, {
|
|
448
460
|
relation: relation,
|
|
449
461
|
name: name,
|
|
450
462
|
placeholder: placeholder,
|
|
@@ -464,14 +476,13 @@ const ONE_WAY_RELATIONS = [
|
|
|
464
476
|
]
|
|
465
477
|
});
|
|
466
478
|
};
|
|
479
|
+
const MemoizedRelationsComboboxInput = /*#__PURE__*/ React__namespace.memo(RelationsInput);
|
|
467
480
|
const RelationModalWithContext = ({ relation, name, placeholder, hasNextPage, isLoadingSearchRelations, isLoadingPermissions, handleChange, mainField, setSearchParams, fieldValue, data, ...props })=>{
|
|
468
481
|
const [textValue, setTextValue] = React__namespace.useState('');
|
|
469
482
|
const { formatMessage } = reactIntl.useIntl();
|
|
470
483
|
const canCreate = DocumentRBAC.useDocumentRBAC('RelationModalWrapper', (state)=>state.canCreate);
|
|
471
484
|
const fieldRef = strapiAdmin.useFocusInputField(name);
|
|
472
|
-
const
|
|
473
|
-
componentUID: uid
|
|
474
|
-
}));
|
|
485
|
+
const componentUID = ComponentContext.useComponent('RelationsField', (state)=>state.uid);
|
|
475
486
|
const handleLoadMore = ()=>{
|
|
476
487
|
if (!data || !data.pagination) {
|
|
477
488
|
return;
|
|
@@ -583,11 +594,12 @@ const RelationModalWithContext = ({ relation, name, placeholder, hasNextPage, is
|
|
|
583
594
|
})
|
|
584
595
|
});
|
|
585
596
|
};
|
|
597
|
+
const MemoizedRelationModalWithContext = /*#__PURE__*/ React__namespace.memo(RelationModalWithContext);
|
|
586
598
|
/* -------------------------------------------------------------------------------------------------
|
|
587
599
|
* RelationsList
|
|
588
600
|
* -----------------------------------------------------------------------------------------------*/ const RELATION_ITEM_HEIGHT = 50;
|
|
589
601
|
const RELATION_GUTTER = 4;
|
|
590
|
-
const RelationsList = ({ data, serverData, disabled, name, isLoading, relationType, targetModel, mainField })=>{
|
|
602
|
+
const RelationsList = ({ data, serverData, disabled, name, isLoading, relationType, targetModel, documentParams, mainField })=>{
|
|
591
603
|
const ariaDescriptionId = React__namespace.useId();
|
|
592
604
|
const { formatMessage } = reactIntl.useIntl();
|
|
593
605
|
const listRef = React__namespace.useRef(null);
|
|
@@ -624,38 +636,37 @@ const RelationsList = ({ data, serverData, disabled, name, isLoading, relationTy
|
|
|
624
636
|
isLoading,
|
|
625
637
|
data.length
|
|
626
638
|
]);
|
|
627
|
-
const
|
|
628
|
-
const handleMoveItem = (newIndex, oldIndex)=>{
|
|
639
|
+
const handleMoveItem = React__namespace.useCallback((newIndex, oldIndex)=>{
|
|
629
640
|
const item = data[oldIndex];
|
|
630
641
|
setLiveText(formatMessage({
|
|
631
642
|
id: translations.getTranslation('dnd.reorder'),
|
|
632
643
|
defaultMessage: '{item}, moved. New position in list: {position}.'
|
|
633
644
|
}, {
|
|
634
645
|
item: item.label ?? item.documentId,
|
|
635
|
-
position:
|
|
646
|
+
position: `${newIndex + 1} of ${data.length}`
|
|
636
647
|
}));
|
|
637
648
|
/**
|
|
638
|
-
|
|
639
|
-
|
|
649
|
+
* Splicing mutates the array, so we need to create a new array
|
|
650
|
+
*/ const newData = [
|
|
640
651
|
...data
|
|
641
652
|
];
|
|
642
653
|
const currentRow = data[oldIndex];
|
|
643
654
|
const startKey = oldIndex > newIndex ? newData[newIndex - 1]?.__temp_key__ : newData[newIndex]?.__temp_key__;
|
|
644
655
|
const endKey = oldIndex > newIndex ? newData[newIndex]?.__temp_key__ : newData[newIndex + 1]?.__temp_key__;
|
|
645
656
|
/**
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
657
|
+
* We're moving the relation between two other relations, so
|
|
658
|
+
* we need to generate a new key that keeps the order
|
|
659
|
+
*/ const [newKey] = fractionalIndexing.generateNKeysBetween(startKey, endKey, 1);
|
|
649
660
|
newData.splice(oldIndex, 1);
|
|
650
661
|
newData.splice(newIndex, 0, {
|
|
651
662
|
...currentRow,
|
|
652
663
|
__temp_key__: newKey
|
|
653
664
|
});
|
|
654
665
|
/**
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
666
|
+
* Now we diff against the server to understand what's different so we
|
|
667
|
+
* can keep the connect array nice and tidy. It also needs reversing because
|
|
668
|
+
* we reverse the relations from the server in the first place.
|
|
669
|
+
*/ const connectedRelations = newData.reduce((acc, relation, currentIndex, array)=>{
|
|
659
670
|
const relationOnServer = serverData.find((oldRelation)=>oldRelation.id === relation.id);
|
|
660
671
|
const relationInFront = array[currentIndex + 1];
|
|
661
672
|
if (!relationOnServer || relationOnServer.__temp_key__ !== relation.__temp_key__) {
|
|
@@ -686,28 +697,40 @@ const RelationsList = ({ data, serverData, disabled, name, isLoading, relationTy
|
|
|
686
697
|
return acc;
|
|
687
698
|
}, []).toReversed();
|
|
688
699
|
field.onChange(`${name}.connect`, connectedRelations);
|
|
689
|
-
}
|
|
690
|
-
|
|
700
|
+
}, [
|
|
701
|
+
data,
|
|
702
|
+
field,
|
|
703
|
+
formatMessage,
|
|
704
|
+
name,
|
|
705
|
+
serverData
|
|
706
|
+
]);
|
|
707
|
+
const handleGrabItem = React__namespace.useCallback((index)=>{
|
|
691
708
|
const item = data[index];
|
|
692
709
|
setLiveText(formatMessage({
|
|
693
710
|
id: translations.getTranslation('dnd.grab-item'),
|
|
694
711
|
defaultMessage: `{item}, grabbed. Current position in list: {position}. Press up and down arrow to change position, Spacebar to drop, Escape to cancel.`
|
|
695
712
|
}, {
|
|
696
713
|
item: item.label ?? item.documentId,
|
|
697
|
-
position:
|
|
714
|
+
position: `${index + 1} of ${data.length}`
|
|
698
715
|
}));
|
|
699
|
-
}
|
|
700
|
-
|
|
716
|
+
}, [
|
|
717
|
+
data,
|
|
718
|
+
formatMessage
|
|
719
|
+
]);
|
|
720
|
+
const handleDropItem = React__namespace.useCallback((index)=>{
|
|
701
721
|
const { href: _href, label, ...item } = data[index];
|
|
702
722
|
setLiveText(formatMessage({
|
|
703
723
|
id: translations.getTranslation('dnd.drop-item'),
|
|
704
724
|
defaultMessage: `{item}, dropped. Final position in list: {position}.`
|
|
705
725
|
}, {
|
|
706
726
|
item: label ?? item.documentId,
|
|
707
|
-
position:
|
|
727
|
+
position: `${index + 1} of ${data.length}`
|
|
708
728
|
}));
|
|
709
|
-
}
|
|
710
|
-
|
|
729
|
+
}, [
|
|
730
|
+
data,
|
|
731
|
+
formatMessage
|
|
732
|
+
]);
|
|
733
|
+
const handleCancel = React__namespace.useCallback((index)=>{
|
|
711
734
|
const item = data[index];
|
|
712
735
|
setLiveText(formatMessage({
|
|
713
736
|
id: translations.getTranslation('dnd.cancel-item'),
|
|
@@ -715,13 +738,45 @@ const RelationsList = ({ data, serverData, disabled, name, isLoading, relationTy
|
|
|
715
738
|
}, {
|
|
716
739
|
item: item.label ?? item.documentId
|
|
717
740
|
}));
|
|
718
|
-
}
|
|
741
|
+
}, [
|
|
742
|
+
data,
|
|
743
|
+
formatMessage
|
|
744
|
+
]);
|
|
719
745
|
const handleDisconnect = useHandleDisconnect(name, 'RelationsList');
|
|
720
746
|
/**
|
|
721
747
|
* These relation types will only ever have one item
|
|
722
748
|
* in their list, so you can't reorder a single item!
|
|
723
749
|
*/ const canReorder = !ONE_WAY_RELATIONS.includes(relationType);
|
|
724
750
|
const dynamicListHeight = data.length > RELATIONS_TO_DISPLAY ? Math.min(data.length, RELATIONS_TO_DISPLAY) * (RELATION_ITEM_HEIGHT + RELATION_GUTTER) + RELATION_ITEM_HEIGHT / 2 : Math.min(data.length, RELATIONS_TO_DISPLAY) * (RELATION_ITEM_HEIGHT + RELATION_GUTTER);
|
|
751
|
+
const itemData = React__namespace.useMemo(()=>({
|
|
752
|
+
ariaDescribedBy: ariaDescriptionId,
|
|
753
|
+
canDrag: canReorder,
|
|
754
|
+
disabled,
|
|
755
|
+
documentParams,
|
|
756
|
+
handleCancel,
|
|
757
|
+
handleDropItem,
|
|
758
|
+
handleGrabItem,
|
|
759
|
+
handleMoveItem,
|
|
760
|
+
name,
|
|
761
|
+
handleDisconnect,
|
|
762
|
+
relations: data,
|
|
763
|
+
targetModel,
|
|
764
|
+
mainField
|
|
765
|
+
}), [
|
|
766
|
+
ariaDescriptionId,
|
|
767
|
+
canReorder,
|
|
768
|
+
disabled,
|
|
769
|
+
documentParams,
|
|
770
|
+
handleCancel,
|
|
771
|
+
handleDisconnect,
|
|
772
|
+
handleDropItem,
|
|
773
|
+
handleGrabItem,
|
|
774
|
+
handleMoveItem,
|
|
775
|
+
name,
|
|
776
|
+
data,
|
|
777
|
+
targetModel,
|
|
778
|
+
mainField
|
|
779
|
+
]);
|
|
725
780
|
return /*#__PURE__*/ jsxRuntime.jsxs(ShadowBox, {
|
|
726
781
|
$overflowDirection: overflow,
|
|
727
782
|
children: [
|
|
@@ -742,20 +797,7 @@ const RelationsList = ({ data, serverData, disabled, name, isLoading, relationTy
|
|
|
742
797
|
outerRef: outerListRef,
|
|
743
798
|
itemCount: data.length,
|
|
744
799
|
itemSize: RELATION_ITEM_HEIGHT + RELATION_GUTTER,
|
|
745
|
-
itemData:
|
|
746
|
-
ariaDescribedBy: ariaDescriptionId,
|
|
747
|
-
canDrag: canReorder,
|
|
748
|
-
disabled,
|
|
749
|
-
handleCancel,
|
|
750
|
-
handleDropItem,
|
|
751
|
-
handleGrabItem,
|
|
752
|
-
handleMoveItem,
|
|
753
|
-
name,
|
|
754
|
-
handleDisconnect,
|
|
755
|
-
relations: data,
|
|
756
|
-
targetModel,
|
|
757
|
-
mainField
|
|
758
|
-
},
|
|
800
|
+
itemData: itemData,
|
|
759
801
|
itemKey: (index)=>data[index].id,
|
|
760
802
|
innerElementType: "ol",
|
|
761
803
|
children: ListItem
|
|
@@ -763,6 +805,7 @@ const RelationsList = ({ data, serverData, disabled, name, isLoading, relationTy
|
|
|
763
805
|
]
|
|
764
806
|
});
|
|
765
807
|
};
|
|
808
|
+
const MemoizedRelationsList = /*#__PURE__*/ React__namespace.memo(RelationsList);
|
|
766
809
|
const ShadowBox = styledComponents.styled(designSystem.Box)`
|
|
767
810
|
position: relative;
|
|
768
811
|
overflow: hidden;
|
|
@@ -804,9 +847,8 @@ const RelationRow = styledComponents.styled(designSystem.Flex)`
|
|
|
804
847
|
}
|
|
805
848
|
`;
|
|
806
849
|
const ListItem = ({ data, index, style })=>{
|
|
807
|
-
const { ariaDescribedBy, canDrag = false, disabled = false, handleCancel, handleDisconnect, handleDropItem, handleGrabItem, handleMoveItem, name, relations, targetModel, mainField } = data;
|
|
850
|
+
const { ariaDescribedBy, canDrag = false, disabled = false, handleCancel, handleDisconnect, handleDropItem, handleGrabItem, handleMoveItem, name, relations, targetModel, documentParams, mainField } = data;
|
|
808
851
|
const isDesktop = strapiAdmin.useIsDesktop();
|
|
809
|
-
const { currentDocumentMeta } = useDocumentContext.useDocumentContext('RelationsField');
|
|
810
852
|
const { formatMessage } = reactIntl.useIntl();
|
|
811
853
|
const { href, id, label: originalLabel, status: originalStatus, documentId, apiData, locale } = relations[index];
|
|
812
854
|
/**
|
|
@@ -819,7 +861,7 @@ const ListItem = ({ data, index, style })=>{
|
|
|
819
861
|
collectionType,
|
|
820
862
|
model: targetModel,
|
|
821
863
|
documentId: documentId ?? apiData?.documentId,
|
|
822
|
-
params:
|
|
864
|
+
params: documentParams
|
|
823
865
|
}, {
|
|
824
866
|
skip: !isTemporary
|
|
825
867
|
});
|
|
@@ -848,19 +890,14 @@ const ListItem = ({ data, index, style })=>{
|
|
|
848
890
|
]);
|
|
849
891
|
const safeDocumentId = documentId ?? apiData?.documentId;
|
|
850
892
|
const safeLocale = locale ?? apiData?.locale ?? null;
|
|
851
|
-
const documentMeta =
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
safeDocumentId,
|
|
860
|
-
href,
|
|
861
|
-
safeLocale,
|
|
862
|
-
targetModel
|
|
863
|
-
]);
|
|
893
|
+
const documentMeta = {
|
|
894
|
+
documentId: safeDocumentId,
|
|
895
|
+
model: targetModel,
|
|
896
|
+
collectionType: RelationModal.getCollectionType(href),
|
|
897
|
+
params: {
|
|
898
|
+
locale: safeLocale
|
|
899
|
+
}
|
|
900
|
+
};
|
|
864
901
|
return /*#__PURE__*/ jsxRuntime.jsx(designSystem.Box, {
|
|
865
902
|
style: style,
|
|
866
903
|
tag: "li",
|