@strapi/admin 4.6.1 → 4.9.0-alpha.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 (196) hide show
  1. package/admin/src/assets/images/onboarding-preview.png +0 -0
  2. package/admin/src/content-manager/components/CollectionTypeFormWrapper/index.js +4 -14
  3. package/admin/src/content-manager/components/DynamicTable/CellContent/RelationMultiple/index.js +1 -1
  4. package/admin/src/content-manager/components/DynamicZone/components/DynamicComponent.js +2 -0
  5. package/admin/src/content-manager/components/EditViewDataManagerProvider/reducer.js +39 -9
  6. package/admin/src/content-manager/components/EditViewDataManagerProvider/utils/cleanData.js +9 -15
  7. package/admin/src/content-manager/components/SingleTypeFormWrapper/index.js +4 -12
  8. package/admin/src/content-manager/pages/EditView/DeleteLink/index.js +6 -8
  9. package/admin/src/content-manager/pages/ListView/index.js +6 -11
  10. package/admin/src/index.js +1 -0
  11. package/admin/src/pages/Admin/Onboarding/constants.js +46 -0
  12. package/admin/src/pages/Admin/Onboarding/index.js +161 -89
  13. package/admin/src/pages/Admin/index.js +5 -2
  14. package/admin/src/pages/SettingsPage/components/SettingsNav/index.js +15 -2
  15. package/admin/src/pages/SettingsPage/pages/Users/components/MagicLink/MagicLinkWrapper.js +3 -20
  16. package/admin/src/permissions/defaultPermissions.js +2 -15
  17. package/admin/src/translations/ar.json +4 -4
  18. package/admin/src/translations/ca.json +4 -4
  19. package/admin/src/translations/cs.json +4 -4
  20. package/admin/src/translations/de.json +4 -4
  21. package/admin/src/translations/dk.json +4 -4
  22. package/admin/src/translations/en.json +14 -5
  23. package/admin/src/translations/es.json +4 -4
  24. package/admin/src/translations/eu.json +4 -4
  25. package/admin/src/translations/fr.json +4 -4
  26. package/admin/src/translations/gu.json +4 -4
  27. package/admin/src/translations/he.json +4 -4
  28. package/admin/src/translations/hi.json +4 -4
  29. package/admin/src/translations/hu.json +4 -4
  30. package/admin/src/translations/id.json +4 -4
  31. package/admin/src/translations/it.json +4 -4
  32. package/admin/src/translations/ja.json +4 -4
  33. package/admin/src/translations/ko.json +4 -4
  34. package/admin/src/translations/ml.json +4 -4
  35. package/admin/src/translations/ms.json +4 -4
  36. package/admin/src/translations/nl.json +4 -4
  37. package/admin/src/translations/no.json +4 -4
  38. package/admin/src/translations/pl.json +4 -4
  39. package/admin/src/translations/pt-BR.json +4 -4
  40. package/admin/src/translations/pt.json +4 -4
  41. package/admin/src/translations/ru.json +785 -789
  42. package/admin/src/translations/sa.json +4 -4
  43. package/admin/src/translations/sk.json +4 -4
  44. package/admin/src/translations/sv.json +4 -4
  45. package/admin/src/translations/th.json +4 -4
  46. package/admin/src/translations/tr.json +4 -4
  47. package/admin/src/translations/uk.json +4 -4
  48. package/admin/src/translations/vi.json +4 -4
  49. package/admin/src/translations/zh-Hans.json +4 -4
  50. package/admin/src/translations/zh.json +4 -4
  51. package/build/1683.d59d0f23.chunk.js +268 -0
  52. package/build/19eb2dfcf2603eb55733.png +0 -0
  53. package/build/{4855.bd092921.chunk.js → 2223.1bfea951.chunk.js} +88 -88
  54. package/build/2743.646a1015.chunk.js +45 -0
  55. package/build/3075.3ee481f1.chunk.js +108 -0
  56. package/build/3632.2e378cf8.chunk.js +138 -0
  57. package/build/{4318.f96a9d4d.chunk.js → 4318.cd55ce02.chunk.js} +1 -1
  58. package/build/9707.b36ed71e.chunk.js +96 -0
  59. package/build/Admin-authenticatedApp.a73577e1.chunk.js +79 -0
  60. package/build/{Admin_InternalErrorPage.157152a8.chunk.js → Admin_InternalErrorPage.178ddb90.chunk.js} +1 -1
  61. package/build/{Admin_homePage.b1730882.chunk.js → Admin_homePage.c2f5f27d.chunk.js} +2 -2
  62. package/build/{Admin_marketplace.ea0316c2.chunk.js → Admin_marketplace.1df49c42.chunk.js} +1 -1
  63. package/build/{Admin_pluginsPage.5c24f963.chunk.js → Admin_pluginsPage.8d824408.chunk.js} +2 -2
  64. package/build/{Admin_profilePage.59af1978.chunk.js → Admin_profilePage.cb667bc5.chunk.js} +2 -2
  65. package/build/Admin_settingsPage.f90615fb.chunk.js +178 -0
  66. package/build/{Upload_ConfigureTheView.3f2b6e6a.chunk.js → Upload_ConfigureTheView.d306009d.chunk.js} +1 -1
  67. package/build/admin-app.06f07029.chunk.js +112 -0
  68. package/build/admin-edit-roles-page.35199b9d.chunk.js +1 -0
  69. package/build/admin-edit-users.9e48b00d.chunk.js +10 -0
  70. package/build/admin-users.cf7b4151.chunk.js +11 -0
  71. package/build/{api-tokens-create-page.d248362d.chunk.js → api-tokens-create-page.a31c7fba.chunk.js} +1 -1
  72. package/build/{api-tokens-edit-page.8516fa20.chunk.js → api-tokens-edit-page.64fef287.chunk.js} +1 -1
  73. package/build/{api-tokens-list-page.44a79fda.chunk.js → api-tokens-list-page.e600ad3e.chunk.js} +2 -2
  74. package/build/ar-json.39e54aba.chunk.js +1 -0
  75. package/build/{audit-logs-settings-page.c3dce30d.chunk.js → audit-logs-settings-page.d4da4579.chunk.js} +1 -1
  76. package/build/{ca-json.f6a0f472.chunk.js → ca-json.4d999055.chunk.js} +1 -1
  77. package/build/content-manager.255c3a59.chunk.js +1139 -0
  78. package/build/{content-type-builder-list-view.79e84b36.chunk.js → content-type-builder-list-view.8d7a3d68.chunk.js} +5 -5
  79. package/build/content-type-builder.3c8558a5.chunk.js +126 -0
  80. package/build/cs-json.4b44411c.chunk.js +1 -0
  81. package/build/{de-json.30e1f35b.chunk.js → de-json.866f8a28.chunk.js} +1 -1
  82. package/build/{dk-json.e6d9ffa4.chunk.js → dk-json.10f7b1d1.chunk.js} +1 -1
  83. package/build/email-settings-page.b19f2eb2.chunk.js +10 -0
  84. package/build/en-json.1997583c.chunk.js +1 -0
  85. package/build/es-json.ea15c957.chunk.js +1 -0
  86. package/build/{eu-json.fceecd8b.chunk.js → eu-json.3bc24d60.chunk.js} +1 -1
  87. package/build/{fr-json.78545ef8.chunk.js → fr-json.e88fbdfd.chunk.js} +1 -1
  88. package/build/{gu-json.676518f2.chunk.js → gu-json.94f0d242.chunk.js} +1 -1
  89. package/build/{he-json.ad22e8cc.chunk.js → he-json.f0de8cdb.chunk.js} +1 -1
  90. package/build/{hi-json.19b51c09.chunk.js → hi-json.df3a7be2.chunk.js} +1 -1
  91. package/build/{hu-json.f947088f.chunk.js → hu-json.680e6eef.chunk.js} +1 -1
  92. package/build/{i18n-settings-page.b8d8753e.chunk.js → i18n-settings-page.a6b49eac.chunk.js} +1 -1
  93. package/build/{id-json.504daa84.chunk.js → id-json.e0d83d41.chunk.js} +1 -1
  94. package/build/index.html +1 -1
  95. package/build/{it-json.2fd90f4d.chunk.js → it-json.8be59205.chunk.js} +1 -1
  96. package/build/{ja-json.c9f12d0b.chunk.js → ja-json.97ee41ba.chunk.js} +1 -1
  97. package/build/{ko-json.ef463065.chunk.js → ko-json.4cbbf4f2.chunk.js} +1 -1
  98. package/build/main.7f308c20.js +4322 -0
  99. package/build/{ml-json.490f666c.chunk.js → ml-json.e3747091.chunk.js} +1 -1
  100. package/build/ms-json.0eddffd9.chunk.js +1 -0
  101. package/build/{nl-json.c416295a.chunk.js → nl-json.371a15ee.chunk.js} +1 -1
  102. package/build/{no-json.1a2258ba.chunk.js → no-json.9b3cd181.chunk.js} +1 -1
  103. package/build/{pl-json.8cf0c871.chunk.js → pl-json.e535cbce.chunk.js} +1 -1
  104. package/build/{pt-BR-json.51fab8d0.chunk.js → pt-BR-json.e5fafa46.chunk.js} +1 -1
  105. package/build/pt-json.ee554a41.chunk.js +1 -0
  106. package/build/review-workflows-settings.7b4be1b0.chunk.js +63 -0
  107. package/build/{ru-json.aa5cd123.chunk.js → ru-json.866f0ff1.chunk.js} +1 -1
  108. package/build/runtime~main.bf374148.js +2 -0
  109. package/build/{sa-json.f3fa5407.chunk.js → sa-json.7efeb257.chunk.js} +1 -1
  110. package/build/{sk-json.9ec60d9f.chunk.js → sk-json.7bbeb0af.chunk.js} +1 -1
  111. package/build/{sso-settings-page.b85ad080.chunk.js → sso-settings-page.ad2143dd.chunk.js} +1 -1
  112. package/build/{sv-json.c6b0c237.chunk.js → sv-json.dc40951f.chunk.js} +1 -1
  113. package/build/{th-json.6e68155c.chunk.js → th-json.f664b96d.chunk.js} +1 -1
  114. package/build/{tr-json.9f41dc08.chunk.js → tr-json.b79eae31.chunk.js} +1 -1
  115. package/build/uk-json.b7e38370.chunk.js +1 -0
  116. package/build/upload-settings.eb1a7908.chunk.js +84 -0
  117. package/build/upload.700e2c84.chunk.js +33 -0
  118. package/build/{users-advanced-settings-page.fce9908e.chunk.js → users-advanced-settings-page.aae212f2.chunk.js} +1 -1
  119. package/build/{users-email-settings-page.343d0ad2.chunk.js → users-email-settings-page.8a9b0da1.chunk.js} +1 -1
  120. package/build/{users-providers-settings-page.e5a9a3f1.chunk.js → users-providers-settings-page.e6be909d.chunk.js} +10 -10
  121. package/build/{users-roles-settings-page.66312f31.chunk.js → users-roles-settings-page.97d06a80.chunk.js} +3 -3
  122. package/build/vi-json.ee4c5537.chunk.js +1 -0
  123. package/build/webhook-edit-page.9eb0f789.chunk.js +75 -0
  124. package/build/webhook-list-page.66082323.chunk.js +42 -0
  125. package/build/{zh-Hans-json.9c0eac99.chunk.js → zh-Hans-json.30a18940.chunk.js} +1 -1
  126. package/build/{zh-json.f88f563d.chunk.js → zh-json.49d84433.chunk.js} +1 -1
  127. package/ee/admin/hooks/useSettingsMenu/utils/customAdminLinks.js +12 -12
  128. package/ee/admin/hooks/useSettingsMenu/utils/customGlobalLinks.js +21 -13
  129. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/ReviewWorkflows.js +137 -0
  130. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/actions/index.js +42 -0
  131. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/components/AddStage/AddStage.js +87 -0
  132. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/components/AddStage/index.js +1 -0
  133. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/components/Stages/Stage/Stage.js +90 -0
  134. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/components/Stages/Stage/index.js +1 -0
  135. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/components/Stages/Stages.js +77 -0
  136. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/components/Stages/index.js +1 -0
  137. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/constants.js +6 -0
  138. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/hooks/useReviewWorkflows.js +63 -0
  139. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/index.js +3 -0
  140. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/reducer/index.js +102 -0
  141. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/utils/getWorkflowValidationSchema.js +25 -0
  142. package/ee/admin/pages/SettingsPage/utils/customRoutes.js +16 -2
  143. package/ee/admin/permissions/customPermissions.js +7 -0
  144. package/ee/server/bootstrap.js +7 -1
  145. package/ee/server/config/admin-actions.js +10 -0
  146. package/ee/server/constants/default-stages.json +14 -0
  147. package/ee/server/constants/default-workflow.json +1 -0
  148. package/ee/server/constants/workflows.js +7 -0
  149. package/ee/server/content-types/index.js +9 -0
  150. package/ee/server/content-types/workflow/index.js +34 -0
  151. package/ee/server/content-types/workflow-stage/index.js +36 -0
  152. package/ee/server/controllers/index.js +2 -0
  153. package/ee/server/controllers/workflows/index.js +36 -0
  154. package/ee/server/controllers/workflows/stages/index.js +57 -0
  155. package/ee/server/index.js +1 -0
  156. package/ee/server/routes/index.js +87 -0
  157. package/ee/server/services/index.js +3 -0
  158. package/ee/server/services/review-workflows/review-workflows.js +54 -0
  159. package/ee/server/services/review-workflows/stages.js +133 -0
  160. package/ee/server/services/review-workflows/workflows.js +25 -0
  161. package/ee/server/utils/index.js +8 -0
  162. package/ee/server/utils/test.js +11 -0
  163. package/ee/server/validation/review-workflows.js +17 -0
  164. package/package.json +15 -15
  165. package/server/config/admin-actions.js +0 -16
  166. package/server/controllers/admin.js +0 -55
  167. package/server/routes/admin.js +0 -28
  168. package/webpack.config.js +0 -3
  169. package/build/1683.c8aa7b7c.chunk.js +0 -268
  170. package/build/2743.6d1632f9.chunk.js +0 -45
  171. package/build/3075.dc3894fe.chunk.js +0 -108
  172. package/build/3632.0317b618.chunk.js +0 -138
  173. package/build/9707.7290fd92.chunk.js +0 -96
  174. package/build/Admin-authenticatedApp.ce646f66.chunk.js +0 -75
  175. package/build/Admin_settingsPage.d1493824.chunk.js +0 -178
  176. package/build/admin-app.25934eaa.chunk.js +0 -112
  177. package/build/admin-edit-roles-page.446b69dc.chunk.js +0 -1
  178. package/build/admin-edit-users.2ed69bfd.chunk.js +0 -10
  179. package/build/admin-users.fc003b10.chunk.js +0 -11
  180. package/build/ar-json.932794f7.chunk.js +0 -1
  181. package/build/content-manager.35ff9726.chunk.js +0 -1139
  182. package/build/content-type-builder.855db321.chunk.js +0 -126
  183. package/build/cs-json.79879fb6.chunk.js +0 -1
  184. package/build/email-settings-page.d1fcc7a3.chunk.js +0 -10
  185. package/build/en-json.1f137a90.chunk.js +0 -1
  186. package/build/es-json.e275481d.chunk.js +0 -1
  187. package/build/main.7b151630.js +0 -4377
  188. package/build/ms-json.db87d8d3.chunk.js +0 -1
  189. package/build/pt-json.62927d1e.chunk.js +0 -1
  190. package/build/runtime~main.a20d633b.js +0 -2
  191. package/build/uk-json.b2fcd567.chunk.js +0 -1
  192. package/build/upload-settings.ef64bbf9.chunk.js +0 -84
  193. package/build/upload.c5730dfa.chunk.js +0 -33
  194. package/build/vi-json.f08d7d03.chunk.js +0 -1
  195. package/build/webhook-edit-page.73e51e64.chunk.js +0 -75
  196. package/build/webhook-list-page.1134f130.chunk.js +0 -42
@@ -10,6 +10,7 @@ import {
10
10
  formatContentTypeData,
11
11
  contentManagementUtilRemoveFieldsFromData,
12
12
  useGuidedTour,
13
+ useAPIErrorHandler,
13
14
  useFetchClient,
14
15
  } from '@strapi/helper-plugin';
15
16
  import { useSelector, useDispatch } from 'react-redux';
@@ -45,6 +46,7 @@ const CollectionTypeFormWrapper = ({ allLayoutData, children, slug, id, origin }
45
46
  const { componentsDataStructure, contentTypeDataStructure, data, isLoading, status } =
46
47
  useSelector(selectCrudReducer);
47
48
  const redirectionLink = useFindRedirectionLink(slug);
49
+ const { formatAPIError } = useAPIErrorHandler(getTrad);
48
50
 
49
51
  const isMounted = useRef(true);
50
52
  const trackUsageRef = useRef(trackUsage);
@@ -148,8 +150,6 @@ const CollectionTypeFormWrapper = ({ allLayoutData, children, slug, id, origin }
148
150
  return;
149
151
  }
150
152
 
151
- console.error(err);
152
-
153
153
  const resStatus = get(err, 'response.status', null);
154
154
 
155
155
  if (resStatus === 404) {
@@ -203,19 +203,9 @@ const CollectionTypeFormWrapper = ({ allLayoutData, children, slug, id, origin }
203
203
 
204
204
  const displayErrors = useCallback(
205
205
  (err) => {
206
- const errorPayload = err.response.data;
207
- let errorMessage = get(errorPayload, ['error', 'message'], 'Bad Request');
208
-
209
- // TODO handle errors correctly when back-end ready
210
- if (Array.isArray(errorMessage)) {
211
- errorMessage = get(errorMessage, ['0', 'messages', '0', 'id']);
212
- }
213
-
214
- if (typeof errorMessage === 'string') {
215
- toggleNotification({ type: 'warning', message: errorMessage });
216
- }
206
+ toggleNotification({ type: 'warning', message: formatAPIError(err) });
217
207
  },
218
- [toggleNotification]
208
+ [toggleNotification, formatAPIError]
219
209
  );
220
210
 
221
211
  const onDelete = useCallback(
@@ -67,7 +67,7 @@ const RelationMultiple = ({ fieldSchema, metadatas, name, entityId, value, conte
67
67
  staleTime: 0,
68
68
  select: (data) => ({
69
69
  ...data,
70
- results: data.results.reverse(),
70
+ results: [...data.results].reverse(),
71
71
  }),
72
72
  }
73
73
  );
@@ -42,6 +42,8 @@ const IconButtonCustom = styled(IconButton)`
42
42
  }
43
43
  `;
44
44
 
45
+ // TODO: Delete once https://github.com/strapi/design-system/pull/858
46
+ // is merged and released.
45
47
  const StyledBox = styled(Box)`
46
48
  > div:first-child {
47
49
  box-shadow: ${({ theme }) => theme.shadows.tableShadow};
@@ -8,6 +8,7 @@ import uniqBy from 'lodash/uniqBy';
8
8
  import merge from 'lodash/merge';
9
9
  import castArray from 'lodash/castArray';
10
10
  import isNil from 'lodash/isNil';
11
+ import { generateNKeysBetween } from 'fractional-indexing';
11
12
 
12
13
  import {
13
14
  findLeafByPathAndReplace,
@@ -155,17 +156,33 @@ const reducer = (state, action) =>
155
156
  const initialDataRelations = get(state, initialDataPath);
156
157
  const modifiedDataRelations = get(state, modifiedDataPath);
157
158
 
158
- /**
159
- * Check if the values we're loading are already in initial
160
- * data if they are then we don't need to load them at all
161
- */
162
159
  const valuesToLoad = value.filter((relation) => {
163
160
  return !initialDataRelations.some((initialDataRelation) => {
164
161
  return initialDataRelation.id === relation.id;
165
162
  });
166
163
  });
167
164
 
168
- set(draftState, initialDataPath, uniqBy([...valuesToLoad, ...initialDataRelations], 'id'));
165
+ const keys = generateNKeysBetween(
166
+ null,
167
+ modifiedDataRelations[0]?.__temp_key__,
168
+ valuesToLoad.length
169
+ );
170
+
171
+ /**
172
+ * Check if the values we're loading are already in initial
173
+ * data if they are then we don't need to load them at all
174
+ */
175
+
176
+ const valuesWithKeys = valuesToLoad.map((relation, index) => ({
177
+ ...relation,
178
+ __temp_key__: keys[index],
179
+ }));
180
+
181
+ set(
182
+ draftState,
183
+ initialDataPath,
184
+ uniqBy([...valuesWithKeys, ...initialDataRelations], 'id')
185
+ );
169
186
 
170
187
  /**
171
188
  * We need to set the value also on modifiedData, because initialData
@@ -175,7 +192,7 @@ const reducer = (state, action) =>
175
192
  set(
176
193
  draftState,
177
194
  modifiedDataPath,
178
- uniqBy([...valuesToLoad, ...modifiedDataRelations], 'id')
195
+ uniqBy([...valuesWithKeys, ...modifiedDataRelations], 'id')
179
196
  );
180
197
 
181
198
  break;
@@ -192,7 +209,9 @@ const reducer = (state, action) =>
192
209
  set(draftState, path, [value]);
193
210
  } else {
194
211
  const modifiedDataRelations = get(state, path);
195
- const newRelations = [...modifiedDataRelations, value];
212
+ const [key] = generateNKeysBetween(modifiedDataRelations.at(-1)?.__temp_key__, null, 1);
213
+
214
+ const newRelations = [...modifiedDataRelations, { ...value, __temp_key__: key }];
196
215
  set(draftState, path, newRelations);
197
216
  }
198
217
 
@@ -219,8 +238,19 @@ const reducer = (state, action) =>
219
238
 
220
239
  const newRelations = [...modifiedDataRelations];
221
240
 
222
- newRelations.splice(oldIndex, 1);
223
- newRelations.splice(newIndex, 0, currentItem);
241
+ if (action.type === 'REORDER_RELATION') {
242
+ const [newKey] = generateNKeysBetween(
243
+ modifiedDataRelations[newIndex - 1]?.__temp_key__,
244
+ modifiedDataRelations[newIndex]?.__temp_key__,
245
+ 1
246
+ );
247
+
248
+ newRelations.splice(oldIndex, 1);
249
+ newRelations.splice(newIndex, 0, { ...currentItem, __temp_key__: newKey });
250
+ } else {
251
+ newRelations.splice(oldIndex, 1);
252
+ newRelations.splice(newIndex, 0, currentItem);
253
+ }
224
254
 
225
255
  set(draftState, path, newRelations);
226
256
 
@@ -95,28 +95,22 @@ const cleanData = ({ browserState, serverState }, currentSchema, componentsSchem
95
95
  */
96
96
  let actualOldValue = get(rootServerState, trueInitialDataPath, []);
97
97
 
98
- const valuesWithPositions = value.map((relation, index, allRelations) => {
99
- const nextRelation = allRelations[index + 1];
100
-
101
- if (nextRelation) {
102
- return { ...relation, position: { before: nextRelation.id } };
103
- }
104
-
105
- return { ...relation, position: { end: true } };
106
- });
107
-
108
98
  /**
109
99
  * Instead of the full relation object, we only want to send its ID
110
100
  * connectedRelations are the items that are in the browserState
111
101
  * array but not in the serverState
112
102
  */
113
- const connectedRelations = valuesWithPositions.reduce((acc, relation, currentIndex) => {
114
- const indexOfRelationOnServer = actualOldValue.findIndex(
103
+ const connectedRelations = value.reduce((acc, relation, currentIndex, array) => {
104
+ const relationOnServer = actualOldValue.find(
115
105
  (oldRelation) => oldRelation.id === relation.id
116
106
  );
117
107
 
118
- if (indexOfRelationOnServer === -1 || indexOfRelationOnServer !== currentIndex) {
119
- return [...acc, { id: relation.id, position: relation.position }];
108
+ const relationInFront = array[currentIndex + 1];
109
+
110
+ if (!relationOnServer || relationOnServer.__temp_key__ !== relation.__temp_key__) {
111
+ const position = relationInFront ? { before: relationInFront.id } : { end: true };
112
+
113
+ return [...acc, { id: relation.id, position }];
120
114
  }
121
115
 
122
116
  return acc;
@@ -127,7 +121,7 @@ const cleanData = ({ browserState, serverState }, currentSchema, componentsSchem
127
121
  * are no longer in the browserState
128
122
  */
129
123
  const disconnectedRelations = actualOldValue.reduce((acc, relation) => {
130
- if (!valuesWithPositions.find((newRelation) => newRelation.id === relation.id)) {
124
+ if (!value.find((newRelation) => newRelation.id === relation.id)) {
131
125
  return [...acc, { id: relation.id }];
132
126
  }
133
127
 
@@ -8,6 +8,7 @@ import {
8
8
  useQueryParams,
9
9
  useNotification,
10
10
  useGuidedTour,
11
+ useAPIErrorHandler,
11
12
  useFetchClient,
12
13
  } from '@strapi/helper-plugin';
13
14
  import { useSelector, useDispatch } from 'react-redux';
@@ -39,6 +40,7 @@ const SingleTypeFormWrapper = ({ allLayoutData, children, slug }) => {
39
40
  const searchToSend = buildQueryString(query);
40
41
  const toggleNotification = useNotification();
41
42
  const dispatch = useDispatch();
43
+ const { formatAPIError } = useAPIErrorHandler(getTrad);
42
44
  const fetchClient = useFetchClient();
43
45
  const { post, put, del } = fetchClient;
44
46
 
@@ -151,19 +153,9 @@ const SingleTypeFormWrapper = ({ allLayoutData, children, slug }) => {
151
153
 
152
154
  const displayErrors = useCallback(
153
155
  (err) => {
154
- const errorPayload = err.response.data;
155
- let errorMessage = get(errorPayload, ['error', 'message'], 'Bad Request');
156
-
157
- // TODO handle errors correctly when back-end ready
158
- if (Array.isArray(errorMessage)) {
159
- errorMessage = get(errorMessage, ['0', 'messages', '0', 'id']);
160
- }
161
-
162
- if (typeof errorMessage === 'string') {
163
- toggleNotification({ type: 'warning', message: errorMessage });
164
- }
156
+ toggleNotification({ type: 'warning', message: formatAPIError(err) });
165
157
  },
166
- [toggleNotification]
158
+ [toggleNotification, formatAPIError]
167
159
  );
168
160
 
169
161
  const onDelete = useCallback(
@@ -1,10 +1,9 @@
1
1
  import React, { memo, useState } from 'react';
2
2
  import { useIntl } from 'react-intl';
3
- import get from 'lodash/get';
4
3
  import isEqual from 'react-fast-compare';
5
4
  import { Button } from '@strapi/design-system/Button';
6
5
  import Trash from '@strapi/icons/Trash';
7
- import { ConfirmDialog, useNotification } from '@strapi/helper-plugin';
6
+ import { ConfirmDialog, useNotification, useAPIErrorHandler } from '@strapi/helper-plugin';
8
7
  import PropTypes from 'prop-types';
9
8
  import { getTrad } from '../../../utils';
10
9
  import { connect, select } from './utils';
@@ -13,6 +12,7 @@ const DeleteLink = ({ isCreatingEntry, onDelete, onDeleteSucceeded, trackerPrope
13
12
  const [showWarningDelete, setWarningDelete] = useState(false);
14
13
  const [isModalConfirmButtonLoading, setIsModalConfirmButtonLoading] = useState(false);
15
14
  const { formatMessage } = useIntl();
15
+ const { formatAPIError } = useAPIErrorHandler(getTrad);
16
16
  const toggleNotification = useNotification();
17
17
 
18
18
  const toggleWarningDelete = () => setWarningDelete((prevState) => !prevState);
@@ -29,14 +29,12 @@ const DeleteLink = ({ isCreatingEntry, onDelete, onDeleteSucceeded, trackerPrope
29
29
  toggleWarningDelete();
30
30
  onDeleteSucceeded();
31
31
  } catch (err) {
32
- const errorMessage = get(
33
- err,
34
- 'response.payload.message',
35
- formatMessage({ id: getTrad('error.record.delete') })
36
- );
37
32
  setIsModalConfirmButtonLoading(false);
38
33
  toggleWarningDelete();
39
- toggleNotification({ type: 'warning', message: errorMessage });
34
+ toggleNotification({
35
+ type: 'warning',
36
+ message: formatAPIError(err),
37
+ });
40
38
  }
41
39
  };
42
40
 
@@ -21,6 +21,7 @@ import {
21
21
  useRBACProvider,
22
22
  useTracking,
23
23
  Link,
24
+ useAPIErrorHandler,
24
25
  } from '@strapi/helper-plugin';
25
26
 
26
27
  import { IconButton } from '@strapi/design-system/IconButton';
@@ -84,6 +85,7 @@ function ListView({
84
85
  const trackUsageRef = useRef(trackUsage);
85
86
  const fetchPermissionsRef = useRef(refetchPermissions);
86
87
  const { notifyStatus } = useNotifyAT();
88
+ const { formatAPIError } = useAPIErrorHandler(getTrad);
87
89
 
88
90
  useFocusWhenNavigate();
89
91
 
@@ -148,7 +150,6 @@ function ListView({
148
150
  return;
149
151
  }
150
152
 
151
- console.error(err);
152
153
  toggleNotification({
153
154
  type: 'warning',
154
155
  message: { id: getTrad('error.model.fetch') },
@@ -171,11 +172,11 @@ function ListView({
171
172
  } catch (err) {
172
173
  toggleNotification({
173
174
  type: 'warning',
174
- message: { id: getTrad('error.record.delete') },
175
+ message: formatAPIError(err),
175
176
  });
176
177
  }
177
178
  },
178
- [fetchData, params, slug, toggleNotification, post]
179
+ [fetchData, params, slug, toggleNotification, formatAPIError, post]
179
180
  );
180
181
 
181
182
  const handleConfirmDeleteData = useCallback(
@@ -191,19 +192,13 @@ function ListView({
191
192
  message: { id: getTrad('success.record.delete') },
192
193
  });
193
194
  } catch (err) {
194
- const errorMessage = get(
195
- err,
196
- 'response.payload.message',
197
- formatMessage({ id: getTrad('error.record.delete') })
198
- );
199
-
200
195
  toggleNotification({
201
196
  type: 'warning',
202
- message: errorMessage,
197
+ message: formatAPIError(err),
203
198
  });
204
199
  }
205
200
  },
206
- [slug, params, fetchData, toggleNotification, formatMessage, del]
201
+ [slug, params, fetchData, toggleNotification, formatAPIError, del]
207
202
  );
208
203
 
209
204
  useEffect(() => {
@@ -13,6 +13,7 @@ window.strapi = {
13
13
  features: {
14
14
  SSO: 'sso',
15
15
  AUDIT_LOGS: 'audit-logs',
16
+ REVIEW_WORKFLOWS: 'review-workflows',
16
17
  },
17
18
  projectType: 'Community',
18
19
  };
@@ -0,0 +1,46 @@
1
+ import { Book, PaperPlane } from '@strapi/icons';
2
+
3
+ export const VIDEO_LINKS = [
4
+ {
5
+ label: {
6
+ id: 'app.components.Onboarding.link.build-content',
7
+ defaultMessage: 'Build a content architecture',
8
+ },
9
+ href: 'https://www.youtube.com/watch?v=G9GjN0RxhkE',
10
+ duration: '5:48',
11
+ },
12
+ {
13
+ label: {
14
+ id: 'app.components.Onboarding.link.manage-content',
15
+ defaultMessage: 'Add & manage content',
16
+ },
17
+ href: 'https://www.youtube.com/watch?v=DEZw4KbybAI',
18
+ duration: '3:18',
19
+ },
20
+ {
21
+ label: { id: 'app.components.Onboarding.link.manage-media', defaultMessage: 'Manage media' },
22
+ href: 'https://www.youtube.com/watch?v=-61MuiMQb38',
23
+ duration: '3:41',
24
+ },
25
+ ];
26
+
27
+ export const WATCH_MORE = {
28
+ href: 'https://www.youtube.com/playlist?list=PL7Q0DQYATmvidz6lEmwE5nIcOAYagxWqq',
29
+ label: {
30
+ id: 'app.components.Onboarding.link.more-videos',
31
+ defaultMessage: 'Watch more videos',
32
+ },
33
+ };
34
+
35
+ export const DOCUMENTATION_LINKS = [
36
+ {
37
+ label: { id: 'global.documentation', defaultMessage: 'documentation' },
38
+ href: 'https://docs.strapi.io',
39
+ icon: Book,
40
+ },
41
+ {
42
+ label: { id: 'app.static.links.cheatsheet', defaultMessage: 'cheatsheet' },
43
+ href: 'https://strapi-showcase.s3-us-west-2.amazonaws.com/CheatSheet.pdf',
44
+ icon: PaperPlane,
45
+ },
46
+ ];