@strapi/admin 4.11.0-exp.push-transfer-push-stuck → 4.11.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 (137) 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/DynamicTable/BulkActionsBar/index.js +307 -0
  6. package/admin/src/content-manager/components/DynamicTable/index.js +20 -4
  7. package/admin/src/content-manager/components/DynamicZone/components/AddComponentButton.js +32 -95
  8. package/admin/src/content-manager/components/DynamicZone/components/ComponentCard.js +10 -2
  9. package/admin/src/content-manager/components/DynamicZone/components/ComponentCategory.js +63 -15
  10. package/admin/src/content-manager/components/DynamicZone/components/ComponentPicker.js +50 -63
  11. package/admin/src/content-manager/components/DynamicZone/components/DynamicComponent.js +132 -58
  12. package/admin/src/content-manager/components/DynamicZone/components/DynamicZoneLabel.js +29 -37
  13. package/admin/src/content-manager/components/DynamicZone/index.js +131 -83
  14. package/admin/src/content-manager/components/EditViewDataManagerProvider/index.js +31 -8
  15. package/admin/src/content-manager/components/EditViewDataManagerProvider/reducer.js +18 -6
  16. package/admin/src/content-manager/components/EditViewDataManagerProvider/utils/index.js +0 -1
  17. package/admin/src/content-manager/components/Inputs/index.js +18 -11
  18. package/admin/src/content-manager/components/Inputs/utils/index.js +0 -1
  19. package/admin/src/content-manager/pages/EditSettingsView/components/DynamicZoneList.js +7 -1
  20. package/admin/src/content-manager/pages/EditView/index.js +1 -1
  21. package/admin/src/content-manager/pages/ListView/index.js +118 -2
  22. package/admin/src/content-manager/utils/index.js +2 -0
  23. package/admin/src/content-manager/{components/EditViewDataManagerProvider/utils → utils}/schema.js +1 -1
  24. package/admin/src/hooks/useContentTypes/useContentTypes.js +0 -2
  25. package/admin/src/index.js +4 -3
  26. package/admin/src/injectionZones.js +6 -1
  27. package/admin/src/pages/SettingsPage/pages/Users/ListPage/index.js +1 -1
  28. package/admin/src/pages/SettingsPage/pages/Webhooks/EditView/components/EventTable/EventTableCE.js +13 -0
  29. package/admin/src/pages/SettingsPage/pages/Webhooks/EditView/components/EventTable/index.js +3 -0
  30. package/admin/src/pages/SettingsPage/pages/Webhooks/EditView/components/Events/index.js +331 -0
  31. package/admin/src/pages/SettingsPage/pages/Webhooks/EditView/components/HeadersInput/Combobox.js +54 -4
  32. package/admin/src/pages/SettingsPage/pages/Webhooks/EditView/components/HeadersInput/index.js +12 -23
  33. package/admin/src/pages/SettingsPage/pages/Webhooks/EditView/components/WebhookForm/index.js +129 -116
  34. package/admin/src/pages/SettingsPage/pages/Webhooks/EditView/components/WebhookForm/utils/makeWebhookValidationSchema.js +62 -0
  35. package/admin/src/pages/SettingsPage/pages/Webhooks/EditView/index.js +59 -64
  36. package/admin/src/translations/ar.json +684 -1
  37. package/admin/src/translations/en.json +12 -1
  38. package/build/3562.e0b1a0b3.chunk.js +50 -0
  39. package/build/371.6e4e2c1f.chunk.js +71 -0
  40. package/build/5297.31c9ffdc.chunk.js +39 -0
  41. package/build/5542.64b623c9.chunk.js +63 -0
  42. package/build/{5563.79950369.chunk.js → 5563.badbffde.chunk.js} +2 -2
  43. package/build/6691.f7a3b5ac.chunk.js +105 -0
  44. package/build/6970.d456705f.chunk.js +1 -0
  45. package/build/{7259.5cc67413.chunk.js → 7259.5d0de931.chunk.js} +1 -1
  46. package/build/8976.0022f5a3.chunk.js +50 -0
  47. package/build/{1657.ca8562dd.chunk.js → 9932.5ef475c5.chunk.js} +54 -62
  48. package/build/Admin-authenticatedApp.ab2b5910.chunk.js +79 -0
  49. package/build/{Admin_InternalErrorPage.96ceaae1.chunk.js → Admin_InternalErrorPage.f25f04f3.chunk.js} +1 -1
  50. package/build/Admin_homePage.05063e43.chunk.js +73 -0
  51. package/build/Admin_marketplace.005d2d5b.chunk.js +55 -0
  52. package/build/Admin_pluginsPage.5d9d4060.chunk.js +6 -0
  53. package/build/{Admin_profilePage.a8fa3a56.chunk.js → Admin_profilePage.ab7b94d7.chunk.js} +2 -2
  54. package/build/Admin_settingsPage.07a6a5f0.chunk.js +79 -0
  55. package/build/{Upload_ConfigureTheView.aa64ed9a.chunk.js → Upload_ConfigureTheView.121deffb.chunk.js} +1 -1
  56. package/build/admin-app.7cc667be.chunk.js +63 -0
  57. package/build/{admin-edit-roles-page.0d12b741.chunk.js → admin-edit-roles-page.bfe3304d.chunk.js} +3 -3
  58. package/build/{admin-edit-users.f9ce7844.chunk.js → admin-edit-users.6efe0382.chunk.js} +2 -2
  59. package/build/admin-roles-list.b2577370.chunk.js +23 -0
  60. package/build/admin-users.4af49ccf.chunk.js +26 -0
  61. package/build/{api-tokens-create-page.973d2816.chunk.js → api-tokens-create-page.65411a36.chunk.js} +1 -1
  62. package/build/{api-tokens-edit-page.29725c5e.chunk.js → api-tokens-edit-page.60312cb6.chunk.js} +1 -1
  63. package/build/{api-tokens-list-page.66c4fbdd.chunk.js → api-tokens-list-page.01a4d5cd.chunk.js} +2 -2
  64. package/build/ar-json.f530bc3f.chunk.js +1 -0
  65. package/build/audit-logs-settings-page.b165679b.chunk.js +16 -0
  66. package/build/content-manager.8cc6c3f9.chunk.js +1094 -0
  67. package/build/content-type-builder-list-view.58f9ed20.chunk.js +211 -0
  68. package/build/{content-type-builder-translation-en-json.af293c9e.chunk.js → content-type-builder-translation-en-json.f592325b.chunk.js} +1 -1
  69. package/build/content-type-builder.baeb0413.chunk.js +132 -0
  70. package/build/email-settings-page.8caad83f.chunk.js +11 -0
  71. package/build/en-json.a8f34002.chunk.js +1 -0
  72. package/build/i18n-settings-page.579d5eab.chunk.js +9 -0
  73. package/build/i18n-translation-en-json.1ec7becf.chunk.js +1 -0
  74. package/build/index.html +1 -1
  75. package/build/main.1d678f7b.js +2926 -0
  76. package/build/{review-workflows-settings.56cab253.chunk.js → review-workflows-settings.3a7bae25.chunk.js} +2 -2
  77. package/build/{runtime~main.adbe36a4.js → runtime~main.9dbd4553.js} +2 -2
  78. package/build/{sso-settings-page.265e3d72.chunk.js → sso-settings-page.4bb073e0.chunk.js} +1 -1
  79. package/build/{transfer-tokens-create-page.170acee6.chunk.js → transfer-tokens-create-page.9ec277d7.chunk.js} +1 -1
  80. package/build/{transfer-tokens-edit-page.6cf23295.chunk.js → transfer-tokens-edit-page.fa5ade14.chunk.js} +1 -1
  81. package/build/{transfer-tokens-list-page.c3fec4c1.chunk.js → transfer-tokens-list-page.5d68d590.chunk.js} +2 -2
  82. package/build/upload-settings.2c1565d6.chunk.js +14 -0
  83. package/build/upload.257b2aef.chunk.js +26 -0
  84. package/build/users-advanced-settings-page.ddd29040.chunk.js +9 -0
  85. package/build/users-email-settings-page.717e2a51.chunk.js +24 -0
  86. package/build/users-providers-settings-page.c7eae829.chunk.js +29 -0
  87. package/build/{users-roles-settings-page.2549794b.chunk.js → users-roles-settings-page.63cf2838.chunk.js} +1 -1
  88. package/build/webhook-edit-page.8576742e.chunk.js +31 -0
  89. package/build/webhook-list-page.abf5747c.chunk.js +63 -0
  90. package/ee/admin/pages/SettingsPage/pages/Webhooks/EditView/components/EventTable/EventTableEE.js +23 -0
  91. package/ee/admin/pages/SettingsPage/pages/Webhooks/EditView/components/EventTable/index.js +3 -0
  92. package/ee/server/services/review-workflows/review-workflows.js +4 -0
  93. package/package.json +22 -24
  94. package/server/controllers/webhooks.js +6 -6
  95. package/admin/src/content-manager/components/DynamicTable/ConfirmDialogDeleteAll/index.js +0 -73
  96. package/admin/src/content-manager/components/DynamicZone/utils/connect.js +0 -12
  97. package/admin/src/content-manager/components/DynamicZone/utils/select.js +0 -53
  98. package/admin/src/content-manager/components/Inputs/utils/getStep.js +0 -13
  99. package/admin/src/pages/SettingsPage/pages/Webhooks/EditView/components/EventInput/EventRow.js +0 -70
  100. package/admin/src/pages/SettingsPage/pages/Webhooks/EditView/components/EventInput/index.js +0 -174
  101. package/admin/src/pages/SettingsPage/pages/Webhooks/EditView/components/HeadersInput/keys.js +0 -39
  102. package/admin/src/pages/SettingsPage/pages/Webhooks/EditView/components/utils/fieldsRegex.js +0 -4
  103. package/admin/src/pages/SettingsPage/pages/Webhooks/EditView/components/utils/schema.js +0 -35
  104. package/admin/src/pages/SettingsPage/pages/Webhooks/EditView/reducer.js +0 -100
  105. package/admin/src/pages/SettingsPage/pages/Webhooks/EditView/utils/formatData.js +0 -20
  106. package/build/3081.c2cdfac8.chunk.js +0 -108
  107. package/build/3816.60f858cf.chunk.js +0 -211
  108. package/build/462.a073ff1f.chunk.js +0 -71
  109. package/build/5542.002522eb.chunk.js +0 -71
  110. package/build/617.87b2fe96.chunk.js +0 -155
  111. package/build/6858.85d76858.chunk.js +0 -50
  112. package/build/6970.6a329e15.chunk.js +0 -1
  113. package/build/Admin-authenticatedApp.d425b485.chunk.js +0 -79
  114. package/build/Admin_homePage.107a9fe0.chunk.js +0 -73
  115. package/build/Admin_marketplace.717bd7ca.chunk.js +0 -55
  116. package/build/Admin_pluginsPage.7df6b5a9.chunk.js +0 -6
  117. package/build/Admin_settingsPage.1394aaf2.chunk.js +0 -79
  118. package/build/admin-app.ac5b1f59.chunk.js +0 -63
  119. package/build/admin-roles-list.e8bf9685.chunk.js +0 -31
  120. package/build/admin-users.751b28b2.chunk.js +0 -34
  121. package/build/ar-json.39e54aba.chunk.js +0 -1
  122. package/build/audit-logs-settings-page.3c6cea81.chunk.js +0 -129
  123. package/build/content-manager.70548048.chunk.js +0 -1123
  124. package/build/content-type-builder-list-view.1e821eb9.chunk.js +0 -215
  125. package/build/content-type-builder.b10576e7.chunk.js +0 -126
  126. package/build/email-settings-page.dba83275.chunk.js +0 -11
  127. package/build/en-json.d965e364.chunk.js +0 -1
  128. package/build/i18n-settings-page.55628f74.chunk.js +0 -114
  129. package/build/i18n-translation-en-json.60af6722.chunk.js +0 -1
  130. package/build/main.d9d9ed10.js +0 -2630
  131. package/build/upload-settings.63d99bf5.chunk.js +0 -14
  132. package/build/upload.c50d8c7a.chunk.js +0 -34
  133. package/build/users-advanced-settings-page.4f49ca57.chunk.js +0 -9
  134. package/build/users-email-settings-page.d2429d0a.chunk.js +0 -24
  135. package/build/users-providers-settings-page.50c5ba27.chunk.js +0 -29
  136. package/build/webhook-edit-page.ddd5963d.chunk.js +0 -128
  137. package/build/webhook-list-page.e2fca9f8.chunk.js +0 -71
@@ -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';
@@ -21,12 +22,13 @@ import {
21
22
  getAPIInnerErrors,
22
23
  } from '@strapi/helper-plugin';
23
24
 
24
- import { getTrad } from '../../utils';
25
+ import { createYupSchema, getTrad } from '../../utils';
25
26
 
26
27
  import selectCrudReducer from '../../sharedReducers/crudReducer/selectors';
27
28
 
28
29
  import reducer, { initialState } from './reducer';
29
- import { cleanData, createYupSchema } from './utils';
30
+ import { cleanData } from './utils';
31
+
30
32
  import { clearSetModifiedDataOnly } from '../../sharedReducers/crudReducer/actions';
31
33
  import { usePrev } from '../../hooks';
32
34
 
@@ -54,6 +56,7 @@ const EditViewDataManagerProvider = ({
54
56
  status,
55
57
  updateActionAllowedFields,
56
58
  }) => {
59
+ const [isSaving, setIsSaving] = React.useState(false);
57
60
  /**
58
61
  * TODO: this should be moved into the global reducer
59
62
  * to match ever other reducer in the CM.
@@ -193,14 +196,21 @@ const EditViewDataManagerProvider = ({
193
196
 
194
197
  const dispatchAddComponent = useCallback(
195
198
  (type) =>
196
- (keys, componentLayoutData, components, shouldCheckErrors = false) => {
199
+ (
200
+ keys,
201
+ componentLayoutData,
202
+ allComponents,
203
+ shouldCheckErrors = false,
204
+ position = undefined
205
+ ) => {
197
206
  trackUsageRef.current('didAddComponentToDynamicZone');
198
207
 
199
208
  dispatch({
200
209
  type,
201
210
  keys: keys.split('.'),
211
+ position,
202
212
  componentLayoutData,
203
- allComponents: components,
213
+ allComponents,
204
214
  shouldCheckErrors,
205
215
  });
206
216
  },
@@ -375,14 +385,20 @@ const EditViewDataManagerProvider = ({
375
385
  try {
376
386
  if (isEmpty(errors)) {
377
387
  const formData = createFormData(modifiedData, initialData);
388
+ flushSync(() => {
389
+ setIsSaving(true);
390
+ });
378
391
 
379
392
  if (isCreatingEntry) {
380
393
  await onPost(formData, trackerProperty);
381
394
  } else {
382
395
  await onPut(formData, trackerProperty);
383
396
  }
397
+
398
+ setIsSaving(false);
384
399
  }
385
400
  } catch (err) {
401
+ setIsSaving(false);
386
402
  errors = {
387
403
  ...errors,
388
404
  ...getAPIInnerErrors(err, { getTrad }),
@@ -444,9 +460,14 @@ const EditViewDataManagerProvider = ({
444
460
 
445
461
  try {
446
462
  if (isEmpty(errors)) {
463
+ flushSync(() => {
464
+ setIsSaving(true);
465
+ });
447
466
  await onPublish();
467
+ setIsSaving(false);
448
468
  }
449
469
  } catch (err) {
470
+ setIsSaving(false);
450
471
  errors = {
451
472
  ...errors,
452
473
  ...getAPIInnerErrors(err, { getTrad }),
@@ -638,10 +659,12 @@ const EditViewDataManagerProvider = ({
638
659
  </Main>
639
660
  ) : (
640
661
  <>
641
- <Prompt
642
- when={!isEqual(modifiedData, initialData)}
643
- message={formatMessage({ id: 'global.prompt.unsaved' })}
644
- />
662
+ {!isSaving ? (
663
+ <Prompt
664
+ when={!isEqual(modifiedData, initialData)}
665
+ message={formatMessage({ id: 'global.prompt.unsaved' })}
666
+ />
667
+ ) : null}
645
668
  <form noValidate onSubmit={handleSubmit}>
646
669
  {children}
647
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
  }
@@ -1,4 +1,3 @@
1
1
  export { default as moveFields } from './moveFields';
2
2
  export { default as cleanData } from './cleanData';
3
- export { default as createYupSchema } from './schema';
4
3
  export { findAllAndReplace } from './findAllAndReplace';
@@ -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';
@@ -21,6 +21,7 @@ import {
21
21
  useTracking,
22
22
  Link,
23
23
  useAPIErrorHandler,
24
+ getYupInnerErrors,
24
25
  } from '@strapi/helper-plugin';
25
26
 
26
27
  import {
@@ -35,6 +36,7 @@ import {
35
36
  } from '@strapi/design-system';
36
37
 
37
38
  import { ArrowLeft, Plus, Cog } from '@strapi/icons';
39
+ import { useMutation } from 'react-query';
38
40
 
39
41
  import DynamicTable from '../../components/DynamicTable';
40
42
  import AttributeFilter from '../../components/AttributeFilter';
@@ -42,7 +44,7 @@ import { InjectionZone } from '../../../shared/components';
42
44
 
43
45
  import permissions from '../../../permissions';
44
46
 
45
- import { getRequestUrl, getTrad } from '../../utils';
47
+ import { createYupSchema, getRequestUrl, getTrad } from '../../utils';
46
48
 
47
49
  import FieldPicker from './FieldPicker';
48
50
  import PaginationFooter from './PaginationFooter';
@@ -64,6 +66,7 @@ function ListView({
64
66
  canCreate,
65
67
  canDelete,
66
68
  canRead,
69
+ canPublish,
67
70
  data,
68
71
  getData,
69
72
  getDataSucceeded,
@@ -100,6 +103,50 @@ function ListView({
100
103
  const fetchClient = useFetchClient();
101
104
  const { post, del } = fetchClient;
102
105
 
106
+ const bulkPublishMutation = useMutation(
107
+ (data) =>
108
+ post(`/content-manager/collection-types/${contentType.uid}/actions/bulkPublish`, data),
109
+ {
110
+ onSuccess() {
111
+ toggleNotification({
112
+ type: 'success',
113
+ message: { id: 'content-manager.success.record.publish', defaultMessage: 'Published' },
114
+ });
115
+
116
+ fetchData(`/content-manager/collection-types/${slug}${params}`);
117
+ },
118
+ onError(error) {
119
+ toggleNotification({
120
+ type: 'warning',
121
+ message: formatAPIError(error),
122
+ });
123
+ },
124
+ }
125
+ );
126
+ const bulkUnpublishMutation = useMutation(
127
+ (data) =>
128
+ post(`/content-manager/collection-types/${contentType.uid}/actions/bulkUnpublish`, data),
129
+ {
130
+ onSuccess() {
131
+ toggleNotification({
132
+ type: 'success',
133
+ message: {
134
+ id: 'content-manager.success.record.unpublish',
135
+ defaultMessage: 'Unpublished',
136
+ },
137
+ });
138
+
139
+ fetchData(`/content-manager/collection-types/${slug}${params}`);
140
+ },
141
+ onError(error) {
142
+ toggleNotification({
143
+ type: 'warning',
144
+ message: formatAPIError(error),
145
+ });
146
+ },
147
+ }
148
+ );
149
+
103
150
  // FIXME
104
151
  // Using a ref to avoid requests being fired multiple times on slug on change
105
152
  // We need it because the hook as mulitple dependencies so it may run before the permissions have checked
@@ -199,6 +246,70 @@ function ListView({
199
246
  [slug, params, fetchData, toggleNotification, formatAPIError, del]
200
247
  );
201
248
 
249
+ /**
250
+ * @param {number[]} selectedEntries - Array of ids to publish
251
+ * @returns {{validIds: number[], errors: Object.<number, string>}} - Returns an object with the valid ids and the errors
252
+ */
253
+ const validateEntriesToPublish = async (selectedEntries) => {
254
+ const validations = { validIds: [], errors: {} };
255
+ // Create the validation schema based on the contentType
256
+ const schema = createYupSchema(
257
+ contentType,
258
+ { components: layout.components },
259
+ { isDraft: false }
260
+ );
261
+ // Get the selected entries
262
+ const entries = data.filter((entry) => {
263
+ return selectedEntries.includes(entry.id);
264
+ });
265
+ // Validate each entry and map the unresolved promises
266
+ const validationPromises = entries.map((entry) =>
267
+ schema.validate(entry, { abortEarly: false })
268
+ );
269
+ // Resolve all the promises in one go
270
+ const resolvedPromises = await Promise.allSettled(validationPromises);
271
+ // Set the validations
272
+ resolvedPromises.forEach((promise) => {
273
+ if (promise.status === 'rejected') {
274
+ const entityId = promise.reason.value.id;
275
+ validations.errors[entityId] = getYupInnerErrors(promise.reason);
276
+ }
277
+
278
+ if (promise.status === 'fulfilled') {
279
+ validations.validIds.push(promise.value.id);
280
+ }
281
+ });
282
+
283
+ return validations;
284
+ };
285
+
286
+ const handleConfirmPublishAllData = async (selectedEntries) => {
287
+ const validations = await validateEntriesToPublish(selectedEntries);
288
+
289
+ if (Object.values(validations.errors).length) {
290
+ toggleNotification({
291
+ type: 'warning',
292
+ title: {
293
+ id: 'content-manager.listView.validation.errors.title',
294
+ defaultMessage: 'Action required',
295
+ },
296
+ message: {
297
+ id: 'content-manager.listView.validation.errors.message',
298
+ defaultMessage:
299
+ 'Please make sure all fields are valid before publishing (required field, min/max character limit, etc.)',
300
+ },
301
+ });
302
+
303
+ throw new Error('Validation error');
304
+ }
305
+
306
+ return bulkPublishMutation.mutateAsync({ ids: selectedEntries });
307
+ };
308
+
309
+ const handleConfirmUnpublishAllData = (selectedEntries) => {
310
+ return bulkUnpublishMutation.mutateAsync({ ids: selectedEntries });
311
+ };
312
+
202
313
  useEffect(() => {
203
314
  const CancelToken = axios.CancelToken;
204
315
  const source = CancelToken.source();
@@ -330,9 +441,12 @@ function ListView({
330
441
  <DynamicTable
331
442
  canCreate={canCreate}
332
443
  canDelete={canDelete}
444
+ canPublish={canPublish}
333
445
  contentTypeName={headerLayoutTitle}
334
- onConfirmDeleteAll={handleConfirmDeleteAllData}
335
446
  onConfirmDelete={handleConfirmDeleteData}
447
+ onConfirmDeleteAll={handleConfirmDeleteAllData}
448
+ onConfirmPublishAll={handleConfirmPublishAllData}
449
+ onConfirmUnpublishAll={handleConfirmUnpublishAllData}
336
450
  isBulkable={isBulkable}
337
451
  isLoading={isLoading}
338
452
  // FIXME: remove the layout props drilling
@@ -354,10 +468,12 @@ ListView.propTypes = {
354
468
  canCreate: PropTypes.bool.isRequired,
355
469
  canDelete: PropTypes.bool.isRequired,
356
470
  canRead: PropTypes.bool.isRequired,
471
+ canPublish: PropTypes.bool.isRequired,
357
472
  data: PropTypes.array.isRequired,
358
473
  layout: PropTypes.exact({
359
474
  components: PropTypes.object.isRequired,
360
475
  contentType: PropTypes.shape({
476
+ uid: PropTypes.string.isRequired,
361
477
  attributes: PropTypes.object.isRequired,
362
478
  metadatas: PropTypes.object.isRequired,
363
479
  info: PropTypes.shape({ displayName: PropTypes.string.isRequired }).isRequired,
@@ -18,3 +18,5 @@ export { default as mergeMetasWithSchema } from './mergeMetasWithSchema';
18
18
 
19
19
  export { default as removeKeyInObject } from './removeKeyInObject';
20
20
  export { default as removePasswordFieldsFromData } from './removePasswordFieldsFromData';
21
+
22
+ export { default as createYupSchema } from './schema';
@@ -7,7 +7,7 @@ import toNumber from 'lodash/toNumber';
7
7
  import * as yup from 'yup';
8
8
  import { translatedErrors as errorsTrads } from '@strapi/helper-plugin';
9
9
 
10
- import isFieldTypeNumber from '../../../utils/isFieldTypeNumber';
10
+ import isFieldTypeNumber from './isFieldTypeNumber';
11
11
 
12
12
  yup.addMethod(yup.mixed, 'defined', function () {
13
13
  return this.test('defined', errorsTrads.required, (value) => value !== undefined);
@@ -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();
@@ -13,7 +13,12 @@ const injectionZones = {
13
13
  },
14
14
  contentManager: {
15
15
  editView: { informations: [], 'right-links': [] },
16
- listView: { actions: [], deleteModalAdditionalInfos: [] },
16
+ listView: {
17
+ actions: [],
18
+ deleteModalAdditionalInfos: [],
19
+ publishModalAdditionalInfos: [],
20
+ unpublishModalAdditionalInfos: [],
21
+ },
17
22
  },
18
23
  };
19
24
 
@@ -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;