@strapi/content-manager 0.0.0-experimental.a4161dd0ce4a6742074cbfc43734281e14a29baa → 0.0.0-experimental.a4cee39f4705cbd534afa66170f94f2f68e65b75
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/chunks/{ComponentConfigurationPage-CDKJ1saA.js → ComponentConfigurationPage-BWB_urBW.js} +3 -3
- package/dist/admin/chunks/{ComponentConfigurationPage-CDKJ1saA.js.map → ComponentConfigurationPage-BWB_urBW.js.map} +1 -1
- package/dist/admin/chunks/{ComponentConfigurationPage-BdKTyTdt.mjs → ComponentConfigurationPage-Bw3SD5w3.mjs} +3 -3
- package/dist/admin/chunks/{ComponentConfigurationPage-BdKTyTdt.mjs.map → ComponentConfigurationPage-Bw3SD5w3.mjs.map} +1 -1
- package/dist/admin/chunks/{EditConfigurationPage-BW5fpvkO.js → EditConfigurationPage-BazMqkY5.js} +3 -3
- package/dist/admin/chunks/{EditConfigurationPage-BW5fpvkO.js.map → EditConfigurationPage-BazMqkY5.js.map} +1 -1
- package/dist/admin/chunks/{EditConfigurationPage-CaJ_CmJz.mjs → EditConfigurationPage-bP8cL5u8.mjs} +3 -3
- package/dist/admin/chunks/{EditConfigurationPage-CaJ_CmJz.mjs.map → EditConfigurationPage-bP8cL5u8.mjs.map} +1 -1
- package/dist/admin/chunks/{EditViewPage-BDekCXSy.mjs → EditViewPage-D3F0FbHV.mjs} +10 -7
- package/dist/admin/chunks/EditViewPage-D3F0FbHV.mjs.map +1 -0
- package/dist/admin/chunks/{EditViewPage-CNacGhk_.js → EditViewPage-DjB2aEuN.js} +11 -8
- package/dist/admin/chunks/EditViewPage-DjB2aEuN.js.map +1 -0
- package/dist/admin/chunks/{Form-2LZDIqUE.mjs → Form-CO-twQva.mjs} +2 -2
- package/dist/admin/chunks/{Form-2LZDIqUE.mjs.map → Form-CO-twQva.mjs.map} +1 -1
- package/dist/admin/chunks/{Form-CouVf26p.js → Form-Dyr8enar.js} +2 -2
- package/dist/admin/chunks/{Form-CouVf26p.js.map → Form-Dyr8enar.js.map} +1 -1
- package/dist/admin/chunks/{History-Cv3uNjvV.js → History-BsZCxc7e.js} +6 -6
- package/dist/admin/chunks/{History-Cv3uNjvV.js.map → History-BsZCxc7e.js.map} +1 -1
- package/dist/admin/chunks/{History-B7zZvnQF.mjs → History-DJ_pI0gL.mjs} +5 -5
- package/dist/admin/chunks/{History-B7zZvnQF.mjs.map → History-DJ_pI0gL.mjs.map} +1 -1
- package/dist/admin/chunks/{Input-DPH5j7Yl.js → Input-D-yPzkxz.js} +634 -848
- package/dist/admin/chunks/Input-D-yPzkxz.js.map +1 -0
- package/dist/admin/chunks/{Input-BPTHgeyh.mjs → Input-DWQWd5MK.mjs} +634 -847
- package/dist/admin/chunks/Input-DWQWd5MK.mjs.map +1 -0
- package/dist/admin/chunks/{ListConfigurationPage-FS8YuoKF.mjs → ListConfigurationPage-DlvGrjR_.mjs} +2 -2
- package/dist/admin/chunks/{ListConfigurationPage-FS8YuoKF.mjs.map → ListConfigurationPage-DlvGrjR_.mjs.map} +1 -1
- package/dist/admin/chunks/{ListConfigurationPage-Cj1tt01r.js → ListConfigurationPage-dHbA6tve.js} +2 -2
- package/dist/admin/chunks/{ListConfigurationPage-Cj1tt01r.js.map → ListConfigurationPage-dHbA6tve.js.map} +1 -1
- package/dist/admin/chunks/{ListViewPage-Xv5mmaJq.mjs → ListViewPage-DaxIL_8o.mjs} +3 -3
- package/dist/admin/chunks/{ListViewPage-Xv5mmaJq.mjs.map → ListViewPage-DaxIL_8o.mjs.map} +1 -1
- package/dist/admin/chunks/{ListViewPage-BCmGmK7N.js → ListViewPage-gsJS3ulI.js} +3 -3
- package/dist/admin/chunks/{ListViewPage-BCmGmK7N.js.map → ListViewPage-gsJS3ulI.js.map} +1 -1
- package/dist/admin/chunks/{NoContentTypePage-DpvfQfhU.js → NoContentTypePage-BD-VEn6M.js} +2 -2
- package/dist/admin/chunks/{NoContentTypePage-DpvfQfhU.js.map → NoContentTypePage-BD-VEn6M.js.map} +1 -1
- package/dist/admin/chunks/{NoContentTypePage-Bbqw5ZV9.mjs → NoContentTypePage-xzAGzlVY.mjs} +2 -2
- package/dist/admin/chunks/{NoContentTypePage-Bbqw5ZV9.mjs.map → NoContentTypePage-xzAGzlVY.mjs.map} +1 -1
- package/dist/admin/chunks/{NoPermissionsPage-igrvpcW0.mjs → NoPermissionsPage-BAKqxUK7.mjs} +2 -2
- package/dist/admin/chunks/{NoPermissionsPage-igrvpcW0.mjs.map → NoPermissionsPage-BAKqxUK7.mjs.map} +1 -1
- package/dist/admin/chunks/{NoPermissionsPage-BYEkhBnk.js → NoPermissionsPage-BmE5T_Mq.js} +2 -2
- package/dist/admin/chunks/{NoPermissionsPage-BYEkhBnk.js.map → NoPermissionsPage-BmE5T_Mq.js.map} +1 -1
- package/dist/admin/chunks/{Preview-DR-9uYxZ.mjs → Preview-Bz2ir5R5.mjs} +102 -182
- package/dist/admin/chunks/Preview-Bz2ir5R5.mjs.map +1 -0
- package/dist/admin/chunks/{Preview-DlRltQbE.js → Preview-CP4m2RBm.js} +101 -181
- package/dist/admin/chunks/Preview-CP4m2RBm.js.map +1 -0
- package/dist/admin/chunks/{en-DBP0Gaid.mjs → en-C2zEwS3-.mjs} +3 -1
- package/dist/admin/chunks/{en-DBP0Gaid.mjs.map → en-C2zEwS3-.mjs.map} +1 -1
- package/dist/admin/chunks/{en-CH__IC8g.js → en-G976DLsg.js} +3 -1
- package/dist/admin/chunks/{en-CH__IC8g.js.map → en-G976DLsg.js.map} +1 -1
- package/dist/admin/chunks/{index-CISU19oJ.js → index-CFa6xmgK.js} +197 -127
- package/dist/admin/chunks/index-CFa6xmgK.js.map +1 -0
- package/dist/admin/chunks/{index-C_e5v8f7.mjs → index-ZyDJIuQ1.mjs} +196 -129
- package/dist/admin/chunks/index-ZyDJIuQ1.mjs.map +1 -0
- package/dist/admin/chunks/{layout-CrqscUTi.mjs → layout-D2tOWWAq.mjs} +4 -4
- package/dist/admin/chunks/{layout-CrqscUTi.mjs.map → layout-D2tOWWAq.mjs.map} +1 -1
- package/dist/admin/chunks/{layout-CajJum-G.js → layout-XA97mHoN.js} +4 -4
- package/dist/admin/chunks/{layout-CajJum-G.js.map → layout-XA97mHoN.js.map} +1 -1
- package/dist/admin/chunks/uk-BtM6WnaE.mjs +313 -0
- package/dist/admin/chunks/uk-BtM6WnaE.mjs.map +1 -0
- package/dist/admin/chunks/uk-DB6OgySY.js +318 -0
- package/dist/admin/chunks/uk-DB6OgySY.js.map +1 -0
- package/dist/admin/chunks/{usePrev-CHotxABl.js → usePrev-BEkg-rKP.js} +2 -2
- package/dist/admin/chunks/{usePrev-CHotxABl.js.map → usePrev-BEkg-rKP.js.map} +1 -1
- package/dist/admin/chunks/{usePrev-DF3ZO0z4.mjs → usePrev-DAPoUN3D.mjs} +2 -2
- package/dist/admin/chunks/{usePrev-DF3ZO0z4.mjs.map → usePrev-DAPoUN3D.mjs.map} +1 -1
- package/dist/admin/index.js +1 -1
- package/dist/admin/index.mjs +1 -1
- package/dist/admin/src/content-manager.d.ts +1 -0
- package/dist/admin/src/features/DocumentContext.d.ts +13 -2
- package/dist/admin/src/hooks/useDocument.d.ts +2 -0
- package/dist/admin/src/pages/EditView/components/DocumentActions.d.ts +1 -1
- package/dist/admin/src/pages/EditView/components/FormInputs/Relations/RelationModal.d.ts +5 -7
- package/dist/admin/src/pages/EditView/components/FormInputs/Relations/Relations.d.ts +1 -2
- package/dist/admin/src/pages/EditView/components/FormLayout.d.ts +3 -1
- package/dist/admin/src/pages/EditView/components/InputRenderer.d.ts +5 -2
- package/dist/admin/src/preview/components/PreviewHeader.d.ts +1 -2
- package/package.json +8 -8
- package/dist/admin/chunks/EditViewPage-BDekCXSy.mjs.map +0 -1
- package/dist/admin/chunks/EditViewPage-CNacGhk_.js.map +0 -1
- package/dist/admin/chunks/Input-BPTHgeyh.mjs.map +0 -1
- package/dist/admin/chunks/Input-DPH5j7Yl.js.map +0 -1
- package/dist/admin/chunks/Preview-DR-9uYxZ.mjs.map +0 -1
- package/dist/admin/chunks/Preview-DlRltQbE.js.map +0 -1
- package/dist/admin/chunks/index-CISU19oJ.js.map +0 -1
- package/dist/admin/chunks/index-C_e5v8f7.mjs.map +0 -1
- package/dist/admin/chunks/uk-B24MoTVg.js +0 -145
- package/dist/admin/chunks/uk-B24MoTVg.js.map +0 -1
- package/dist/admin/chunks/uk-Cpgmm7gE.mjs +0 -140
- package/dist/admin/chunks/uk-Cpgmm7gE.mjs.map +0 -1
- package/dist/admin/src/preview/components/PreviewContent.d.ts +0 -3
@@ -6,7 +6,7 @@ var strapiAdmin = require('@strapi/admin/strapi-admin');
|
|
6
6
|
var designSystem = require('@strapi/design-system');
|
7
7
|
var Icons = require('@strapi/icons');
|
8
8
|
var reactIntl = require('react-intl');
|
9
|
-
var index = require('./index-
|
9
|
+
var index = require('./index-CFa6xmgK.js');
|
10
10
|
var styledComponents = require('styled-components');
|
11
11
|
var slate = require('slate');
|
12
12
|
var slateHistory = require('slate-history');
|
@@ -62,7 +62,7 @@ require('prismjs/components/prism-typescript');
|
|
62
62
|
require('prismjs/components/prism-tsx');
|
63
63
|
require('prismjs/components/prism-vbnet');
|
64
64
|
require('prismjs/components/prism-yaml');
|
65
|
-
var usePrev = require('./usePrev-
|
65
|
+
var usePrev = require('./usePrev-BEkg-rKP.js');
|
66
66
|
var objects = require('./objects-BJTP843m.js');
|
67
67
|
var Toolbar = require('@radix-ui/react-toolbar');
|
68
68
|
var reactDndHtml5Backend = require('react-dnd-html5-backend');
|
@@ -108,31 +108,6 @@ var React__namespace = /*#__PURE__*/_interopNamespaceDefault(React);
|
|
108
108
|
var Prism__namespace = /*#__PURE__*/_interopNamespaceDefault(Prism);
|
109
109
|
var Toolbar__namespace = /*#__PURE__*/_interopNamespaceDefault(Toolbar);
|
110
110
|
|
111
|
-
const [DocumentProvider, useDocumentContext] = strapiAdmin.createContext('DocumentContext');
|
112
|
-
/**
|
113
|
-
* TODO: Document in contributor docs, Add unit test
|
114
|
-
*
|
115
|
-
* This context provider and its associated hook are used to access a document at its root level
|
116
|
-
* and expose a function to change the current document being viewed to one of the root level docuemnt's relations.
|
117
|
-
*
|
118
|
-
* The useDocumentContext hook exposes:
|
119
|
-
* - meta: information about the currentDocument,
|
120
|
-
* - document: the actual document,
|
121
|
-
* - changeDocument: a function to change the current document to one of its relations.
|
122
|
-
*/ const DocumentContextProvider = ({ children, initialDocument })=>{
|
123
|
-
/**
|
124
|
-
* Initialize with the "root" document and expose a setter method to change to
|
125
|
-
* one of the root level document's relations.
|
126
|
-
*/ const [currentDocumentMeta, changeDocument] = React__namespace.useState(initialDocument);
|
127
|
-
const document = index.useDocument(currentDocumentMeta);
|
128
|
-
return /*#__PURE__*/ jsxRuntime.jsx(DocumentProvider, {
|
129
|
-
changeDocument: changeDocument,
|
130
|
-
document: document,
|
131
|
-
meta: currentDocumentMeta,
|
132
|
-
children: children
|
133
|
-
});
|
134
|
-
};
|
135
|
-
|
136
111
|
const componentStore = new Map();
|
137
112
|
/**
|
138
113
|
* @description A hook to lazy load custom field components
|
@@ -3628,15 +3603,24 @@ const ComponentCategory = ({ category, components = [], variant = 'primary', onA
|
|
3628
3603
|
const ResponsiveAccordionContent = styledComponents.styled(designSystem.Accordion.Content)`
|
3629
3604
|
container-type: inline-size;
|
3630
3605
|
`;
|
3631
|
-
|
3632
|
-
|
3633
|
-
|
3634
|
-
|
3635
|
-
|
3636
|
-
|
3637
|
-
|
3638
|
-
|
3639
|
-
|
3606
|
+
/**
|
3607
|
+
* TODO:
|
3608
|
+
* JSDOM cannot handle container queries.
|
3609
|
+
* This is a temporary workaround so that tests do not fail in the CI when jestdom throws an error
|
3610
|
+
* for failing to parse the stylesheet.
|
3611
|
+
*/ const Grid = process.env.NODE_ENV !== 'test' ? styledComponents.styled(designSystem.Box)`
|
3612
|
+
display: grid;
|
3613
|
+
grid-template-columns: repeat(auto-fill, 100%);
|
3614
|
+
grid-gap: 4px;
|
3615
|
+
|
3616
|
+
@container (min-width: ${()=>RESPONSIVE_CONTAINER_BREAKPOINTS.sm}) {
|
3617
|
+
grid-template-columns: repeat(auto-fill, 14rem);
|
3618
|
+
}
|
3619
|
+
` : styledComponents.styled(designSystem.Box)`
|
3620
|
+
display: grid;
|
3621
|
+
grid-template-columns: repeat(auto-fill, 100%);
|
3622
|
+
grid-gap: 4px;
|
3623
|
+
`;
|
3640
3624
|
const ComponentBox = styledComponents.styled(designSystem.Flex)`
|
3641
3625
|
color: ${({ theme })=>theme.colors.neutral600};
|
3642
3626
|
cursor: pointer;
|
@@ -3701,8 +3685,19 @@ const ComponentPicker = ({ dynamicComponentsByCategory = {}, isOpen, onClickAddC
|
|
3701
3685
|
const DynamicComponent = ({ componentUid, disabled, index: index$1, name, onRemoveComponentClick, onMoveComponent, onGrabItem, onDropItem, onCancel, dynamicComponentsByCategory = {}, onAddComponent, children })=>{
|
3702
3686
|
const { formatMessage } = reactIntl.useIntl();
|
3703
3687
|
const formValues = strapiAdmin.useForm('DynamicComponent', (state)=>state.values);
|
3704
|
-
const documentMeta = useDocumentContext('DynamicComponent', (state)=>state.meta);
|
3705
|
-
const
|
3688
|
+
const documentMeta = index.useDocumentContext('DynamicComponent', (state)=>state.meta);
|
3689
|
+
const rootDocumentMeta = index.useDocumentContext('DynamicComponent', (state)=>state.rootDocumentMeta);
|
3690
|
+
const { edit: { components: rootComponents } } = index.useDocumentLayout(rootDocumentMeta.model);
|
3691
|
+
const { edit: { components: relatedComponents } } = index.useDocumentLayout(documentMeta.model);
|
3692
|
+
// Merge the root level components and dynamic zone components
|
3693
|
+
const components = React__namespace.useMemo(()=>({
|
3694
|
+
...rootComponents,
|
3695
|
+
...relatedComponents
|
3696
|
+
}), [
|
3697
|
+
rootComponents,
|
3698
|
+
relatedComponents
|
3699
|
+
]);
|
3700
|
+
const document = index.useDocumentContext('DynamicComponent', (state)=>state.document);
|
3706
3701
|
const title = React__namespace.useMemo(()=>{
|
3707
3702
|
const { mainField } = components[componentUid]?.settings ?? {
|
3708
3703
|
mainField: 'id'
|
@@ -3934,9 +3929,11 @@ const DynamicComponent = ({ componentUid, disabled, index: index$1, name, onRemo
|
|
3934
3929
|
alignItems: "stretch",
|
3935
3930
|
children: children ? children({
|
3936
3931
|
...fieldWithTranslatedLabel,
|
3932
|
+
document,
|
3937
3933
|
name: fieldName
|
3938
3934
|
}) : /*#__PURE__*/ jsxRuntime.jsx(MemoizedInputRenderer, {
|
3939
3935
|
...fieldWithTranslatedLabel,
|
3936
|
+
document: document,
|
3940
3937
|
name: fieldName
|
3941
3938
|
})
|
3942
3939
|
}, fieldName);
|
@@ -4054,7 +4051,7 @@ const DynamicZone = ({ attribute, disabled: disabledProp, hint, label, labelActi
|
|
4054
4051
|
const { max = Infinity, min = -Infinity } = attribute ?? {};
|
4055
4052
|
const [addComponentIsOpen, setAddComponentIsOpen] = React__namespace.useState(false);
|
4056
4053
|
const [liveText, setLiveText] = React__namespace.useState('');
|
4057
|
-
const document = useDocumentContext('DynamicZone', (state)=>state.document);
|
4054
|
+
const document = index.useDocumentContext('DynamicZone', (state)=>state.document);
|
4058
4055
|
const { components, isLoading } = document;
|
4059
4056
|
const disabled = disabledProp || isLoading;
|
4060
4057
|
const { addFieldRow, removeFieldRow, moveFieldRow } = strapiAdmin.useForm('DynamicZone', ({ addFieldRow, removeFieldRow, moveFieldRow })=>({
|
@@ -4299,68 +4296,278 @@ const CustomModalContent = styledComponents.styled(designSystem.Modal.Content)`
|
|
4299
4296
|
height: 90%;
|
4300
4297
|
max-height: 100%;
|
4301
4298
|
`;
|
4302
|
-
const
|
4299
|
+
const [RelationModalProvider, useRelationModal] = strapiAdmin.createContext('RelationModal', {
|
4300
|
+
parentModified: false,
|
4301
|
+
depth: 0
|
4302
|
+
});
|
4303
|
+
const RelationModalForm = ({ relation, triggerButtonLabel })=>{
|
4304
|
+
const navigate = reactRouterDom.useNavigate();
|
4305
|
+
const { pathname, search } = reactRouterDom.useLocation();
|
4303
4306
|
const { formatMessage } = reactIntl.useIntl();
|
4304
|
-
|
4305
|
-
|
4306
|
-
|
4307
|
-
|
4308
|
-
|
4309
|
-
|
4310
|
-
|
4307
|
+
const [triggerRefetchDocument] = index.useLazyGetDocumentQuery();
|
4308
|
+
const currentDocument = index.useDocumentContext('RelationModalForm', (state)=>state.document);
|
4309
|
+
const rootDocumentMeta = index.useDocumentContext('RelationModalForm', (state)=>state.rootDocumentMeta);
|
4310
|
+
const currentDocumentMeta = index.useDocumentContext('RelationModalForm', (state)=>state.meta);
|
4311
|
+
const changeDocument = index.useDocumentContext('RelationModalForm', (state)=>state.changeDocument);
|
4312
|
+
const documentHistory = index.useDocumentContext('RelationModalForm', (state)=>state.documentHistory);
|
4313
|
+
const setDocumentHistory = index.useDocumentContext('RelationModalForm', (state)=>state.setDocumentHistory);
|
4314
|
+
const [isConfirmationOpen, setIsConfirmationOpen] = React__namespace.useState(false);
|
4315
|
+
const [actionPosition, setActionPosition] = React__namespace.useState('cancel');
|
4316
|
+
const [isModalOpen, setIsModalOpen] = React__namespace.useState(false);
|
4317
|
+
// NOTE: Not sure about this relation modal context, maybe we should move this to DocumentContext?
|
4318
|
+
// Get parent modal context if it exists
|
4319
|
+
const parentContext = useRelationModal('RelationModalForm', (state)=>state);
|
4320
|
+
// Get depth of nested modals
|
4321
|
+
const depth = parentContext ? parentContext.depth + 1 : 0;
|
4322
|
+
// Check if this is a nested modal
|
4323
|
+
const isNested = depth > 0;
|
4324
|
+
const addDocumentToHistory = (document)=>setDocumentHistory((prev)=>[
|
4325
|
+
...prev,
|
4326
|
+
document
|
4327
|
+
]);
|
4328
|
+
const getPreviousDocument = ()=>{
|
4329
|
+
if (documentHistory.length === 0) return undefined;
|
4330
|
+
const lastDocument = documentHistory[documentHistory.length - 1];
|
4331
|
+
return lastDocument;
|
4332
|
+
};
|
4333
|
+
const removeLastDocumentFromHistory = ()=>{
|
4334
|
+
setDocumentHistory((prev)=>[
|
4335
|
+
...prev
|
4336
|
+
].slice(0, prev.length - 1));
|
4337
|
+
};
|
4338
|
+
const handleToggleModal = ()=>{
|
4339
|
+
if (isModalOpen) {
|
4340
|
+
setIsModalOpen(false);
|
4341
|
+
const document = {
|
4342
|
+
collectionType: rootDocumentMeta.collectionType,
|
4343
|
+
model: rootDocumentMeta.model,
|
4344
|
+
documentId: rootDocumentMeta.documentId
|
4345
|
+
};
|
4346
|
+
// Change back to the root document
|
4347
|
+
changeDocument(document);
|
4348
|
+
// Reset the document history
|
4349
|
+
setDocumentHistory([]);
|
4350
|
+
// Reset action position
|
4351
|
+
setActionPosition('cancel');
|
4352
|
+
// Read from cache or refetch root document
|
4353
|
+
triggerRefetchDocument(document, // Favor the cache
|
4354
|
+
true);
|
4355
|
+
} else {
|
4356
|
+
changeDocument(relation);
|
4357
|
+
setIsModalOpen(true);
|
4358
|
+
}
|
4359
|
+
};
|
4360
|
+
const getFullPageLink = ()=>{
|
4361
|
+
const isSingleType = currentDocumentMeta.collectionType === index.SINGLE_TYPES;
|
4362
|
+
const queryParams = currentDocumentMeta.params?.locale ? `?plugins[i18n][locale]=${currentDocumentMeta.params.locale}` : '';
|
4363
|
+
return `/content-manager/${currentDocumentMeta.collectionType}/${currentDocumentMeta.model}${isSingleType ? '' : '/' + currentDocumentMeta.documentId}${queryParams}`;
|
4364
|
+
};
|
4365
|
+
const handleRedirection = ()=>{
|
4366
|
+
const editViewUrl = `${pathname}${search}`;
|
4367
|
+
const isRootDocumentUrl = editViewUrl.includes(getFullPageLink());
|
4368
|
+
if (isRootDocumentUrl) {
|
4369
|
+
handleToggleModal();
|
4370
|
+
} else {
|
4371
|
+
navigate(getFullPageLink());
|
4372
|
+
}
|
4373
|
+
};
|
4374
|
+
const handleConfirm = ()=>{
|
4375
|
+
if (actionPosition === 'navigate') {
|
4376
|
+
handleRedirection();
|
4377
|
+
} else if (actionPosition === 'back') {
|
4378
|
+
const previousRelation = getPreviousDocument();
|
4379
|
+
if (previousRelation) {
|
4380
|
+
removeLastDocumentFromHistory();
|
4381
|
+
changeDocument(previousRelation);
|
4382
|
+
}
|
4383
|
+
} else {
|
4384
|
+
handleToggleModal();
|
4385
|
+
}
|
4386
|
+
};
|
4387
|
+
return /*#__PURE__*/ jsxRuntime.jsx(strapiAdmin.Form, {
|
4388
|
+
method: "PUT",
|
4389
|
+
initialValues: currentDocument.getInitialFormValues(),
|
4390
|
+
validate: (values, options)=>{
|
4391
|
+
const yupSchema = index.createYupSchema(currentDocument.schema?.attributes, currentDocument.components, {
|
4392
|
+
status: currentDocument.document?.status,
|
4393
|
+
...options
|
4394
|
+
});
|
4395
|
+
return yupSchema.validate(values, {
|
4396
|
+
abortEarly: false
|
4397
|
+
});
|
4398
|
+
},
|
4399
|
+
children: ({ modified, isSubmitting, resetForm })=>{
|
4400
|
+
// We don't count the root document, so history starts after 1
|
4401
|
+
const hasHistory = documentHistory.length > 1;
|
4402
|
+
return /*#__PURE__*/ jsxRuntime.jsxs(RelationModalProvider, {
|
4403
|
+
parentModified: modified,
|
4404
|
+
depth: depth,
|
4405
|
+
children: [
|
4406
|
+
/*#__PURE__*/ jsxRuntime.jsxs(designSystem.Modal.Root, {
|
4407
|
+
open: isModalOpen,
|
4408
|
+
onOpenChange: ()=>{
|
4409
|
+
if (isModalOpen) {
|
4410
|
+
if (modified && !isSubmitting) {
|
4411
|
+
setIsConfirmationOpen(true);
|
4412
|
+
} else {
|
4413
|
+
handleToggleModal();
|
4414
|
+
}
|
4415
|
+
}
|
4416
|
+
},
|
4311
4417
|
children: [
|
4312
|
-
/*#__PURE__*/ jsxRuntime.jsx(designSystem.
|
4313
|
-
|
4314
|
-
|
4315
|
-
|
4316
|
-
|
4317
|
-
|
4318
|
-
|
4319
|
-
|
4320
|
-
|
4321
|
-
|
4322
|
-
|
4323
|
-
|
4324
|
-
|
4325
|
-
|
4326
|
-
|
4418
|
+
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Modal.Trigger, {
|
4419
|
+
children: /*#__PURE__*/ jsxRuntime.jsx(designSystem.Tooltip, {
|
4420
|
+
description: triggerButtonLabel,
|
4421
|
+
children: /*#__PURE__*/ jsxRuntime.jsx(CustomTextButton, {
|
4422
|
+
onClick: ()=>{
|
4423
|
+
// Check if parent modal has unsaved changes
|
4424
|
+
if (isNested && parentContext.parentModified) {
|
4425
|
+
setIsConfirmationOpen(true);
|
4426
|
+
// Return early to avoid opening the modal
|
4427
|
+
return;
|
4428
|
+
} else {
|
4429
|
+
if (modified && !isSubmitting) {
|
4430
|
+
setIsConfirmationOpen(true);
|
4431
|
+
} else {
|
4432
|
+
// Add current relation to history before opening a new one
|
4433
|
+
if (currentDocumentMeta && Object.keys(currentDocumentMeta).length > 0) {
|
4434
|
+
addDocumentToHistory(currentDocumentMeta);
|
4435
|
+
}
|
4436
|
+
handleToggleModal();
|
4437
|
+
}
|
4438
|
+
if (!isModalOpen) {
|
4439
|
+
setIsModalOpen(true);
|
4440
|
+
}
|
4441
|
+
}
|
4442
|
+
},
|
4443
|
+
children: triggerButtonLabel
|
4444
|
+
})
|
4327
4445
|
})
|
4446
|
+
}),
|
4447
|
+
/*#__PURE__*/ jsxRuntime.jsxs(CustomModalContent, {
|
4448
|
+
children: [
|
4449
|
+
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Modal.Header, {
|
4450
|
+
gap: 2,
|
4451
|
+
children: /*#__PURE__*/ jsxRuntime.jsx(designSystem.Flex, {
|
4452
|
+
justifyContent: "space-between",
|
4453
|
+
alignItems: "center",
|
4454
|
+
width: "100%",
|
4455
|
+
children: /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Flex, {
|
4456
|
+
gap: 2,
|
4457
|
+
children: [
|
4458
|
+
/*#__PURE__*/ jsxRuntime.jsx(designSystem.IconButton, {
|
4459
|
+
withTooltip: false,
|
4460
|
+
label: "Back",
|
4461
|
+
variant: "ghost",
|
4462
|
+
disabled: !hasHistory,
|
4463
|
+
onClick: ()=>{
|
4464
|
+
setActionPosition('back');
|
4465
|
+
if (modified && !isSubmitting) {
|
4466
|
+
setIsConfirmationOpen(true);
|
4467
|
+
} else {
|
4468
|
+
const previousRelation = getPreviousDocument();
|
4469
|
+
if (previousRelation) {
|
4470
|
+
removeLastDocumentFromHistory();
|
4471
|
+
changeDocument(previousRelation);
|
4472
|
+
}
|
4473
|
+
}
|
4474
|
+
},
|
4475
|
+
marginRight: 1,
|
4476
|
+
children: /*#__PURE__*/ jsxRuntime.jsx(Icons.ArrowLeft, {})
|
4477
|
+
}),
|
4478
|
+
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Typography, {
|
4479
|
+
tag: "span",
|
4480
|
+
fontWeight: 600,
|
4481
|
+
children: formatMessage({
|
4482
|
+
id: 'content-manager.components.RelationInputModal.modal-title',
|
4483
|
+
defaultMessage: 'Edit a relation'
|
4484
|
+
})
|
4485
|
+
})
|
4486
|
+
]
|
4487
|
+
})
|
4488
|
+
})
|
4489
|
+
}),
|
4490
|
+
/*#__PURE__*/ jsxRuntime.jsx(RelationModalBody, {
|
4491
|
+
children: /*#__PURE__*/ jsxRuntime.jsx(designSystem.IconButton, {
|
4492
|
+
onClick: ()=>{
|
4493
|
+
setActionPosition('navigate');
|
4494
|
+
if (modified && !isSubmitting) {
|
4495
|
+
setIsConfirmationOpen(true);
|
4496
|
+
} else {
|
4497
|
+
navigate(getFullPageLink());
|
4498
|
+
}
|
4499
|
+
},
|
4500
|
+
variant: "tertiary",
|
4501
|
+
label: formatMessage({
|
4502
|
+
id: 'content-manager.components.RelationInputModal.button-fullpage',
|
4503
|
+
defaultMessage: 'Go to entry'
|
4504
|
+
}),
|
4505
|
+
children: /*#__PURE__*/ jsxRuntime.jsx(Icons.ArrowsOut, {})
|
4506
|
+
})
|
4507
|
+
}),
|
4508
|
+
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Modal.Footer, {
|
4509
|
+
children: /*#__PURE__*/ jsxRuntime.jsx(designSystem.Button, {
|
4510
|
+
onClick: ()=>{
|
4511
|
+
if (modified && !isSubmitting) {
|
4512
|
+
setIsConfirmationOpen(true);
|
4513
|
+
} else {
|
4514
|
+
handleToggleModal();
|
4515
|
+
}
|
4516
|
+
},
|
4517
|
+
variant: "tertiary",
|
4518
|
+
children: formatMessage({
|
4519
|
+
id: 'app.components.Button.cancel',
|
4520
|
+
defaultMessage: 'Cancel'
|
4521
|
+
})
|
4522
|
+
})
|
4523
|
+
})
|
4524
|
+
]
|
4328
4525
|
})
|
4329
4526
|
]
|
4330
|
-
})
|
4331
|
-
|
4332
|
-
|
4333
|
-
|
4334
|
-
|
4335
|
-
|
4336
|
-
|
4337
|
-
|
4338
|
-
|
4339
|
-
|
4340
|
-
|
4341
|
-
|
4342
|
-
|
4343
|
-
|
4344
|
-
|
4345
|
-
|
4527
|
+
}),
|
4528
|
+
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Dialog.Root, {
|
4529
|
+
open: isConfirmationOpen,
|
4530
|
+
onOpenChange: setIsConfirmationOpen,
|
4531
|
+
children: /*#__PURE__*/ jsxRuntime.jsx(strapiAdmin.ConfirmDialog, {
|
4532
|
+
onConfirm: ()=>{
|
4533
|
+
handleConfirm();
|
4534
|
+
setIsConfirmationOpen(false);
|
4535
|
+
resetForm();
|
4536
|
+
},
|
4537
|
+
onCancel: ()=>{
|
4538
|
+
setIsConfirmationOpen(false);
|
4539
|
+
},
|
4540
|
+
variant: "danger",
|
4541
|
+
children: formatMessage({
|
4542
|
+
id: 'content-manager.components.RelationInputModal.confirmation-message',
|
4543
|
+
defaultMessage: 'Some changes were not saved. Are you sure you want to close this relation? All changes that were not saved will be lost.'
|
4544
|
+
})
|
4346
4545
|
})
|
4347
4546
|
})
|
4348
|
-
|
4349
|
-
|
4350
|
-
}
|
4547
|
+
]
|
4548
|
+
});
|
4549
|
+
}
|
4351
4550
|
});
|
4352
4551
|
};
|
4353
|
-
const
|
4552
|
+
const CustomTextButton = styledComponents.styled(designSystem.TextButton)`
|
4553
|
+
& > span {
|
4554
|
+
font-size: ${({ theme })=>theme.fontSizes[2]};
|
4555
|
+
}
|
4556
|
+
`;
|
4557
|
+
const RelationModalBody = ({ children })=>{
|
4354
4558
|
const { formatMessage } = reactIntl.useIntl();
|
4355
|
-
const documentMeta = useDocumentContext('RelationModalBody', (state)=>state.meta);
|
4356
|
-
const documentResponse = useDocumentContext('RelationModalBody', (state)=>state.document);
|
4559
|
+
const documentMeta = index.useDocumentContext('RelationModalBody', (state)=>state.meta);
|
4560
|
+
const documentResponse = index.useDocumentContext('RelationModalBody', (state)=>state.document);
|
4561
|
+
const onPreview = index.useDocumentContext('RelationModalBody', (state)=>state.onPreview);
|
4357
4562
|
const documentLayoutResponse = index.useDocumentLayout(documentMeta.model);
|
4563
|
+
const plugins = strapiAdmin.useStrapiApp('RelationModalBody', (state)=>state.plugins);
|
4358
4564
|
const initialValues = documentResponse.getInitialFormValues();
|
4359
|
-
const { permissions = [], isLoading, error } = strapiAdmin.useRBAC(index.PERMISSIONS.map((action)=>({
|
4565
|
+
const { permissions = [], isLoading: isLoadingPermissions, error } = strapiAdmin.useRBAC(index.PERMISSIONS.map((action)=>({
|
4360
4566
|
action,
|
4361
4567
|
subject: documentMeta.model
|
4362
4568
|
})));
|
4363
|
-
|
4569
|
+
const isLoading = isLoadingPermissions || documentLayoutResponse.isLoading || documentResponse.isLoading;
|
4570
|
+
if (isLoading && !documentResponse.document?.documentId) {
|
4364
4571
|
return /*#__PURE__*/ jsxRuntime.jsx(designSystem.Loader, {
|
4365
4572
|
small: true,
|
4366
4573
|
children: formatMessage({
|
@@ -4387,44 +4594,95 @@ const RelationModalBody = ({ id })=>{
|
|
4387
4594
|
}
|
4388
4595
|
const documentTitle = documentResponse.getTitle(documentLayoutResponse.edit.settings.mainField);
|
4389
4596
|
const hasDraftAndPublished = documentResponse.schema?.options?.draftAndPublish ?? false;
|
4597
|
+
const props = {
|
4598
|
+
activeTab: 'draft',
|
4599
|
+
collectionType: documentMeta.collectionType,
|
4600
|
+
model: documentMeta.model,
|
4601
|
+
documentId: documentMeta.documentId,
|
4602
|
+
document: documentResponse.document,
|
4603
|
+
meta: documentResponse.meta,
|
4604
|
+
onPreview
|
4605
|
+
};
|
4390
4606
|
return /*#__PURE__*/ jsxRuntime.jsx(designSystem.Modal.Body, {
|
4391
4607
|
children: /*#__PURE__*/ jsxRuntime.jsxs(index.DocumentRBAC, {
|
4392
4608
|
permissions: permissions,
|
4393
4609
|
model: documentMeta.model,
|
4394
4610
|
children: [
|
4395
4611
|
/*#__PURE__*/ jsxRuntime.jsxs(designSystem.Flex, {
|
4396
|
-
direction: "column",
|
4397
4612
|
alignItems: "flex-start",
|
4613
|
+
direction: "column",
|
4398
4614
|
gap: 2,
|
4399
4615
|
children: [
|
4400
|
-
/*#__PURE__*/ jsxRuntime.
|
4401
|
-
|
4402
|
-
|
4403
|
-
|
4616
|
+
/*#__PURE__*/ jsxRuntime.jsxs(designSystem.Flex, {
|
4617
|
+
width: "100%",
|
4618
|
+
justifyContent: "space-between",
|
4619
|
+
gap: 2,
|
4620
|
+
children: [
|
4621
|
+
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Typography, {
|
4622
|
+
tag: "h2",
|
4623
|
+
variant: "alpha",
|
4624
|
+
children: documentTitle
|
4625
|
+
}),
|
4626
|
+
/*#__PURE__*/ jsxRuntime.jsxs(designSystem.Flex, {
|
4627
|
+
gap: 2,
|
4628
|
+
children: [
|
4629
|
+
children,
|
4630
|
+
/*#__PURE__*/ jsxRuntime.jsx(strapiAdmin.DescriptionComponentRenderer, {
|
4631
|
+
props: props,
|
4632
|
+
descriptions: plugins['content-manager'].apis.getDocumentActions('relation-modal'),
|
4633
|
+
children: (actions)=>{
|
4634
|
+
const filteredActions = actions.filter((action)=>{
|
4635
|
+
return [
|
4636
|
+
action.position
|
4637
|
+
].flat().includes('relation-modal');
|
4638
|
+
});
|
4639
|
+
const [primaryAction, secondaryAction] = filteredActions;
|
4640
|
+
if (!primaryAction && !secondaryAction) return null;
|
4641
|
+
// Both actions are available when draft and publish enabled
|
4642
|
+
if (primaryAction && secondaryAction) {
|
4643
|
+
return /*#__PURE__*/ jsxRuntime.jsxs(jsxRuntime.Fragment, {
|
4644
|
+
children: [
|
4645
|
+
/*#__PURE__*/ jsxRuntime.jsx(index.DocumentActionButton, {
|
4646
|
+
...secondaryAction,
|
4647
|
+
variant: secondaryAction.variant || 'secondary'
|
4648
|
+
}),
|
4649
|
+
/*#__PURE__*/ jsxRuntime.jsx(index.DocumentActionButton, {
|
4650
|
+
...primaryAction,
|
4651
|
+
variant: primaryAction.variant || 'default'
|
4652
|
+
})
|
4653
|
+
]
|
4654
|
+
});
|
4655
|
+
}
|
4656
|
+
// Otherwise we just have the save action
|
4657
|
+
return /*#__PURE__*/ jsxRuntime.jsx(index.DocumentActionButton, {
|
4658
|
+
...primaryAction,
|
4659
|
+
variant: primaryAction.variant || 'secondary'
|
4660
|
+
});
|
4661
|
+
}
|
4662
|
+
})
|
4663
|
+
]
|
4664
|
+
})
|
4665
|
+
]
|
4404
4666
|
}),
|
4405
4667
|
hasDraftAndPublished ? /*#__PURE__*/ jsxRuntime.jsx(designSystem.Box, {
|
4406
|
-
marginTop: 1,
|
4407
4668
|
children: /*#__PURE__*/ jsxRuntime.jsx(index.DocumentStatus, {
|
4408
4669
|
status: documentResponse.document?.status
|
4409
4670
|
})
|
4410
4671
|
}) : null
|
4411
4672
|
]
|
4412
4673
|
}),
|
4413
|
-
/*#__PURE__*/ jsxRuntime.jsx(
|
4414
|
-
|
4415
|
-
|
4416
|
-
|
4417
|
-
|
4674
|
+
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Flex, {
|
4675
|
+
flex: 1,
|
4676
|
+
overflow: "auto",
|
4677
|
+
alignItems: "stretch",
|
4678
|
+
paddingTop: 7,
|
4679
|
+
children: /*#__PURE__*/ jsxRuntime.jsx(designSystem.Box, {
|
4418
4680
|
overflow: "auto",
|
4419
|
-
|
4420
|
-
|
4421
|
-
|
4422
|
-
|
4423
|
-
|
4424
|
-
children: /*#__PURE__*/ jsxRuntime.jsx(FormLayout, {
|
4425
|
-
layout: documentLayoutResponse.edit.layout,
|
4426
|
-
hasBackground: false
|
4427
|
-
})
|
4681
|
+
flex: 1,
|
4682
|
+
children: /*#__PURE__*/ jsxRuntime.jsx(FormLayout, {
|
4683
|
+
layout: documentLayoutResponse.edit.layout,
|
4684
|
+
document: documentResponse,
|
4685
|
+
hasBackground: false
|
4428
4686
|
})
|
4429
4687
|
})
|
4430
4688
|
})
|
@@ -4485,15 +4743,18 @@ const ONE_WAY_RELATIONS = [
|
|
4485
4743
|
* @description The relations field holds a lot of domain logic for handling relations which is rather complicated
|
4486
4744
|
* At present we do not expose this to plugin developers, however, they are able to overwrite it themselves should
|
4487
4745
|
* they wish to do so.
|
4488
|
-
*/ const
|
4489
|
-
const
|
4490
|
-
const
|
4491
|
-
const
|
4746
|
+
*/ const RelationsField = /*#__PURE__*/ React__namespace.forwardRef(({ disabled, label, ...props }, ref)=>{
|
4747
|
+
const currentDocumentMeta = index.useDocumentContext('RelationsField', (state)=>state.meta);
|
4748
|
+
const currentDocument = index.useDocumentContext('RelationsField', (state)=>state.document);
|
4749
|
+
const rootDocumentMeta = index.useDocumentContext('RelationsField', (state)=>state.rootDocumentMeta);
|
4492
4750
|
const [currentPage, setCurrentPage] = React__namespace.useState(1);
|
4493
|
-
const
|
4751
|
+
const isRootDocument = rootDocumentMeta.documentId === currentDocumentMeta.documentId;
|
4752
|
+
const documentMeta = isRootDocument ? rootDocumentMeta : currentDocumentMeta;
|
4753
|
+
// Use the documentId from the actual document, not the params (meta)
|
4754
|
+
const documentId = currentDocument.document?.documentId;
|
4494
4755
|
const { formatMessage } = reactIntl.useIntl();
|
4495
4756
|
const [{ query }] = strapiAdmin.useQueryParams();
|
4496
|
-
const params = index.buildValidParams(query);
|
4757
|
+
const params = documentMeta.params ?? index.buildValidParams(query);
|
4497
4758
|
const isMorph = props.attribute.relation.toLowerCase().includes('morph');
|
4498
4759
|
const isDisabled = isMorph || disabled;
|
4499
4760
|
const { componentId, componentUID } = useComponent('RelationsField', ({ uid, id })=>({
|
@@ -4506,17 +4767,24 @@ const ONE_WAY_RELATIONS = [
|
|
4506
4767
|
}, [
|
4507
4768
|
isSubmitting
|
4508
4769
|
]);
|
4770
|
+
const component = componentUID && currentDocument.components[componentUID];
|
4509
4771
|
/**
|
4510
4772
|
* We'll always have a documentId in a created entry, so we look for a componentId first.
|
4511
4773
|
* Same with `uid` and `documentModel`.
|
4512
|
-
*/ const
|
4513
|
-
const
|
4774
|
+
*/ const model = component ? component.uid : documentMeta.model;
|
4775
|
+
const id = component && componentId ? componentId.toString() : documentId;
|
4514
4776
|
/**
|
4515
4777
|
* The `name` prop is a complete path to the field, e.g. `field1.field2.field3`.
|
4516
4778
|
* Where the above example would a nested field within two components, however
|
4517
4779
|
* we only require the field on the component not the complete path since we query
|
4518
4780
|
* individual components. Therefore we split the string and take the last item.
|
4519
4781
|
*/ const [targetField] = props.name.split('.').slice(-1);
|
4782
|
+
const schemaAttributes = component ? component.attributes ?? {} : currentDocument.schema?.attributes ?? {};
|
4783
|
+
/**
|
4784
|
+
* Confirm the target field is related to the current document.
|
4785
|
+
* Since relations can exist in a modal on top of the root document,
|
4786
|
+
* we need to ensure we are fetching relations for the correct document (root document vs related document),
|
4787
|
+
*/ const isRelatedToCurrentDocument = Object.values(schemaAttributes).filter((attribute)=>attribute.type === 'relation' && 'target' in attribute && 'target' in props.attribute && attribute.target === props.attribute.target).length > 0;
|
4520
4788
|
const { data, isLoading, isFetching } = usePrev.useGetRelationsQuery({
|
4521
4789
|
model,
|
4522
4790
|
targetField,
|
@@ -4529,7 +4797,7 @@ const ONE_WAY_RELATIONS = [
|
|
4529
4797
|
}
|
4530
4798
|
}, {
|
4531
4799
|
refetchOnMountOrArgChange: true,
|
4532
|
-
skip: !id,
|
4800
|
+
skip: !id || !isRelatedToCurrentDocument,
|
4533
4801
|
selectFromResult: (result)=>{
|
4534
4802
|
return {
|
4535
4803
|
...result,
|
@@ -4638,10 +4906,11 @@ const ONE_WAY_RELATIONS = [
|
|
4638
4906
|
/*#__PURE__*/ jsxRuntime.jsx(RelationsInput, {
|
4639
4907
|
disabled: isDisabled,
|
4640
4908
|
// NOTE: we should not default to using the documentId if the component is being created (componentUID is undefined)
|
4641
|
-
id: componentUID ? componentId ? `${componentId}` : '' : documentId,
|
4909
|
+
id: componentUID && component ? componentId ? `${componentId}` : '' : documentId,
|
4642
4910
|
label: `${label} ${relationsCount > 0 ? `(${relationsCount})` : ''}`,
|
4643
4911
|
model: model,
|
4644
4912
|
onChange: handleConnect,
|
4913
|
+
isRelatedToCurrentDocument: isRelatedToCurrentDocument,
|
4645
4914
|
...props
|
4646
4915
|
}),
|
4647
4916
|
'pagination' in data && data.pagination && data.pagination.pageCount > data.pagination.page ? /*#__PURE__*/ jsxRuntime.jsx(designSystem.TextButton, {
|
@@ -4658,7 +4927,7 @@ const ONE_WAY_RELATIONS = [
|
|
4658
4927
|
}) : null
|
4659
4928
|
]
|
4660
4929
|
}),
|
4661
|
-
/*#__PURE__*/ jsxRuntime.jsx(
|
4930
|
+
/*#__PURE__*/ jsxRuntime.jsx(RelationsList, {
|
4662
4931
|
data: relations,
|
4663
4932
|
serverData: data.results,
|
4664
4933
|
disabled: isDisabled,
|
@@ -4666,575 +4935,226 @@ const ONE_WAY_RELATIONS = [
|
|
4666
4935
|
isLoading: isFetchingMoreRelations,
|
4667
4936
|
relationType: props.attribute.relation,
|
4668
4937
|
// @ts-expect-error – targetModel does exist on the attribute. But it's not typed.
|
4669
|
-
targetModel: props.attribute.targetModel
|
4670
|
-
setCurrentDocument: changeDocument
|
4938
|
+
targetModel: props.attribute.targetModel
|
4671
4939
|
})
|
4672
4940
|
]
|
4673
4941
|
});
|
4674
4942
|
});
|
4675
|
-
|
4676
|
-
|
4677
|
-
|
4678
|
-
|
4679
|
-
|
4943
|
+
/**
|
4944
|
+
* TODO: this can be removed once we stop shipping Inputs with
|
4945
|
+
* labels wrapped round in DS@2.
|
4946
|
+
*/ const StyledFlex = styledComponents.styled(designSystem.Flex)`
|
4947
|
+
& > div {
|
4948
|
+
width: 100%;
|
4949
|
+
}
|
4950
|
+
`;
|
4951
|
+
/**
|
4952
|
+
* If it's in the connected array, it can get out of our data array,
|
4953
|
+
* we'll be putting it back in later and sorting it anyway.
|
4954
|
+
*/ const removeConnected = ({ field })=>(relations)=>{
|
4955
|
+
return relations.filter((relation)=>{
|
4956
|
+
const connectedRelations = field?.connect ?? [];
|
4957
|
+
return connectedRelations.findIndex((rel)=>rel.id === relation.id) === -1;
|
4958
|
+
});
|
4959
|
+
};
|
4960
|
+
/**
|
4961
|
+
* @description Removes relations that are in the `disconnect` array of the field
|
4962
|
+
*/ const removeDisconnected = ({ field })=>(relations)=>relations.filter((relation)=>{
|
4963
|
+
const disconnectedRelations = field?.disconnect ?? [];
|
4964
|
+
return disconnectedRelations.findIndex((rel)=>rel.id === relation.id) === -1;
|
4965
|
+
});
|
4966
|
+
/**
|
4967
|
+
* @description Adds a label and href to the relation object we use this to render
|
4968
|
+
* a better UI where we can link to the relation and display a human-readable label.
|
4969
|
+
*/ const addLabelAndHref = ({ mainField, href })=>(relations)=>relations.map((relation)=>{
|
4970
|
+
return {
|
4971
|
+
...relation,
|
4972
|
+
// Fallback to `id` if there is no `mainField` value, which will overwrite the above `documentId` property with the exact same data.
|
4973
|
+
[mainField?.name ?? 'documentId']: relation[mainField?.name ?? 'documentId'],
|
4974
|
+
label: usePrev.getRelationLabel(relation, mainField),
|
4975
|
+
href: `${href}/${relation.documentId}?${relation.locale ? `plugins[i18n][locale]=${relation.locale}` : ''}`
|
4976
|
+
};
|
4977
|
+
});
|
4978
|
+
/**
|
4979
|
+
* @description Contains all the logic for the combobox that can search
|
4980
|
+
* for relations and then add them to the field's connect array.
|
4981
|
+
*/ const RelationsInput = ({ hint, id, model, label, labelAction, name, mainField, placeholder, required, unique: _unique, 'aria-label': _ariaLabel, onChange, isRelatedToCurrentDocument, ...props })=>{
|
4982
|
+
const [textValue, setTextValue] = React__namespace.useState('');
|
4983
|
+
const [searchParams, setSearchParams] = React__namespace.useState({
|
4984
|
+
_q: '',
|
4985
|
+
page: 1
|
4986
|
+
});
|
4987
|
+
const { toggleNotification } = strapiAdmin.useNotification();
|
4680
4988
|
const [{ query }] = strapiAdmin.useQueryParams();
|
4681
|
-
const
|
4682
|
-
const
|
4683
|
-
const
|
4684
|
-
const
|
4685
|
-
|
4686
|
-
|
4687
|
-
|
4688
|
-
const
|
4689
|
-
|
4690
|
-
setCurrentPage(1);
|
4691
|
-
}, [
|
4692
|
-
isSubmitting
|
4693
|
-
]);
|
4694
|
-
/**
|
4695
|
-
* We'll always have a documentId in a created entry, so we look for a componentId first.
|
4696
|
-
* Same with `uid` and `documentModel`.
|
4697
|
-
*/ const id = componentId ? componentId.toString() : documentId;
|
4698
|
-
const model = componentUID ?? documentModel;
|
4989
|
+
const currentDocumentMeta = index.useDocumentContext('RelationsInput', (state)=>state.meta);
|
4990
|
+
const rootDocumentMeta = index.useDocumentContext('RelationsInput', (state)=>state.rootDocumentMeta);
|
4991
|
+
const isRootDocument = rootDocumentMeta.documentId === currentDocumentMeta.documentId;
|
4992
|
+
const documentMeta = isRootDocument ? rootDocumentMeta : currentDocumentMeta;
|
4993
|
+
const { formatMessage } = reactIntl.useIntl();
|
4994
|
+
const fieldRef = strapiAdmin.useFocusInputField(name);
|
4995
|
+
const field = strapiAdmin.useField(name);
|
4996
|
+
const searchParamsDebounced = usePrev.useDebounce(searchParams, 300);
|
4997
|
+
const [searchForTrigger, { data, isLoading }] = usePrev.useLazySearchRelationsQuery();
|
4699
4998
|
/**
|
4999
|
+
* Because we're using a lazy query, we need to trigger the search
|
5000
|
+
* when the component mounts and when the search params change.
|
5001
|
+
* We also need to trigger the search when the field value changes
|
5002
|
+
* so that we can filter out the relations that are already connected.
|
5003
|
+
*/ React__namespace.useEffect(()=>{
|
5004
|
+
/**
|
4700
5005
|
* The `name` prop is a complete path to the field, e.g. `field1.field2.field3`.
|
4701
5006
|
* Where the above example would a nested field within two components, however
|
4702
5007
|
* we only require the field on the component not the complete path since we query
|
4703
5008
|
* individual components. Therefore we split the string and take the last item.
|
4704
|
-
*/ const [targetField] =
|
4705
|
-
|
5009
|
+
*/ const [targetField] = name.split('.').slice(-1);
|
5010
|
+
// Return early if there is no relation to the document
|
5011
|
+
if (!isRelatedToCurrentDocument) return;
|
5012
|
+
const params = documentMeta.params ?? index.buildValidParams(query);
|
5013
|
+
searchForTrigger({
|
5014
|
+
model,
|
5015
|
+
targetField,
|
5016
|
+
params: {
|
5017
|
+
...params,
|
5018
|
+
id: id ?? '',
|
5019
|
+
pageSize: 10,
|
5020
|
+
idsToInclude: field.value?.disconnect?.map((rel)=>rel.id.toString()) ?? [],
|
5021
|
+
idsToOmit: field.value?.connect?.map((rel)=>rel.id.toString()) ?? [],
|
5022
|
+
...searchParamsDebounced
|
5023
|
+
}
|
5024
|
+
});
|
5025
|
+
}, [
|
5026
|
+
field.value?.connect,
|
5027
|
+
field.value?.disconnect,
|
5028
|
+
id,
|
4706
5029
|
model,
|
4707
|
-
|
4708
|
-
|
4709
|
-
|
4710
|
-
|
4711
|
-
|
4712
|
-
|
4713
|
-
|
5030
|
+
name,
|
5031
|
+
query,
|
5032
|
+
searchForTrigger,
|
5033
|
+
searchParamsDebounced,
|
5034
|
+
isRelatedToCurrentDocument,
|
5035
|
+
documentMeta
|
5036
|
+
]);
|
5037
|
+
const handleSearch = async (search)=>{
|
5038
|
+
setSearchParams((s)=>({
|
5039
|
+
...s,
|
5040
|
+
_q: search,
|
5041
|
+
page: 1
|
5042
|
+
}));
|
5043
|
+
};
|
5044
|
+
const hasNextPage = data?.pagination ? data.pagination.page < data.pagination.pageCount : false;
|
5045
|
+
const options = data?.results ?? [];
|
5046
|
+
const handleChange = (relationId)=>{
|
5047
|
+
if (!relationId) {
|
5048
|
+
return;
|
4714
5049
|
}
|
4715
|
-
|
4716
|
-
|
4717
|
-
|
4718
|
-
|
4719
|
-
|
4720
|
-
|
4721
|
-
|
4722
|
-
|
4723
|
-
|
4724
|
-
|
4725
|
-
};
|
5050
|
+
const relation = options.find((opt)=>opt.id.toString() === relationId);
|
5051
|
+
if (!relation) {
|
5052
|
+
// This is very unlikely to happen, but it ensures we don't have any data for.
|
5053
|
+
console.error("You've tried to add a relation with an id that does not exist in the options you can see, this is likely a bug with Strapi. Please open an issue.");
|
5054
|
+
toggleNotification({
|
5055
|
+
message: formatMessage({
|
5056
|
+
id: index.getTranslation('relation.error-adding-relation'),
|
5057
|
+
defaultMessage: 'An error occurred while trying to add the relation.'
|
5058
|
+
}),
|
5059
|
+
type: 'danger'
|
5060
|
+
});
|
5061
|
+
return;
|
4726
5062
|
}
|
4727
|
-
|
4728
|
-
|
4729
|
-
|
4730
|
-
|
4731
|
-
|
4732
|
-
|
4733
|
-
|
4734
|
-
/**
|
4735
|
-
* Items that are already connected, but reordered would be in
|
4736
|
-
* this list, so to get an accurate figure, we remove them.
|
4737
|
-
*/ const relationsConnected = (field.value?.connect ?? []).filter((rel)=>data.results.findIndex((relation)=>relation.id === rel.id) === -1).length ?? 0;
|
4738
|
-
const relationsDisconnected = field.value?.disconnect?.length ?? 0;
|
4739
|
-
const relationsCount = realServerRelationsCount + relationsConnected - relationsDisconnected;
|
4740
|
-
/**
|
4741
|
-
* This is it, the source of truth for reordering in conjunction with partial loading & updating
|
4742
|
-
* of relations. Relations on load are given __temp_key__ when fetched, because we don't want to
|
4743
|
-
* create brand new keys everytime the data updates, just keep adding them onto the newly loaded ones.
|
4744
|
-
*/ const relations = React__namespace.useMemo(()=>{
|
4745
|
-
const ctx = {
|
4746
|
-
field: field.value,
|
4747
|
-
// @ts-expect-error – targetModel does exist on the attribute. But it's not typed.
|
4748
|
-
href: `../${index.COLLECTION_TYPES}/${props.attribute.targetModel}`,
|
4749
|
-
mainField: props.mainField
|
4750
|
-
};
|
4751
|
-
/**
|
4752
|
-
* Tidy up our data.
|
4753
|
-
*/ const transformations = pipe$1(removeConnected(ctx), removeDisconnected(ctx), addLabelAndHref(ctx));
|
4754
|
-
const transformedRels = transformations([
|
4755
|
-
...data.results
|
4756
|
-
]);
|
4757
|
-
/**
|
4758
|
-
* THIS IS CRUCIAL. If you don't sort by the __temp_key__ which comes from fractional indexing
|
4759
|
-
* then the list will be in the wrong order.
|
4760
|
-
*/ return [
|
4761
|
-
...transformedRels,
|
4762
|
-
...field.value?.connect ?? []
|
4763
|
-
].sort((a, b)=>{
|
4764
|
-
if (a.__temp_key__ < b.__temp_key__) return -1;
|
4765
|
-
if (a.__temp_key__ > b.__temp_key__) return 1;
|
4766
|
-
return 0;
|
4767
|
-
});
|
4768
|
-
}, [
|
4769
|
-
data.results,
|
4770
|
-
field.value,
|
4771
|
-
// @ts-expect-error – targetModel does exist on the attribute. But it's not typed.
|
4772
|
-
props.attribute.targetModel,
|
4773
|
-
props.mainField
|
4774
|
-
]);
|
4775
|
-
const handleDisconnect = useHandleDisconnect(props.name, 'RelationsField');
|
4776
|
-
const handleConnect = (relation)=>{
|
4777
|
-
const [lastItemInList] = relations.slice(-1);
|
4778
|
-
const item = {
|
4779
|
-
id: relation.id,
|
4780
|
-
apiData: {
|
4781
|
-
id: relation.id,
|
4782
|
-
documentId: relation.documentId,
|
4783
|
-
locale: relation.locale
|
4784
|
-
},
|
4785
|
-
status: relation.status,
|
4786
|
-
/**
|
4787
|
-
* If there's a last item, that's the first key we use to generate out next one.
|
4788
|
-
*/ __temp_key__: fractionalIndexing.generateNKeysBetween(lastItemInList?.__temp_key__ ?? null, null, 1)[0],
|
4789
|
-
// Fallback to `id` if there is no `mainField` value, which will overwrite the above `id` property with the exact same data.
|
4790
|
-
[props.mainField?.name ?? 'documentId']: relation[props.mainField?.name ?? 'documentId'],
|
4791
|
-
label: usePrev.getRelationLabel(relation, props.mainField),
|
4792
|
-
// @ts-expect-error – targetModel does exist on the attribute, but it's not typed.
|
4793
|
-
href: `../${index.COLLECTION_TYPES}/${props.attribute.targetModel}/${relation.documentId}?${relation.locale ? `plugins[i18n][locale]=${relation.locale}` : ''}`
|
4794
|
-
};
|
4795
|
-
if (ONE_WAY_RELATIONS.includes(props.attribute.relation)) {
|
4796
|
-
// Remove any existing relation so they can be replaced with the new one
|
4797
|
-
field.value?.connect?.forEach(handleDisconnect);
|
4798
|
-
relations.forEach(handleDisconnect);
|
4799
|
-
field.onChange(`${props.name}.connect`, [
|
4800
|
-
item
|
4801
|
-
]);
|
4802
|
-
} else {
|
4803
|
-
field.onChange(`${props.name}.connect`, [
|
4804
|
-
...field.value?.connect ?? [],
|
4805
|
-
item
|
4806
|
-
]);
|
4807
|
-
}
|
4808
|
-
};
|
4809
|
-
return /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Flex, {
|
4810
|
-
ref: ref,
|
4811
|
-
direction: "column",
|
4812
|
-
gap: 3,
|
4813
|
-
justifyContent: "space-between",
|
4814
|
-
alignItems: "stretch",
|
4815
|
-
wrap: "wrap",
|
4816
|
-
children: [
|
4817
|
-
/*#__PURE__*/ jsxRuntime.jsxs(StyledFlex, {
|
4818
|
-
direction: "column",
|
4819
|
-
alignItems: "start",
|
4820
|
-
gap: 2,
|
4821
|
-
width: "100%",
|
4822
|
-
children: [
|
4823
|
-
/*#__PURE__*/ jsxRuntime.jsx(RelationsInput, {
|
4824
|
-
disabled: isDisabled,
|
4825
|
-
// NOTE: we should not default to using the documentId if the component is being created (componentUID is undefined)
|
4826
|
-
id: componentUID ? componentId ? `${componentId}` : '' : documentId,
|
4827
|
-
label: `${label} ${relationsCount > 0 ? `(${relationsCount})` : ''}`,
|
4828
|
-
model: model,
|
4829
|
-
onChange: handleConnect,
|
4830
|
-
...props
|
4831
|
-
}),
|
4832
|
-
'pagination' in data && data.pagination && data.pagination.pageCount > data.pagination.page ? /*#__PURE__*/ jsxRuntime.jsx(designSystem.TextButton, {
|
4833
|
-
disabled: isFetchingMoreRelations,
|
4834
|
-
onClick: handleLoadMore,
|
4835
|
-
loading: isFetchingMoreRelations,
|
4836
|
-
startIcon: /*#__PURE__*/ jsxRuntime.jsx(Icons.ArrowClockwise, {}),
|
4837
|
-
// prevent the label from line-wrapping
|
4838
|
-
shrink: 0,
|
4839
|
-
children: formatMessage({
|
4840
|
-
id: index.getTranslation('relation.loadMore'),
|
4841
|
-
defaultMessage: 'Load More'
|
4842
|
-
})
|
4843
|
-
}) : null
|
4844
|
-
]
|
4845
|
-
}),
|
4846
|
-
/*#__PURE__*/ jsxRuntime.jsx(RelationsList, {
|
4847
|
-
data: relations,
|
4848
|
-
serverData: data.results,
|
4849
|
-
disabled: isDisabled,
|
4850
|
-
name: props.name,
|
4851
|
-
isLoading: isFetchingMoreRelations,
|
4852
|
-
relationType: props.attribute.relation
|
4853
|
-
})
|
4854
|
-
]
|
4855
|
-
});
|
4856
|
-
});
|
4857
|
-
/**
|
4858
|
-
* TODO: this can be removed once we stop shipping Inputs with
|
4859
|
-
* labels wrapped round in DS@2.
|
4860
|
-
*/ const StyledFlex = styledComponents.styled(designSystem.Flex)`
|
4861
|
-
& > div {
|
4862
|
-
width: 100%;
|
4863
|
-
}
|
4864
|
-
`;
|
4865
|
-
/**
|
4866
|
-
* If it's in the connected array, it can get out of our data array,
|
4867
|
-
* we'll be putting it back in later and sorting it anyway.
|
4868
|
-
*/ const removeConnected = ({ field })=>(relations)=>{
|
4869
|
-
return relations.filter((relation)=>{
|
4870
|
-
const connectedRelations = field?.connect ?? [];
|
4871
|
-
return connectedRelations.findIndex((rel)=>rel.id === relation.id) === -1;
|
4872
|
-
});
|
4873
|
-
};
|
4874
|
-
/**
|
4875
|
-
* @description Removes relations that are in the `disconnect` array of the field
|
4876
|
-
*/ const removeDisconnected = ({ field })=>(relations)=>relations.filter((relation)=>{
|
4877
|
-
const disconnectedRelations = field?.disconnect ?? [];
|
4878
|
-
return disconnectedRelations.findIndex((rel)=>rel.id === relation.id) === -1;
|
4879
|
-
});
|
4880
|
-
/**
|
4881
|
-
* @description Adds a label and href to the relation object we use this to render
|
4882
|
-
* a better UI where we can link to the relation and display a human-readable label.
|
4883
|
-
*/ const addLabelAndHref = ({ mainField, href })=>(relations)=>relations.map((relation)=>{
|
4884
|
-
return {
|
4885
|
-
...relation,
|
4886
|
-
// Fallback to `id` if there is no `mainField` value, which will overwrite the above `documentId` property with the exact same data.
|
4887
|
-
[mainField?.name ?? 'documentId']: relation[mainField?.name ?? 'documentId'],
|
4888
|
-
label: usePrev.getRelationLabel(relation, mainField),
|
4889
|
-
href: `${href}/${relation.documentId}?${relation.locale ? `plugins[i18n][locale]=${relation.locale}` : ''}`
|
4890
|
-
};
|
4891
|
-
});
|
4892
|
-
/**
|
4893
|
-
* @description Contains all the logic for the combobox that can search
|
4894
|
-
* for relations and then add them to the field's connect array.
|
4895
|
-
*/ const RelationsInput = ({ hint, id, model, label, labelAction, name, mainField, placeholder, required, unique: _unique, 'aria-label': _ariaLabel, onChange, ...props })=>{
|
4896
|
-
const [textValue, setTextValue] = React__namespace.useState('');
|
4897
|
-
const [searchParams, setSearchParams] = React__namespace.useState({
|
4898
|
-
_q: '',
|
4899
|
-
page: 1
|
4900
|
-
});
|
4901
|
-
const { toggleNotification } = strapiAdmin.useNotification();
|
4902
|
-
const [{ query }] = strapiAdmin.useQueryParams();
|
4903
|
-
const { formatMessage } = reactIntl.useIntl();
|
4904
|
-
const fieldRef = strapiAdmin.useFocusInputField(name);
|
4905
|
-
const field = strapiAdmin.useField(name);
|
4906
|
-
const searchParamsDebounced = usePrev.useDebounce(searchParams, 300);
|
4907
|
-
const [searchForTrigger, { data, isLoading }] = usePrev.useLazySearchRelationsQuery();
|
4908
|
-
/**
|
4909
|
-
* Because we're using a lazy query, we need to trigger the search
|
4910
|
-
* when the component mounts and when the search params change.
|
4911
|
-
* We also need to trigger the search when the field value changes
|
4912
|
-
* so that we can filter out the relations that are already connected.
|
4913
|
-
*/ React__namespace.useEffect(()=>{
|
4914
|
-
/**
|
4915
|
-
* The `name` prop is a complete path to the field, e.g. `field1.field2.field3`.
|
4916
|
-
* Where the above example would a nested field within two components, however
|
4917
|
-
* we only require the field on the component not the complete path since we query
|
4918
|
-
* individual components. Therefore we split the string and take the last item.
|
4919
|
-
*/ const [targetField] = name.split('.').slice(-1);
|
4920
|
-
searchForTrigger({
|
4921
|
-
model,
|
4922
|
-
targetField,
|
4923
|
-
params: {
|
4924
|
-
...index.buildValidParams(query),
|
4925
|
-
id: id ?? '',
|
4926
|
-
pageSize: 10,
|
4927
|
-
idsToInclude: field.value?.disconnect?.map((rel)=>rel.id.toString()) ?? [],
|
4928
|
-
idsToOmit: field.value?.connect?.map((rel)=>rel.id.toString()) ?? [],
|
4929
|
-
...searchParamsDebounced
|
4930
|
-
}
|
4931
|
-
});
|
4932
|
-
}, [
|
4933
|
-
field.value?.connect,
|
4934
|
-
field.value?.disconnect,
|
4935
|
-
id,
|
4936
|
-
model,
|
4937
|
-
name,
|
4938
|
-
query,
|
4939
|
-
searchForTrigger,
|
4940
|
-
searchParamsDebounced
|
4941
|
-
]);
|
4942
|
-
const handleSearch = async (search)=>{
|
4943
|
-
setSearchParams((s)=>({
|
4944
|
-
...s,
|
4945
|
-
_q: search,
|
4946
|
-
page: 1
|
4947
|
-
}));
|
4948
|
-
};
|
4949
|
-
const hasNextPage = data?.pagination ? data.pagination.page < data.pagination.pageCount : false;
|
4950
|
-
const options = data?.results ?? [];
|
4951
|
-
const handleChange = (relationId)=>{
|
4952
|
-
if (!relationId) {
|
4953
|
-
return;
|
4954
|
-
}
|
4955
|
-
const relation = options.find((opt)=>opt.id.toString() === relationId);
|
4956
|
-
if (!relation) {
|
4957
|
-
// This is very unlikely to happen, but it ensures we don't have any data for.
|
4958
|
-
console.error("You've tried to add a relation with an id that does not exist in the options you can see, this is likely a bug with Strapi. Please open an issue.");
|
4959
|
-
toggleNotification({
|
4960
|
-
message: formatMessage({
|
4961
|
-
id: index.getTranslation('relation.error-adding-relation'),
|
4962
|
-
defaultMessage: 'An error occurred while trying to add the relation.'
|
4963
|
-
}),
|
4964
|
-
type: 'danger'
|
4965
|
-
});
|
4966
|
-
return;
|
4967
|
-
}
|
4968
|
-
/**
|
4969
|
-
* You need to give this relation a correct _temp_key_ but
|
4970
|
-
* this component doesn't know about those ones, you can't rely
|
4971
|
-
* on the connect array because that doesn't hold items that haven't
|
4972
|
-
* moved. So use a callback to fill in the gaps when connecting.
|
4973
|
-
*
|
4974
|
-
*/ onChange(relation);
|
4975
|
-
};
|
4976
|
-
const handleLoadMore = ()=>{
|
4977
|
-
if (!data || !data.pagination) {
|
4978
|
-
return;
|
4979
|
-
} else if (data.pagination.page < data.pagination.pageCount) {
|
4980
|
-
setSearchParams((s)=>({
|
4981
|
-
...s,
|
4982
|
-
page: s.page + 1
|
4983
|
-
}));
|
4984
|
-
}
|
4985
|
-
};
|
4986
|
-
React__namespace.useLayoutEffect(()=>{
|
4987
|
-
setTextValue('');
|
4988
|
-
}, [
|
4989
|
-
field.value
|
4990
|
-
]);
|
4991
|
-
return /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Field.Root, {
|
4992
|
-
error: field.error,
|
4993
|
-
hint: hint,
|
4994
|
-
name: name,
|
4995
|
-
required: required,
|
4996
|
-
children: [
|
4997
|
-
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Field.Label, {
|
4998
|
-
action: labelAction,
|
4999
|
-
children: label
|
5000
|
-
}),
|
5001
|
-
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Combobox, {
|
5002
|
-
ref: fieldRef,
|
5003
|
-
name: name,
|
5004
|
-
autocomplete: "list",
|
5005
|
-
placeholder: placeholder || formatMessage({
|
5006
|
-
id: index.getTranslation('relation.add'),
|
5007
|
-
defaultMessage: 'Add relation'
|
5008
|
-
}),
|
5009
|
-
hasMoreItems: hasNextPage,
|
5010
|
-
loading: isLoading,
|
5011
|
-
onOpenChange: ()=>{
|
5012
|
-
handleSearch(textValue ?? '');
|
5013
|
-
},
|
5014
|
-
noOptionsMessage: ()=>formatMessage({
|
5015
|
-
id: index.getTranslation('relation.notAvailable'),
|
5016
|
-
defaultMessage: 'No relations available'
|
5017
|
-
}),
|
5018
|
-
loadingMessage: formatMessage({
|
5019
|
-
id: index.getTranslation('relation.isLoading'),
|
5020
|
-
defaultMessage: 'Relations are loading'
|
5021
|
-
}),
|
5022
|
-
onLoadMore: handleLoadMore,
|
5023
|
-
textValue: textValue,
|
5024
|
-
onChange: handleChange,
|
5025
|
-
onTextValueChange: (text)=>{
|
5026
|
-
setTextValue(text);
|
5027
|
-
},
|
5028
|
-
onInputChange: (event)=>{
|
5029
|
-
handleSearch(event.currentTarget.value);
|
5030
|
-
},
|
5031
|
-
...props,
|
5032
|
-
children: options.map((opt)=>{
|
5033
|
-
const textValue = usePrev.getRelationLabel(opt, mainField);
|
5034
|
-
return /*#__PURE__*/ jsxRuntime.jsx(designSystem.ComboboxOption, {
|
5035
|
-
value: opt.id.toString(),
|
5036
|
-
textValue: textValue,
|
5037
|
-
children: /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Flex, {
|
5038
|
-
gap: 2,
|
5039
|
-
justifyContent: "space-between",
|
5040
|
-
children: [
|
5041
|
-
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Typography, {
|
5042
|
-
ellipsis: true,
|
5043
|
-
children: textValue
|
5044
|
-
}),
|
5045
|
-
opt.status ? /*#__PURE__*/ jsxRuntime.jsx(index.DocumentStatus, {
|
5046
|
-
status: opt.status
|
5047
|
-
}) : null
|
5048
|
-
]
|
5049
|
-
})
|
5050
|
-
}, opt.id);
|
5051
|
-
})
|
5052
|
-
}),
|
5053
|
-
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Field.Error, {}),
|
5054
|
-
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Field.Hint, {})
|
5055
|
-
]
|
5056
|
-
});
|
5057
|
-
};
|
5058
|
-
/* -------------------------------------------------------------------------------------------------
|
5059
|
-
* RelationsList
|
5060
|
-
* -----------------------------------------------------------------------------------------------*/ const RELATION_ITEM_HEIGHT = 50;
|
5061
|
-
const RELATION_GUTTER = 4;
|
5062
|
-
const UnstableRelationsList = ({ data, serverData, disabled, name, isLoading, relationType, targetModel, setCurrentDocument })=>{
|
5063
|
-
const ariaDescriptionId = React__namespace.useId();
|
5064
|
-
const { formatMessage } = reactIntl.useIntl();
|
5065
|
-
const listRef = React__namespace.useRef(null);
|
5066
|
-
const outerListRef = React__namespace.useRef(null);
|
5067
|
-
const [overflow, setOverflow] = React__namespace.useState();
|
5068
|
-
const [liveText, setLiveText] = React__namespace.useState('');
|
5069
|
-
const field = strapiAdmin.useField(name);
|
5070
|
-
React__namespace.useEffect(()=>{
|
5071
|
-
if (data.length <= RELATIONS_TO_DISPLAY) {
|
5072
|
-
return setOverflow(undefined);
|
5073
|
-
}
|
5074
|
-
const handleNativeScroll = (e)=>{
|
5075
|
-
const el = e.target;
|
5076
|
-
const parentScrollContainerHeight = el.parentNode.scrollHeight;
|
5077
|
-
const maxScrollBottom = el.scrollHeight - el.scrollTop;
|
5078
|
-
if (el.scrollTop === 0) {
|
5079
|
-
return setOverflow('bottom');
|
5080
|
-
}
|
5081
|
-
if (maxScrollBottom === parentScrollContainerHeight) {
|
5082
|
-
return setOverflow('top');
|
5083
|
-
}
|
5084
|
-
return setOverflow('top-bottom');
|
5085
|
-
};
|
5086
|
-
const outerListRefCurrent = outerListRef?.current;
|
5087
|
-
if (!isLoading && data.length > 0 && outerListRefCurrent) {
|
5088
|
-
outerListRef.current.addEventListener('scroll', handleNativeScroll);
|
5089
|
-
}
|
5090
|
-
return ()=>{
|
5091
|
-
if (outerListRefCurrent) {
|
5092
|
-
outerListRefCurrent.removeEventListener('scroll', handleNativeScroll);
|
5093
|
-
}
|
5094
|
-
};
|
5095
|
-
}, [
|
5096
|
-
isLoading,
|
5097
|
-
data.length
|
5098
|
-
]);
|
5099
|
-
const getItemPos = (index)=>`${index + 1} of ${data.length}`;
|
5100
|
-
const handleMoveItem = (newIndex, oldIndex)=>{
|
5101
|
-
const item = data[oldIndex];
|
5102
|
-
setLiveText(formatMessage({
|
5103
|
-
id: index.getTranslation('dnd.reorder'),
|
5104
|
-
defaultMessage: '{item}, moved. New position in list: {position}.'
|
5105
|
-
}, {
|
5106
|
-
item: item.label ?? item.documentId,
|
5107
|
-
position: getItemPos(newIndex)
|
5108
|
-
}));
|
5109
|
-
/**
|
5110
|
-
* Splicing mutates the array, so we need to create a new array
|
5111
|
-
*/ const newData = [
|
5112
|
-
...data
|
5113
|
-
];
|
5114
|
-
const currentRow = data[oldIndex];
|
5115
|
-
const startKey = oldIndex > newIndex ? newData[newIndex - 1]?.__temp_key__ : newData[newIndex]?.__temp_key__;
|
5116
|
-
const endKey = oldIndex > newIndex ? newData[newIndex]?.__temp_key__ : newData[newIndex + 1]?.__temp_key__;
|
5117
|
-
/**
|
5118
|
-
* We're moving the relation between two other relations, so
|
5119
|
-
* we need to generate a new key that keeps the order
|
5120
|
-
*/ const [newKey] = fractionalIndexing.generateNKeysBetween(startKey, endKey, 1);
|
5121
|
-
newData.splice(oldIndex, 1);
|
5122
|
-
newData.splice(newIndex, 0, {
|
5123
|
-
...currentRow,
|
5124
|
-
__temp_key__: newKey
|
5125
|
-
});
|
5126
|
-
/**
|
5127
|
-
* Now we diff against the server to understand what's different so we
|
5128
|
-
* can keep the connect array nice and tidy. It also needs reversing because
|
5129
|
-
* we reverse the relations from the server in the first place.
|
5130
|
-
*/ const connectedRelations = newData.reduce((acc, relation, currentIndex, array)=>{
|
5131
|
-
const relationOnServer = serverData.find((oldRelation)=>oldRelation.id === relation.id);
|
5132
|
-
const relationInFront = array[currentIndex + 1];
|
5133
|
-
if (!relationOnServer || relationOnServer.__temp_key__ !== relation.__temp_key__) {
|
5134
|
-
const position = relationInFront ? {
|
5135
|
-
before: relationInFront.documentId,
|
5136
|
-
locale: relationInFront.locale,
|
5137
|
-
status: 'publishedAt' in relationInFront && relationInFront.publishedAt ? 'published' : 'draft'
|
5138
|
-
} : {
|
5139
|
-
end: true
|
5140
|
-
};
|
5141
|
-
const relationWithPosition = {
|
5142
|
-
...relation,
|
5143
|
-
...{
|
5144
|
-
apiData: {
|
5145
|
-
id: relation.id,
|
5146
|
-
documentId: relation.documentId,
|
5147
|
-
locale: relation.locale,
|
5148
|
-
position
|
5149
|
-
}
|
5150
|
-
}
|
5151
|
-
};
|
5152
|
-
return [
|
5153
|
-
...acc,
|
5154
|
-
relationWithPosition
|
5155
|
-
];
|
5156
|
-
}
|
5157
|
-
return acc;
|
5158
|
-
}, []).toReversed();
|
5159
|
-
field.onChange(`${name}.connect`, connectedRelations);
|
5160
|
-
};
|
5161
|
-
const handleGrabItem = (index$1)=>{
|
5162
|
-
const item = data[index$1];
|
5163
|
-
setLiveText(formatMessage({
|
5164
|
-
id: index.getTranslation('dnd.grab-item'),
|
5165
|
-
defaultMessage: `{item}, grabbed. Current position in list: {position}. Press up and down arrow to change position, Spacebar to drop, Escape to cancel.`
|
5166
|
-
}, {
|
5167
|
-
item: item.label ?? item.documentId,
|
5168
|
-
position: getItemPos(index$1)
|
5169
|
-
}));
|
5170
|
-
};
|
5171
|
-
const handleDropItem = (index$1)=>{
|
5172
|
-
const { href: _href, label, ...item } = data[index$1];
|
5173
|
-
setLiveText(formatMessage({
|
5174
|
-
id: index.getTranslation('dnd.drop-item'),
|
5175
|
-
defaultMessage: `{item}, dropped. Final position in list: {position}.`
|
5176
|
-
}, {
|
5177
|
-
item: label ?? item.documentId,
|
5178
|
-
position: getItemPos(index$1)
|
5179
|
-
}));
|
5063
|
+
/**
|
5064
|
+
* You need to give this relation a correct _temp_key_ but
|
5065
|
+
* this component doesn't know about those ones, you can't rely
|
5066
|
+
* on the connect array because that doesn't hold items that haven't
|
5067
|
+
* moved. So use a callback to fill in the gaps when connecting.
|
5068
|
+
*
|
5069
|
+
*/ onChange(relation);
|
5180
5070
|
};
|
5181
|
-
const
|
5182
|
-
|
5183
|
-
|
5184
|
-
|
5185
|
-
|
5186
|
-
|
5187
|
-
|
5188
|
-
|
5071
|
+
const handleLoadMore = ()=>{
|
5072
|
+
if (!data || !data.pagination) {
|
5073
|
+
return;
|
5074
|
+
} else if (data.pagination.page < data.pagination.pageCount) {
|
5075
|
+
setSearchParams((s)=>({
|
5076
|
+
...s,
|
5077
|
+
page: s.page + 1
|
5078
|
+
}));
|
5079
|
+
}
|
5189
5080
|
};
|
5190
|
-
|
5191
|
-
|
5192
|
-
|
5193
|
-
|
5194
|
-
|
5195
|
-
|
5196
|
-
|
5197
|
-
|
5081
|
+
React__namespace.useLayoutEffect(()=>{
|
5082
|
+
setTextValue('');
|
5083
|
+
}, [
|
5084
|
+
field.value
|
5085
|
+
]);
|
5086
|
+
return /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Field.Root, {
|
5087
|
+
error: field.error,
|
5088
|
+
hint: hint,
|
5089
|
+
name: name,
|
5090
|
+
required: required,
|
5198
5091
|
children: [
|
5199
|
-
/*#__PURE__*/ jsxRuntime.jsx(designSystem.
|
5200
|
-
|
5201
|
-
children:
|
5202
|
-
id: index.getTranslation('dnd.instructions'),
|
5203
|
-
defaultMessage: `Press spacebar to grab and re-order`
|
5204
|
-
})
|
5205
|
-
}),
|
5206
|
-
/*#__PURE__*/ jsxRuntime.jsx(designSystem.VisuallyHidden, {
|
5207
|
-
"aria-live": "assertive",
|
5208
|
-
children: liveText
|
5092
|
+
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Field.Label, {
|
5093
|
+
action: labelAction,
|
5094
|
+
children: label
|
5209
5095
|
}),
|
5210
|
-
/*#__PURE__*/ jsxRuntime.jsx(
|
5211
|
-
|
5212
|
-
|
5213
|
-
|
5214
|
-
|
5215
|
-
|
5216
|
-
|
5217
|
-
|
5218
|
-
|
5219
|
-
|
5220
|
-
|
5221
|
-
|
5222
|
-
handleGrabItem,
|
5223
|
-
handleMoveItem,
|
5224
|
-
name,
|
5225
|
-
handleDisconnect,
|
5226
|
-
relations: data,
|
5227
|
-
targetModel,
|
5228
|
-
setCurrentDocument
|
5096
|
+
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Combobox, {
|
5097
|
+
ref: fieldRef,
|
5098
|
+
name: name,
|
5099
|
+
autocomplete: "list",
|
5100
|
+
placeholder: placeholder || formatMessage({
|
5101
|
+
id: index.getTranslation('relation.add'),
|
5102
|
+
defaultMessage: 'Add relation'
|
5103
|
+
}),
|
5104
|
+
hasMoreItems: hasNextPage,
|
5105
|
+
loading: isLoading,
|
5106
|
+
onOpenChange: ()=>{
|
5107
|
+
handleSearch(textValue ?? '');
|
5229
5108
|
},
|
5230
|
-
|
5231
|
-
|
5232
|
-
|
5233
|
-
|
5109
|
+
noOptionsMessage: ()=>formatMessage({
|
5110
|
+
id: index.getTranslation('relation.notAvailable'),
|
5111
|
+
defaultMessage: 'No relations available'
|
5112
|
+
}),
|
5113
|
+
loadingMessage: formatMessage({
|
5114
|
+
id: index.getTranslation('relation.isLoading'),
|
5115
|
+
defaultMessage: 'Relations are loading'
|
5116
|
+
}),
|
5117
|
+
onLoadMore: handleLoadMore,
|
5118
|
+
textValue: textValue,
|
5119
|
+
onChange: handleChange,
|
5120
|
+
onTextValueChange: (text)=>{
|
5121
|
+
setTextValue(text);
|
5122
|
+
},
|
5123
|
+
onInputChange: (event)=>{
|
5124
|
+
handleSearch(event.currentTarget.value);
|
5125
|
+
},
|
5126
|
+
...props,
|
5127
|
+
children: options.map((opt)=>{
|
5128
|
+
const textValue = usePrev.getRelationLabel(opt, mainField);
|
5129
|
+
return /*#__PURE__*/ jsxRuntime.jsx(designSystem.ComboboxOption, {
|
5130
|
+
value: opt.id.toString(),
|
5131
|
+
textValue: textValue,
|
5132
|
+
children: /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Flex, {
|
5133
|
+
gap: 2,
|
5134
|
+
justifyContent: "space-between",
|
5135
|
+
children: [
|
5136
|
+
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Typography, {
|
5137
|
+
ellipsis: true,
|
5138
|
+
children: textValue
|
5139
|
+
}),
|
5140
|
+
opt.status ? /*#__PURE__*/ jsxRuntime.jsx(index.DocumentStatus, {
|
5141
|
+
status: opt.status
|
5142
|
+
}) : null
|
5143
|
+
]
|
5144
|
+
})
|
5145
|
+
}, opt.id);
|
5146
|
+
})
|
5147
|
+
}),
|
5148
|
+
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Field.Error, {}),
|
5149
|
+
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Field.Hint, {})
|
5234
5150
|
]
|
5235
5151
|
});
|
5236
5152
|
};
|
5237
|
-
|
5153
|
+
/* -------------------------------------------------------------------------------------------------
|
5154
|
+
* RelationsList
|
5155
|
+
* -----------------------------------------------------------------------------------------------*/ const RELATION_ITEM_HEIGHT = 50;
|
5156
|
+
const RELATION_GUTTER = 4;
|
5157
|
+
const RelationsList = ({ data, serverData, disabled, name, isLoading, relationType, targetModel })=>{
|
5238
5158
|
const ariaDescriptionId = React__namespace.useId();
|
5239
5159
|
const { formatMessage } = reactIntl.useIntl();
|
5240
5160
|
const listRef = React__namespace.useRef(null);
|
@@ -5398,7 +5318,8 @@ const RelationsList = ({ data, serverData, disabled, name, isLoading, relationTy
|
|
5398
5318
|
handleMoveItem,
|
5399
5319
|
name,
|
5400
5320
|
handleDisconnect,
|
5401
|
-
relations: data
|
5321
|
+
relations: data,
|
5322
|
+
targetModel
|
5402
5323
|
},
|
5403
5324
|
itemKey: (index)=>data[index].id,
|
5404
5325
|
innerElementType: "ol",
|
@@ -5438,144 +5359,10 @@ const ShadowBox = styledComponents.styled(designSystem.Box)`
|
|
5438
5359
|
transition: opacity 0.2s ease-in-out;
|
5439
5360
|
}
|
5440
5361
|
`;
|
5441
|
-
const CustomTextButton = styledComponents.styled(designSystem.TextButton)`
|
5442
|
-
& > span {
|
5443
|
-
font-size: ${({ theme })=>theme.fontSizes[2]};
|
5444
|
-
}
|
5445
|
-
`;
|
5446
|
-
const UnstableListItem = ({ data, index: index$1, style })=>{
|
5447
|
-
const { ariaDescribedBy, canDrag = false, disabled = false, handleCancel, handleDisconnect, handleDropItem, handleGrabItem, handleMoveItem, name, relations, targetModel, setCurrentDocument } = data;
|
5448
|
-
const { formatMessage } = reactIntl.useIntl();
|
5449
|
-
const [isModalOpen, setIsModalOpen] = React__namespace.useState(false);
|
5450
|
-
const { id, label, status, documentId, href, apiData } = relations[index$1];
|
5451
|
-
const [{ handlerId, isDragging, handleKeyDown }, relationRef, dropRef, dragRef, dragPreviewRef] = objects.useDragAndDrop(canDrag && !disabled, {
|
5452
|
-
type: `${objects.ItemTypes.RELATION}_${name}`,
|
5453
|
-
index: index$1,
|
5454
|
-
item: {
|
5455
|
-
displayedValue: label,
|
5456
|
-
status,
|
5457
|
-
id: id,
|
5458
|
-
index: index$1
|
5459
|
-
},
|
5460
|
-
onMoveItem: handleMoveItem,
|
5461
|
-
onDropItem: handleDropItem,
|
5462
|
-
onGrabItem: handleGrabItem,
|
5463
|
-
onCancel: handleCancel,
|
5464
|
-
dropSensitivity: objects.DROP_SENSITIVITY.REGULAR
|
5465
|
-
});
|
5466
|
-
const composedRefs = designSystem.useComposedRefs(relationRef, dragRef);
|
5467
|
-
const handleChangeModalContent = ()=>{
|
5468
|
-
if (setCurrentDocument) {
|
5469
|
-
const newRelation = {
|
5470
|
-
documentId: documentId ? documentId : apiData?.documentId || '',
|
5471
|
-
model: targetModel,
|
5472
|
-
collectionType: getCollectionType(href)
|
5473
|
-
};
|
5474
|
-
setCurrentDocument(newRelation);
|
5475
|
-
}
|
5476
|
-
};
|
5477
|
-
React__namespace.useEffect(()=>{
|
5478
|
-
dragPreviewRef(reactDndHtml5Backend.getEmptyImage());
|
5479
|
-
}, [
|
5480
|
-
dragPreviewRef
|
5481
|
-
]);
|
5482
|
-
return /*#__PURE__*/ jsxRuntime.jsx(designSystem.Box, {
|
5483
|
-
style: style,
|
5484
|
-
tag: "li",
|
5485
|
-
ref: dropRef,
|
5486
|
-
"aria-describedby": ariaDescribedBy,
|
5487
|
-
cursor: canDrag ? 'all-scroll' : 'default',
|
5488
|
-
children: isDragging ? /*#__PURE__*/ jsxRuntime.jsx(RelationItemPlaceholder, {}) : /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Flex, {
|
5489
|
-
paddingTop: 2,
|
5490
|
-
paddingBottom: 2,
|
5491
|
-
paddingLeft: canDrag ? 2 : 4,
|
5492
|
-
paddingRight: 4,
|
5493
|
-
hasRadius: true,
|
5494
|
-
borderColor: "neutral200",
|
5495
|
-
background: disabled ? 'neutral150' : 'neutral0',
|
5496
|
-
justifyContent: "space-between",
|
5497
|
-
ref: composedRefs,
|
5498
|
-
"data-handler-id": handlerId,
|
5499
|
-
children: [
|
5500
|
-
/*#__PURE__*/ jsxRuntime.jsxs(FlexWrapper, {
|
5501
|
-
gap: 1,
|
5502
|
-
children: [
|
5503
|
-
canDrag ? /*#__PURE__*/ jsxRuntime.jsx(designSystem.IconButton, {
|
5504
|
-
tag: "div",
|
5505
|
-
role: "button",
|
5506
|
-
tabIndex: 0,
|
5507
|
-
withTooltip: false,
|
5508
|
-
label: formatMessage({
|
5509
|
-
id: index.getTranslation('components.RelationInput.icon-button-aria-label'),
|
5510
|
-
defaultMessage: 'Drag'
|
5511
|
-
}),
|
5512
|
-
variant: "ghost",
|
5513
|
-
onKeyDown: handleKeyDown,
|
5514
|
-
disabled: disabled,
|
5515
|
-
children: /*#__PURE__*/ jsxRuntime.jsx(Icons.Drag, {})
|
5516
|
-
}) : null,
|
5517
|
-
/*#__PURE__*/ jsxRuntime.jsxs(designSystem.Flex, {
|
5518
|
-
width: "100%",
|
5519
|
-
minWidth: 0,
|
5520
|
-
justifyContent: "space-between",
|
5521
|
-
children: [
|
5522
|
-
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Box, {
|
5523
|
-
minWidth: 0,
|
5524
|
-
paddingTop: 1,
|
5525
|
-
paddingBottom: 1,
|
5526
|
-
paddingRight: 4,
|
5527
|
-
children: /*#__PURE__*/ jsxRuntime.jsx(designSystem.Tooltip, {
|
5528
|
-
description: label,
|
5529
|
-
children: isModalOpen ? /*#__PURE__*/ jsxRuntime.jsx(CustomTextButton, {
|
5530
|
-
onClick: handleChangeModalContent,
|
5531
|
-
children: label
|
5532
|
-
}) : /*#__PURE__*/ jsxRuntime.jsx(CustomTextButton, {
|
5533
|
-
onClick: ()=>{
|
5534
|
-
setIsModalOpen(true);
|
5535
|
-
handleChangeModalContent();
|
5536
|
-
},
|
5537
|
-
children: label
|
5538
|
-
})
|
5539
|
-
})
|
5540
|
-
}),
|
5541
|
-
status ? /*#__PURE__*/ jsxRuntime.jsx(index.DocumentStatus, {
|
5542
|
-
status: status
|
5543
|
-
}) : null,
|
5544
|
-
isModalOpen && /*#__PURE__*/ jsxRuntime.jsx(RelationModal, {
|
5545
|
-
open: isModalOpen,
|
5546
|
-
onToggle: ()=>{
|
5547
|
-
setIsModalOpen(!isModalOpen);
|
5548
|
-
},
|
5549
|
-
model: targetModel,
|
5550
|
-
id: documentId ? documentId : apiData?.documentId,
|
5551
|
-
relationUrl: href
|
5552
|
-
})
|
5553
|
-
]
|
5554
|
-
})
|
5555
|
-
]
|
5556
|
-
}),
|
5557
|
-
/*#__PURE__*/ jsxRuntime.jsx(designSystem.Box, {
|
5558
|
-
paddingLeft: 4,
|
5559
|
-
children: /*#__PURE__*/ jsxRuntime.jsx(designSystem.IconButton, {
|
5560
|
-
onClick: ()=>handleDisconnect(relations[index$1]),
|
5561
|
-
disabled: disabled,
|
5562
|
-
label: formatMessage({
|
5563
|
-
id: index.getTranslation('relation.disconnect'),
|
5564
|
-
defaultMessage: 'Remove'
|
5565
|
-
}),
|
5566
|
-
variant: "ghost",
|
5567
|
-
size: "S",
|
5568
|
-
children: /*#__PURE__*/ jsxRuntime.jsx(Icons.Cross, {})
|
5569
|
-
})
|
5570
|
-
})
|
5571
|
-
]
|
5572
|
-
})
|
5573
|
-
});
|
5574
|
-
};
|
5575
5362
|
const ListItem = ({ data, index: index$1, style })=>{
|
5576
|
-
const { ariaDescribedBy, canDrag = false, disabled = false, handleCancel, handleDisconnect, handleDropItem, handleGrabItem, handleMoveItem, name, relations } = data;
|
5363
|
+
const { ariaDescribedBy, canDrag = false, disabled = false, handleCancel, handleDisconnect, handleDropItem, handleGrabItem, handleMoveItem, name, relations, targetModel } = data;
|
5577
5364
|
const { formatMessage } = reactIntl.useIntl();
|
5578
|
-
const { href, id, label, status } = relations[index$1];
|
5365
|
+
const { href, id, label, status, documentId, apiData, locale } = relations[index$1];
|
5579
5366
|
const [{ handlerId, isDragging, handleKeyDown }, relationRef, dropRef, dragRef, dragPreviewRef] = objects.useDragAndDrop(canDrag && !disabled, {
|
5580
5367
|
type: `${objects.ItemTypes.RELATION}_${name}`,
|
5581
5368
|
index: index$1,
|
@@ -5642,18 +5429,16 @@ const ListItem = ({ data, index: index$1, style })=>{
|
|
5642
5429
|
paddingTop: 1,
|
5643
5430
|
paddingBottom: 1,
|
5644
5431
|
paddingRight: 4,
|
5645
|
-
children: /*#__PURE__*/ jsxRuntime.jsx(
|
5646
|
-
|
5647
|
-
|
5648
|
-
|
5649
|
-
|
5650
|
-
|
5651
|
-
|
5652
|
-
|
5653
|
-
|
5654
|
-
|
5655
|
-
children: label
|
5656
|
-
})
|
5432
|
+
children: /*#__PURE__*/ jsxRuntime.jsx(RelationModalForm, {
|
5433
|
+
triggerButtonLabel: label,
|
5434
|
+
relation: {
|
5435
|
+
documentId: documentId ?? apiData?.documentId,
|
5436
|
+
model: targetModel,
|
5437
|
+
collectionType: getCollectionType(href),
|
5438
|
+
params: {
|
5439
|
+
locale: locale || apiData?.locale || null
|
5440
|
+
}
|
5441
|
+
}
|
5657
5442
|
})
|
5658
5443
|
}),
|
5659
5444
|
status ? /*#__PURE__*/ jsxRuntime.jsx(index.DocumentStatus, {
|
@@ -5723,7 +5508,6 @@ const RelationItemPlaceholder = ()=>/*#__PURE__*/ jsxRuntime.jsx(designSystem.Bo
|
|
5723
5508
|
height: `calc(100% - ${RELATION_GUTTER}px)`
|
5724
5509
|
});
|
5725
5510
|
const MemoizedRelationsField = /*#__PURE__*/ React__namespace.memo(RelationsField);
|
5726
|
-
const MemoizedUnstableRelationsField = /*#__PURE__*/ React__namespace.memo(UnstableRelationsField);
|
5727
5511
|
|
5728
5512
|
const uidApi = index.contentManagerApi.injectEndpoints({
|
5729
5513
|
endpoints: (builder)=>({
|
@@ -7893,22 +7677,27 @@ const Wysiwyg = /*#__PURE__*/ React__namespace.forwardRef(({ hint, disabled, lab
|
|
7893
7677
|
});
|
7894
7678
|
const MemoizedWysiwyg = /*#__PURE__*/ React__namespace.memo(Wysiwyg);
|
7895
7679
|
|
7896
|
-
|
7897
|
-
|
7898
|
-
|
7899
|
-
|
7900
|
-
|
7901
|
-
|
7902
|
-
|
7680
|
+
/**
|
7681
|
+
* @internal
|
7682
|
+
*
|
7683
|
+
* @description An abstraction around the regular form input renderer designed
|
7684
|
+
* specifically to be used in the EditView of the content-manager this understands
|
7685
|
+
* the complete EditFieldLayout and will handle RBAC conditions and rendering CM specific
|
7686
|
+
* components such as Blocks / Relations.
|
7687
|
+
*/ const InputRenderer = ({ visible, hint: providedHint, document, ...props })=>{
|
7688
|
+
const { model: rootModel } = index.useDoc();
|
7689
|
+
const documentLayout = index.useDocumentLayout(document.schema?.uid ?? rootModel);
|
7690
|
+
const components = documentLayout.edit.components;
|
7691
|
+
const collectionType = document.schema?.kind === 'collectionType' ? 'collection-types' : 'single-types';
|
7903
7692
|
const isInDynamicZone = useDynamicZone('isInDynamicZone', (state)=>state.isInDynamicZone);
|
7904
7693
|
const isFormDisabled = strapiAdmin.useForm('InputRenderer', (state)=>state.disabled);
|
7905
7694
|
const canCreateFields = index.useDocumentRBAC('InputRenderer', (rbac)=>rbac.canCreateFields);
|
7906
7695
|
const canReadFields = index.useDocumentRBAC('InputRenderer', (rbac)=>rbac.canReadFields);
|
7907
7696
|
const canUpdateFields = index.useDocumentRBAC('InputRenderer', (rbac)=>rbac.canUpdateFields);
|
7908
7697
|
const canUserAction = index.useDocumentRBAC('InputRenderer', (rbac)=>rbac.canUserAction);
|
7909
|
-
let idToCheck =
|
7698
|
+
let idToCheck = document.document?.documentId;
|
7910
7699
|
if (collectionType === index.SINGLE_TYPES) {
|
7911
|
-
idToCheck = document?.documentId;
|
7700
|
+
idToCheck = document?.document?.documentId;
|
7912
7701
|
}
|
7913
7702
|
const editableFields = idToCheck ? canUpdateFields : canCreateFields;
|
7914
7703
|
const readableFields = idToCheck ? canReadFields : canCreateFields;
|
@@ -7922,8 +7711,6 @@ const InputRenderer = ({ visible, hint: providedHint, ...props })=>{
|
|
7922
7711
|
props.attribute.customField
|
7923
7712
|
] : undefined);
|
7924
7713
|
const hint = useFieldHint(providedHint, props.attribute);
|
7925
|
-
const { edit: { components: rootDocumentComponents } } = index.useDocLayout();
|
7926
|
-
const components = Object.keys(rootDocumentComponents).length !== 0 ? rootDocumentComponents : documentLayout.edit.components;
|
7927
7714
|
// We pass field in case of Custom Fields to keep backward compatibility
|
7928
7715
|
const field = strapiAdmin.useField(props.name);
|
7929
7716
|
if (!visible) {
|
@@ -8000,13 +7787,6 @@ const InputRenderer = ({ visible, hint: providedHint, ...props })=>{
|
|
8000
7787
|
disabled: fieldIsDisabled
|
8001
7788
|
});
|
8002
7789
|
case 'relation':
|
8003
|
-
if (window.strapi.future.isEnabled('unstableRelationsOnTheFly')) {
|
8004
|
-
return /*#__PURE__*/ jsxRuntime.jsx(MemoizedUnstableRelationsField, {
|
8005
|
-
...props,
|
8006
|
-
hint: hint,
|
8007
|
-
disabled: fieldIsDisabled
|
8008
|
-
});
|
8009
|
-
}
|
8010
7790
|
return /*#__PURE__*/ jsxRuntime.jsx(MemoizedRelationsField, {
|
8011
7791
|
...props,
|
8012
7792
|
hint: hint,
|
@@ -8112,10 +7892,12 @@ const RESPONSIVE_CONTAINER_BREAKPOINTS = {
|
|
8112
7892
|
const ResponsiveGridRoot = styledComponents.styled(designSystem.Grid.Root)`
|
8113
7893
|
container-type: inline-size;
|
8114
7894
|
`;
|
8115
|
-
|
8116
|
-
|
8117
|
-
|
8118
|
-
|
7895
|
+
const ResponsiveGridItem = /**
|
7896
|
+
* TODO:
|
7897
|
+
* JSDOM cannot handle container queries.
|
7898
|
+
* This is a temporary workaround so that tests do not fail in the CI when jestdom throws an error
|
7899
|
+
* for failing to parse the stylesheet.
|
7900
|
+
*/ process.env.NODE_ENV !== 'test' ? styledComponents.styled(designSystem.Grid.Item)`
|
8119
7901
|
grid-column: span 12;
|
8120
7902
|
@container (min-width: ${RESPONSIVE_CONTAINER_BREAKPOINTS.sm}) {
|
8121
7903
|
${({ col })=>col && `grid-column: span ${col};`}
|
@@ -8123,10 +7905,9 @@ process.env.NODE_ENV !== 'test' ? styledComponents.styled(designSystem.Grid.Item
|
|
8123
7905
|
` : styledComponents.styled(designSystem.Grid.Item)`
|
8124
7906
|
grid-column: span 12;
|
8125
7907
|
`;
|
8126
|
-
const FormLayout = ({ layout, hasBackground = true })=>{
|
7908
|
+
const FormLayout = ({ layout, document, hasBackground = true })=>{
|
8127
7909
|
const { formatMessage } = reactIntl.useIntl();
|
8128
|
-
const
|
8129
|
-
const model = documentMeta.model;
|
7910
|
+
const model = document.schema?.modelName;
|
8130
7911
|
return /*#__PURE__*/ jsxRuntime.jsx(designSystem.Flex, {
|
8131
7912
|
direction: "column",
|
8132
7913
|
alignItems: "stretch",
|
@@ -8151,7 +7932,8 @@ const FormLayout = ({ layout, hasBackground = true })=>{
|
|
8151
7932
|
direction: "column",
|
8152
7933
|
alignItems: "stretch",
|
8153
7934
|
children: /*#__PURE__*/ jsxRuntime.jsx(MemoizedInputRenderer, {
|
8154
|
-
...fieldWithTranslatedLabel
|
7935
|
+
...fieldWithTranslatedLabel,
|
7936
|
+
document: document
|
8155
7937
|
})
|
8156
7938
|
})
|
8157
7939
|
}, field.name);
|
@@ -8185,7 +7967,8 @@ const FormLayout = ({ layout, hasBackground = true })=>{
|
|
8185
7967
|
direction: "column",
|
8186
7968
|
alignItems: "stretch",
|
8187
7969
|
children: /*#__PURE__*/ jsxRuntime.jsx(MemoizedInputRenderer, {
|
8188
|
-
...fieldWithTranslatedLabel
|
7970
|
+
...fieldWithTranslatedLabel,
|
7971
|
+
document: document
|
8189
7972
|
})
|
8190
7973
|
}, field.name);
|
8191
7974
|
})
|
@@ -8201,6 +7984,7 @@ const NonRepeatableComponent = ({ attribute, name, children, layout })=>{
|
|
8201
7984
|
const { value } = strapiAdmin.useField(name);
|
8202
7985
|
const level = useComponent('NonRepeatableComponent', (state)=>state.level);
|
8203
7986
|
const isNested = level > 0;
|
7987
|
+
const currentDocument = index.useDocumentContext('NonRepeatableComponent', (state)=>state.document);
|
8204
7988
|
return /*#__PURE__*/ jsxRuntime.jsx(ComponentProvider, {
|
8205
7989
|
id: value?.id,
|
8206
7990
|
uid: attribute.component,
|
@@ -8241,7 +8025,8 @@ const NonRepeatableComponent = ({ attribute, name, children, layout })=>{
|
|
8241
8025
|
children: children({
|
8242
8026
|
...field,
|
8243
8027
|
label: translatedLabel,
|
8244
|
-
name: completeFieldName
|
8028
|
+
name: completeFieldName,
|
8029
|
+
document: currentDocument
|
8245
8030
|
})
|
8246
8031
|
}, completeFieldName);
|
8247
8032
|
})
|
@@ -8259,7 +8044,8 @@ const RepeatableComponent = ({ attribute, disabled, name, mainField, children, l
|
|
8259
8044
|
const search = React__namespace.useMemo(()=>new URLSearchParams(searchString), [
|
8260
8045
|
searchString
|
8261
8046
|
]);
|
8262
|
-
const
|
8047
|
+
const currentDocument = index.useDocumentContext('RepeatableComponent', (state)=>state.document);
|
8048
|
+
const components = currentDocument.components;
|
8263
8049
|
const { value = [], error, rawError } = strapiAdmin.useField(name);
|
8264
8050
|
const addFieldRow = strapiAdmin.useForm('RepeatableComponent', (state)=>state.addFieldRow);
|
8265
8051
|
const moveFieldRow = strapiAdmin.useForm('RepeatableComponent', (state)=>state.moveFieldRow);
|
@@ -8462,7 +8248,8 @@ const RepeatableComponent = ({ attribute, disabled, name, mainField, children, l
|
|
8462
8248
|
children: children({
|
8463
8249
|
...field,
|
8464
8250
|
label: translatedLabel,
|
8465
|
-
name: completeFieldName
|
8251
|
+
name: completeFieldName,
|
8252
|
+
document: currentDocument
|
8466
8253
|
})
|
8467
8254
|
}, completeFieldName);
|
8468
8255
|
})
|
@@ -8624,7 +8411,7 @@ const ComponentInput = ({ label, required, name, attribute, disabled, labelActio
|
|
8624
8411
|
const { formatMessage } = reactIntl.useIntl();
|
8625
8412
|
const field = strapiAdmin.useField(name);
|
8626
8413
|
const showResetComponent = !attribute.repeatable && field.value && !disabled;
|
8627
|
-
const components = useDocumentContext('ComponentInput', (state)=>state.document.components);
|
8414
|
+
const components = index.useDocumentContext('ComponentInput', (state)=>state.document.components);
|
8628
8415
|
const handleInitialisationClick = ()=>{
|
8629
8416
|
const schema = components[attribute.component];
|
8630
8417
|
const form = index.createDefaultForm(schema, components);
|
@@ -8690,7 +8477,6 @@ const ComponentInput = ({ label, required, name, attribute, disabled, labelActio
|
|
8690
8477
|
const MemoizedComponentInput = /*#__PURE__*/ React__namespace.memo(ComponentInput);
|
8691
8478
|
|
8692
8479
|
exports.DisconnectButton = DisconnectButton;
|
8693
|
-
exports.DocumentContextProvider = DocumentContextProvider;
|
8694
8480
|
exports.DynamicZone = DynamicZone;
|
8695
8481
|
exports.FlexWrapper = FlexWrapper;
|
8696
8482
|
exports.FormLayout = FormLayout;
|
@@ -8703,4 +8489,4 @@ exports.NotAllowedInput = NotAllowedInput;
|
|
8703
8489
|
exports.useDynamicZone = useDynamicZone;
|
8704
8490
|
exports.useFieldHint = useFieldHint;
|
8705
8491
|
exports.useLazyComponents = useLazyComponents;
|
8706
|
-
//# sourceMappingURL=Input-
|
8492
|
+
//# sourceMappingURL=Input-D-yPzkxz.js.map
|