@strapi/content-manager 5.12.3 → 5.12.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. package/dist/admin/content-manager.js.map +1 -1
  2. package/dist/admin/content-manager.mjs.map +1 -1
  3. package/dist/admin/history/pages/History.js +1 -9
  4. package/dist/admin/history/pages/History.js.map +1 -1
  5. package/dist/admin/history/pages/History.mjs +1 -9
  6. package/dist/admin/history/pages/History.mjs.map +1 -1
  7. package/dist/admin/hooks/useDocumentActions.js +8 -1
  8. package/dist/admin/hooks/useDocumentActions.js.map +1 -1
  9. package/dist/admin/hooks/useDocumentActions.mjs +8 -1
  10. package/dist/admin/hooks/useDocumentActions.mjs.map +1 -1
  11. package/dist/admin/hooks/useDocumentContext.js +57 -0
  12. package/dist/admin/hooks/useDocumentContext.js.map +1 -0
  13. package/dist/admin/hooks/useDocumentContext.mjs +36 -0
  14. package/dist/admin/hooks/useDocumentContext.mjs.map +1 -0
  15. package/dist/admin/pages/EditView/EditViewPage.js +85 -93
  16. package/dist/admin/pages/EditView/EditViewPage.js.map +1 -1
  17. package/dist/admin/pages/EditView/EditViewPage.mjs +86 -94
  18. package/dist/admin/pages/EditView/EditViewPage.mjs.map +1 -1
  19. package/dist/admin/pages/EditView/components/DocumentActions.js +28 -32
  20. package/dist/admin/pages/EditView/components/DocumentActions.js.map +1 -1
  21. package/dist/admin/pages/EditView/components/DocumentActions.mjs +32 -36
  22. package/dist/admin/pages/EditView/components/DocumentActions.mjs.map +1 -1
  23. package/dist/admin/pages/EditView/components/FormInputs/Component/Input.js +2 -2
  24. package/dist/admin/pages/EditView/components/FormInputs/Component/Input.js.map +1 -1
  25. package/dist/admin/pages/EditView/components/FormInputs/Component/Input.mjs +2 -2
  26. package/dist/admin/pages/EditView/components/FormInputs/Component/Input.mjs.map +1 -1
  27. package/dist/admin/pages/EditView/components/FormInputs/Component/NonRepeatable.js +2 -2
  28. package/dist/admin/pages/EditView/components/FormInputs/Component/NonRepeatable.js.map +1 -1
  29. package/dist/admin/pages/EditView/components/FormInputs/Component/NonRepeatable.mjs +2 -2
  30. package/dist/admin/pages/EditView/components/FormInputs/Component/NonRepeatable.mjs.map +1 -1
  31. package/dist/admin/pages/EditView/components/FormInputs/Component/Repeatable.js +2 -2
  32. package/dist/admin/pages/EditView/components/FormInputs/Component/Repeatable.js.map +1 -1
  33. package/dist/admin/pages/EditView/components/FormInputs/Component/Repeatable.mjs +2 -2
  34. package/dist/admin/pages/EditView/components/FormInputs/Component/Repeatable.mjs.map +1 -1
  35. package/dist/admin/pages/EditView/components/FormInputs/DynamicZone/DynamicComponent.js +5 -16
  36. package/dist/admin/pages/EditView/components/FormInputs/DynamicZone/DynamicComponent.js.map +1 -1
  37. package/dist/admin/pages/EditView/components/FormInputs/DynamicZone/DynamicComponent.mjs +5 -16
  38. package/dist/admin/pages/EditView/components/FormInputs/DynamicZone/DynamicComponent.mjs.map +1 -1
  39. package/dist/admin/pages/EditView/components/FormInputs/DynamicZone/Field.js +2 -3
  40. package/dist/admin/pages/EditView/components/FormInputs/DynamicZone/Field.js.map +1 -1
  41. package/dist/admin/pages/EditView/components/FormInputs/DynamicZone/Field.mjs +2 -3
  42. package/dist/admin/pages/EditView/components/FormInputs/DynamicZone/Field.mjs.map +1 -1
  43. package/dist/admin/pages/EditView/components/FormInputs/Relations/RelationModal.js +432 -344
  44. package/dist/admin/pages/EditView/components/FormInputs/Relations/RelationModal.js.map +1 -1
  45. package/dist/admin/pages/EditView/components/FormInputs/Relations/RelationModal.mjs +432 -346
  46. package/dist/admin/pages/EditView/components/FormInputs/Relations/RelationModal.mjs.map +1 -1
  47. package/dist/admin/pages/EditView/components/FormInputs/Relations/Relations.js +55 -37
  48. package/dist/admin/pages/EditView/components/FormInputs/Relations/Relations.js.map +1 -1
  49. package/dist/admin/pages/EditView/components/FormInputs/Relations/Relations.mjs +57 -39
  50. package/dist/admin/pages/EditView/components/FormInputs/Relations/Relations.mjs.map +1 -1
  51. package/dist/admin/pages/EditView/components/FormInputs/UID.js +7 -7
  52. package/dist/admin/pages/EditView/components/FormInputs/UID.js.map +1 -1
  53. package/dist/admin/pages/EditView/components/FormInputs/UID.mjs +7 -7
  54. package/dist/admin/pages/EditView/components/FormInputs/UID.mjs.map +1 -1
  55. package/dist/admin/pages/EditView/components/InputRenderer.js +3 -10
  56. package/dist/admin/pages/EditView/components/InputRenderer.js.map +1 -1
  57. package/dist/admin/pages/EditView/components/InputRenderer.mjs +3 -10
  58. package/dist/admin/pages/EditView/components/InputRenderer.mjs.map +1 -1
  59. package/dist/admin/preview/components/PreviewHeader.js +2 -5
  60. package/dist/admin/preview/components/PreviewHeader.js.map +1 -1
  61. package/dist/admin/preview/components/PreviewHeader.mjs +2 -5
  62. package/dist/admin/preview/components/PreviewHeader.mjs.map +1 -1
  63. package/dist/admin/preview/pages/Preview.js +94 -102
  64. package/dist/admin/preview/pages/Preview.js.map +1 -1
  65. package/dist/admin/preview/pages/Preview.mjs +94 -102
  66. package/dist/admin/preview/pages/Preview.mjs.map +1 -1
  67. package/dist/admin/src/content-manager.d.ts +0 -3
  68. package/dist/admin/src/features/DocumentRBAC.d.ts +1 -1
  69. package/dist/admin/src/history/pages/History.d.ts +1 -1
  70. package/dist/admin/src/hooks/useDocumentContext.d.ts +30 -0
  71. package/dist/admin/src/pages/EditView/components/FormInputs/ComponentContext.d.ts +1 -1
  72. package/dist/admin/src/pages/EditView/components/FormInputs/DynamicZone/Field.d.ts +1 -1
  73. package/dist/admin/src/pages/EditView/components/FormInputs/Relations/RelationModal.d.ts +50 -5
  74. package/dist/admin/src/pages/EditView/components/FormInputs/Relations/Relations.d.ts +1 -0
  75. package/dist/admin/src/pages/EditView/components/InputRenderer.d.ts +1 -1
  76. package/dist/admin/src/preview/pages/Preview.d.ts +2 -1
  77. package/package.json +8 -8
  78. package/dist/admin/features/DocumentContext.js +0 -71
  79. package/dist/admin/features/DocumentContext.js.map +0 -1
  80. package/dist/admin/features/DocumentContext.mjs +0 -49
  81. package/dist/admin/features/DocumentContext.mjs.map +0 -1
  82. package/dist/admin/src/features/DocumentContext.d.ts +0 -53
@@ -10,13 +10,15 @@ var reactRouterDom = require('react-router-dom');
10
10
  var styledComponents = require('styled-components');
11
11
  var collections = require('../../../../../constants/collections.js');
12
12
  var plugin = require('../../../../../constants/plugin.js');
13
- var DocumentContext = require('../../../../../features/DocumentContext.js');
14
- var DocumentRBAC = require('../../../../../features/DocumentRBAC.js');
15
- var useDocumentLayout = require('../../../../../hooks/useDocumentLayout.js');
13
+ var api = require('../../../../../utils/api.js');
14
+ var DocumentStatus = require('../../DocumentStatus.js');
15
+ var useDocument = require('../../../../../hooks/useDocument.js');
16
+ require('../../../../../preview/pages/Preview.js');
16
17
  var documents = require('../../../../../services/documents.js');
18
+ var useDocumentLayout = require('../../../../../hooks/useDocumentLayout.js');
19
+ var DocumentRBAC = require('../../../../../features/DocumentRBAC.js');
17
20
  var validation = require('../../../../../utils/validation.js');
18
21
  var DocumentActions = require('../../DocumentActions.js');
19
- var DocumentStatus = require('../../DocumentStatus.js');
20
22
  var FormLayout = require('../../FormLayout.js');
21
23
 
22
24
  function _interopNamespaceDefault(e) {
@@ -43,271 +45,361 @@ function getCollectionType(url) {
43
45
  const match = url.match(regex);
44
46
  return match ? match[1] : undefined;
45
47
  }
46
- const CustomModalContent = styledComponents.styled(designSystem.Modal.Content)`
48
+ const StyledModalContent = styledComponents.styled(designSystem.Modal.Content)`
47
49
  width: 90%;
48
50
  max-width: 100%;
49
51
  height: 90%;
50
52
  max-height: 100%;
51
53
  `;
52
- const [RelationModalProvider, useRelationModal] = strapiAdmin.createContext('RelationModal', {
53
- parentModified: false,
54
- depth: 0
55
- });
56
- const RelationModalForm = ({ relation, triggerButtonLabel })=>{
54
+ function reducer(state, action) {
55
+ switch(action.type){
56
+ case 'GO_TO_RELATION':
57
+ if (state.hasUnsavedChanges && !action.payload.shouldBypassConfirmation) {
58
+ return {
59
+ ...state,
60
+ confirmDialogIntent: action.payload.document
61
+ };
62
+ }
63
+ return {
64
+ ...state,
65
+ documentHistory: [
66
+ ...state.documentHistory,
67
+ action.payload.document
68
+ ],
69
+ confirmDialogIntent: null,
70
+ isModalOpen: true
71
+ };
72
+ case 'GO_BACK':
73
+ if (state.hasUnsavedChanges && !action.payload.shouldBypassConfirmation) {
74
+ return {
75
+ ...state,
76
+ confirmDialogIntent: 'back'
77
+ };
78
+ }
79
+ return {
80
+ ...state,
81
+ documentHistory: state.documentHistory.slice(0, -1),
82
+ confirmDialogIntent: null
83
+ };
84
+ case 'GO_FULL_PAGE':
85
+ if (state.hasUnsavedChanges) {
86
+ return {
87
+ ...state,
88
+ confirmDialogIntent: 'navigate'
89
+ };
90
+ }
91
+ return {
92
+ ...state,
93
+ documentHistory: [],
94
+ hasUnsavedChanges: false,
95
+ isModalOpen: false,
96
+ confirmDialogIntent: null
97
+ };
98
+ case 'CANCEL_CONFIRM_DIALOG':
99
+ return {
100
+ ...state,
101
+ confirmDialogIntent: null
102
+ };
103
+ case 'CLOSE_MODAL':
104
+ if (state.hasUnsavedChanges && !action.payload.shouldBypassConfirmation) {
105
+ return {
106
+ ...state,
107
+ confirmDialogIntent: 'close'
108
+ };
109
+ }
110
+ return {
111
+ ...state,
112
+ documentHistory: [],
113
+ confirmDialogIntent: null,
114
+ hasUnsavedChanges: false,
115
+ isModalOpen: false
116
+ };
117
+ case 'SET_HAS_UNSAVED_CHANGES':
118
+ return {
119
+ ...state,
120
+ hasUnsavedChanges: action.payload.hasUnsavedChanges
121
+ };
122
+ default:
123
+ return state;
124
+ }
125
+ }
126
+ const [RelationModalProvider, useRelationModal] = strapiAdmin.createContext('RelationModal');
127
+ const getFullPageUrl = (currentDocumentMeta)=>{
128
+ const isSingleType = currentDocumentMeta.collectionType === collections.SINGLE_TYPES;
129
+ const queryParams = currentDocumentMeta.params?.locale ? `?plugins[i18n][locale]=${currentDocumentMeta.params.locale}` : '';
130
+ return `/content-manager/${currentDocumentMeta.collectionType}/${currentDocumentMeta.model}${isSingleType ? '' : '/' + currentDocumentMeta.documentId}${queryParams}`;
131
+ };
132
+ /**
133
+ * Component responsible of rendering its children wrapped in a modal, form and context if needed
134
+ */ const RelationModalRenderer = ({ children, trigger, relation })=>{
135
+ const { formatMessage } = reactIntl.useIntl();
136
+ const navigate = reactRouterDom.useNavigate();
137
+ const [state, dispatch] = React__namespace.useReducer(reducer, {
138
+ documentHistory: [],
139
+ confirmDialogIntent: null,
140
+ isModalOpen: false,
141
+ hasUnsavedChanges: false
142
+ });
143
+ const rootDocument = useDocument.useDoc();
144
+ const [{ query }] = strapiAdmin.useQueryParams();
145
+ const params = React__namespace.useMemo(()=>api.buildValidParams(query ?? {}), [
146
+ query
147
+ ]);
148
+ const rootDocumentMeta = {
149
+ documentId: rootDocument.document?.documentId || '',
150
+ model: rootDocument.model,
151
+ collectionType: rootDocument.collectionType,
152
+ params
153
+ };
154
+ const currentDocumentMeta = state.documentHistory.at(-1) ?? rootDocumentMeta;
155
+ const currentDocument = useDocument.useDocument(currentDocumentMeta);
156
+ const parentContextValue = useRelationModal('RelationContextWrapper', (state)=>state, false);
157
+ // A parent relation is already rendering a modal. In this case simply render the trigger
158
+ if (parentContextValue) {
159
+ return trigger;
160
+ }
161
+ /**
162
+ * There is no parent relation, so the relation modal doesn't exist. Create it and set up all the
163
+ * pieces that will be used by potential child relations: the context, header, form, and footer.
164
+ */ return /*#__PURE__*/ jsxRuntime.jsx(RelationModalProvider, {
165
+ state: state,
166
+ dispatch: dispatch,
167
+ rootDocumentMeta: rootDocumentMeta,
168
+ currentDocumentMeta: currentDocumentMeta,
169
+ currentDocument: currentDocument,
170
+ children: /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Modal.Root, {
171
+ open: state.isModalOpen,
172
+ onOpenChange: (open)=>{
173
+ if (open) {
174
+ dispatch({
175
+ type: 'GO_TO_RELATION',
176
+ payload: {
177
+ document: relation,
178
+ shouldBypassConfirmation: false
179
+ }
180
+ });
181
+ } else {
182
+ dispatch({
183
+ type: 'CLOSE_MODAL',
184
+ payload: {
185
+ shouldBypassConfirmation: false
186
+ }
187
+ });
188
+ }
189
+ },
190
+ children: [
191
+ trigger,
192
+ /*#__PURE__*/ jsxRuntime.jsxs(StyledModalContent, {
193
+ children: [
194
+ /*#__PURE__*/ jsxRuntime.jsx(designSystem.Modal.Header, {
195
+ gap: 2,
196
+ children: /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Flex, {
197
+ justifyContent: "space-between",
198
+ alignItems: "center",
199
+ width: "100%",
200
+ children: [
201
+ /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Flex, {
202
+ gap: 2,
203
+ children: [
204
+ /*#__PURE__*/ jsxRuntime.jsx(designSystem.IconButton, {
205
+ withTooltip: false,
206
+ label: formatMessage({
207
+ id: 'global.back',
208
+ defaultMessage: 'Back'
209
+ }),
210
+ variant: "ghost",
211
+ disabled: state.documentHistory.length < 2,
212
+ onClick: ()=>{
213
+ dispatch({
214
+ type: 'GO_BACK',
215
+ payload: {
216
+ shouldBypassConfirmation: false
217
+ }
218
+ });
219
+ },
220
+ marginRight: 1,
221
+ children: /*#__PURE__*/ jsxRuntime.jsx(Icons.ArrowLeft, {})
222
+ }),
223
+ /*#__PURE__*/ jsxRuntime.jsx(designSystem.Typography, {
224
+ tag: "span",
225
+ fontWeight: 600,
226
+ children: formatMessage({
227
+ id: 'content-manager.components.RelationInputModal.modal-title',
228
+ defaultMessage: 'Edit a relation'
229
+ })
230
+ })
231
+ ]
232
+ }),
233
+ /*#__PURE__*/ jsxRuntime.jsx(designSystem.IconButton, {
234
+ onClick: ()=>{
235
+ dispatch({
236
+ type: 'GO_FULL_PAGE'
237
+ });
238
+ if (!state.hasUnsavedChanges) {
239
+ navigate(getFullPageUrl(currentDocumentMeta));
240
+ }
241
+ },
242
+ variant: "tertiary",
243
+ label: formatMessage({
244
+ id: 'content-manager.components.RelationInputModal.button-fullpage',
245
+ defaultMessage: 'Go to entry'
246
+ }),
247
+ children: /*#__PURE__*/ jsxRuntime.jsx(Icons.ArrowsOut, {})
248
+ })
249
+ ]
250
+ })
251
+ }),
252
+ /*#__PURE__*/ jsxRuntime.jsx(designSystem.Modal.Body, {
253
+ children: /*#__PURE__*/ jsxRuntime.jsx(strapiAdmin.Form, {
254
+ method: "PUT",
255
+ initialValues: currentDocument.getInitialFormValues(),
256
+ validate: (values, options)=>{
257
+ const yupSchema = validation.createYupSchema(currentDocument.schema?.attributes, currentDocument.components, {
258
+ status: currentDocument.document?.status,
259
+ ...options
260
+ });
261
+ return yupSchema.validate(values, {
262
+ abortEarly: false
263
+ });
264
+ },
265
+ children: children
266
+ })
267
+ })
268
+ ]
269
+ })
270
+ ]
271
+ })
272
+ });
273
+ };
274
+ /**
275
+ * All the main content (not header and footer) of the relation modal, plus the confirmation dialog.
276
+ * Will be wrapped in a Modal.Body by the RelationModalRenderer.
277
+ * Cannot be moved directly inside RelationModal because it needs access to the context via hooks.
278
+ */ const RelationModalBody = ()=>{
57
279
  const navigate = reactRouterDom.useNavigate();
58
280
  const { pathname, search } = reactRouterDom.useLocation();
59
281
  const { formatMessage } = reactIntl.useIntl();
60
282
  const [triggerRefetchDocument] = documents.useLazyGetDocumentQuery();
61
- const currentDocument = DocumentContext.useDocumentContext('RelationModalForm', (state)=>state.document);
62
- const rootDocumentMeta = DocumentContext.useDocumentContext('RelationModalForm', (state)=>state.rootDocumentMeta);
63
- const currentDocumentMeta = DocumentContext.useDocumentContext('RelationModalForm', (state)=>state.meta);
64
- const changeDocument = DocumentContext.useDocumentContext('RelationModalForm', (state)=>state.changeDocument);
65
- const documentHistory = DocumentContext.useDocumentContext('RelationModalForm', (state)=>state.documentHistory);
66
- const setDocumentHistory = DocumentContext.useDocumentContext('RelationModalForm', (state)=>state.setDocumentHistory);
67
- const [isConfirmationOpen, setIsConfirmationOpen] = React__namespace.useState(false);
68
- const [actionPosition, setActionPosition] = React__namespace.useState('cancel');
69
- const [isModalOpen, setIsModalOpen] = React__namespace.useState(false);
70
- // NOTE: Not sure about this relation modal context, maybe we should move this to DocumentContext?
71
- // Get parent modal context if it exists
72
- const parentContext = useRelationModal('RelationModalForm', (state)=>state);
73
- // Get depth of nested modals
74
- const depth = parentContext ? parentContext.depth + 1 : 0;
75
- // Check if this is a nested modal
76
- const isNested = depth > 0;
77
- const addDocumentToHistory = (document)=>setDocumentHistory((prev)=>[
78
- ...prev,
79
- document
80
- ]);
81
- const getPreviousDocument = ()=>{
82
- if (documentHistory.length === 0) return undefined;
83
- const lastDocument = documentHistory[documentHistory.length - 1];
84
- return lastDocument;
85
- };
86
- const removeLastDocumentFromHistory = ()=>{
87
- setDocumentHistory((prev)=>[
88
- ...prev
89
- ].slice(0, prev.length - 1));
90
- };
91
- const handleToggleModal = ()=>{
92
- if (isModalOpen) {
93
- setIsModalOpen(false);
94
- const document = {
95
- collectionType: rootDocumentMeta.collectionType,
96
- model: rootDocumentMeta.model,
97
- documentId: rootDocumentMeta.documentId
98
- };
99
- // Change back to the root document
100
- changeDocument(document);
101
- // Reset the document history
102
- setDocumentHistory([]);
103
- // Reset action position
104
- setActionPosition('cancel');
105
- // Read from cache or refetch root document
106
- triggerRefetchDocument(document, // Favor the cache
283
+ const state = useRelationModal('RelationModalForm', (state)=>state.state);
284
+ const dispatch = useRelationModal('RelationModalForm', (state)=>state.dispatch);
285
+ const rootDocumentMeta = useRelationModal('RelationModalForm', (state)=>state.rootDocumentMeta);
286
+ const currentDocumentMeta = useRelationModal('RelationModalForm', (state)=>state.currentDocumentMeta);
287
+ /**
288
+ * One-way sync the modified state from the form to the modal state.
289
+ * It is needed because we need to consume state from the form context in order to lift it up
290
+ * into the modal context. It is not possible otherwise because the modal needs the form state,
291
+ * but it must be a parent of the form.
292
+ */ const modified = strapiAdmin.useForm('FormWatcher', (state)=>state.modified);
293
+ const isSubmitting = strapiAdmin.useForm('FormWatcher', (state)=>state.isSubmitting);
294
+ const hasUnsavedChanges = modified && !isSubmitting;
295
+ React__namespace.useEffect(()=>{
296
+ dispatch({
297
+ type: 'SET_HAS_UNSAVED_CHANGES',
298
+ payload: {
299
+ hasUnsavedChanges
300
+ }
301
+ });
302
+ }, [
303
+ hasUnsavedChanges,
304
+ dispatch
305
+ ]);
306
+ const handleCloseModal = (shouldBypassConfirmation)=>{
307
+ dispatch({
308
+ type: 'CLOSE_MODAL',
309
+ payload: {
310
+ shouldBypassConfirmation
311
+ }
312
+ });
313
+ {
314
+ // TODO: check if we can avoid this by relying on RTK invalidatesTags.
315
+ // If so we can delete this function and dispatch the events directly
316
+ triggerRefetchDocument(// TODO check if params should be removed (as they were before)
317
+ rootDocumentMeta, // Favor the cache
107
318
  true);
108
- } else {
109
- changeDocument(relation);
110
- setIsModalOpen(true);
111
319
  }
112
320
  };
113
- const getFullPageLink = ()=>{
114
- const isSingleType = currentDocumentMeta.collectionType === collections.SINGLE_TYPES;
115
- const queryParams = currentDocumentMeta.params?.locale ? `?plugins[i18n][locale]=${currentDocumentMeta.params.locale}` : '';
116
- return `/content-manager/${currentDocumentMeta.collectionType}/${currentDocumentMeta.model}${isSingleType ? '' : '/' + currentDocumentMeta.documentId}${queryParams}`;
117
- };
118
321
  const handleRedirection = ()=>{
119
322
  const editViewUrl = `${pathname}${search}`;
120
- const isRootDocumentUrl = editViewUrl.includes(getFullPageLink());
323
+ const fullPageUrl = getFullPageUrl(currentDocumentMeta);
324
+ const isRootDocumentUrl = editViewUrl.includes(fullPageUrl);
121
325
  if (isRootDocumentUrl) {
122
- handleToggleModal();
326
+ handleCloseModal(true);
123
327
  } else {
124
- navigate(getFullPageLink());
328
+ navigate(fullPageUrl);
125
329
  }
126
330
  };
127
331
  const handleConfirm = ()=>{
128
- if (actionPosition === 'navigate') {
129
- handleRedirection();
130
- } else if (actionPosition === 'back') {
131
- const previousRelation = getPreviousDocument();
132
- if (previousRelation) {
133
- removeLastDocumentFromHistory();
134
- changeDocument(previousRelation);
135
- }
136
- } else {
137
- // Add current relation to history before opening a new one in case we are opening a new one
138
- if (currentDocumentMeta && Object.keys(currentDocumentMeta).length > 0) {
139
- addDocumentToHistory(currentDocumentMeta);
140
- }
141
- handleToggleModal();
332
+ if (state.confirmDialogIntent === null) {
333
+ return;
142
334
  }
143
- };
144
- return /*#__PURE__*/ jsxRuntime.jsx(strapiAdmin.Form, {
145
- method: "PUT",
146
- initialValues: currentDocument.getInitialFormValues(),
147
- validate: (values, options)=>{
148
- const yupSchema = validation.createYupSchema(currentDocument.schema?.attributes, currentDocument.components, {
149
- status: currentDocument.document?.status,
150
- ...options
335
+ if (state.confirmDialogIntent === 'navigate') {
336
+ handleRedirection();
337
+ } else if (state.confirmDialogIntent === 'back') {
338
+ dispatch({
339
+ type: 'GO_BACK',
340
+ payload: {
341
+ shouldBypassConfirmation: true
342
+ }
151
343
  });
152
- return yupSchema.validate(values, {
153
- abortEarly: false
344
+ } else if (state.confirmDialogIntent === 'close') {
345
+ handleCloseModal(true);
346
+ } else if ('documentId' in state.confirmDialogIntent) {
347
+ dispatch({
348
+ type: 'GO_TO_RELATION',
349
+ payload: {
350
+ document: state.confirmDialogIntent,
351
+ shouldBypassConfirmation: true
352
+ }
154
353
  });
155
- },
156
- children: ({ modified, isSubmitting, resetForm })=>{
157
- // We don't count the root document, so history starts after 1
158
- const hasHistory = documentHistory.length > 1;
159
- return /*#__PURE__*/ jsxRuntime.jsxs(RelationModalProvider, {
160
- parentModified: modified,
161
- depth: depth,
162
- children: [
163
- /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Modal.Root, {
164
- open: isModalOpen,
165
- onOpenChange: ()=>{
166
- if (isModalOpen) {
167
- if (modified && !isSubmitting) {
168
- setIsConfirmationOpen(true);
169
- } else {
170
- handleToggleModal();
171
- }
172
- }
173
- },
174
- children: [
175
- /*#__PURE__*/ jsxRuntime.jsx(designSystem.Modal.Trigger, {
176
- children: /*#__PURE__*/ jsxRuntime.jsx(designSystem.Tooltip, {
177
- description: triggerButtonLabel,
178
- children: /*#__PURE__*/ jsxRuntime.jsx(CustomTextButton, {
179
- onClick: ()=>{
180
- // Check if parent modal has unsaved changes
181
- if (isNested && parentContext.parentModified) {
182
- setIsConfirmationOpen(true);
183
- // Return early to avoid opening the modal
184
- return;
185
- } else {
186
- if (modified && !isSubmitting) {
187
- setIsConfirmationOpen(true);
188
- } else {
189
- // Add current relation to history before opening a new one
190
- if (currentDocumentMeta && Object.keys(currentDocumentMeta).length > 0) {
191
- addDocumentToHistory(currentDocumentMeta);
192
- }
193
- handleToggleModal();
194
- }
195
- if (!isModalOpen) {
196
- setIsModalOpen(true);
197
- }
198
- }
199
- },
200
- width: "100%",
201
- children: triggerButtonLabel
202
- })
203
- })
204
- }),
205
- /*#__PURE__*/ jsxRuntime.jsxs(CustomModalContent, {
206
- children: [
207
- /*#__PURE__*/ jsxRuntime.jsx(designSystem.Modal.Header, {
208
- gap: 2,
209
- children: /*#__PURE__*/ jsxRuntime.jsx(designSystem.Flex, {
210
- justifyContent: "space-between",
211
- alignItems: "center",
212
- width: "100%",
213
- children: /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Flex, {
214
- gap: 2,
215
- children: [
216
- /*#__PURE__*/ jsxRuntime.jsx(designSystem.IconButton, {
217
- withTooltip: false,
218
- label: "Back",
219
- variant: "ghost",
220
- disabled: !hasHistory,
221
- onClick: ()=>{
222
- setActionPosition('back');
223
- if (modified && !isSubmitting) {
224
- setIsConfirmationOpen(true);
225
- } else {
226
- const previousRelation = getPreviousDocument();
227
- if (previousRelation) {
228
- removeLastDocumentFromHistory();
229
- changeDocument(previousRelation);
230
- }
231
- }
232
- },
233
- marginRight: 1,
234
- children: /*#__PURE__*/ jsxRuntime.jsx(Icons.ArrowLeft, {})
235
- }),
236
- /*#__PURE__*/ jsxRuntime.jsx(designSystem.Typography, {
237
- tag: "span",
238
- fontWeight: 600,
239
- children: formatMessage({
240
- id: 'content-manager.components.RelationInputModal.modal-title',
241
- defaultMessage: 'Edit a relation'
242
- })
243
- })
244
- ]
245
- })
246
- })
247
- }),
248
- /*#__PURE__*/ jsxRuntime.jsx(RelationModalBody, {
249
- children: /*#__PURE__*/ jsxRuntime.jsx(designSystem.IconButton, {
250
- onClick: ()=>{
251
- setActionPosition('navigate');
252
- if (modified && !isSubmitting) {
253
- setIsConfirmationOpen(true);
254
- } else {
255
- navigate(getFullPageLink());
256
- }
257
- },
258
- variant: "tertiary",
259
- label: formatMessage({
260
- id: 'content-manager.components.RelationInputModal.button-fullpage',
261
- defaultMessage: 'Go to entry'
262
- }),
263
- children: /*#__PURE__*/ jsxRuntime.jsx(Icons.ArrowsOut, {})
264
- })
265
- }),
266
- /*#__PURE__*/ jsxRuntime.jsx(designSystem.Modal.Footer, {
267
- children: /*#__PURE__*/ jsxRuntime.jsx(designSystem.Button, {
268
- onClick: ()=>{
269
- if (modified && !isSubmitting) {
270
- setIsConfirmationOpen(true);
271
- } else {
272
- handleToggleModal();
273
- }
274
- },
275
- variant: "tertiary",
276
- children: formatMessage({
277
- id: 'app.components.Button.cancel',
278
- defaultMessage: 'Cancel'
279
- })
280
- })
281
- })
282
- ]
283
- })
284
- ]
285
- }),
286
- /*#__PURE__*/ jsxRuntime.jsx(designSystem.Dialog.Root, {
287
- open: isConfirmationOpen,
288
- onOpenChange: setIsConfirmationOpen,
289
- children: /*#__PURE__*/ jsxRuntime.jsx(strapiAdmin.ConfirmDialog, {
290
- onConfirm: ()=>{
291
- handleConfirm();
292
- setIsConfirmationOpen(false);
293
- resetForm();
294
- },
295
- onCancel: ()=>{
296
- setIsConfirmationOpen(false);
297
- },
298
- variant: "danger",
299
- children: formatMessage({
300
- id: 'content-manager.components.RelationInputModal.confirmation-message',
301
- defaultMessage: 'Some changes were not saved. Are you sure you want to close this relation? All changes that were not saved will be lost.'
302
- })
303
- })
354
+ }
355
+ };
356
+ return /*#__PURE__*/ jsxRuntime.jsxs(jsxRuntime.Fragment, {
357
+ children: [
358
+ /*#__PURE__*/ jsxRuntime.jsx(RelationEditView, {}),
359
+ /*#__PURE__*/ jsxRuntime.jsx(designSystem.Dialog.Root, {
360
+ open: state.confirmDialogIntent != null,
361
+ children: /*#__PURE__*/ jsxRuntime.jsx(strapiAdmin.ConfirmDialog, {
362
+ onConfirm: ()=>handleConfirm(),
363
+ onCancel: ()=>dispatch({
364
+ type: 'CANCEL_CONFIRM_DIALOG'
365
+ }),
366
+ variant: "danger",
367
+ children: formatMessage({
368
+ id: 'content-manager.components.RelationInputModal.confirmation-message',
369
+ defaultMessage: 'Some changes were not saved. Are you sure you want to close this relation? All changes that were not saved will be lost.'
304
370
  })
305
- ]
371
+ })
372
+ })
373
+ ]
374
+ });
375
+ };
376
+ const ModalTrigger = ({ children, relation })=>{
377
+ const dispatch = useRelationModal('ModalTrigger', (state)=>state.dispatch);
378
+ return /*#__PURE__*/ jsxRuntime.jsx(StyledTextButton, {
379
+ onClick: ()=>{
380
+ dispatch({
381
+ type: 'GO_TO_RELATION',
382
+ payload: {
383
+ document: relation,
384
+ shouldBypassConfirmation: false
385
+ }
306
386
  });
307
- }
387
+ },
388
+ children: children
308
389
  });
309
390
  };
310
- const CustomTextButton = styledComponents.styled(designSystem.TextButton)`
391
+ const RelationModal = /*#__PURE__*/ React__namespace.memo(({ relation, children })=>{
392
+ return /*#__PURE__*/ jsxRuntime.jsx(RelationModalRenderer, {
393
+ relation: relation,
394
+ trigger: /*#__PURE__*/ jsxRuntime.jsx(ModalTrigger, {
395
+ relation: relation,
396
+ children: children
397
+ }),
398
+ children: /*#__PURE__*/ jsxRuntime.jsx(RelationModalBody, {})
399
+ });
400
+ });
401
+ const StyledTextButton = styledComponents.styled(designSystem.TextButton)`
402
+ max-width: 100%;
311
403
  & > span {
312
404
  font-size: ${({ theme })=>theme.fontSizes[2]};
313
405
  width: inherit;
@@ -316,20 +408,22 @@ const CustomTextButton = styledComponents.styled(designSystem.TextButton)`
316
408
  text-overflow: ellipsis;
317
409
  }
318
410
  `;
319
- const RelationModalBody = ({ children })=>{
411
+ /**
412
+ * The mini edit view for a relation that is displayed inside a modal.
413
+ * It's complete with its header, document actions and form layout.
414
+ */ const RelationEditView = ()=>{
320
415
  const { formatMessage } = reactIntl.useIntl();
321
- const documentMeta = DocumentContext.useDocumentContext('RelationModalBody', (state)=>state.meta);
322
- const documentResponse = DocumentContext.useDocumentContext('RelationModalBody', (state)=>state.document);
323
- const onPreview = DocumentContext.useDocumentContext('RelationModalBody', (state)=>state.onPreview);
324
- const documentLayoutResponse = useDocumentLayout.useDocumentLayout(documentMeta.model);
416
+ const currentDocumentMeta = useRelationModal('RelationModalBody', (state)=>state.currentDocumentMeta);
417
+ const currentDocument = useRelationModal('RelationModalBody', (state)=>state.currentDocument);
418
+ const documentLayoutResponse = useDocumentLayout.useDocumentLayout(currentDocumentMeta.model);
325
419
  const plugins = strapiAdmin.useStrapiApp('RelationModalBody', (state)=>state.plugins);
326
- const initialValues = documentResponse.getInitialFormValues();
420
+ const initialValues = currentDocument.getInitialFormValues();
327
421
  const { permissions = [], isLoading: isLoadingPermissions, error } = strapiAdmin.useRBAC(plugin.PERMISSIONS.map((action)=>({
328
422
  action,
329
- subject: documentMeta.model
423
+ subject: currentDocumentMeta.model
330
424
  })));
331
- const isLoading = isLoadingPermissions || documentLayoutResponse.isLoading || documentResponse.isLoading;
332
- if (isLoading && !documentResponse.document?.documentId) {
425
+ const isLoading = isLoadingPermissions || documentLayoutResponse.isLoading || currentDocument.isLoading;
426
+ if (isLoading && !currentDocument.document?.documentId) {
333
427
  return /*#__PURE__*/ jsxRuntime.jsx(designSystem.Loader, {
334
428
  small: true,
335
429
  children: formatMessage({
@@ -338,7 +432,7 @@ const RelationModalBody = ({ children })=>{
338
432
  })
339
433
  });
340
434
  }
341
- if (error || !documentMeta.model || documentLayoutResponse.error || !documentResponse.document || !documentResponse.meta || !documentResponse.schema || !initialValues) {
435
+ if (error || !currentDocumentMeta.model || documentLayoutResponse.error || !currentDocument.document || !currentDocument.meta || !currentDocument.schema || !initialValues) {
342
436
  return /*#__PURE__*/ jsxRuntime.jsx(designSystem.Flex, {
343
437
  alignItems: "center",
344
438
  height: "100%",
@@ -354,107 +448,101 @@ const RelationModalBody = ({ children })=>{
354
448
  })
355
449
  });
356
450
  }
357
- const documentTitle = documentResponse.getTitle(documentLayoutResponse.edit.settings.mainField);
358
- const hasDraftAndPublished = documentResponse.schema?.options?.draftAndPublish ?? false;
451
+ const documentTitle = currentDocument.getTitle(documentLayoutResponse.edit.settings.mainField);
452
+ const hasDraftAndPublished = currentDocument.schema?.options?.draftAndPublish ?? false;
359
453
  const props = {
360
454
  activeTab: 'draft',
361
- collectionType: documentMeta.collectionType,
362
- model: documentMeta.model,
363
- documentId: documentMeta.documentId,
364
- document: documentResponse.document,
365
- meta: documentResponse.meta,
366
- onPreview,
367
- fromRelationModal: true,
368
- fromPreview: onPreview !== undefined
455
+ collectionType: currentDocumentMeta.collectionType,
456
+ model: currentDocumentMeta.model,
457
+ documentId: currentDocumentMeta.documentId,
458
+ document: currentDocument.document,
459
+ meta: currentDocument.meta
369
460
  };
370
- return /*#__PURE__*/ jsxRuntime.jsx(designSystem.Modal.Body, {
371
- children: /*#__PURE__*/ jsxRuntime.jsxs(DocumentRBAC.DocumentRBAC, {
372
- permissions: permissions,
373
- model: documentMeta.model,
374
- children: [
375
- /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Flex, {
376
- alignItems: "flex-start",
377
- direction: "column",
378
- gap: 2,
379
- children: [
380
- /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Flex, {
381
- width: "100%",
382
- justifyContent: "space-between",
383
- gap: 2,
384
- children: [
385
- /*#__PURE__*/ jsxRuntime.jsx(designSystem.Typography, {
386
- tag: "h2",
387
- variant: "alpha",
388
- children: documentTitle
389
- }),
390
- /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Flex, {
391
- gap: 2,
392
- children: [
393
- children,
394
- /*#__PURE__*/ jsxRuntime.jsx(strapiAdmin.DescriptionComponentRenderer, {
395
- props: props,
396
- descriptions: plugins['content-manager'].apis.getDocumentActions('relation-modal'),
397
- children: (actions)=>{
398
- const filteredActions = actions.filter((action)=>{
399
- return [
400
- action.position
401
- ].flat().includes('relation-modal');
402
- });
403
- const [primaryAction, secondaryAction] = filteredActions;
404
- if (!primaryAction && !secondaryAction) return null;
405
- // Both actions are available when draft and publish enabled
406
- if (primaryAction && secondaryAction) {
407
- return /*#__PURE__*/ jsxRuntime.jsxs(jsxRuntime.Fragment, {
408
- children: [
409
- /*#__PURE__*/ jsxRuntime.jsx(DocumentActions.DocumentActionButton, {
410
- ...secondaryAction,
411
- variant: secondaryAction.variant || 'secondary'
412
- }),
413
- /*#__PURE__*/ jsxRuntime.jsx(DocumentActions.DocumentActionButton, {
414
- ...primaryAction,
415
- variant: primaryAction.variant || 'default'
416
- })
417
- ]
418
- });
419
- }
420
- // Otherwise we just have the save action
421
- return /*#__PURE__*/ jsxRuntime.jsx(DocumentActions.DocumentActionButton, {
422
- ...primaryAction,
423
- variant: primaryAction.variant || 'secondary'
424
- });
425
- }
426
- })
427
- ]
461
+ return /*#__PURE__*/ jsxRuntime.jsxs(DocumentRBAC.DocumentRBAC, {
462
+ permissions: permissions,
463
+ model: currentDocumentMeta.model,
464
+ children: [
465
+ /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Flex, {
466
+ alignItems: "flex-start",
467
+ direction: "column",
468
+ gap: 2,
469
+ children: [
470
+ /*#__PURE__*/ jsxRuntime.jsxs(designSystem.Flex, {
471
+ width: "100%",
472
+ justifyContent: "space-between",
473
+ gap: 2,
474
+ children: [
475
+ /*#__PURE__*/ jsxRuntime.jsx(designSystem.Typography, {
476
+ tag: "h2",
477
+ variant: "alpha",
478
+ children: documentTitle
479
+ }),
480
+ /*#__PURE__*/ jsxRuntime.jsx(designSystem.Flex, {
481
+ gap: 2,
482
+ children: /*#__PURE__*/ jsxRuntime.jsx(strapiAdmin.DescriptionComponentRenderer, {
483
+ props: props,
484
+ descriptions: plugins['content-manager'].apis.getDocumentActions('relation-modal'),
485
+ children: (actions)=>{
486
+ const filteredActions = actions.filter((action)=>{
487
+ return [
488
+ action.position
489
+ ].flat().includes('relation-modal');
490
+ });
491
+ const [primaryAction, secondaryAction] = filteredActions;
492
+ if (!primaryAction && !secondaryAction) return null;
493
+ // Both actions are available when draft and publish enabled
494
+ if (primaryAction && secondaryAction) {
495
+ return /*#__PURE__*/ jsxRuntime.jsxs(jsxRuntime.Fragment, {
496
+ children: [
497
+ /*#__PURE__*/ jsxRuntime.jsx(DocumentActions.DocumentActionButton, {
498
+ ...secondaryAction,
499
+ variant: secondaryAction.variant || 'secondary'
500
+ }),
501
+ /*#__PURE__*/ jsxRuntime.jsx(DocumentActions.DocumentActionButton, {
502
+ ...primaryAction,
503
+ variant: primaryAction.variant || 'default'
504
+ })
505
+ ]
506
+ });
507
+ }
508
+ // Otherwise we just have the save action
509
+ return /*#__PURE__*/ jsxRuntime.jsx(DocumentActions.DocumentActionButton, {
510
+ ...primaryAction,
511
+ variant: primaryAction.variant || 'secondary'
512
+ });
513
+ }
428
514
  })
429
- ]
430
- }),
431
- hasDraftAndPublished ? /*#__PURE__*/ jsxRuntime.jsx(designSystem.Box, {
432
- children: /*#__PURE__*/ jsxRuntime.jsx(DocumentStatus.DocumentStatus, {
433
- status: documentResponse.document?.status
434
515
  })
435
- }) : null
436
- ]
437
- }),
438
- /*#__PURE__*/ jsxRuntime.jsx(designSystem.Flex, {
439
- flex: 1,
440
- overflow: "auto",
441
- alignItems: "stretch",
442
- paddingTop: 7,
443
- children: /*#__PURE__*/ jsxRuntime.jsx(designSystem.Box, {
444
- overflow: "auto",
445
- flex: 1,
446
- children: /*#__PURE__*/ jsxRuntime.jsx(FormLayout.FormLayout, {
447
- layout: documentLayoutResponse.edit.layout,
448
- document: documentResponse,
449
- hasBackground: false
516
+ ]
517
+ }),
518
+ hasDraftAndPublished ? /*#__PURE__*/ jsxRuntime.jsx(designSystem.Box, {
519
+ children: /*#__PURE__*/ jsxRuntime.jsx(DocumentStatus.DocumentStatus, {
520
+ status: currentDocument.document?.status
450
521
  })
522
+ }) : null
523
+ ]
524
+ }),
525
+ /*#__PURE__*/ jsxRuntime.jsx(designSystem.Flex, {
526
+ flex: 1,
527
+ overflow: "auto",
528
+ alignItems: "stretch",
529
+ paddingTop: 7,
530
+ children: /*#__PURE__*/ jsxRuntime.jsx(designSystem.Box, {
531
+ overflow: "auto",
532
+ flex: 1,
533
+ children: /*#__PURE__*/ jsxRuntime.jsx(FormLayout.FormLayout, {
534
+ layout: documentLayoutResponse.edit.layout,
535
+ document: currentDocument,
536
+ hasBackground: false
451
537
  })
452
538
  })
453
- ]
454
- })
539
+ })
540
+ ]
455
541
  });
456
542
  };
457
543
 
458
- exports.RelationModalForm = RelationModalForm;
544
+ exports.RelationModal = RelationModal;
459
545
  exports.getCollectionType = getCollectionType;
546
+ exports.reducer = reducer;
547
+ exports.useRelationModal = useRelationModal;
460
548
  //# sourceMappingURL=RelationModal.js.map