@strapi/admin 4.5.0-beta.0 → 4.5.1

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 (264) hide show
  1. package/admin/src/StrapiApp.js +17 -6
  2. package/admin/src/assets/images/hot-air-balloon.png +0 -0
  3. package/admin/src/assets/images/icon_offline-cloud.svg +3 -3
  4. package/admin/src/assets/images/logo-strapi-2022.svg +7 -0
  5. package/admin/src/assets/images/upgrade-details.png +0 -0
  6. package/admin/src/content-manager/components/DynamicTable/CellContent/CellValue.js +1 -1
  7. package/admin/src/content-manager/components/DynamicTable/CellContent/RelationMultiple/index.js +5 -4
  8. package/admin/src/content-manager/components/DynamicTable/CellContent/index.js +10 -0
  9. package/admin/src/content-manager/components/DynamicTable/index.js +21 -4
  10. package/admin/src/content-manager/components/DynamicZone/components/{AddComponentButton/index.js → AddComponentButton.js} +12 -6
  11. package/admin/src/content-manager/components/DynamicZone/components/{ComponentPicker/Category/ComponentCard/index.js → ComponentCard.js} +8 -19
  12. package/admin/src/content-manager/components/DynamicZone/components/{ComponentPicker/Category/index.js → ComponentCategory.js} +19 -18
  13. package/admin/src/content-manager/components/DynamicZone/components/{ComponentPicker/index.js → ComponentPicker.js} +36 -38
  14. package/admin/src/content-manager/components/DynamicZone/components/DynamicComponent.js +195 -0
  15. package/admin/src/content-manager/components/DynamicZone/components/{DzLabel/index.js → DynamicZoneLabel.js} +13 -5
  16. package/admin/src/content-manager/components/DynamicZone/index.js +35 -116
  17. package/admin/src/content-manager/components/EditViewDataManagerProvider/index.js +103 -60
  18. package/admin/src/content-manager/components/EditViewDataManagerProvider/reducer.js +169 -162
  19. package/admin/src/content-manager/components/EditViewDataManagerProvider/utils/cleanData.js +70 -16
  20. package/admin/src/content-manager/components/EditViewDataManagerProvider/utils/findLeafByPathAndReplace.js +52 -0
  21. package/admin/src/content-manager/components/EditViewDataManagerProvider/utils/index.js +2 -0
  22. package/admin/src/content-manager/components/EditViewDataManagerProvider/utils/recursivelyFindPathsBasedOnCondition.js +72 -0
  23. package/admin/src/content-manager/components/FieldComponent/index.js +9 -2
  24. package/admin/src/content-manager/components/PreviewWysiwyg/index.js +1 -1
  25. package/admin/src/content-manager/components/RelationInput/RelationInput.js +80 -76
  26. package/admin/src/content-manager/components/RelationInputDataManager/RelationInputDataManager.js +95 -63
  27. package/admin/src/content-manager/components/RelationInputDataManager/utils/diffRelations.js +24 -0
  28. package/admin/src/content-manager/components/RelationInputDataManager/utils/index.js +2 -1
  29. package/admin/src/content-manager/components/RelationInputDataManager/utils/normalizeRelations.js +8 -29
  30. package/admin/src/content-manager/components/RelationInputDataManager/utils/normalizeSearchResults.js +8 -4
  31. package/admin/src/content-manager/components/RelationInputDataManager/utils/select.js +1 -0
  32. package/admin/src/content-manager/components/RepeatableComponent/index.js +4 -3
  33. package/admin/src/content-manager/hooks/__test__/usePrev.test.js +26 -0
  34. package/admin/src/content-manager/hooks/index.js +1 -0
  35. package/admin/src/content-manager/hooks/useFetchContentTypeLayout/utils/formatLayouts.js +19 -48
  36. package/admin/src/content-manager/hooks/usePrev.js +14 -0
  37. package/admin/src/content-manager/hooks/useRelation/useRelation.js +100 -7
  38. package/admin/src/content-manager/pages/App/reducer.js +3 -0
  39. package/admin/src/content-manager/pages/ListSettingsView/components/DraggableCard.js +3 -3
  40. package/admin/src/content-manager/pages/ListSettingsView/components/Settings.js +2 -2
  41. package/admin/src/content-manager/pages/ListSettingsView/components/SortDisplayedFields.js +1 -1
  42. package/admin/src/core/apis/CustomFields.js +0 -1
  43. package/admin/src/core/store/configureStore.js +17 -2
  44. package/admin/src/favicon.png +0 -0
  45. package/admin/src/hooks/useFetchMarketplacePlugins/index.js +2 -2
  46. package/admin/src/hooks/useFetchMarketplacePlugins/utils/api.js +4 -2
  47. package/admin/src/hooks/useFetchMarketplaceProviders/index.js +3 -3
  48. package/admin/src/hooks/useFetchMarketplaceProviders/utils/api.js +5 -3
  49. package/admin/src/index.js +1 -0
  50. package/admin/src/pages/App/index.js +1 -1
  51. package/admin/src/pages/HomePage/assets/corner-ornament.svg +48 -0
  52. package/admin/src/pages/HomePage/index.js +4 -3
  53. package/admin/src/pages/MarketplacePage/components/NpmPackageCard/CardButton.js +110 -0
  54. package/admin/src/pages/MarketplacePage/components/NpmPackageCard/InstallPluginButton.js +32 -21
  55. package/admin/src/pages/MarketplacePage/components/NpmPackageCard/PackageStats.js +79 -0
  56. package/admin/src/pages/MarketplacePage/components/NpmPackageCard/index.js +28 -11
  57. package/admin/src/pages/MarketplacePage/components/NpmPackagesFilters/FilterSelect.js +42 -0
  58. package/admin/src/pages/MarketplacePage/components/NpmPackagesFilters/FiltersPopover.js +96 -0
  59. package/admin/src/pages/MarketplacePage/components/NpmPackagesFilters/index.js +107 -0
  60. package/admin/src/pages/MarketplacePage/components/NpmPackagesGrid/index.js +4 -0
  61. package/admin/src/pages/MarketplacePage/components/SortSelect/index.js +70 -0
  62. package/admin/src/pages/MarketplacePage/index.js +68 -8
  63. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/FormApiTokenContainer/index.js +5 -4
  64. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/FormBody/index.js +4 -3
  65. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/FormHead/index.js +6 -2
  66. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/Regenerate/index.js +1 -1
  67. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/index.js +5 -4
  68. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/utils/schema.js +1 -1
  69. package/admin/src/pages/SettingsPage/pages/Roles/EditPage/components/ConditionsModal/ActionRow/index.js +7 -38
  70. package/admin/src/pages/SettingsPage/pages/Roles/EditPage/components/ConditionsModal/ActionRow/utils/options.js +31 -0
  71. package/admin/src/pages/SettingsPage/pages/Roles/EditPage/components/ConditionsModal/index.js +32 -43
  72. package/admin/src/pages/SettingsPage/pages/Roles/EditPage/components/ContentTypeCollapse/Collapse/index.js +1 -1
  73. package/admin/src/pages/SettingsPage/pages/Roles/ListPage/components/RoleRow/index.js +3 -1
  74. package/admin/src/pages/SettingsPage/pages/Roles/ListPage/index.js +2 -1
  75. package/admin/src/pages/SettingsPage/pages/Webhooks/EditView/components/EventInput/index.js +2 -2
  76. package/admin/src/translations/ca.json +1 -1
  77. package/admin/src/translations/de.json +1 -1
  78. package/admin/src/translations/dk.json +1 -1
  79. package/admin/src/translations/en.json +21 -7
  80. package/admin/src/translations/es.json +1 -1
  81. package/admin/src/translations/fr.json +1 -1
  82. package/admin/src/translations/gu.json +1 -1
  83. package/admin/src/translations/he.json +1 -1
  84. package/admin/src/translations/hi.json +1 -1
  85. package/admin/src/translations/hu.json +1 -1
  86. package/admin/src/translations/id.json +1 -1
  87. package/admin/src/translations/it.json +1 -1
  88. package/admin/src/translations/ja.json +1 -1
  89. package/admin/src/translations/ko.json +1 -1
  90. package/admin/src/translations/ml.json +1 -1
  91. package/admin/src/translations/nl.json +1 -1
  92. package/admin/src/translations/no.json +1 -1
  93. package/admin/src/translations/pl.json +1 -1
  94. package/admin/src/translations/pt-BR.json +15 -15
  95. package/admin/src/translations/ru.json +1 -1
  96. package/admin/src/translations/sa.json +1 -1
  97. package/admin/src/translations/sk.json +1 -1
  98. package/admin/src/translations/sv.json +118 -86
  99. package/admin/src/translations/th.json +1 -1
  100. package/admin/src/translations/zh-Hans.json +1 -1
  101. package/admin/src/translations/zh.json +1 -1
  102. package/build/1856.db9f5782.chunk.js +174 -0
  103. package/build/2077.fed8c9c3.chunk.js +206 -0
  104. package/build/2912.fccb2c43.chunk.js +259 -0
  105. package/build/4318.5e670740.chunk.js +30 -0
  106. package/build/{9166.8fcb3019.chunk.js → 4610.7614b003.chunk.js} +22 -21
  107. package/build/4715.8e33d630.chunk.js +387 -0
  108. package/build/{4800.d09f1225.chunk.js → 4800.a6935af6.chunk.js} +1 -1
  109. package/build/4982.9e58ea3f.chunk.js +325 -0
  110. package/build/617f9c948fa79e6d73bd.png +0 -0
  111. package/build/6925.bb6dd64d.chunk.js +762 -0
  112. package/build/6d21938306785f176538.png +0 -0
  113. package/build/70674f63fc3904c20de0.svg +7 -0
  114. package/build/{7379.d246dd38.chunk.js → 7379.e972985f.chunk.js} +1 -1
  115. package/build/7692.31e83caa.chunk.js +470 -0
  116. package/build/7841.4804bd98.chunk.js +259 -0
  117. package/build/7866.6db2248d.chunk.js +505 -0
  118. package/build/7e9af4fb7e723fcebf1f.svg +48 -0
  119. package/build/8380.37126e0d.chunk.js +299 -0
  120. package/build/8549.5e5fb6b6.chunk.js +159 -0
  121. package/build/8738.5a02bffb.chunk.js +463 -0
  122. package/build/{9066.26faf397.chunk.js → 9066.5d980488.chunk.js} +5 -5
  123. package/build/9420.7addc099.chunk.js +505 -0
  124. package/build/9649.b6afc945.chunk.js +199 -0
  125. package/build/9d5d788027e86620c234.svg +5 -0
  126. package/build/Admin-authenticatedApp.c07d2a86.chunk.js +80 -0
  127. package/build/{Admin_homePage.4b2be829.chunk.js → Admin_homePage.26d32e30.chunk.js} +5 -4
  128. package/build/Admin_marketplace.444ff7b8.chunk.js +22 -0
  129. package/build/Admin_settingsPage.bf2234e1.chunk.js +178 -0
  130. package/build/admin-app.b157c10a.chunk.js +112 -0
  131. package/build/{admin-edit-roles-page.4dd6bcb9.chunk.js → admin-edit-roles-page.69d9fcb2.chunk.js} +1 -1
  132. package/build/ca-json.07ae0f2c.chunk.js +1 -0
  133. package/build/content-manager.f38edbb6.chunk.js +1202 -0
  134. package/build/content-type-builder-translation-pt-BR-json.6fe3b8d1.chunk.js +1 -0
  135. package/build/content-type-builder-translation-sv-json.6deff030.chunk.js +1 -0
  136. package/build/{content-type-builder.a6e29716.chunk.js → content-type-builder.16af63a6.chunk.js} +13 -13
  137. package/build/de-json.6b3e1894.chunk.js +1 -0
  138. package/build/dk-json.144c6a8e.chunk.js +1 -0
  139. package/build/{email-settings-page.bfe6227f.chunk.js → email-settings-page.91c925a5.chunk.js} +6 -6
  140. package/build/email-translation-en-json.ebad8943.chunk.js +1 -0
  141. package/build/en-json.4a269f6b.chunk.js +1 -0
  142. package/build/es-json.6d123a82.chunk.js +1 -0
  143. package/build/fr-json.28ab54cb.chunk.js +1 -0
  144. package/build/gu-json.9a50ea64.chunk.js +1 -0
  145. package/build/he-json.72f18790.chunk.js +1 -0
  146. package/build/hi-json.0301b7ba.chunk.js +1 -0
  147. package/build/hu-json.c4b641bb.chunk.js +1 -0
  148. package/build/{i18n-settings-page.18166125.chunk.js → i18n-settings-page.4ef64441.chunk.js} +5 -5
  149. package/build/id-json.86035797.chunk.js +1 -0
  150. package/build/index.html +1 -1
  151. package/build/it-json.bbdc8993.chunk.js +1 -0
  152. package/build/ja-json.1c9eeeec.chunk.js +1 -0
  153. package/build/ko-json.e1f66398.chunk.js +1 -0
  154. package/build/main.ca8b0ee3.js +9465 -0
  155. package/build/ml-json.963c889f.chunk.js +1 -0
  156. package/build/nl-json.2b8cc3a0.chunk.js +1 -0
  157. package/build/no-json.a58c28bd.chunk.js +1 -0
  158. package/build/pl-json.249626b3.chunk.js +1 -0
  159. package/build/pt-BR-json.2b72b1d6.chunk.js +1 -0
  160. package/build/ru-json.d7cfc2ff.chunk.js +1 -0
  161. package/build/runtime~main.ede9da1e.js +2 -0
  162. package/build/sa-json.44e95991.chunk.js +1 -0
  163. package/build/sk-json.7ba4b330.chunk.js +1 -0
  164. package/build/sv-json.fb1081ff.chunk.js +1 -0
  165. package/build/th-json.a67309b1.chunk.js +1 -0
  166. package/build/{upload-settings.3d613216.chunk.js → upload-settings.3f7ad973.chunk.js} +5 -5
  167. package/build/{users-advanced-settings-page.f4051d92.chunk.js → users-advanced-settings-page.6a838320.chunk.js} +5 -5
  168. package/build/users-permissions-translation-sv-json.d5d11648.chunk.js +1 -0
  169. package/build/{webhook-edit-page.9e46fc3f.chunk.js → webhook-edit-page.dc9442ce.chunk.js} +1 -1
  170. package/build/webhook-list-page.a110c462.chunk.js +134 -0
  171. package/build/zh-Hans-json.21617c24.chunk.js +1 -0
  172. package/build/zh-json.608aaf24.chunk.js +1 -0
  173. package/ee/admin/pages/SettingsPage/pages/Roles/ListPage/index.js +3 -2
  174. package/env.js +1 -0
  175. package/package.json +18 -17
  176. package/scripts/build.js +11 -0
  177. package/server/content-types/api-token.js +1 -1
  178. package/utils/create-plugins-exclude-path.js +40 -0
  179. package/webpack.alias.js +0 -13
  180. package/webpack.config.js +4 -1
  181. package/admin/src/assets/images/banner_strapi-rocket.png +0 -0
  182. package/admin/src/assets/images/big-logo-home.png +0 -0
  183. package/admin/src/assets/images/homepage-logo.png +0 -0
  184. package/admin/src/assets/images/icon_made-by-strapi.svg +0 -5
  185. package/admin/src/assets/images/logo_strapi_auth.png +0 -0
  186. package/admin/src/assets/images/logo_strapi_auth_v4.png +0 -0
  187. package/admin/src/assets/images/logo_strapi_menu.png +0 -0
  188. package/admin/src/assets/images/oops.png +0 -0
  189. package/admin/src/content-manager/components/DynamicZone/components/Component/Rectangle.js +0 -19
  190. package/admin/src/content-manager/components/DynamicZone/components/Component/index.js +0 -191
  191. package/admin/src/content-manager/components/State/index.js +0 -37
  192. package/admin/src/content-manager/icons/Bold/index.js +0 -22
  193. package/admin/src/content-manager/icons/Code/index.js +0 -13
  194. package/admin/src/content-manager/icons/Cross/index.js +0 -28
  195. package/admin/src/content-manager/icons/Italic/index.js +0 -23
  196. package/admin/src/content-manager/icons/Link/index.js +0 -21
  197. package/admin/src/content-manager/icons/Media/index.js +0 -14
  198. package/admin/src/content-manager/icons/Na/index.js +0 -39
  199. package/admin/src/content-manager/icons/Ol/index.js +0 -13
  200. package/admin/src/content-manager/icons/Quote/index.js +0 -13
  201. package/admin/src/content-manager/icons/Striked/index.js +0 -24
  202. package/admin/src/content-manager/icons/Ul/index.js +0 -15
  203. package/admin/src/content-manager/icons/Underline/index.js +0 -22
  204. package/admin/src/favicon.ico +0 -0
  205. package/build/15026a3d58aeb2828134.png +0 -0
  206. package/build/1856.d8f13391.chunk.js +0 -173
  207. package/build/1939.e3c87653.chunk.js +0 -325
  208. package/build/2077.31a2d91e.chunk.js +0 -205
  209. package/build/2912.ab68a736.chunk.js +0 -258
  210. package/build/4318.7d167b58.chunk.js +0 -30
  211. package/build/4715.44b1ef9b.chunk.js +0 -386
  212. package/build/4982.c2a311b7.chunk.js +0 -324
  213. package/build/6925.f5c8b6fc.chunk.js +0 -761
  214. package/build/7841.4b67af3f.chunk.js +0 -258
  215. package/build/7866.5fbeb7e5.chunk.js +0 -504
  216. package/build/8380.9b53a31d.chunk.js +0 -284
  217. package/build/8549.cf10b5d1.chunk.js +0 -158
  218. package/build/8738.a30a2160.chunk.js +0 -461
  219. package/build/90f49a385afb000fb1d4.svg +0 -5
  220. package/build/9420.0fe11290.chunk.js +0 -504
  221. package/build/962.8651ba3f.chunk.js +0 -184
  222. package/build/Admin-authenticatedApp.883449a5.chunk.js +0 -80
  223. package/build/Admin_marketplace.82c0570b.chunk.js +0 -11
  224. package/build/Admin_settingsPage.98e2a62b.chunk.js +0 -178
  225. package/build/a6b842e0b6d2b61135d1.svg +0 -5
  226. package/build/admin-app.a61d5c2e.chunk.js +0 -112
  227. package/build/b997a22a2e0b87ef1fa2.ico +0 -0
  228. package/build/bd81ba6c07827282255d.png +0 -0
  229. package/build/c3de6118ef47086ad05c.png +0 -0
  230. package/build/ca-json.82df6eab.chunk.js +0 -1
  231. package/build/content-manager.933dc286.chunk.js +0 -1201
  232. package/build/content-type-builder-translation-pt-BR-json.d6c7fcc1.chunk.js +0 -1
  233. package/build/de-json.0ad554eb.chunk.js +0 -1
  234. package/build/dk-json.e195ea1a.chunk.js +0 -1
  235. package/build/email-translation-en-json.3d74ff95.chunk.js +0 -1
  236. package/build/en-json.1889403c.chunk.js +0 -1
  237. package/build/es-json.09f80f6e.chunk.js +0 -1
  238. package/build/fb376b132d18bf4522ca.png +0 -0
  239. package/build/fde9b1ad0670d29a2516.png +0 -0
  240. package/build/fr-json.606d056b.chunk.js +0 -1
  241. package/build/gu-json.9881264f.chunk.js +0 -1
  242. package/build/he-json.3b825d80.chunk.js +0 -1
  243. package/build/hi-json.83dcf48f.chunk.js +0 -1
  244. package/build/hu-json.6f328bce.chunk.js +0 -1
  245. package/build/id-json.1f3c4303.chunk.js +0 -1
  246. package/build/it-json.494ac432.chunk.js +0 -1
  247. package/build/ja-json.6f262117.chunk.js +0 -1
  248. package/build/ko-json.36dc3b9a.chunk.js +0 -1
  249. package/build/main.63e7ea0a.js +0 -9338
  250. package/build/ml-json.9566bf9a.chunk.js +0 -1
  251. package/build/nl-json.94c3a289.chunk.js +0 -1
  252. package/build/no-json.40386397.chunk.js +0 -1
  253. package/build/pl-json.ccc6ef23.chunk.js +0 -1
  254. package/build/pt-BR-json.744f024d.chunk.js +0 -1
  255. package/build/ru-json.d22ea13c.chunk.js +0 -1
  256. package/build/runtime~main.3a5e1b07.js +0 -2
  257. package/build/sa-json.8fb1c04d.chunk.js +0 -1
  258. package/build/sk-json.6c7335d4.chunk.js +0 -1
  259. package/build/sv-json.2e589a7d.chunk.js +0 -1
  260. package/build/th-json.72e8de3d.chunk.js +0 -1
  261. package/build/users-permissions-translation-sv-json.83c60841.chunk.js +0 -1
  262. package/build/webhook-list-page.a712ae40.chunk.js +0 -134
  263. package/build/zh-Hans-json.a4d7dc69.chunk.js +0 -1
  264. package/build/zh-json.66aa2ae1.chunk.js +0 -1
@@ -17,7 +17,14 @@ const StyledBox = styled(Box)`
17
17
  border-radius: ${pxToRem(26)};
18
18
  `;
19
19
 
20
- const DzLabel = ({ label, labelAction, name, numberOfComponents, required, intlDescription }) => {
20
+ const DynamicZoneLabel = ({
21
+ label,
22
+ labelAction,
23
+ name,
24
+ numberOfComponents,
25
+ required,
26
+ intlDescription,
27
+ }) => {
21
28
  const { formatMessage } = useIntl();
22
29
  const intlLabel = formatMessage({ id: label || name, defaultMessage: label || name });
23
30
 
@@ -58,14 +65,15 @@ const DzLabel = ({ label, labelAction, name, numberOfComponents, required, intlD
58
65
  );
59
66
  };
60
67
 
61
- DzLabel.defaultProps = {
68
+ DynamicZoneLabel.defaultProps = {
62
69
  intlDescription: undefined,
63
70
  label: '',
64
71
  labelAction: undefined,
72
+ numberOfComponents: 0,
65
73
  required: false,
66
74
  };
67
75
 
68
- DzLabel.propTypes = {
76
+ DynamicZoneLabel.propTypes = {
69
77
  intlDescription: PropTypes.shape({
70
78
  id: PropTypes.string.isRequired,
71
79
  defaultMessage: PropTypes.string.isRequired,
@@ -73,8 +81,8 @@ DzLabel.propTypes = {
73
81
  label: PropTypes.string,
74
82
  labelAction: PropTypes.element,
75
83
  name: PropTypes.string.isRequired,
76
- numberOfComponents: PropTypes.number.isRequired,
84
+ numberOfComponents: PropTypes.number,
77
85
  required: PropTypes.bool,
78
86
  };
79
87
 
80
- export default DzLabel;
88
+ export default DynamicZoneLabel;
@@ -1,23 +1,22 @@
1
- import React, { memo, useCallback, useMemo, useState, useEffect } from 'react';
1
+ import React, { memo, useMemo, useState } from 'react';
2
2
  import get from 'lodash/get';
3
3
  import isEqual from 'react-fast-compare';
4
4
  import PropTypes from 'prop-types';
5
5
  import { Stack } from '@strapi/design-system/Stack';
6
6
  import { Box } from '@strapi/design-system/Box';
7
7
  import { NotAllowedInput, useNotification } from '@strapi/helper-plugin';
8
+
8
9
  import { getTrad } from '../../utils';
10
+
9
11
  import connect from './utils/connect';
10
12
  import select from './utils/select';
11
- import AddComponentButton from './components/AddComponentButton';
12
- import DzLabel from './components/DzLabel';
13
- import Component from './components/Component';
14
13
 
14
+ import DynamicZoneComponent from './components/DynamicComponent';
15
+ import AddComponentButton from './components/AddComponentButton';
16
+ import DynamicZoneLabel from './components/DynamicZoneLabel';
15
17
  import ComponentPicker from './components/ComponentPicker';
16
18
 
17
- /* eslint-disable react/no-array-index-key */
18
-
19
- const createCollapses = (arrayLength) =>
20
- Array.from({ length: arrayLength }).map(() => ({ isOpen: false }));
19
+ import { useContentTypeLayout } from '../../hooks';
21
20
 
22
21
  const DynamicZone = ({
23
22
  name,
@@ -35,38 +34,16 @@ const DynamicZone = ({
35
34
  fieldSchema,
36
35
  metadatas,
37
36
  }) => {
37
+ const [addComponentIsOpen, setAddComponentIsOpen] = useState(false);
38
+
38
39
  const toggleNotification = useNotification();
39
- const [isOpen, setIsOpen] = useState(false);
40
- const [shouldOpenAddedComponent, setShouldOpenAddedComponent] = useState(false);
40
+ const { getComponentLayout, components } = useContentTypeLayout();
41
+
41
42
  const dynamicDisplayedComponentsLength = dynamicDisplayedComponents.length;
42
43
  const intlDescription = metadatas.description
43
44
  ? { id: metadatas.description, defaultMessage: metadatas.description }
44
45
  : null;
45
46
 
46
- const [componentCollapses, setComponentsCollapses] = useState(
47
- createCollapses(dynamicDisplayedComponentsLength)
48
- );
49
-
50
- useEffect(() => {
51
- setComponentsCollapses(createCollapses(dynamicDisplayedComponentsLength));
52
- }, [dynamicDisplayedComponentsLength]);
53
-
54
- useEffect(() => {
55
- if (shouldOpenAddedComponent) {
56
- setComponentsCollapses((prev) =>
57
- prev.map((collapse, index) => {
58
- if (index === prev.length - 1) {
59
- return { ...collapse, isOpen: true };
60
- }
61
-
62
- return collapse;
63
- })
64
- );
65
-
66
- setShouldOpenAddedComponent(false);
67
- }
68
- }, [shouldOpenAddedComponent]);
69
-
70
47
  // We cannot use the default props here
71
48
  const { max = Infinity, min = -Infinity } = fieldSchema;
72
49
  const dynamicZoneErrors = useMemo(() => {
@@ -77,8 +54,6 @@ const DynamicZone = ({
77
54
  .map((key) => formErrors[key]);
78
55
  }, [formErrors, name]);
79
56
 
80
- const dynamicZoneAvailableComponents = useMemo(() => fieldSchema.components || [], [fieldSchema]);
81
-
82
57
  const missingComponentNumber = min - dynamicDisplayedComponentsLength;
83
58
  const hasError = dynamicZoneErrors.length > 0;
84
59
 
@@ -88,19 +63,17 @@ const DynamicZone = ({
88
63
  const hasMaxError =
89
64
  hasError && get(dynamicZoneErrors, [0, 'id'], '') === 'components.Input.error.validation.max';
90
65
 
91
- const handleAddComponent = useCallback(
92
- (componentUid) => {
93
- setIsOpen(false);
66
+ const handleAddComponent = (componentUid) => {
67
+ setAddComponentIsOpen(false);
94
68
 
95
- addComponentToDynamicZone(name, componentUid, hasError);
96
- setShouldOpenAddedComponent(true);
97
- },
98
- [addComponentToDynamicZone, hasError, name]
99
- );
69
+ const componentLayoutData = getComponentLayout(componentUid);
70
+
71
+ addComponentToDynamicZone(name, componentLayoutData, components, hasError);
72
+ };
100
73
 
101
74
  const handleClickOpenPicker = () => {
102
75
  if (dynamicDisplayedComponentsLength < max) {
103
- setIsOpen((prev) => !prev);
76
+ setAddComponentIsOpen((prev) => !prev);
104
77
  } else {
105
78
  toggleNotification({
106
79
  type: 'info',
@@ -109,68 +82,19 @@ const DynamicZone = ({
109
82
  }
110
83
  };
111
84
 
112
- const handleToggleComponent = (indexToToggle) => {
113
- setComponentsCollapses((prev) =>
114
- prev.map(({ isOpen }, index) => {
115
- if (index === indexToToggle) {
116
- return { isOpen: !isOpen };
117
- }
118
-
119
- return { isOpen };
120
- })
121
- );
122
- };
123
-
124
- const handleMoveComponentDown = (name, currentIndex) => {
125
- moveComponentDown(name, currentIndex);
126
- setComponentsCollapses((prev) => {
127
- return prev.map(({ isOpen }, index, refArray) => {
128
- if (index === currentIndex + 1) {
129
- return { isOpen: refArray[currentIndex].isOpen };
130
- }
131
-
132
- if (index === currentIndex) {
133
- return { isOpen: refArray[index + 1].isOpen };
134
- }
135
-
136
- return { isOpen };
137
- });
138
- });
85
+ const handleMoveComponentDown = (name, componentIndex) => () => {
86
+ moveComponentDown(name, componentIndex);
139
87
  };
140
88
 
141
- const handleMoveComponentUp = (name, currentIndex) => {
142
- moveComponentUp(name, currentIndex);
143
- setComponentsCollapses((prev) => {
144
- return prev.map(({ isOpen }, index, refArray) => {
145
- if (index === currentIndex - 1) {
146
- return { isOpen: refArray[currentIndex].isOpen };
147
- }
148
-
149
- if (index === currentIndex) {
150
- return { isOpen: refArray[index - 1].isOpen };
151
- }
152
-
153
- return { isOpen };
154
- });
155
- });
89
+ const handleMoveComponentUp = (name, componentIndex) => () => {
90
+ moveComponentUp(name, componentIndex);
156
91
  };
157
92
 
158
- const handleRemoveComponent = (name, currentIndex) => {
93
+ const handleRemoveComponent = (name, currentIndex) => () => {
159
94
  removeComponentFromDynamicZone(name, currentIndex);
160
95
  };
161
96
 
162
- if (!isFieldAllowed && isCreatingEntry) {
163
- return (
164
- <NotAllowedInput
165
- description={intlDescription}
166
- intlLabel={{ id: metadatas.label, defaultMessage: metadatas.label }}
167
- labelAction={labelAction}
168
- name={name}
169
- />
170
- );
171
- }
172
-
173
- if (!isFieldAllowed && !isFieldReadable && !isCreatingEntry) {
97
+ if (!isFieldAllowed && (isCreatingEntry || (!isFieldReadable && !isCreatingEntry))) {
174
98
  return (
175
99
  <NotAllowedInput
176
100
  description={intlDescription}
@@ -185,7 +109,7 @@ const DynamicZone = ({
185
109
  <Stack spacing={6}>
186
110
  {dynamicDisplayedComponentsLength > 0 && (
187
111
  <Box>
188
- <DzLabel
112
+ <DynamicZoneLabel
189
113
  intlDescription={intlDescription}
190
114
  label={metadatas.label}
191
115
  labelAction={labelAction}
@@ -194,26 +118,21 @@ const DynamicZone = ({
194
118
  required={fieldSchema.required || false}
195
119
  />
196
120
  {dynamicDisplayedComponents.map((componentUid, index) => {
197
- const showDownIcon =
198
- isFieldAllowed &&
199
- dynamicDisplayedComponentsLength > 0 &&
200
- index < dynamicDisplayedComponentsLength - 1;
201
- const showUpIcon = isFieldAllowed && dynamicDisplayedComponentsLength > 0 && index > 0;
202
- const isOpen = componentCollapses[index]?.isOpen || false;
121
+ const showDownIcon = isFieldAllowed && index < dynamicDisplayedComponentsLength - 1;
122
+ const showUpIcon = isFieldAllowed && index > 0;
203
123
 
204
124
  return (
205
- <Component
125
+ <DynamicZoneComponent
206
126
  componentUid={componentUid}
207
127
  formErrors={formErrors}
128
+ // eslint-disable-next-line react/no-array-index-key
208
129
  key={index}
209
130
  index={index}
210
- isOpen={isOpen}
211
131
  isFieldAllowed={isFieldAllowed}
212
- moveComponentDown={handleMoveComponentDown}
213
- moveComponentUp={handleMoveComponentUp}
214
- onToggle={handleToggleComponent}
132
+ onMoveComponentDownClick={handleMoveComponentDown(name, index)}
133
+ onMoveComponentUpClick={handleMoveComponentUp(name, index)}
215
134
  name={name}
216
- removeComponentFromDynamicZone={handleRemoveComponent}
135
+ onRemoveComponentClick={handleRemoveComponent(name, index)}
217
136
  showDownIcon={showDownIcon}
218
137
  showUpIcon={showUpIcon}
219
138
  />
@@ -229,13 +148,13 @@ const DynamicZone = ({
229
148
  isDisabled={!isFieldAllowed}
230
149
  label={metadatas.label}
231
150
  missingComponentNumber={missingComponentNumber}
232
- isOpen={isOpen}
151
+ isOpen={addComponentIsOpen}
233
152
  name={name}
234
153
  onClick={handleClickOpenPicker}
235
154
  />
236
155
  <ComponentPicker
237
- isOpen={isOpen}
238
- components={dynamicZoneAvailableComponents}
156
+ isOpen={addComponentIsOpen}
157
+ components={fieldSchema.components ?? []}
239
158
  onClickAddComponent={handleAddComponent}
240
159
  />
241
160
  </Stack>
@@ -1,3 +1,4 @@
1
+ /* eslint-disable react/jsx-no-constructed-context-values */
1
2
  import React, { useCallback, useEffect, useMemo, useRef, useReducer } from 'react';
2
3
  import isEmpty from 'lodash/isEmpty';
3
4
  import cloneDeep from 'lodash/cloneDeep';
@@ -20,7 +21,7 @@ import {
20
21
 
21
22
  import { getTrad, removeKeyInObject } from '../../utils';
22
23
  import reducer, { initialState } from './reducer';
23
- import { cleanData, createYupSchema } from './utils';
24
+ import { cleanData, createYupSchema, recursivelyFindPathsBasedOnCondition } from './utils';
24
25
 
25
26
  const EditViewDataManagerProvider = ({
26
27
  allLayoutData,
@@ -46,6 +47,10 @@ const EditViewDataManagerProvider = ({
46
47
  status,
47
48
  updateActionAllowedFields,
48
49
  }) => {
50
+ /**
51
+ * TODO: this should be moved into the global reducer
52
+ * to match ever other reducer in the CM.
53
+ */
49
54
  const [reducerState, dispatch] = useReducer(reducer, initialState);
50
55
  const {
51
56
  formErrors,
@@ -137,45 +142,86 @@ const EditViewDataManagerProvider = ({
137
142
  });
138
143
  }, [componentsDataStructure, contentTypeDataStructure]);
139
144
 
145
+ const { components } = allLayoutData;
146
+
140
147
  useEffect(() => {
141
- if (initialValues) {
142
- const relationalFields = Object.keys(initialValues).filter(
143
- (key) => currentContentTypeLayout?.attributes[key]?.type === 'relation'
144
- );
148
+ if (initialValues && currentContentTypeLayout?.attributes) {
149
+ /**
150
+ * This will return an array of paths:
151
+ * ['many_to_one', 'one_to_many', 'one_to_one']
152
+ * it can also return a path to a relation:
153
+ * ['relation_component.categories']
154
+ */
155
+ const relationalFieldPaths = recursivelyFindPathsBasedOnCondition(
156
+ components,
157
+ (value) => value.type === 'relation'
158
+ )(currentContentTypeLayout.attributes);
159
+
160
+ const componentPaths = recursivelyFindPathsBasedOnCondition(
161
+ components,
162
+ (value) => value.type === 'component' && !value.repeatable
163
+ )(currentContentTypeLayout.attributes);
164
+
165
+ const repeatableComponentPaths = recursivelyFindPathsBasedOnCondition(
166
+ components,
167
+ (value) => value.type === 'component' && value.repeatable
168
+ )(currentContentTypeLayout.attributes);
169
+
170
+ const dynamicZonePaths = recursivelyFindPathsBasedOnCondition(
171
+ components,
172
+ (value) => value.type === 'dynamiczone'
173
+ )(currentContentTypeLayout.attributes);
145
174
 
146
175
  dispatch({
147
176
  type: 'INIT_FORM',
148
177
  initialValues,
149
- relationalFields,
178
+ relationalFieldPaths,
179
+ componentPaths,
180
+ repeatableComponentPaths,
181
+ dynamicZonePaths,
150
182
  });
151
183
  }
152
- }, [initialValues, currentContentTypeLayout]);
184
+ }, [initialValues, currentContentTypeLayout, components]);
153
185
 
154
- const addComponentToDynamicZone = useCallback((keys, componentUid, shouldCheckErrors = false) => {
155
- trackUsageRef.current('didAddComponentToDynamicZone');
186
+ const dispatchAddComponent = useCallback(
187
+ (type) =>
188
+ (keys, componentLayoutData, components, shouldCheckErrors = false) => {
189
+ trackUsageRef.current('didAddComponentToDynamicZone');
156
190
 
157
- dispatch({
158
- type: 'ADD_COMPONENT_TO_DYNAMIC_ZONE',
159
- keys: keys.split('.'),
160
- componentUid,
161
- shouldCheckErrors,
162
- });
163
- }, []);
191
+ dispatch({
192
+ type,
193
+ keys: keys.split('.'),
194
+ componentLayoutData,
195
+ allComponents: components,
196
+ shouldCheckErrors,
197
+ });
198
+ },
199
+ []
200
+ );
164
201
 
165
- const addNonRepeatableComponentToField = useCallback((keys, componentUid) => {
166
- dispatch({
167
- type: 'ADD_NON_REPEATABLE_COMPONENT_TO_FIELD',
168
- keys: keys.split('.'),
169
- componentUid,
170
- });
171
- }, []);
202
+ const addComponentToDynamicZone = dispatchAddComponent('ADD_COMPONENT_TO_DYNAMIC_ZONE');
203
+
204
+ const addNonRepeatableComponentToField = useCallback(
205
+ (keys, componentLayoutData, allComponents) => {
206
+ dispatch({
207
+ type: 'ADD_NON_REPEATABLE_COMPONENT_TO_FIELD',
208
+ keys: keys.split('.'),
209
+ componentLayoutData,
210
+ allComponents,
211
+ });
212
+ },
213
+ []
214
+ );
172
215
 
173
- const connectRelation = useCallback(({ target: { name, value, replace } }) => {
216
+ /**
217
+ * @type {({ name: string, value: Relation, toOneRelation: boolean}) => void}
218
+ */
219
+ const connectRelation = useCallback(({ name, value, toOneRelation }) => {
174
220
  dispatch({
175
221
  type: 'CONNECT_RELATION',
176
222
  keys: name.split('.'),
177
223
  value,
178
- replace,
224
+ toOneRelation,
179
225
  });
180
226
  }, []);
181
227
 
@@ -187,17 +233,7 @@ const EditViewDataManagerProvider = ({
187
233
  });
188
234
  }, []);
189
235
 
190
- const addRepeatableComponentToField = useCallback(
191
- (keys, componentUid, shouldCheckErrors = false) => {
192
- dispatch({
193
- type: 'ADD_REPEATABLE_COMPONENT_TO_FIELD',
194
- keys: keys.split('.'),
195
- componentUid,
196
- shouldCheckErrors,
197
- });
198
- },
199
- []
200
- );
236
+ const addRepeatableComponentToField = dispatchAddComponent('ADD_REPEATABLE_COMPONENT_TO_FIELD');
201
237
 
202
238
  const yupSchema = useMemo(() => {
203
239
  const options = { isCreatingEntry, isDraft: shouldNotRunValidations, isFromComponent: false };
@@ -287,12 +323,12 @@ const EditViewDataManagerProvider = ({
287
323
  );
288
324
 
289
325
  const createFormData = useCallback(
290
- (data) => {
326
+ (modifiedData, initialData) => {
291
327
  // First we need to remove the added keys needed for the dnd
292
- const preparedData = removeKeyInObject(cloneDeep(data), '__temp_key__');
328
+ const preparedData = removeKeyInObject(cloneDeep(modifiedData), '__temp_key__');
293
329
  // Then we need to apply our helper
294
330
  const cleanedData = cleanData(
295
- preparedData,
331
+ { browserState: preparedData, serverState: initialData },
296
332
  currentContentTypeLayout,
297
333
  allLayoutData.components
298
334
  );
@@ -331,7 +367,7 @@ const EditViewDataManagerProvider = ({
331
367
 
332
368
  try {
333
369
  if (isEmpty(errors)) {
334
- const formData = createFormData(modifiedData);
370
+ const formData = createFormData(modifiedData, initialData);
335
371
 
336
372
  if (isCreatingEntry) {
337
373
  await onPost(formData, trackerProperty);
@@ -351,7 +387,16 @@ const EditViewDataManagerProvider = ({
351
387
  errors,
352
388
  });
353
389
  },
354
- [createFormData, isCreatingEntry, modifiedData, onPost, onPut, trackerProperty, yupSchema]
390
+ [
391
+ createFormData,
392
+ isCreatingEntry,
393
+ modifiedData,
394
+ initialData,
395
+ onPost,
396
+ onPut,
397
+ trackerProperty,
398
+ yupSchema,
399
+ ]
355
400
  );
356
401
 
357
402
  const handlePublish = useCallback(async () => {
@@ -462,11 +507,11 @@ const EditViewDataManagerProvider = ({
462
507
  });
463
508
  }, []);
464
509
 
465
- const disconnectRelation = useCallback(({ target: { name, value } }) => {
510
+ const disconnectRelation = useCallback(({ name, id }) => {
466
511
  dispatch({
467
512
  type: 'DISCONNECT_RELATION',
468
513
  keys: name.split('.'),
469
- value,
514
+ id,
470
515
  });
471
516
  }, []);
472
517
 
@@ -554,23 +599,21 @@ const EditViewDataManagerProvider = ({
554
599
  publishConfirmation,
555
600
  }}
556
601
  >
557
- <>
558
- {isLoadingForData || (!isCreatingEntry && !initialData.id) ? (
559
- <Main aria-busy="true">
560
- <LoadingIndicatorPage />
561
- </Main>
562
- ) : (
563
- <>
564
- <Prompt
565
- when={!isEqual(modifiedData, initialData)}
566
- message={formatMessage({ id: 'global.prompt.unsaved' })}
567
- />
568
- <form noValidate onSubmit={handleSubmit}>
569
- {children}
570
- </form>
571
- </>
572
- )}
573
- </>
602
+ {isLoadingForData || (!isCreatingEntry && !initialData.id) ? (
603
+ <Main aria-busy="true">
604
+ <LoadingIndicatorPage />
605
+ </Main>
606
+ ) : (
607
+ <>
608
+ <Prompt
609
+ when={!isEqual(modifiedData, initialData)}
610
+ message={formatMessage({ id: 'global.prompt.unsaved' })}
611
+ />
612
+ <form noValidate onSubmit={handleSubmit}>
613
+ {children}
614
+ </form>
615
+ </>
616
+ )}
574
617
  </ContentManagerEditViewDataManagerContext.Provider>
575
618
  );
576
619
  };