@strapi/admin 4.7.0-beta.0 → 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 (257) hide show
  1. package/admin/src/content-manager/components/CollectionTypeFormWrapper/index.js +6 -14
  2. package/admin/src/content-manager/components/DynamicTable/CellContent/RelationMultiple/index.js +1 -1
  3. package/admin/src/content-manager/components/DynamicZone/components/DynamicComponent.js +2 -0
  4. package/admin/src/content-manager/components/EditViewDataManagerProvider/reducer.js +39 -9
  5. package/admin/src/content-manager/components/EditViewDataManagerProvider/utils/cleanData.js +9 -15
  6. package/admin/src/content-manager/components/SingleTypeFormWrapper/index.js +4 -12
  7. package/admin/src/content-manager/pages/EditView/DeleteLink/index.js +6 -8
  8. package/admin/src/content-manager/pages/ListView/index.js +6 -11
  9. package/admin/src/hooks/useRegenerate/index.js +2 -2
  10. package/admin/src/hooks/useSettingsMenu/utils/defaultGlobalLinks.js +0 -7
  11. package/admin/src/index.js +1 -0
  12. package/admin/src/pages/SettingsPage/components/SettingsNav/index.js +15 -2
  13. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/CollapsableContentType/index.js +3 -5
  14. package/admin/src/pages/SettingsPage/{components/Tokens/TokenBox → pages/ApiTokens/EditView/components/ContentBox}/index.js +17 -17
  15. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/FormApiTokenContainer/index.js +142 -52
  16. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/FormBody/index.js +78 -0
  17. package/admin/src/pages/SettingsPage/{components/Tokens → pages/ApiTokens/EditView/components}/FormHead/index.js +19 -36
  18. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/Regenerate/index.js +1 -5
  19. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/index.js +14 -37
  20. package/admin/src/pages/SettingsPage/{components/Tokens/Table → pages/ApiTokens/ListView/DynamicTable}/DefaultButton/index.js +1 -1
  21. package/admin/src/pages/SettingsPage/{components/Tokens/Table → pages/ApiTokens/ListView/DynamicTable}/DeleteButton/index.js +1 -1
  22. package/admin/src/pages/SettingsPage/{components/Tokens/Table → pages/ApiTokens/ListView/DynamicTable}/ReadButton/index.js +0 -0
  23. package/admin/src/pages/SettingsPage/{components/Tokens/Table → pages/ApiTokens/ListView/DynamicTable}/UpdateButton/index.js +0 -0
  24. package/admin/src/pages/SettingsPage/pages/ApiTokens/ListView/DynamicTable/index.js +112 -0
  25. package/admin/src/pages/SettingsPage/pages/ApiTokens/ListView/index.js +13 -5
  26. package/admin/src/pages/SettingsPage/pages/Users/components/MagicLink/MagicLinkWrapper.js +3 -20
  27. package/admin/src/pages/SettingsPage/utils/defaultRoutes.js +0 -33
  28. package/admin/src/permissions/defaultPermissions.js +2 -23
  29. package/admin/src/translations/ar.json +4 -4
  30. package/admin/src/translations/ca.json +4 -4
  31. package/admin/src/translations/cs.json +4 -4
  32. package/admin/src/translations/de.json +4 -4
  33. package/admin/src/translations/dk.json +4 -4
  34. package/admin/src/translations/en.json +9 -17
  35. package/admin/src/translations/es.json +4 -4
  36. package/admin/src/translations/eu.json +4 -4
  37. package/admin/src/translations/fr.json +4 -4
  38. package/admin/src/translations/gu.json +4 -4
  39. package/admin/src/translations/he.json +4 -4
  40. package/admin/src/translations/hi.json +4 -4
  41. package/admin/src/translations/hu.json +4 -4
  42. package/admin/src/translations/id.json +4 -4
  43. package/admin/src/translations/it.json +4 -4
  44. package/admin/src/translations/ja.json +4 -4
  45. package/admin/src/translations/ko.json +4 -4
  46. package/admin/src/translations/ml.json +4 -4
  47. package/admin/src/translations/ms.json +4 -4
  48. package/admin/src/translations/nl.json +4 -4
  49. package/admin/src/translations/no.json +4 -4
  50. package/admin/src/translations/pl.json +4 -4
  51. package/admin/src/translations/pt-BR.json +4 -4
  52. package/admin/src/translations/pt.json +4 -4
  53. package/admin/src/translations/ru.json +785 -789
  54. package/admin/src/translations/sa.json +4 -4
  55. package/admin/src/translations/sk.json +4 -4
  56. package/admin/src/translations/sv.json +4 -4
  57. package/admin/src/translations/th.json +4 -4
  58. package/admin/src/translations/tr.json +4 -4
  59. package/admin/src/translations/uk.json +4 -4
  60. package/admin/src/translations/vi.json +4 -4
  61. package/admin/src/translations/zh-Hans.json +4 -4
  62. package/admin/src/translations/zh.json +4 -4
  63. package/build/1683.d59d0f23.chunk.js +268 -0
  64. package/build/{4855.bd092921.chunk.js → 2223.1bfea951.chunk.js} +88 -88
  65. package/build/2743.646a1015.chunk.js +45 -0
  66. package/build/3075.3ee481f1.chunk.js +108 -0
  67. package/build/3632.2e378cf8.chunk.js +138 -0
  68. package/build/4318.cd55ce02.chunk.js +30 -0
  69. package/build/8633.00ccd382.chunk.js +1 -0
  70. package/build/9707.b36ed71e.chunk.js +96 -0
  71. package/build/{Admin-authenticatedApp.f29f6021.chunk.js → Admin-authenticatedApp.a73577e1.chunk.js} +2 -2
  72. package/build/{Admin_InternalErrorPage.157152a8.chunk.js → Admin_InternalErrorPage.178ddb90.chunk.js} +1 -1
  73. package/build/{Admin_homePage.b1730882.chunk.js → Admin_homePage.c2f5f27d.chunk.js} +2 -2
  74. package/build/{Admin_marketplace.ea0316c2.chunk.js → Admin_marketplace.1df49c42.chunk.js} +1 -1
  75. package/build/{Admin_pluginsPage.5c24f963.chunk.js → Admin_pluginsPage.8d824408.chunk.js} +2 -2
  76. package/build/{Admin_profilePage.59af1978.chunk.js → Admin_profilePage.cb667bc5.chunk.js} +2 -2
  77. package/build/Admin_settingsPage.f90615fb.chunk.js +178 -0
  78. package/build/{Upload_ConfigureTheView.3f2b6e6a.chunk.js → Upload_ConfigureTheView.d306009d.chunk.js} +1 -1
  79. package/build/admin-app.06f07029.chunk.js +112 -0
  80. package/build/admin-edit-roles-page.35199b9d.chunk.js +1 -0
  81. package/build/admin-edit-users.9e48b00d.chunk.js +10 -0
  82. package/build/admin-users.cf7b4151.chunk.js +11 -0
  83. package/build/{api-tokens-create-page.0db3aec1.chunk.js → api-tokens-create-page.a31c7fba.chunk.js} +1 -1
  84. package/build/{api-tokens-edit-page.671e0e26.chunk.js → api-tokens-edit-page.64fef287.chunk.js} +1 -1
  85. package/build/api-tokens-list-page.e600ad3e.chunk.js +16 -0
  86. package/build/ar-json.39e54aba.chunk.js +1 -0
  87. package/build/{audit-logs-settings-page.c3dce30d.chunk.js → audit-logs-settings-page.d4da4579.chunk.js} +1 -1
  88. package/build/{ca-json.f6a0f472.chunk.js → ca-json.4d999055.chunk.js} +1 -1
  89. package/build/content-manager.255c3a59.chunk.js +1139 -0
  90. package/build/{content-type-builder-list-view.79e84b36.chunk.js → content-type-builder-list-view.8d7a3d68.chunk.js} +5 -5
  91. package/build/content-type-builder.3c8558a5.chunk.js +126 -0
  92. package/build/cs-json.4b44411c.chunk.js +1 -0
  93. package/build/{de-json.30e1f35b.chunk.js → de-json.866f8a28.chunk.js} +1 -1
  94. package/build/{dk-json.e6d9ffa4.chunk.js → dk-json.10f7b1d1.chunk.js} +1 -1
  95. package/build/email-settings-page.b19f2eb2.chunk.js +10 -0
  96. package/build/en-json.1997583c.chunk.js +1 -0
  97. package/build/es-json.ea15c957.chunk.js +1 -0
  98. package/build/{eu-json.fceecd8b.chunk.js → eu-json.3bc24d60.chunk.js} +1 -1
  99. package/build/{fr-json.78545ef8.chunk.js → fr-json.e88fbdfd.chunk.js} +1 -1
  100. package/build/{gu-json.676518f2.chunk.js → gu-json.94f0d242.chunk.js} +1 -1
  101. package/build/{he-json.ad22e8cc.chunk.js → he-json.f0de8cdb.chunk.js} +1 -1
  102. package/build/{hi-json.19b51c09.chunk.js → hi-json.df3a7be2.chunk.js} +1 -1
  103. package/build/{hu-json.f947088f.chunk.js → hu-json.680e6eef.chunk.js} +1 -1
  104. package/build/{i18n-settings-page.b8d8753e.chunk.js → i18n-settings-page.a6b49eac.chunk.js} +1 -1
  105. package/build/{id-json.504daa84.chunk.js → id-json.e0d83d41.chunk.js} +1 -1
  106. package/build/index.html +1 -1
  107. package/build/{it-json.2fd90f4d.chunk.js → it-json.8be59205.chunk.js} +1 -1
  108. package/build/{ja-json.c9f12d0b.chunk.js → ja-json.97ee41ba.chunk.js} +1 -1
  109. package/build/{ko-json.ef463065.chunk.js → ko-json.4cbbf4f2.chunk.js} +1 -1
  110. package/build/main.7f308c20.js +4322 -0
  111. package/build/{ml-json.490f666c.chunk.js → ml-json.e3747091.chunk.js} +1 -1
  112. package/build/ms-json.0eddffd9.chunk.js +1 -0
  113. package/build/{nl-json.c416295a.chunk.js → nl-json.371a15ee.chunk.js} +1 -1
  114. package/build/{no-json.1a2258ba.chunk.js → no-json.9b3cd181.chunk.js} +1 -1
  115. package/build/{pl-json.8cf0c871.chunk.js → pl-json.e535cbce.chunk.js} +1 -1
  116. package/build/{pt-BR-json.51fab8d0.chunk.js → pt-BR-json.e5fafa46.chunk.js} +1 -1
  117. package/build/pt-json.ee554a41.chunk.js +1 -0
  118. package/build/review-workflows-settings.7b4be1b0.chunk.js +63 -0
  119. package/build/{ru-json.aa5cd123.chunk.js → ru-json.866f0ff1.chunk.js} +1 -1
  120. package/build/runtime~main.bf374148.js +2 -0
  121. package/build/{sa-json.f3fa5407.chunk.js → sa-json.7efeb257.chunk.js} +1 -1
  122. package/build/{sk-json.9ec60d9f.chunk.js → sk-json.7bbeb0af.chunk.js} +1 -1
  123. package/build/{sso-settings-page.b85ad080.chunk.js → sso-settings-page.ad2143dd.chunk.js} +1 -1
  124. package/build/{sv-json.c6b0c237.chunk.js → sv-json.dc40951f.chunk.js} +1 -1
  125. package/build/{th-json.6e68155c.chunk.js → th-json.f664b96d.chunk.js} +1 -1
  126. package/build/{tr-json.9f41dc08.chunk.js → tr-json.b79eae31.chunk.js} +1 -1
  127. package/build/uk-json.b7e38370.chunk.js +1 -0
  128. package/build/upload-settings.eb1a7908.chunk.js +84 -0
  129. package/build/upload.700e2c84.chunk.js +33 -0
  130. package/build/{users-advanced-settings-page.fce9908e.chunk.js → users-advanced-settings-page.aae212f2.chunk.js} +1 -1
  131. package/build/{users-email-settings-page.343d0ad2.chunk.js → users-email-settings-page.8a9b0da1.chunk.js} +1 -1
  132. package/build/{users-providers-settings-page.e5a9a3f1.chunk.js → users-providers-settings-page.e6be909d.chunk.js} +10 -10
  133. package/build/{users-roles-settings-page.66312f31.chunk.js → users-roles-settings-page.97d06a80.chunk.js} +3 -3
  134. package/build/vi-json.ee4c5537.chunk.js +1 -0
  135. package/build/webhook-edit-page.9eb0f789.chunk.js +75 -0
  136. package/build/webhook-list-page.66082323.chunk.js +42 -0
  137. package/build/{zh-Hans-json.9c0eac99.chunk.js → zh-Hans-json.30a18940.chunk.js} +1 -1
  138. package/build/{zh-json.f88f563d.chunk.js → zh-json.49d84433.chunk.js} +1 -1
  139. package/ee/admin/hooks/useSettingsMenu/utils/customAdminLinks.js +12 -12
  140. package/ee/admin/hooks/useSettingsMenu/utils/customGlobalLinks.js +21 -13
  141. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/ReviewWorkflows.js +137 -0
  142. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/actions/index.js +42 -0
  143. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/components/AddStage/AddStage.js +87 -0
  144. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/components/AddStage/index.js +1 -0
  145. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/components/Stages/Stage/Stage.js +90 -0
  146. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/components/Stages/Stage/index.js +1 -0
  147. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/components/Stages/Stages.js +77 -0
  148. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/components/Stages/index.js +1 -0
  149. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/constants.js +6 -0
  150. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/hooks/useReviewWorkflows.js +63 -0
  151. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/index.js +3 -0
  152. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/reducer/index.js +102 -0
  153. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/utils/getWorkflowValidationSchema.js +25 -0
  154. package/ee/admin/pages/SettingsPage/utils/customRoutes.js +16 -2
  155. package/ee/admin/permissions/customPermissions.js +7 -0
  156. package/ee/server/bootstrap.js +7 -1
  157. package/ee/server/config/admin-actions.js +10 -0
  158. package/ee/server/constants/default-stages.json +14 -0
  159. package/ee/server/constants/default-workflow.json +1 -0
  160. package/ee/server/constants/workflows.js +7 -0
  161. package/ee/server/content-types/index.js +9 -0
  162. package/ee/server/content-types/workflow/index.js +34 -0
  163. package/ee/server/content-types/workflow-stage/index.js +36 -0
  164. package/ee/server/controllers/index.js +2 -0
  165. package/ee/server/controllers/workflows/index.js +36 -0
  166. package/ee/server/controllers/workflows/stages/index.js +57 -0
  167. package/ee/server/index.js +1 -0
  168. package/ee/server/routes/index.js +87 -0
  169. package/ee/server/services/index.js +3 -0
  170. package/ee/server/services/review-workflows/review-workflows.js +54 -0
  171. package/ee/server/services/review-workflows/stages.js +133 -0
  172. package/ee/server/services/review-workflows/workflows.js +25 -0
  173. package/ee/server/utils/index.js +8 -0
  174. package/ee/server/utils/test.js +11 -0
  175. package/ee/server/validation/review-workflows.js +17 -0
  176. package/package.json +13 -13
  177. package/server/bootstrap.js +0 -2
  178. package/server/config/admin-actions.js +0 -64
  179. package/server/content-types/index.js +0 -2
  180. package/server/controllers/admin.js +0 -55
  181. package/server/controllers/api-token.js +5 -4
  182. package/server/controllers/index.js +0 -1
  183. package/server/register.js +9 -2
  184. package/server/routes/admin.js +0 -28
  185. package/server/routes/index.js +0 -2
  186. package/server/services/api-token.js +3 -2
  187. package/server/services/constants.js +0 -6
  188. package/server/services/index.js +0 -1
  189. package/server/strategies/api-token.js +2 -4
  190. package/server/strategies/index.js +0 -1
  191. package/server/utils/index.d.ts +0 -2
  192. package/server/validation/api-tokens.js +6 -1
  193. package/webpack.config.js +0 -3
  194. package/admin/src/pages/SettingsPage/components/Tokens/FormiTokenContainer/LifeSpanInput.js +0 -96
  195. package/admin/src/pages/SettingsPage/components/Tokens/LifeSpanInput/index.js +0 -98
  196. package/admin/src/pages/SettingsPage/components/Tokens/Regenerate/index.js +0 -73
  197. package/admin/src/pages/SettingsPage/components/Tokens/Table/index.js +0 -135
  198. package/admin/src/pages/SettingsPage/components/Tokens/TokenDescription/index.js +0 -51
  199. package/admin/src/pages/SettingsPage/components/Tokens/TokenName/index.js +0 -46
  200. package/admin/src/pages/SettingsPage/components/Tokens/TokenTypeSelect/index.js +0 -69
  201. package/admin/src/pages/SettingsPage/pages/TransferTokens/EditView/components/FormTransferTokenContainer/index.js +0 -105
  202. package/admin/src/pages/SettingsPage/pages/TransferTokens/EditView/components/LoadingView/index.js +0 -50
  203. package/admin/src/pages/SettingsPage/pages/TransferTokens/EditView/index.js +0 -201
  204. package/admin/src/pages/SettingsPage/pages/TransferTokens/EditView/utils/getDateOfExpiration.js +0 -16
  205. package/admin/src/pages/SettingsPage/pages/TransferTokens/EditView/utils/index.js +0 -4
  206. package/admin/src/pages/SettingsPage/pages/TransferTokens/EditView/utils/schema.js +0 -10
  207. package/admin/src/pages/SettingsPage/pages/TransferTokens/ListView/index.js +0 -182
  208. package/admin/src/pages/SettingsPage/pages/TransferTokens/ListView/utils/tableHeaders.js +0 -48
  209. package/admin/src/pages/SettingsPage/pages/TransferTokens/ProtectedCreateView/index.js +0 -14
  210. package/admin/src/pages/SettingsPage/pages/TransferTokens/ProtectedEditView/index.js +0 -14
  211. package/admin/src/pages/SettingsPage/pages/TransferTokens/ProtectedListView/index.js +0 -12
  212. package/build/1683.c8aa7b7c.chunk.js +0 -268
  213. package/build/2743.6d1632f9.chunk.js +0 -45
  214. package/build/3075.dc3894fe.chunk.js +0 -108
  215. package/build/3632.0317b618.chunk.js +0 -138
  216. package/build/4649.15cc0afe.chunk.js +0 -30
  217. package/build/7259.aa68d808.chunk.js +0 -1
  218. package/build/7407.883fb1f5.chunk.js +0 -1
  219. package/build/9707.7290fd92.chunk.js +0 -96
  220. package/build/Admin_settingsPage.178dc6e3.chunk.js +0 -178
  221. package/build/admin-app.77a50e1f.chunk.js +0 -112
  222. package/build/admin-edit-roles-page.446b69dc.chunk.js +0 -1
  223. package/build/admin-edit-users.2ed69bfd.chunk.js +0 -10
  224. package/build/admin-users.fc003b10.chunk.js +0 -11
  225. package/build/api-tokens-list-page.7387102c.chunk.js +0 -16
  226. package/build/ar-json.932794f7.chunk.js +0 -1
  227. package/build/content-manager.42b24d46.chunk.js +0 -1139
  228. package/build/content-type-builder.855db321.chunk.js +0 -126
  229. package/build/cs-json.79879fb6.chunk.js +0 -1
  230. package/build/email-settings-page.d1fcc7a3.chunk.js +0 -10
  231. package/build/en-json.b0748970.chunk.js +0 -1
  232. package/build/es-json.e275481d.chunk.js +0 -1
  233. package/build/main.1022ed01.js +0 -4393
  234. package/build/ms-json.db87d8d3.chunk.js +0 -1
  235. package/build/pt-json.62927d1e.chunk.js +0 -1
  236. package/build/runtime~main.84941a97.js +0 -2
  237. package/build/transfer-tokens-create-page.16e23791.chunk.js +0 -1
  238. package/build/transfer-tokens-edit-page.3886c973.chunk.js +0 -1
  239. package/build/transfer-tokens-list-page.e8010a89.chunk.js +0 -16
  240. package/build/uk-json.b2fcd567.chunk.js +0 -1
  241. package/build/upload-settings.ef64bbf9.chunk.js +0 -84
  242. package/build/upload.c5730dfa.chunk.js +0 -33
  243. package/build/vi-json.f08d7d03.chunk.js +0 -1
  244. package/build/webhook-edit-page.73e51e64.chunk.js +0 -75
  245. package/build/webhook-list-page.1134f130.chunk.js +0 -42
  246. package/server/content-types/transfer-token-permission.js +0 -36
  247. package/server/content-types/transfer-token.js +0 -66
  248. package/server/controllers/transfer/index.js +0 -13
  249. package/server/controllers/transfer/runner.js +0 -24
  250. package/server/controllers/transfer/token.js +0 -131
  251. package/server/routes/transfer.js +0 -95
  252. package/server/services/transfer/index.js +0 -6
  253. package/server/services/transfer/permission.js +0 -22
  254. package/server/services/transfer/token.js +0 -409
  255. package/server/strategies/data-transfer.js +0 -107
  256. package/server/validation/transfer/index.js +0 -5
  257. package/server/validation/transfer/token.js +0 -34
@@ -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,23 +203,15 @@ 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(
222
212
  async (trackerProperty) => {
213
+ console.log('onDelete');
214
+
223
215
  try {
224
216
  trackUsageRef.current('willDeleteEntry', trackerProperty);
225
217
 
@@ -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(() => {
@@ -2,7 +2,7 @@ import { useState } from 'react';
2
2
  import { get } from 'lodash';
3
3
  import { useFetchClient, useNotification } from '@strapi/helper-plugin';
4
4
 
5
- const useRegenerate = (url, id, onRegenerate) => {
5
+ const useRegenerate = (id, onRegenerate) => {
6
6
  const [isLoadingConfirmation, setIsLoadingConfirmation] = useState(false);
7
7
  const toggleNotification = useNotification();
8
8
  const { post } = useFetchClient();
@@ -13,7 +13,7 @@ const useRegenerate = (url, id, onRegenerate) => {
13
13
  data: {
14
14
  data: { accessKey },
15
15
  },
16
- } = await post(`${url}${id}/regenerate`);
16
+ } = await post(`/admin/api-tokens/${id}/regenerate`);
17
17
  setIsLoadingConfirmation(false);
18
18
  onRegenerate(accessKey);
19
19
  } catch (error) {
@@ -22,13 +22,6 @@ const defaultGlobalLinks = [
22
22
  isDisplayed: false,
23
23
  permissions: adminPermissions.settings['api-tokens'].main,
24
24
  },
25
- {
26
- intlLabel: { id: 'Settings.transferTokens.title', defaultMessage: 'Transfer Tokens' },
27
- to: '/settings/transfer-tokens?sort=name:ASC',
28
- id: 'transfer-tokens',
29
- isDisplayed: false,
30
- permissions: adminPermissions.settings['transfer-tokens'].main,
31
- },
32
25
  ];
33
26
 
34
27
  export default defaultGlobalLinks;
@@ -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
  };
@@ -1,7 +1,8 @@
1
1
  import React from 'react';
2
- import { NavLink } from 'react-router-dom';
2
+ import { NavLink, useLocation } from 'react-router-dom';
3
3
  import { useIntl } from 'react-intl';
4
4
  import PropTypes from 'prop-types';
5
+ import { useTracking } from '@strapi/helper-plugin';
5
6
  import {
6
7
  SubNav,
7
8
  SubNavHeader,
@@ -13,6 +14,8 @@ import { getSectionsToDisplay } from '../../utils';
13
14
 
14
15
  const SettingsNav = ({ menu }) => {
15
16
  const { formatMessage } = useIntl();
17
+ const { trackUsage } = useTracking();
18
+ const { pathname } = useLocation();
16
19
 
17
20
  const filteredMenu = getSectionsToDisplay(menu);
18
21
 
@@ -35,6 +38,10 @@ const SettingsNav = ({ menu }) => {
35
38
  defaultMessage: 'Settings',
36
39
  });
37
40
 
41
+ const handleClickOnLink = (destination = null) => {
42
+ trackUsage('willNavigate', { from: pathname, to: destination });
43
+ };
44
+
38
45
  return (
39
46
  <SubNav ariaLabel={label}>
40
47
  <SubNavHeader label={label} />
@@ -42,7 +49,13 @@ const SettingsNav = ({ menu }) => {
42
49
  {sections.map((section) => (
43
50
  <SubNavSection key={section.id} label={formatMessage(section.intlLabel)}>
44
51
  {section.links.map((link) => (
45
- <SubNavLink as={NavLink} withBullet={link.hasNotification} to={link.to} key={link.id}>
52
+ <SubNavLink
53
+ as={NavLink}
54
+ withBullet={link.hasNotification}
55
+ to={link.to}
56
+ onClick={() => handleClickOnLink(link.to)}
57
+ key={link.id}
58
+ >
46
59
  {formatMessage(link.intlLabel)}
47
60
  </SubNavLink>
48
61
  ))}
@@ -1,8 +1,5 @@
1
1
  import React, { useState, useEffect } from 'react';
2
2
  import { capitalize } from 'lodash';
3
- import { useIntl } from 'react-intl';
4
- import styled from 'styled-components';
5
- import PropTypes from 'prop-types';
6
3
  import { Accordion, AccordionToggle, AccordionContent } from '@strapi/design-system/Accordion';
7
4
  import { Checkbox } from '@strapi/design-system/Checkbox';
8
5
  import { Grid, GridItem } from '@strapi/design-system/Grid';
@@ -10,6 +7,8 @@ import { Typography } from '@strapi/design-system/Typography';
10
7
  import { Box } from '@strapi/design-system/Box';
11
8
  import { Flex } from '@strapi/design-system/Flex';
12
9
  import CogIcon from '@strapi/icons/Cog';
10
+ import styled from 'styled-components';
11
+ import PropTypes from 'prop-types';
13
12
  import { useApiTokenPermissionsContext } from '../../../../../../../contexts/ApiTokenPermissions';
14
13
  import CheckboxWrapper from './CheckBoxWrapper';
15
14
 
@@ -31,7 +30,6 @@ const CollapsableContentType = ({
31
30
  value: { onChangeSelectAll, onChange, selectedActions, setSelectedAction, selectedAction },
32
31
  } = useApiTokenPermissionsContext();
33
32
  const [expanded, setExpanded] = useState(false);
34
- const { formatMessage } = useIntl();
35
33
 
36
34
  const handleExpandedAccordion = () => {
37
35
  setExpanded((s) => !s);
@@ -85,7 +83,7 @@ const CollapsableContentType = ({
85
83
  }}
86
84
  disabled={disabled}
87
85
  >
88
- {formatMessage({ id: 'app.utils.select-all', defaultMessage: 'Select all' })}
86
+ Select all
89
87
  </Checkbox>
90
88
  </Box>
91
89
  </Flex>
@@ -1,32 +1,32 @@
1
1
  import React, { useRef } from 'react';
2
2
  import { useIntl } from 'react-intl';
3
- import PropTypes from 'prop-types';
4
- import { CopyToClipboard } from 'react-copy-to-clipboard';
5
3
  import { ContentBox, useNotification, useTracking } from '@strapi/helper-plugin';
6
4
  import { IconButton } from '@strapi/design-system/IconButton';
7
5
  import Duplicate from '@strapi/icons/Duplicate';
6
+ import PropTypes from 'prop-types';
7
+ import { CopyToClipboard } from 'react-copy-to-clipboard';
8
8
  import Key from '@strapi/icons/Key';
9
9
 
10
- const TokenBox = ({ token }) => {
10
+ const HeaderContentBox = ({ apiToken }) => {
11
11
  const { formatMessage } = useIntl();
12
12
  const toggleNotification = useNotification();
13
- const { trackUsage } = useTracking(); // TODO: Track different types of tokens
13
+ const { trackUsage } = useTracking();
14
14
  const trackUsageRef = useRef(trackUsage);
15
15
 
16
16
  return (
17
17
  <ContentBox
18
18
  endAction={
19
- token && (
19
+ apiToken && (
20
20
  <span style={{ alignSelf: 'start' }}>
21
21
  <CopyToClipboard
22
22
  onCopy={() => {
23
23
  trackUsageRef.current('didCopyTokenKey');
24
24
  toggleNotification({
25
25
  type: 'success',
26
- message: { id: 'Settings.tokens.notification.copied' },
26
+ message: { id: 'Settings.apiTokens.notification.copied' },
27
27
  });
28
28
  }}
29
- text={token}
29
+ text={apiToken}
30
30
  >
31
31
  <IconButton
32
32
  label={formatMessage({
@@ -42,20 +42,20 @@ const TokenBox = ({ token }) => {
42
42
  )
43
43
  }
44
44
  title={
45
- token ||
45
+ apiToken ||
46
46
  formatMessage({
47
- id: 'Settings.tokens.copy.editTitle',
47
+ id: 'Settings.apiTokens.copy.editTitle',
48
48
  defaultMessage: 'This token isn’t accessible anymore.',
49
49
  })
50
50
  }
51
51
  subtitle={
52
- token
52
+ apiToken
53
53
  ? formatMessage({
54
- id: 'Settings.tokens.copy.lastWarning',
54
+ id: 'Settings.apiTokens.copy.lastWarning',
55
55
  defaultMessage: 'Make sure to copy this token, you won’t be able to see it again!',
56
56
  })
57
57
  : formatMessage({
58
- id: 'Settings.tokens.copy.editMessage',
58
+ id: 'Settings.apiTokens.copy.editMessage',
59
59
  defaultMessage: 'For security reasons, you can only see your token once.',
60
60
  })
61
61
  }
@@ -65,12 +65,12 @@ const TokenBox = ({ token }) => {
65
65
  );
66
66
  };
67
67
 
68
- TokenBox.defaultProps = {
69
- token: null,
68
+ HeaderContentBox.defaultProps = {
69
+ apiToken: null,
70
70
  };
71
71
 
72
- TokenBox.propTypes = {
73
- token: PropTypes.string,
72
+ HeaderContentBox.propTypes = {
73
+ apiToken: PropTypes.string,
74
74
  };
75
75
 
76
- export default TokenBox;
76
+ export default HeaderContentBox;