@strapi/admin 4.11.0-beta.0 → 4.11.0-exp.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (123) hide show
  1. package/admin/src/components/Providers/index.js +32 -32
  2. package/admin/src/components/Theme/index.js +5 -3
  3. package/admin/src/content-manager/components/ComponentIcon/ComponentIcon.js +16 -26
  4. package/admin/src/content-manager/components/ComponentIcon/constants.js +133 -0
  5. package/admin/src/content-manager/components/DynamicZone/components/AddComponentButton.js +32 -95
  6. package/admin/src/content-manager/components/DynamicZone/components/ComponentCard.js +10 -2
  7. package/admin/src/content-manager/components/DynamicZone/components/ComponentCategory.js +63 -15
  8. package/admin/src/content-manager/components/DynamicZone/components/ComponentPicker.js +50 -63
  9. package/admin/src/content-manager/components/DynamicZone/components/DynamicComponent.js +132 -58
  10. package/admin/src/content-manager/components/DynamicZone/components/DynamicZoneLabel.js +29 -37
  11. package/admin/src/content-manager/components/DynamicZone/index.js +131 -83
  12. package/admin/src/content-manager/components/EditViewDataManagerProvider/index.js +28 -6
  13. package/admin/src/content-manager/components/EditViewDataManagerProvider/reducer.js +18 -6
  14. package/admin/src/content-manager/components/Inputs/index.js +18 -11
  15. package/admin/src/content-manager/components/Inputs/utils/index.js +0 -1
  16. package/admin/src/content-manager/pages/EditSettingsView/components/DynamicZoneList.js +7 -1
  17. package/admin/src/content-manager/pages/EditView/index.js +1 -1
  18. package/admin/src/hooks/useContentTypes/useContentTypes.js +0 -2
  19. package/admin/src/index.js +4 -3
  20. package/admin/src/pages/SettingsPage/pages/Users/ListPage/index.js +1 -1
  21. package/admin/src/pages/SettingsPage/pages/Webhooks/EditView/components/EventTable/EventTableCE.js +13 -0
  22. package/admin/src/pages/SettingsPage/pages/Webhooks/EditView/components/EventTable/index.js +3 -0
  23. package/admin/src/pages/SettingsPage/pages/Webhooks/EditView/components/Events/index.js +331 -0
  24. package/admin/src/pages/SettingsPage/pages/Webhooks/EditView/components/HeadersInput/Combobox.js +54 -4
  25. package/admin/src/pages/SettingsPage/pages/Webhooks/EditView/components/HeadersInput/index.js +12 -23
  26. package/admin/src/pages/SettingsPage/pages/Webhooks/EditView/components/WebhookForm/index.js +129 -116
  27. package/admin/src/pages/SettingsPage/pages/Webhooks/EditView/components/WebhookForm/utils/makeWebhookValidationSchema.js +62 -0
  28. package/admin/src/pages/SettingsPage/pages/Webhooks/EditView/index.js +59 -64
  29. package/admin/src/translations/ar.json +684 -1
  30. package/admin/src/translations/en.json +7 -0
  31. package/build/1887.6f71e8b2.chunk.js +39 -0
  32. package/build/3081.7e9329cb.chunk.js +105 -0
  33. package/build/371.6e4e2c1f.chunk.js +71 -0
  34. package/build/5542.64b623c9.chunk.js +63 -0
  35. package/build/{5563.79950369.chunk.js → 5563.badbffde.chunk.js} +2 -2
  36. package/build/{6970.7ea35fbd.chunk.js → 6970.d456705f.chunk.js} +1 -1
  37. package/build/{7259.5cc67413.chunk.js → 7259.5d0de931.chunk.js} +1 -1
  38. package/build/8976.a85384ce.chunk.js +155 -0
  39. package/build/{1657.ca8562dd.chunk.js → 9932.5ef475c5.chunk.js} +54 -62
  40. package/build/{Admin-authenticatedApp.65172a0c.chunk.js → Admin-authenticatedApp.c985d4a0.chunk.js} +2 -2
  41. package/build/{Admin_InternalErrorPage.96ceaae1.chunk.js → Admin_InternalErrorPage.f25f04f3.chunk.js} +1 -1
  42. package/build/Admin_homePage.05063e43.chunk.js +73 -0
  43. package/build/Admin_marketplace.23ea289f.chunk.js +55 -0
  44. package/build/Admin_pluginsPage.b1031a00.chunk.js +6 -0
  45. package/build/{Admin_profilePage.a8fa3a56.chunk.js → Admin_profilePage.e7ccee9f.chunk.js} +2 -2
  46. package/build/Admin_settingsPage.07a6a5f0.chunk.js +79 -0
  47. package/build/{Upload_ConfigureTheView.aa64ed9a.chunk.js → Upload_ConfigureTheView.121deffb.chunk.js} +1 -1
  48. package/build/admin-app.8644c322.chunk.js +63 -0
  49. package/build/{admin-edit-roles-page.0d12b741.chunk.js → admin-edit-roles-page.bfe3304d.chunk.js} +3 -3
  50. package/build/{admin-edit-users.f9ce7844.chunk.js → admin-edit-users.6efe0382.chunk.js} +2 -2
  51. package/build/admin-roles-list.b2577370.chunk.js +23 -0
  52. package/build/admin-users.4af49ccf.chunk.js +26 -0
  53. package/build/{api-tokens-create-page.973d2816.chunk.js → api-tokens-create-page.65411a36.chunk.js} +1 -1
  54. package/build/{api-tokens-edit-page.29725c5e.chunk.js → api-tokens-edit-page.60312cb6.chunk.js} +1 -1
  55. package/build/{api-tokens-list-page.66c4fbdd.chunk.js → api-tokens-list-page.01a4d5cd.chunk.js} +2 -2
  56. package/build/ar-json.f530bc3f.chunk.js +1 -0
  57. package/build/audit-logs-settings-page.09c75037.chunk.js +121 -0
  58. package/build/content-manager.04fa9c14.chunk.js +1094 -0
  59. package/build/content-type-builder-list-view.58f9ed20.chunk.js +211 -0
  60. package/build/{content-type-builder-translation-en-json.af293c9e.chunk.js → content-type-builder-translation-en-json.f592325b.chunk.js} +1 -1
  61. package/build/content-type-builder.baeb0413.chunk.js +132 -0
  62. package/build/email-settings-page.85b71afc.chunk.js +11 -0
  63. package/build/en-json.a8f34002.chunk.js +1 -0
  64. package/build/i18n-settings-page.c0da2362.chunk.js +114 -0
  65. package/build/index.html +1 -1
  66. package/build/main.8605d88e.js +2633 -0
  67. package/build/{review-workflows-settings.4b39b837.chunk.js → review-workflows-settings.3a7bae25.chunk.js} +1 -1
  68. package/build/{runtime~main.96d92f16.js → runtime~main.36375726.js} +2 -2
  69. package/build/{sso-settings-page.265e3d72.chunk.js → sso-settings-page.4bb073e0.chunk.js} +1 -1
  70. package/build/{transfer-tokens-create-page.170acee6.chunk.js → transfer-tokens-create-page.9ec277d7.chunk.js} +1 -1
  71. package/build/{transfer-tokens-edit-page.6cf23295.chunk.js → transfer-tokens-edit-page.fa5ade14.chunk.js} +1 -1
  72. package/build/{transfer-tokens-list-page.c3fec4c1.chunk.js → transfer-tokens-list-page.5d68d590.chunk.js} +2 -2
  73. package/build/upload-settings.2c1565d6.chunk.js +14 -0
  74. package/build/upload.257b2aef.chunk.js +26 -0
  75. package/build/users-advanced-settings-page.dda58320.chunk.js +9 -0
  76. package/build/users-email-settings-page.a0c08594.chunk.js +24 -0
  77. package/build/users-providers-settings-page.14a82632.chunk.js +29 -0
  78. package/build/{users-roles-settings-page.2549794b.chunk.js → users-roles-settings-page.1f408276.chunk.js} +1 -1
  79. package/build/webhook-edit-page.b9a13be7.chunk.js +136 -0
  80. package/build/webhook-list-page.84e5abc9.chunk.js +63 -0
  81. package/ee/admin/pages/SettingsPage/pages/Webhooks/EditView/components/EventTable/EventTableEE.js +23 -0
  82. package/ee/admin/pages/SettingsPage/pages/Webhooks/EditView/components/EventTable/index.js +3 -0
  83. package/ee/server/services/review-workflows/review-workflows.js +4 -0
  84. package/package.json +22 -24
  85. package/server/controllers/webhooks.js +6 -6
  86. package/admin/src/content-manager/components/DynamicZone/utils/connect.js +0 -12
  87. package/admin/src/content-manager/components/DynamicZone/utils/select.js +0 -53
  88. package/admin/src/content-manager/components/Inputs/utils/getStep.js +0 -13
  89. package/admin/src/pages/SettingsPage/pages/Webhooks/EditView/components/EventInput/EventRow.js +0 -70
  90. package/admin/src/pages/SettingsPage/pages/Webhooks/EditView/components/EventInput/index.js +0 -174
  91. package/admin/src/pages/SettingsPage/pages/Webhooks/EditView/components/HeadersInput/keys.js +0 -39
  92. package/admin/src/pages/SettingsPage/pages/Webhooks/EditView/components/utils/fieldsRegex.js +0 -4
  93. package/admin/src/pages/SettingsPage/pages/Webhooks/EditView/components/utils/schema.js +0 -35
  94. package/admin/src/pages/SettingsPage/pages/Webhooks/EditView/reducer.js +0 -100
  95. package/admin/src/pages/SettingsPage/pages/Webhooks/EditView/utils/formatData.js +0 -20
  96. package/build/3081.c2cdfac8.chunk.js +0 -108
  97. package/build/3816.60f858cf.chunk.js +0 -211
  98. package/build/462.a073ff1f.chunk.js +0 -71
  99. package/build/5542.002522eb.chunk.js +0 -71
  100. package/build/617.87b2fe96.chunk.js +0 -155
  101. package/build/Admin_homePage.107a9fe0.chunk.js +0 -73
  102. package/build/Admin_marketplace.717bd7ca.chunk.js +0 -55
  103. package/build/Admin_pluginsPage.7df6b5a9.chunk.js +0 -6
  104. package/build/Admin_settingsPage.bd715ed3.chunk.js +0 -79
  105. package/build/admin-app.9c79b484.chunk.js +0 -63
  106. package/build/admin-roles-list.e8bf9685.chunk.js +0 -31
  107. package/build/admin-users.751b28b2.chunk.js +0 -34
  108. package/build/ar-json.39e54aba.chunk.js +0 -1
  109. package/build/audit-logs-settings-page.3c6cea81.chunk.js +0 -129
  110. package/build/content-manager.bf060d8e.chunk.js +0 -1123
  111. package/build/content-type-builder-list-view.1e821eb9.chunk.js +0 -215
  112. package/build/content-type-builder.b10576e7.chunk.js +0 -126
  113. package/build/email-settings-page.dba83275.chunk.js +0 -11
  114. package/build/en-json.19e9ff9b.chunk.js +0 -1
  115. package/build/i18n-settings-page.55628f74.chunk.js +0 -114
  116. package/build/main.576a9d22.js +0 -2630
  117. package/build/upload-settings.63d99bf5.chunk.js +0 -14
  118. package/build/upload.c50d8c7a.chunk.js +0 -34
  119. package/build/users-advanced-settings-page.4f49ca57.chunk.js +0 -9
  120. package/build/users-email-settings-page.d2429d0a.chunk.js +0 -24
  121. package/build/users-providers-settings-page.50c5ba27.chunk.js +0 -29
  122. package/build/webhook-edit-page.ddd5963d.chunk.js +0 -128
  123. package/build/webhook-list-page.e2fca9f8.chunk.js +0 -71
@@ -1,76 +1,113 @@
1
- import React, { memo, useMemo, useState } from 'react';
2
- import get from 'lodash/get';
3
- import isEqual from 'lodash/isEqual';
1
+ import React, { useMemo, useState } from 'react';
4
2
  import PropTypes from 'prop-types';
5
3
  import { Box, Flex, VisuallyHidden } from '@strapi/design-system';
6
- import { NotAllowedInput, useNotification } from '@strapi/helper-plugin';
4
+ import { NotAllowedInput, useNotification, useCMEditViewDataManager } from '@strapi/helper-plugin';
7
5
  import { useIntl } from 'react-intl';
8
6
 
9
7
  import { getTrad } from '../../utils';
10
8
 
11
- import connect from './utils/connect';
12
- import select from './utils/select';
13
-
14
- import DynamicZoneComponent from './components/DynamicComponent';
15
- import AddComponentButton from './components/AddComponentButton';
16
- import DynamicZoneLabel from './components/DynamicZoneLabel';
17
- import ComponentPicker from './components/ComponentPicker';
9
+ import { DynamicComponent } from './components/DynamicComponent';
10
+ import { AddComponentButton } from './components/AddComponentButton';
11
+ import { DynamicZoneLabel } from './components/DynamicZoneLabel';
12
+ import { ComponentPicker } from './components/ComponentPicker';
18
13
 
19
14
  import { useContentTypeLayout } from '../../hooks';
20
15
 
21
- const DynamicZone = ({
22
- name,
23
- // Passed with the select function
24
- addComponentToDynamicZone,
25
- formErrors,
26
- isCreatingEntry,
27
- isFieldAllowed,
28
- isFieldReadable,
29
- labelAction,
30
- moveComponentField,
31
- removeComponentFromDynamicZone,
32
- dynamicDisplayedComponents,
33
- fieldSchema,
34
- metadatas,
35
- }) => {
16
+ const DynamicZone = ({ name, labelAction, fieldSchema, metadatas }) => {
17
+ // We cannot use the default props here
18
+ const { max = Infinity, min = -Infinity, components = [], required = false } = fieldSchema;
19
+
36
20
  const [addComponentIsOpen, setAddComponentIsOpen] = useState(false);
37
21
  const [liveText, setLiveText] = useState('');
38
22
 
23
+ const {
24
+ addComponentToDynamicZone,
25
+ createActionAllowedFields,
26
+ isCreatingEntry,
27
+ formErrors,
28
+ modifiedData,
29
+ moveComponentField,
30
+ removeComponentFromDynamicZone,
31
+ readActionAllowedFields,
32
+ updateActionAllowedFields,
33
+ } = useCMEditViewDataManager();
34
+
35
+ const dynamicDisplayedComponents = useMemo(
36
+ () =>
37
+ (modifiedData?.[name] ?? []).map((data) => {
38
+ return {
39
+ componentUid: data.__component,
40
+ id: data.id ?? data.__temp_key__,
41
+ };
42
+ }),
43
+ [modifiedData, name]
44
+ );
45
+
46
+ const { getComponentLayout } = useContentTypeLayout();
47
+
48
+ /**
49
+ * @type {Record<string, Array<{category: string; info: unknown, attributes: Record<string, unknown>}>>}
50
+ */
51
+ const dynamicComponentsByCategory = useMemo(() => {
52
+ return components.reduce((acc, componentUid) => {
53
+ const { category, info, attributes } = getComponentLayout(componentUid);
54
+ const component = { componentUid, info, attributes };
55
+
56
+ if (!acc[category]) {
57
+ acc[category] = [];
58
+ }
59
+
60
+ acc[category] = [...acc[category], component];
61
+
62
+ return acc;
63
+ }, {});
64
+ }, [components, getComponentLayout]);
65
+
39
66
  const { formatMessage } = useIntl();
40
67
 
41
68
  const toggleNotification = useNotification();
42
- const { getComponentLayout, components } = useContentTypeLayout();
69
+
70
+ const isFieldAllowed = useMemo(() => {
71
+ const allowedFields = isCreatingEntry ? createActionAllowedFields : updateActionAllowedFields;
72
+
73
+ return allowedFields.includes(name);
74
+ }, [name, isCreatingEntry, createActionAllowedFields, updateActionAllowedFields]);
75
+
76
+ const isFieldReadable = useMemo(() => {
77
+ const allowedFields = isCreatingEntry ? [] : readActionAllowedFields;
78
+
79
+ return allowedFields.includes(name);
80
+ }, [name, isCreatingEntry, readActionAllowedFields]);
43
81
 
44
82
  const dynamicDisplayedComponentsLength = dynamicDisplayedComponents.length;
45
83
  const intlDescription = metadatas.description
46
84
  ? { id: metadatas.description, defaultMessage: metadatas.description }
47
85
  : null;
48
86
 
49
- // We cannot use the default props here
50
- const { max = Infinity, min = -Infinity } = fieldSchema;
51
- const dynamicZoneErrors = useMemo(() => {
52
- return Object.keys(formErrors)
53
- .filter((key) => {
54
- return key === name;
55
- })
56
- .map((key) => formErrors[key]);
57
- }, [formErrors, name]);
87
+ const dynamicZoneError = formErrors[name];
58
88
 
59
89
  const missingComponentNumber = min - dynamicDisplayedComponentsLength;
60
- const hasError = dynamicZoneErrors.length > 0;
61
-
62
- const hasMinError =
63
- dynamicZoneErrors.length > 0 && get(dynamicZoneErrors, [0, 'id'], '').includes('min');
90
+ const hasError = !!dynamicZoneError;
64
91
 
65
- const hasMaxError =
66
- hasError && get(dynamicZoneErrors, [0, 'id'], '') === 'components.Input.error.validation.max';
67
-
68
- const handleAddComponent = (componentUid) => {
92
+ const handleAddComponent = (componentUid, position) => {
69
93
  setAddComponentIsOpen(false);
70
94
 
71
95
  const componentLayoutData = getComponentLayout(componentUid);
72
96
 
73
- addComponentToDynamicZone(name, componentLayoutData, components, hasError);
97
+ const allComponents = Object.values(dynamicComponentsByCategory).reduce((acc, components) => {
98
+ const componentObjects = components.reduce((acc, { componentUid, attributes }) => {
99
+ acc[componentUid] = {
100
+ attributes,
101
+ uid: componentUid,
102
+ };
103
+
104
+ return acc;
105
+ }, {});
106
+
107
+ return { ...acc, ...componentObjects };
108
+ }, {});
109
+
110
+ addComponentToDynamicZone(name, componentLayoutData, allComponents, hasError, position);
74
111
  };
75
112
 
76
113
  const handleClickOpenPicker = () => {
@@ -160,6 +197,38 @@ const DynamicZone = ({
160
197
  removeComponentFromDynamicZone(name, currentIndex);
161
198
  };
162
199
 
200
+ const renderButtonLabel = () => {
201
+ if (addComponentIsOpen) {
202
+ return formatMessage({ id: 'app.utils.close-label', defaultMessage: 'Close' });
203
+ }
204
+
205
+ if (hasError && dynamicZoneError.id.includes('max')) {
206
+ return formatMessage({
207
+ id: 'components.Input.error.validation.max',
208
+ defaultMessage: 'The value is too high.',
209
+ });
210
+ }
211
+
212
+ if (hasError && dynamicZoneError.id.includes('min')) {
213
+ return formatMessage(
214
+ {
215
+ id: getTrad(`components.DynamicZone.missing-components`),
216
+ defaultMessage:
217
+ 'There {number, plural, =0 {are # missing components} one {is # missing component} other {are # missing components}}',
218
+ },
219
+ { number: missingComponentNumber }
220
+ );
221
+ }
222
+
223
+ return formatMessage(
224
+ {
225
+ id: getTrad('components.DynamicZone.add-component'),
226
+ defaultMessage: 'Add a component to {componentName}',
227
+ },
228
+ { componentName: metadatas.label || name }
229
+ );
230
+ };
231
+
163
232
  if (!isFieldAllowed && (isCreatingEntry || (!isFieldReadable && !isCreatingEntry))) {
164
233
  return (
165
234
  <NotAllowedInput
@@ -183,7 +252,7 @@ const DynamicZone = ({
183
252
  labelAction={labelAction}
184
253
  name={name}
185
254
  numberOfComponents={dynamicDisplayedComponentsLength}
186
- required={fieldSchema.required || false}
255
+ required={required}
187
256
  />
188
257
  <VisuallyHidden id={ariaDescriptionId}>
189
258
  {formatMessage({
@@ -194,7 +263,7 @@ const DynamicZone = ({
194
263
  <VisuallyHidden aria-live="assertive">{liveText}</VisuallyHidden>
195
264
  <ol aria-describedby={ariaDescriptionId}>
196
265
  {dynamicDisplayedComponents.map(({ componentUid, id }, index) => (
197
- <DynamicZoneComponent
266
+ <DynamicComponent
198
267
  componentUid={componentUid}
199
268
  formErrors={formErrors}
200
269
  key={`${componentUid}-${id}`}
@@ -206,26 +275,26 @@ const DynamicZone = ({
206
275
  onCancel={handleCancel}
207
276
  onDropItem={handleDropItem}
208
277
  onGrabItem={handleGrabItem}
278
+ onAddComponent={handleAddComponent}
279
+ dynamicComponentsByCategory={dynamicComponentsByCategory}
209
280
  />
210
281
  ))}
211
282
  </ol>
212
283
  </Box>
213
284
  )}
214
-
215
- <AddComponentButton
216
- hasError={hasError}
217
- hasMaxError={hasMaxError}
218
- hasMinError={hasMinError}
219
- isDisabled={!isFieldAllowed}
220
- label={metadatas.label}
221
- missingComponentNumber={missingComponentNumber}
222
- isOpen={addComponentIsOpen}
223
- name={name}
224
- onClick={handleClickOpenPicker}
225
- />
285
+ <Flex justifyContent="center">
286
+ <AddComponentButton
287
+ hasError={hasError}
288
+ isDisabled={!isFieldAllowed}
289
+ isOpen={addComponentIsOpen}
290
+ onClick={handleClickOpenPicker}
291
+ >
292
+ {renderButtonLabel()}
293
+ </AddComponentButton>
294
+ </Flex>
226
295
  <ComponentPicker
296
+ dynamicComponentsByCategory={dynamicComponentsByCategory}
227
297
  isOpen={addComponentIsOpen}
228
- components={fieldSchema.components ?? []}
229
298
  onClickAddComponent={handleAddComponent}
230
299
  />
231
300
  </Flex>
@@ -233,44 +302,23 @@ const DynamicZone = ({
233
302
  };
234
303
 
235
304
  DynamicZone.defaultProps = {
236
- dynamicDisplayedComponents: [],
237
- fieldSchema: {
238
- max: Infinity,
239
- min: -Infinity,
240
- },
305
+ fieldSchema: {},
241
306
  labelAction: null,
242
307
  };
243
308
 
244
309
  DynamicZone.propTypes = {
245
- addComponentToDynamicZone: PropTypes.func.isRequired,
246
- dynamicDisplayedComponents: PropTypes.arrayOf(
247
- PropTypes.shape({
248
- componentUid: PropTypes.string.isRequired,
249
- id: PropTypes.number.isRequired,
250
- })
251
- ),
252
310
  fieldSchema: PropTypes.shape({
253
- components: PropTypes.array.isRequired,
311
+ components: PropTypes.array,
254
312
  max: PropTypes.number,
255
313
  min: PropTypes.number,
256
314
  required: PropTypes.bool,
257
315
  }),
258
- formErrors: PropTypes.object.isRequired,
259
- isCreatingEntry: PropTypes.bool.isRequired,
260
- isFieldAllowed: PropTypes.bool.isRequired,
261
- isFieldReadable: PropTypes.bool.isRequired,
262
316
  labelAction: PropTypes.element,
263
317
  metadatas: PropTypes.shape({
264
318
  description: PropTypes.string,
265
319
  label: PropTypes.string,
266
320
  }).isRequired,
267
- moveComponentField: PropTypes.func.isRequired,
268
321
  name: PropTypes.string.isRequired,
269
- removeComponentFromDynamicZone: PropTypes.func.isRequired,
270
322
  };
271
323
 
272
- const Memoized = memo(DynamicZone, isEqual);
273
-
274
- export default connect(Memoized, select);
275
-
276
324
  export { DynamicZone };
@@ -8,6 +8,7 @@ import set from 'lodash/set';
8
8
  import PropTypes from 'prop-types';
9
9
  import { useIntl } from 'react-intl';
10
10
  import { Prompt, Redirect } from 'react-router-dom';
11
+ import { flushSync } from 'react-dom';
11
12
  import { useDispatch, useSelector } from 'react-redux';
12
13
 
13
14
  import { Main } from '@strapi/design-system';
@@ -55,6 +56,7 @@ const EditViewDataManagerProvider = ({
55
56
  status,
56
57
  updateActionAllowedFields,
57
58
  }) => {
59
+ const [isSaving, setIsSaving] = React.useState(false);
58
60
  /**
59
61
  * TODO: this should be moved into the global reducer
60
62
  * to match ever other reducer in the CM.
@@ -194,14 +196,21 @@ const EditViewDataManagerProvider = ({
194
196
 
195
197
  const dispatchAddComponent = useCallback(
196
198
  (type) =>
197
- (keys, componentLayoutData, components, shouldCheckErrors = false) => {
199
+ (
200
+ keys,
201
+ componentLayoutData,
202
+ allComponents,
203
+ shouldCheckErrors = false,
204
+ position = undefined
205
+ ) => {
198
206
  trackUsageRef.current('didAddComponentToDynamicZone');
199
207
 
200
208
  dispatch({
201
209
  type,
202
210
  keys: keys.split('.'),
211
+ position,
203
212
  componentLayoutData,
204
- allComponents: components,
213
+ allComponents,
205
214
  shouldCheckErrors,
206
215
  });
207
216
  },
@@ -376,14 +385,20 @@ const EditViewDataManagerProvider = ({
376
385
  try {
377
386
  if (isEmpty(errors)) {
378
387
  const formData = createFormData(modifiedData, initialData);
388
+ flushSync(() => {
389
+ setIsSaving(true);
390
+ });
379
391
 
380
392
  if (isCreatingEntry) {
381
393
  await onPost(formData, trackerProperty);
382
394
  } else {
383
395
  await onPut(formData, trackerProperty);
384
396
  }
397
+
398
+ setIsSaving(false);
385
399
  }
386
400
  } catch (err) {
401
+ setIsSaving(false);
387
402
  errors = {
388
403
  ...errors,
389
404
  ...getAPIInnerErrors(err, { getTrad }),
@@ -445,9 +460,14 @@ const EditViewDataManagerProvider = ({
445
460
 
446
461
  try {
447
462
  if (isEmpty(errors)) {
463
+ flushSync(() => {
464
+ setIsSaving(true);
465
+ });
448
466
  await onPublish();
467
+ setIsSaving(false);
449
468
  }
450
469
  } catch (err) {
470
+ setIsSaving(false);
451
471
  errors = {
452
472
  ...errors,
453
473
  ...getAPIInnerErrors(err, { getTrad }),
@@ -639,10 +659,12 @@ const EditViewDataManagerProvider = ({
639
659
  </Main>
640
660
  ) : (
641
661
  <>
642
- <Prompt
643
- when={!isEqual(modifiedData, initialData)}
644
- message={formatMessage({ id: 'global.prompt.unsaved' })}
645
- />
662
+ {!isSaving ? (
663
+ <Prompt
664
+ when={!isEqual(modifiedData, initialData)}
665
+ message={formatMessage({ id: 'global.prompt.unsaved' })}
666
+ />
667
+ ) : null}
646
668
  <form noValidate onSubmit={handleSubmit}>
647
669
  {children}
648
670
  </form>
@@ -52,7 +52,13 @@ const reducer = (state, action) =>
52
52
  }
53
53
  case 'ADD_COMPONENT_TO_DYNAMIC_ZONE':
54
54
  case 'ADD_REPEATABLE_COMPONENT_TO_FIELD': {
55
- const { keys, allComponents, componentLayoutData, shouldCheckErrors } = action;
55
+ const {
56
+ keys,
57
+ allComponents,
58
+ componentLayoutData,
59
+ shouldCheckErrors,
60
+ position = undefined,
61
+ } = action;
56
62
 
57
63
  if (shouldCheckErrors) {
58
64
  draftState.shouldCheckErrors = !state.shouldCheckErrors;
@@ -62,7 +68,15 @@ const reducer = (state, action) =>
62
68
  draftState.modifiedDZName = keys[0];
63
69
  }
64
70
 
65
- const currentValue = get(state, ['modifiedData', ...keys], []);
71
+ const currentValue = [...get(state, ['modifiedData', ...keys], [])];
72
+
73
+ let actualPosition = position;
74
+
75
+ if (actualPosition === undefined) {
76
+ actualPosition = currentValue.length;
77
+ } else if (actualPosition < 0) {
78
+ actualPosition = 0;
79
+ }
66
80
 
67
81
  const defaultDataStructure =
68
82
  action.type === 'ADD_COMPONENT_TO_DYNAMIC_ZONE'
@@ -87,11 +101,9 @@ const reducer = (state, action) =>
87
101
  componentLayoutData.attributes
88
102
  );
89
103
 
90
- const newValue = Array.isArray(currentValue)
91
- ? [...currentValue, componentDataStructure]
92
- : [componentDataStructure];
104
+ currentValue.splice(actualPosition, 0, componentDataStructure);
93
105
 
94
- set(draftState, ['modifiedData', ...keys], newValue);
106
+ set(draftState, ['modifiedData', ...keys], currentValue);
95
107
 
96
108
  break;
97
109
  }
@@ -12,14 +12,7 @@ import Wysiwyg from '../Wysiwyg';
12
12
  import InputUID from '../InputUID';
13
13
  import { RelationInputDataManager } from '../RelationInputDataManager';
14
14
 
15
- import {
16
- connect,
17
- generateOptions,
18
- getInputType,
19
- getStep,
20
- select,
21
- VALIDATIONS_TO_OMIT,
22
- } from './utils';
15
+ import { connect, generateOptions, getInputType, select, VALIDATIONS_TO_OMIT } from './utils';
23
16
 
24
17
  function Inputs({
25
18
  allowedFields,
@@ -93,9 +86,7 @@ function Inputs({
93
86
  return value;
94
87
  }, [type, value]);
95
88
 
96
- const step = useMemo(() => {
97
- return getStep(type);
98
- }, [type]);
89
+ const step = getStep(type);
99
90
 
100
91
  const isUserAllowedToEditField = useMemo(() => {
101
92
  const joinedName = fieldName.join('.');
@@ -184,6 +175,9 @@ function Inputs({
184
175
 
185
176
  let minutes;
186
177
 
178
+ /**
179
+ * Wtf is this?
180
+ */
187
181
  if (inputType === 'datetime') {
188
182
  minutes = parseInt(inputValue.substr(14, 2), 10);
189
183
  } else if (inputType === 'time') {
@@ -316,6 +310,19 @@ Inputs.propTypes = {
316
310
  customFieldInputs: PropTypes.object,
317
311
  };
318
312
 
313
+ const getStep = (type) => {
314
+ switch (type) {
315
+ case 'float':
316
+ case 'decimal':
317
+ return 0.01;
318
+ case 'time':
319
+ case 'datetime':
320
+ return 15;
321
+ default:
322
+ return 1;
323
+ }
324
+ };
325
+
319
326
  const Memoized = memo(Inputs, isEqual);
320
327
 
321
328
  export default connect(Memoized, select);
@@ -1,6 +1,5 @@
1
1
  export { default as connect } from './connect';
2
2
  export { default as generateOptions } from './generateOptions';
3
3
  export { default as getInputType } from './getInputType';
4
- export { default as getStep } from './getStep';
5
4
  export { default as select } from './select';
6
5
  export { default as VALIDATIONS_TO_OMIT } from './VALIDATIONS_TO_OMIT';
@@ -25,6 +25,12 @@ const CustomLink = styled(Flex)`
25
25
  > div:first-child {
26
26
  background: ${({ theme }) => theme.colors.primary200};
27
27
  color: ${({ theme }) => theme.colors.primary600};
28
+
29
+ svg {
30
+ path {
31
+ fill: ${({ theme }) => theme.colors.primary600};
32
+ }
33
+ }
28
34
  }
29
35
  }
30
36
  `;
@@ -49,7 +55,7 @@ const DynamicZoneList = ({ components }) => {
49
55
  as={Link}
50
56
  to={`/content-manager/components/${componentUid}/configurations/edit`}
51
57
  >
52
- <ComponentIcon />
58
+ <ComponentIcon icon={componentLayouts?.[componentUid]?.info?.icon} />
53
59
 
54
60
  <Box paddingTop={1}>
55
61
  <Typography fontSize={1} textColor="neutral600" fontWeight="bold">
@@ -13,7 +13,7 @@ import { Pencil, Layer } from '@strapi/icons';
13
13
  import InformationBox from 'ee_else_ce/content-manager/pages/EditView/InformationBox';
14
14
  import { InjectionZone } from '../../../shared/components';
15
15
  import permissions from '../../../permissions';
16
- import DynamicZone from '../../components/DynamicZone';
16
+ import { DynamicZone } from '../../components/DynamicZone';
17
17
  import CollectionTypeFormWrapper from '../../components/CollectionTypeFormWrapper';
18
18
  import EditViewDataManagerProvider from '../../components/EditViewDataManagerProvider';
19
19
  import SingleTypeFormWrapper from '../../components/SingleTypeFormWrapper';
@@ -2,8 +2,6 @@ import { useAPIErrorHandler, useFetchClient, useNotification } from '@strapi/hel
2
2
  import { useQueries } from 'react-query';
3
3
 
4
4
  export function useContentTypes() {
5
- console.log('----> read');
6
-
7
5
  const { get } = useFetchClient();
8
6
  const { formatAPIError } = useAPIErrorHandler();
9
7
  const toggleNotification = useNotification();
@@ -1,7 +1,7 @@
1
- import ReactDOM from 'react-dom';
2
1
  import { getFetchClient } from '@strapi/helper-plugin';
3
- import { Components, Fields, Middlewares, Reducers } from './core/apis';
2
+ import { createRoot } from 'react-dom/client';
4
3
  import appCustomisations from './app';
4
+ import { Components, Fields, Middlewares, Reducers } from './core/apis';
5
5
  // eslint-disable-next-line import/extensions
6
6
  import plugins from './plugins';
7
7
  import appReducers from './reducers';
@@ -68,7 +68,8 @@ const run = async () => {
68
68
 
69
69
  await app.loadTrads();
70
70
 
71
- ReactDOM.render(app.render(), MOUNT_NODE);
71
+ const root = createRoot(MOUNT_NODE);
72
+ root.render(app.render());
72
73
  };
73
74
 
74
75
  run();
@@ -47,7 +47,7 @@ const ListPage = () => {
47
47
  pagination,
48
48
  isError,
49
49
  isLoading,
50
- refetchQueries: refetchAdminUsers,
50
+ refetch: refetchAdminUsers,
51
51
  } = useAdminUsers(qs.parse(search, { ignoreQueryPrefix: true }), {
52
52
  enabled: canRead,
53
53
  });
@@ -0,0 +1,13 @@
1
+ import React from 'react';
2
+
3
+ import EventTable from '../Events';
4
+
5
+ // This component is overwritten by the EE counterpart
6
+ export function EventTableCE() {
7
+ return (
8
+ <EventTable.Root>
9
+ <EventTable.Headers />
10
+ <EventTable.Body />
11
+ </EventTable.Root>
12
+ );
13
+ }
@@ -0,0 +1,3 @@
1
+ import { EventTableCE } from './EventTableCE';
2
+
3
+ export default EventTableCE;