@strapi/admin 4.6.0-alpha.1 → 4.6.0-beta.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 (248) hide show
  1. package/admin/src/components/AuthenticatedApp/index.js +13 -2
  2. package/admin/src/components/GlobalStyle/index.js +0 -5
  3. package/admin/src/content-manager/components/ComponentIcon/ComponentIcon.js +49 -0
  4. package/admin/src/content-manager/components/ComponentIcon/index.js +1 -0
  5. package/admin/src/content-manager/components/ComponentInitializer/index.js +1 -7
  6. package/admin/src/content-manager/components/{RepeatableComponent/DragPreview.js → DragLayer/ComponentDragPreview.js} +10 -11
  7. package/admin/src/content-manager/components/DragLayer/RelationDragPreview.js +75 -0
  8. package/admin/src/content-manager/components/DragLayer/index.js +23 -7
  9. package/admin/src/content-manager/components/DynamicZone/components/ComponentCard.js +17 -31
  10. package/admin/src/content-manager/components/DynamicZone/components/ComponentCategory.js +2 -2
  11. package/admin/src/content-manager/components/DynamicZone/components/DynamicComponent.js +129 -85
  12. package/admin/src/content-manager/components/DynamicZone/index.js +99 -24
  13. package/admin/src/content-manager/components/DynamicZone/utils/select.js +9 -5
  14. package/admin/src/content-manager/components/EditViewDataManagerProvider/index.js +76 -14
  15. package/admin/src/content-manager/components/EditViewDataManagerProvider/reducer.js +42 -25
  16. package/admin/src/content-manager/components/EditViewDataManagerProvider/utils/cleanData.js +24 -5
  17. package/admin/src/content-manager/components/EditViewDataManagerProvider/utils/recursivelyFindPathsBasedOnCondition.js +8 -1
  18. package/admin/src/content-manager/components/InputJSON/FieldWrapper.js +10 -2
  19. package/admin/src/content-manager/components/InputJSON/Label.js +2 -18
  20. package/admin/src/content-manager/components/InputJSON/index.js +7 -3
  21. package/admin/src/content-manager/components/NonRepeatableComponent/index.js +4 -0
  22. package/admin/src/content-manager/components/RelationInput/RelationInput.js +205 -74
  23. package/admin/src/content-manager/components/RelationInput/components/RelationItem.js +136 -21
  24. package/admin/src/content-manager/components/RelationInput/components/RelationList.js +1 -2
  25. package/admin/src/content-manager/components/RelationInput/constants.js +1 -0
  26. package/admin/src/content-manager/components/RelationInput/index.js +1 -0
  27. package/admin/src/content-manager/components/RelationInputDataManager/RelationInputDataManager.js +132 -10
  28. package/admin/src/content-manager/components/RepeatableComponent/components/Accordion.js +77 -0
  29. package/admin/src/content-manager/components/RepeatableComponent/components/Component.js +262 -0
  30. package/admin/src/content-manager/components/RepeatableComponent/{DraggedItem → components}/Preview.js +0 -0
  31. package/admin/src/content-manager/components/RepeatableComponent/index.js +148 -90
  32. package/admin/src/content-manager/components/RepeatableComponent/utils/getComponentErrorKeys.js +1 -1
  33. package/admin/src/content-manager/components/SingleTypeFormWrapper/index.js +1 -1
  34. package/admin/src/content-manager/components/Wysiwyg/Editor.js +1 -1
  35. package/admin/src/content-manager/hooks/index.js +2 -0
  36. package/admin/src/content-manager/hooks/useDragAndDrop.js +134 -0
  37. package/admin/src/content-manager/hooks/useKeyboardDragAndDrop.js +98 -0
  38. package/admin/src/content-manager/hooks/useLazyComponents/index.js +40 -15
  39. package/admin/src/content-manager/pages/EditSettingsView/components/DynamicZoneList.js +18 -38
  40. package/admin/src/content-manager/sharedReducers/crudReducer/actions.js +5 -0
  41. package/admin/src/content-manager/sharedReducers/crudReducer/constants.js +2 -0
  42. package/admin/src/content-manager/sharedReducers/crudReducer/reducer.js +7 -0
  43. package/admin/src/content-manager/utils/ItemTypes.js +1 -1
  44. package/admin/src/content-manager/utils/composeRefs.js +28 -0
  45. package/admin/src/content-manager/utils/getMaxTempKey.js +1 -1
  46. package/admin/src/content-manager/utils/index.js +7 -0
  47. package/admin/src/core/utils/axiosInstance.js +4 -2
  48. package/admin/src/hooks/index.js +1 -0
  49. package/admin/src/hooks/useFetchClient/index.js +23 -0
  50. package/admin/src/hooks/useSettingsMenu/init.js +0 -7
  51. package/admin/src/pages/Admin/Onboarding/index.js +42 -44
  52. package/admin/src/pages/App/index.js +20 -13
  53. package/admin/src/pages/AuthPage/components/Register/index.js +1 -1
  54. package/admin/src/pages/AuthPage/components/ResetPassword/index.js +1 -1
  55. package/admin/src/pages/HomePage/SocialLinks.js +4 -4
  56. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/index.js +2 -3
  57. package/admin/src/pages/SettingsPage/pages/Users/ListPage/ModalForm/index.js +23 -18
  58. package/admin/src/pages/SettingsPage/utils/defaultRoutes.js +0 -11
  59. package/admin/src/permissions/defaultPermissions.js +0 -4
  60. package/admin/src/translations/en.json +8 -8
  61. package/admin/src/translations/sk.json +274 -52
  62. package/admin/src/translations/tr.json +485 -5
  63. package/admin/src/utils/fetchClient.js +45 -0
  64. package/admin/src/utils/getFetchClient.js +10 -0
  65. package/admin/src/utils/index.js +1 -0
  66. package/admin/src/utils/uniqueAdminHash.js +22 -0
  67. package/build/2235.06c13219.chunk.js +106 -0
  68. package/build/2598.962797b2.chunk.js +159 -0
  69. package/build/4318.0bbd3f4b.chunk.js +30 -0
  70. package/build/4958.7c118f5e.chunk.js +276 -0
  71. package/build/5052.712419ea.chunk.js +65 -0
  72. package/build/7295.04ac49dc.chunk.js +114 -0
  73. package/build/805.ddcead70.chunk.js +138 -0
  74. package/build/{8633.8da5488a.chunk.js → 8633.59223842.chunk.js} +1 -1
  75. package/build/874.bde3ea04.chunk.js +104 -0
  76. package/build/{1233.80b05d66.chunk.js → 9159.ac968e72.chunk.js} +67 -67
  77. package/build/9707.77e475ee.chunk.js +101 -0
  78. package/build/Admin-authenticatedApp.9dd415b8.chunk.js +72 -0
  79. package/build/{Admin_homePage.54e33c2d.chunk.js → Admin_homePage.8945f71a.chunk.js} +5 -5
  80. package/build/{Admin_marketplace.8219fda6.chunk.js → Admin_marketplace.ed754a4a.chunk.js} +1 -1
  81. package/build/Admin_pluginsPage.67728975.chunk.js +6 -0
  82. package/build/{Admin_profilePage.e9fcce92.chunk.js → Admin_profilePage.60ab80bb.chunk.js} +1 -1
  83. package/build/{Admin_settingsPage.d3f48e9e.chunk.js → Admin_settingsPage.9ce40fed.chunk.js} +15 -15
  84. package/build/Upload_ConfigureTheView.7cb2a3fd.chunk.js +1 -0
  85. package/build/admin-app.d8fc7c4d.chunk.js +112 -0
  86. package/build/admin-edit-roles-page.f407538c.chunk.js +1 -0
  87. package/build/admin-edit-users.5547b126.chunk.js +10 -0
  88. package/build/{admin-users.a0748674.chunk.js → admin-users.4b6b47f8.chunk.js} +2 -2
  89. package/build/api-tokens-create-page.dd4ddfcb.chunk.js +1 -0
  90. package/build/api-tokens-edit-page.821c5a6c.chunk.js +1 -0
  91. package/build/{api-tokens-list-page.700e575f.chunk.js → api-tokens-list-page.50519ed7.chunk.js} +1 -1
  92. package/build/content-manager.f2214e32.chunk.js +1166 -0
  93. package/build/content-type-builder-list-view.4aea46fa.chunk.js +198 -0
  94. package/build/content-type-builder-translation-de-json.a52482c7.chunk.js +1 -0
  95. package/build/content-type-builder-translation-dk-json.a8616510.chunk.js +1 -0
  96. package/build/content-type-builder-translation-en-json.1d9a3c14.chunk.js +1 -0
  97. package/build/content-type-builder-translation-es-json.c3ea46fb.chunk.js +1 -0
  98. package/build/content-type-builder-translation-ko-json.3fb7ddc8.chunk.js +1 -0
  99. package/build/content-type-builder-translation-pl-json.9b2993b2.chunk.js +1 -0
  100. package/build/content-type-builder-translation-pt-BR-json.6d255441.chunk.js +1 -0
  101. package/build/content-type-builder-translation-sv-json.c608b9ca.chunk.js +1 -0
  102. package/build/content-type-builder-translation-tr-json.949e22eb.chunk.js +1 -0
  103. package/build/content-type-builder-translation-zh-json.b79513e4.chunk.js +1 -0
  104. package/build/content-type-builder.8a9a77f9.chunk.js +127 -0
  105. package/build/email-settings-page.c6e62f6b.chunk.js +15 -0
  106. package/build/email-translation-tr-json.8aa034bb.chunk.js +1 -0
  107. package/build/en-json.1abdade9.chunk.js +1 -0
  108. package/build/{i18n-settings-page.195d42fe.chunk.js → i18n-settings-page.ee572037.chunk.js} +1 -1
  109. package/build/i18n-translation-tr-json.34ca9d61.chunk.js +1 -0
  110. package/build/index.html +1 -1
  111. package/build/main.91f6e21e.js +4099 -0
  112. package/build/runtime~main.447b0382.js +2 -0
  113. package/build/sk-json.2af48064.chunk.js +1 -0
  114. package/build/sso-settings-page.91924df1.chunk.js +41 -0
  115. package/build/tr-json.eac8bd79.chunk.js +1 -0
  116. package/build/upload-settings.326cd9fd.chunk.js +89 -0
  117. package/build/upload-translation-en-json.32cf9aff.chunk.js +1 -0
  118. package/build/upload-translation-sk-json.fe86c53b.chunk.js +1 -0
  119. package/build/upload-translation-tr-json.b173223a.chunk.js +1 -0
  120. package/build/upload.2977cb13.chunk.js +38 -0
  121. package/build/users-advanced-settings-page.0c0b8230.chunk.js +13 -0
  122. package/build/users-email-settings-page.18d4a475.chunk.js +28 -0
  123. package/build/{users-permissions-translation-dk-json.fe39c74b.chunk.js → users-permissions-translation-dk-json.bad0b786.chunk.js} +1 -1
  124. package/build/{users-permissions-translation-en-json.765abf48.chunk.js → users-permissions-translation-en-json.aeab388a.chunk.js} +1 -1
  125. package/build/{users-permissions-translation-es-json.1bb9cde2.chunk.js → users-permissions-translation-es-json.152a923f.chunk.js} +1 -1
  126. package/build/{users-permissions-translation-ko-json.3be77775.chunk.js → users-permissions-translation-ko-json.6bd0ae22.chunk.js} +1 -1
  127. package/build/{users-permissions-translation-pl-json.1dbdd4a1.chunk.js → users-permissions-translation-pl-json.c6a02992.chunk.js} +1 -1
  128. package/build/{users-permissions-translation-sv-json.d5d11648.chunk.js → users-permissions-translation-sv-json.370d6eee.chunk.js} +1 -1
  129. package/build/users-permissions-translation-tr-json.9bebc250.chunk.js +1 -0
  130. package/build/{users-permissions-translation-zh-json.92f406f9.chunk.js → users-permissions-translation-zh-json.1fea833f.chunk.js} +1 -1
  131. package/build/users-providers-settings-page.25dd858e.chunk.js +1 -0
  132. package/build/users-roles-settings-page.8482a999.chunk.js +30 -0
  133. package/build/{webhook-edit-page.14ad1e6e.chunk.js → webhook-edit-page.dcc3d145.chunk.js} +4 -4
  134. package/build/{webhook-list-page.b87821f2.chunk.js → webhook-list-page.894e6959.chunk.js} +1 -1
  135. package/ee/server/services/passport/provider-registry.js +1 -1
  136. package/package.json +16 -22
  137. package/server/controllers/admin.js +2 -0
  138. package/server/routes/admin.js +1 -1
  139. package/server/services/metrics.js +5 -2
  140. package/server/services/role.js +1 -0
  141. package/utils/get-plugins-path.js +17 -3
  142. package/webpack.alias.js +0 -2
  143. package/admin/src/content-manager/components/BackHeader/index.js +0 -8
  144. package/admin/src/content-manager/components/Block/components.js +0 -28
  145. package/admin/src/content-manager/components/Block/index.js +0 -43
  146. package/admin/src/content-manager/components/Container/index.js +0 -7
  147. package/admin/src/content-manager/components/CustomInputCheckbox/components.js +0 -77
  148. package/admin/src/content-manager/components/CustomInputCheckbox/index.js +0 -53
  149. package/admin/src/content-manager/components/DynamicComponentCard/Wrapper.js +0 -63
  150. package/admin/src/content-manager/components/FilterOptionsCTA/index.js +0 -14
  151. package/admin/src/content-manager/components/FormTitle/index.js +0 -22
  152. package/admin/src/content-manager/components/FormWrapper/index.js +0 -20
  153. package/admin/src/content-manager/components/InputJSON/FieldError.js +0 -38
  154. package/admin/src/content-manager/components/LayoutTitle/index.js +0 -19
  155. package/admin/src/content-manager/components/PlusButton/index.js +0 -52
  156. package/admin/src/content-manager/components/PreviewCarret/components.js +0 -27
  157. package/admin/src/content-manager/components/PreviewCarret/index.js +0 -22
  158. package/admin/src/content-manager/components/RepeatableComponent/AccordionGroupCustom/index.js +0 -122
  159. package/admin/src/content-manager/components/RepeatableComponent/AddFieldButton.js +0 -58
  160. package/admin/src/content-manager/components/RepeatableComponent/DraggedItem/DraggingSibling.js +0 -72
  161. package/admin/src/content-manager/components/RepeatableComponent/DraggedItem/IconButtonCustoms.js +0 -32
  162. package/admin/src/content-manager/components/RepeatableComponent/DraggedItem/index.js +0 -322
  163. package/admin/src/content-manager/components/RepeatableComponent/DraggedItem/utils/connect.js +0 -11
  164. package/admin/src/content-manager/components/RepeatableComponent/DraggedItem/utils/index.js +0 -2
  165. package/admin/src/content-manager/components/RepeatableComponent/DraggedItem/utils/select.js +0 -30
  166. package/admin/src/content-manager/components/RepeatableComponent/utils/connect.js +0 -11
  167. package/admin/src/content-manager/components/RepeatableComponent/utils/select.js +0 -12
  168. package/admin/src/content-manager/components/SectionTitle/Title.js +0 -11
  169. package/admin/src/content-manager/components/SectionTitle/index.js +0 -26
  170. package/admin/src/content-manager/hooks/__test__/usePrev.test.js +0 -26
  171. package/admin/src/pages/SettingsPage/pages/AuditLogs/ListView/DynamicTable/TableRows/CellValue.js +0 -19
  172. package/admin/src/pages/SettingsPage/pages/AuditLogs/ListView/DynamicTable/TableRows/index.js +0 -65
  173. package/admin/src/pages/SettingsPage/pages/AuditLogs/ListView/ModalDialog/ActionItem.js +0 -25
  174. package/admin/src/pages/SettingsPage/pages/AuditLogs/ListView/ModalDialog/index.js +0 -76
  175. package/admin/src/pages/SettingsPage/pages/AuditLogs/ListView/hooks/useFormatTimeStamp.js +0 -24
  176. package/admin/src/pages/SettingsPage/pages/AuditLogs/ListView/index.js +0 -84
  177. package/admin/src/pages/SettingsPage/pages/AuditLogs/ListView/utils/tableHeaders.js +0 -37
  178. package/admin/src/pages/SettingsPage/pages/AuditLogs/ProtectedListPage/index.js +0 -12
  179. package/build/1551f4f60c37af51121f.woff2 +0 -0
  180. package/build/1920.74a262e7.chunk.js +0 -245
  181. package/build/1e59d2330b4c6deb84b3.ttf +0 -0
  182. package/build/20fd1704ea223900efa9.woff2 +0 -0
  183. package/build/2285773e6b4b172f07d9.woff +0 -0
  184. package/build/23f19bb08961f37aaf69.eot +0 -0
  185. package/build/2438.61291207.chunk.js +0 -2183
  186. package/build/2517.9b4940f3.chunk.js +0 -117
  187. package/build/2f517e09eb2ca6650ff5.svg +0 -3717
  188. package/build/4306.f03c2b46.chunk.js +0 -98
  189. package/build/4318.7931eee7.chunk.js +0 -30
  190. package/build/4689f52cc96215721344.svg +0 -801
  191. package/build/491974d108fe4002b2aa.ttf +0 -0
  192. package/build/4986.3820d11d.chunk.js +0 -145
  193. package/build/504.9aeff724.chunk.js +0 -758
  194. package/build/527940b104eb2ea366c8.ttf +0 -0
  195. package/build/77206a6bb316fa0aded5.eot +0 -0
  196. package/build/7a3337626410ca2f4071.woff2 +0 -0
  197. package/build/7a8b4f130182d19a2d7c.svg +0 -5034
  198. package/build/805.e991a370.chunk.js +0 -138
  199. package/build/8b43027f47b20503057d.eot +0 -0
  200. package/build/9707.a0cc4ad8.chunk.js +0 -70
  201. package/build/9bbb245e67a133f6e486.eot +0 -0
  202. package/build/Admin-authenticatedApp.ac85652e.chunk.js +0 -80
  203. package/build/Admin_pluginsPage.3c872de7.chunk.js +0 -6
  204. package/build/admin-app.77179e07.chunk.js +0 -112
  205. package/build/admin-audit-logs.334ee871.chunk.js +0 -1
  206. package/build/admin-edit-roles-page.23f15909.chunk.js +0 -1
  207. package/build/admin-edit-users.283b49ed.chunk.js +0 -10
  208. package/build/api-tokens-create-page.93dd0689.chunk.js +0 -1
  209. package/build/api-tokens-edit-page.b0adac81.chunk.js +0 -1
  210. package/build/bb58e57c48a3e911f15f.woff +0 -0
  211. package/build/be9ee23c0c6390141475.ttf +0 -0
  212. package/build/c1e38fd9e0e74ba58f7a.svg +0 -2671
  213. package/build/content-manager.01e04e11.chunk.js +0 -1200
  214. package/build/content-type-builder-list-view.4412efc3.chunk.js +0 -201
  215. package/build/content-type-builder-translation-de-json.0d7696b9.chunk.js +0 -1
  216. package/build/content-type-builder-translation-dk-json.4729f055.chunk.js +0 -1
  217. package/build/content-type-builder-translation-en-json.f985c9c4.chunk.js +0 -1
  218. package/build/content-type-builder-translation-es-json.333cf47f.chunk.js +0 -1
  219. package/build/content-type-builder-translation-ko-json.51201b12.chunk.js +0 -1
  220. package/build/content-type-builder-translation-pl-json.4a42349b.chunk.js +0 -1
  221. package/build/content-type-builder-translation-pt-BR-json.6fe3b8d1.chunk.js +0 -1
  222. package/build/content-type-builder-translation-sv-json.6deff030.chunk.js +0 -1
  223. package/build/content-type-builder-translation-tr-json.2e52bc60.chunk.js +0 -1
  224. package/build/content-type-builder-translation-zh-json.3b0afd31.chunk.js +0 -1
  225. package/build/content-type-builder.aa4ec633.chunk.js +0 -145
  226. package/build/d878b0a6a1144760244f.woff2 +0 -0
  227. package/build/eeccf4f66002c6f2ba24.woff +0 -0
  228. package/build/email-settings-page.d44a57cb.chunk.js +0 -15
  229. package/build/email-translation-tr-json.87f2feb3.chunk.js +0 -1
  230. package/build/en-json.57917cb1.chunk.js +0 -1
  231. package/build/f691f37e57f04c152e23.woff +0 -0
  232. package/build/fontawesome-css-all.15068c6e.chunk.js +0 -4618
  233. package/build/fontawesome-css.418f40da.chunk.js +0 -6
  234. package/build/fontawesome-js.252cc5f3.chunk.js +0 -7
  235. package/build/main.f31112a5.js +0 -2034
  236. package/build/runtime~main.81f05721.js +0 -2
  237. package/build/sk-json.7ba4b330.chunk.js +0 -1
  238. package/build/sso-settings-page.9f091262.chunk.js +0 -1
  239. package/build/tr-json.9c44ea0c.chunk.js +0 -1
  240. package/build/upload-settings.450cab1a.chunk.js +0 -18
  241. package/build/upload-translation-en-json.86da7b0a.chunk.js +0 -1
  242. package/build/upload-translation-sk-json.b03d4904.chunk.js +0 -1
  243. package/build/upload.a73936d9.chunk.js +0 -64
  244. package/build/users-advanced-settings-page.dc23bc56.chunk.js +0 -13
  245. package/build/users-email-settings-page.6541d372.chunk.js +0 -28
  246. package/build/users-permissions-translation-tr-json.cdc49a3c.chunk.js +0 -1
  247. package/build/users-providers-settings-page.e11a2f64.chunk.js +0 -33
  248. package/build/users-roles-settings-page.445e5e16.chunk.js +0 -30
@@ -1,6 +1,6 @@
1
1
  /* eslint-disable no-nested-ternary */
2
2
  import PropTypes from 'prop-types';
3
- import React, { memo, useMemo } from 'react';
3
+ import React, { memo, useMemo, useState } from 'react';
4
4
  import { useIntl } from 'react-intl';
5
5
  import get from 'lodash/get';
6
6
  import pick from 'lodash/pick';
@@ -36,11 +36,20 @@ export const RelationInputDataManager = ({
36
36
  size,
37
37
  targetModel,
38
38
  }) => {
39
+ const [liveText, setLiveText] = useState('');
40
+
39
41
  const { formatMessage } = useIntl();
40
- const { connectRelation, disconnectRelation, loadRelation, modifiedData, slug, initialData } =
41
- useCMEditViewDataManager();
42
+ const {
43
+ slug,
44
+ initialData,
45
+ modifiedData,
46
+ relationConnect,
47
+ relationDisconnect,
48
+ relationLoad,
49
+ relationReorder,
50
+ } = useCMEditViewDataManager();
42
51
 
43
- const relationsFromModifiedData = get(modifiedData, name) ?? [];
52
+ const relationsFromModifiedData = get(modifiedData, name, []);
44
53
 
45
54
  const currentLastPage = Math.ceil(get(initialData, name, []).length / RELATIONS_TO_DISPLAY);
46
55
 
@@ -54,7 +63,7 @@ export const RelationInputDataManager = ({
54
63
  ...defaultParams,
55
64
  pageSize: RELATIONS_TO_DISPLAY,
56
65
  },
57
- onLoad: loadRelation,
66
+ onLoad: relationLoad,
58
67
  normalizeArguments: {
59
68
  mainFieldName: mainField.name,
60
69
  shouldAddLink: shouldDisplayRelationLink,
@@ -104,11 +113,11 @@ export const RelationInputDataManager = ({
104
113
  targetModel,
105
114
  });
106
115
 
107
- connectRelation({ name, value: normalizedRelation, toOneRelation });
116
+ relationConnect({ name, value: normalizedRelation, toOneRelation });
108
117
  };
109
118
 
110
119
  const handleRelationDisconnect = (relation) => {
111
- disconnectRelation({ name, id: relation.id });
120
+ relationDisconnect({ name, id: relation.id });
112
121
  };
113
122
 
114
123
  const handleRelationLoadMore = () => {
@@ -130,6 +139,105 @@ export const RelationInputDataManager = ({
130
139
  const handleSearchMore = () => {
131
140
  search.fetchNextPage();
132
141
  };
142
+ /**
143
+ *
144
+ * @param {number} index
145
+ * @returns {string}
146
+ */
147
+ const getItemPos = (index) => `${index + 1} of ${relationsFromModifiedData.length}`;
148
+
149
+ /**
150
+ *
151
+ * @param {number} currentIndex
152
+ * @param {number} oldIndex
153
+ */
154
+ const handleRelationReorder = (oldIndex, newIndex) => {
155
+ const item = relationsFromModifiedData[oldIndex];
156
+
157
+ setLiveText(
158
+ formatMessage(
159
+ {
160
+ id: getTrad('dnd.reorder'),
161
+ defaultMessage: '{item}, moved. New position in list: {position}.',
162
+ },
163
+ {
164
+ item: item.mainField ?? item.id,
165
+ position: getItemPos(newIndex),
166
+ }
167
+ )
168
+ );
169
+
170
+ relationReorder({
171
+ name,
172
+ newIndex,
173
+ oldIndex,
174
+ });
175
+ };
176
+
177
+ /**
178
+ *
179
+ * @param {number} index
180
+ * @returns {void}
181
+ */
182
+ const handleGrabItem = (index) => {
183
+ const item = relationsFromModifiedData[index];
184
+
185
+ setLiveText(
186
+ formatMessage(
187
+ {
188
+ id: getTrad('dnd.grab-item'),
189
+ defaultMessage: `{item}, grabbed. Current position in list: {position}. Press up and down arrow to change position, Spacebar to drop, Escape to cancel.`,
190
+ },
191
+ {
192
+ item: item.mainField ?? item.id,
193
+ position: getItemPos(index),
194
+ }
195
+ )
196
+ );
197
+ };
198
+
199
+ /**
200
+ *
201
+ * @param {number} index
202
+ * @returns {void}
203
+ */
204
+ const handleDropItem = (index) => {
205
+ const item = relationsFromModifiedData[index];
206
+
207
+ setLiveText(
208
+ formatMessage(
209
+ {
210
+ id: getTrad('dnd.drop-item'),
211
+ defaultMessage: `{item}, dropped. Final position in list: {position}.`,
212
+ },
213
+ {
214
+ item: item.mainField ?? item.id,
215
+ position: getItemPos(index),
216
+ }
217
+ )
218
+ );
219
+ };
220
+
221
+ /**
222
+ *
223
+ * @param {number} index
224
+ * @returns {void}
225
+ */
226
+ const handleCancel = (index) => {
227
+ const item = relationsFromModifiedData[index];
228
+
229
+ setLiveText(
230
+ formatMessage(
231
+ {
232
+ id: getTrad('dnd.cancel-item'),
233
+ defaultMessage: '{item}, dropped. Re-order cancelled.',
234
+ },
235
+ {
236
+ item: item.mainField ?? item.id,
237
+ }
238
+ )
239
+ );
240
+ };
133
241
 
134
242
  if (
135
243
  (!isFieldAllowed && isCreatingEntry) ||
@@ -163,8 +271,13 @@ export const RelationInputDataManager = ({
163
271
  return (
164
272
  <RelationInput
165
273
  error={error}
274
+ canReorder={!toOneRelation}
166
275
  description={description}
167
276
  disabled={isDisabled}
277
+ iconButtonAriaLabel={formatMessage({
278
+ id: getTrad('components.RelationInput.icon-button-aria-label'),
279
+ defaultMessage: 'Drag',
280
+ })}
168
281
  id={name}
169
282
  label={`${formatMessage({
170
283
  id: intlLabel.id,
@@ -183,7 +296,12 @@ export const RelationInputDataManager = ({
183
296
  id: getTrad('relation.disconnect'),
184
297
  defaultMessage: 'Remove',
185
298
  })}
299
+ listAriaDescription={formatMessage({
300
+ id: getTrad('dnd.instructions'),
301
+ defaultMessage: `Press spacebar to grab and re-order`,
302
+ })}
186
303
  listHeight={320}
304
+ liveText={liveText}
187
305
  loadingMessage={formatMessage({
188
306
  id: getTrad('relation.isLoading'),
189
307
  defaultMessage: 'Relations are loading',
@@ -194,9 +312,13 @@ export const RelationInputDataManager = ({
194
312
  defaultMessage: 'No relations available',
195
313
  })}
196
314
  numberOfRelationsToDisplay={RELATIONS_TO_DISPLAY}
197
- onRelationConnect={(relation) => handleRelationConnect(relation)}
198
- onRelationDisconnect={(relation) => handleRelationDisconnect(relation)}
199
- onRelationLoadMore={() => handleRelationLoadMore()}
315
+ onDropItem={handleDropItem}
316
+ onGrabItem={handleGrabItem}
317
+ onCancel={handleCancel}
318
+ onRelationConnect={handleRelationConnect}
319
+ onRelationDisconnect={handleRelationDisconnect}
320
+ onRelationLoadMore={handleRelationLoadMore}
321
+ onRelationReorder={handleRelationReorder}
200
322
  onSearch={(term) => handleSearch(term)}
201
323
  onSearchNextPage={() => handleSearchMore()}
202
324
  placeholder={formatMessage(
@@ -0,0 +1,77 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { useIntl } from 'react-intl';
4
+ import styled from 'styled-components';
5
+ import { Box, Typography, KeyboardNavigable } from '@strapi/design-system';
6
+
7
+ export const Footer = styled(Box)`
8
+ overflow: hidden;
9
+ border-bottom: 1px solid ${({ theme }) => theme.colors.neutral200};
10
+ border-right: 1px solid ${({ theme }) => theme.colors.neutral200};
11
+ border-left: 1px solid ${({ theme }) => theme.colors.neutral200};
12
+ border-radius: 0 0 ${({ theme }) => theme.borderRadius} ${({ theme }) => theme.borderRadius};
13
+ `;
14
+
15
+ export const Content = styled(Box)`
16
+ border-bottom: none;
17
+
18
+ /* add the borders and make sure the top is transparent to avoid jumping with the hover effect */
19
+ & > div > div {
20
+ border: 1px solid ${({ theme }) => theme.colors.neutral200};
21
+ border-top-color: transparent;
22
+ }
23
+
24
+ /* the top accordion _does_ need a border though */
25
+ & > div:first-child > div {
26
+ border-top: 1px solid ${({ theme }) => theme.colors.neutral200};
27
+ }
28
+
29
+ /* Reset all the border-radius' */
30
+ & > div > div,
31
+ & > div > div > div {
32
+ border-radius: unset;
33
+ }
34
+
35
+ /* Give the border radius back to the first accordion */
36
+ & > div:first-child > div,
37
+ & > div:first-child > div > div {
38
+ border-radius: ${({ theme }) => theme.borderRadius} ${({ theme }) => theme.borderRadius} 0 0;
39
+ }
40
+
41
+ & > div > div[data-strapi-expanded='true'] {
42
+ border: 1px solid ${({ theme }) => theme.colors.primary600};
43
+ }
44
+ `;
45
+
46
+ export const Group = ({ children, error }) => {
47
+ const { formatMessage } = useIntl();
48
+
49
+ return (
50
+ <KeyboardNavigable attributeName="data-strapi-accordion-toggle">
51
+ {children}
52
+ {error && (
53
+ <Box paddingTop={1}>
54
+ <Typography variant="pi" textColor="danger600">
55
+ {formatMessage(
56
+ { id: error.id, defaultMessage: error.defaultMessage },
57
+ { ...error.values }
58
+ )}
59
+ </Typography>
60
+ </Box>
61
+ )}
62
+ </KeyboardNavigable>
63
+ );
64
+ };
65
+
66
+ Group.defaultProps = {
67
+ error: undefined,
68
+ };
69
+
70
+ Group.propTypes = {
71
+ children: PropTypes.node.isRequired,
72
+ error: PropTypes.shape({
73
+ id: PropTypes.string.isRequired,
74
+ defaultMessage: PropTypes.string.isRequired,
75
+ values: PropTypes.object,
76
+ }),
77
+ };
@@ -0,0 +1,262 @@
1
+ /* eslint-disable import/no-cycle */
2
+ import React, { memo, useEffect, useRef } from 'react';
3
+ import PropTypes from 'prop-types';
4
+ import { getEmptyImage } from 'react-dnd-html5-backend';
5
+ import styled from 'styled-components';
6
+ import { useIntl } from 'react-intl';
7
+ import toString from 'lodash/toString';
8
+ import get from 'lodash/get';
9
+
10
+ import { useCMEditViewDataManager } from '@strapi/helper-plugin';
11
+ import {
12
+ Accordion,
13
+ AccordionToggle,
14
+ AccordionContent,
15
+ Grid,
16
+ GridItem,
17
+ Stack,
18
+ Box,
19
+ IconButton,
20
+ } from '@strapi/design-system';
21
+ import { Trash, Drag } from '@strapi/icons';
22
+
23
+ import { useDragAndDrop } from '../../../hooks/useDragAndDrop';
24
+
25
+ import { composeRefs, getTrad, ItemTypes } from '../../../utils';
26
+
27
+ import Inputs from '../../Inputs';
28
+ import FieldComponent from '../../FieldComponent';
29
+
30
+ import Preview from './Preview';
31
+ import useLazyComponents from '../../../hooks/useLazyComponents';
32
+
33
+ const CustomIconButton = styled(IconButton)`
34
+ background-color: transparent;
35
+
36
+ svg {
37
+ path {
38
+ fill: ${({ theme, expanded }) =>
39
+ expanded ? theme.colors.primary600 : theme.colors.neutral600};
40
+ }
41
+ }
42
+
43
+ &:hover {
44
+ svg {
45
+ path {
46
+ fill: ${({ theme }) => theme.colors.primary600};
47
+ }
48
+ }
49
+ }
50
+ `;
51
+
52
+ const ActionsStack = styled(Stack)`
53
+ & .drag-handle {
54
+ background: unset;
55
+
56
+ svg {
57
+ path {
58
+ fill: ${({ theme, expanded }) => (expanded ? theme.colors.primary600 : undefined)};
59
+ }
60
+ }
61
+
62
+ &:hover {
63
+ svg {
64
+ path {
65
+ /* keeps the hover style of the accordion */
66
+ fill: ${({ theme }) => theme.colors.primary600};
67
+ }
68
+ }
69
+ }
70
+ }
71
+ `;
72
+
73
+ // Issues:
74
+ // https://github.com/react-dnd/react-dnd/issues/1368
75
+ // https://github.com/frontend-collective/react-sortable-tree/issues/490
76
+
77
+ const DraggedItem = ({
78
+ componentFieldName,
79
+ componentUid,
80
+ fields,
81
+ index,
82
+ isOpen,
83
+ isReadOnly,
84
+ mainField,
85
+ moveComponentField,
86
+ onClickToggle,
87
+ toggleCollapses,
88
+ onGrabItem,
89
+ onDropItem,
90
+ onCancel,
91
+ }) => {
92
+ const { modifiedData, removeRepeatableField, triggerFormValidation } = useCMEditViewDataManager();
93
+
94
+ const displayedValue = toString(
95
+ get(modifiedData, [...componentFieldName.split('.'), mainField], '')
96
+ );
97
+ const accordionRef = useRef(null);
98
+ const { formatMessage } = useIntl();
99
+
100
+ const [parentFieldName] = componentFieldName.split('.');
101
+
102
+ const [{ handlerId, isDragging, handleKeyDown }, boxRef, dropRef, dragRef, dragPreviewRef] =
103
+ useDragAndDrop(!isReadOnly, {
104
+ type: `${ItemTypes.COMPONENT}_${parentFieldName}`,
105
+ index,
106
+ item: {
107
+ displayedValue,
108
+ },
109
+ onMoveItem: moveComponentField,
110
+ onStart() {
111
+ // Close all collapses
112
+ toggleCollapses();
113
+ },
114
+ onEnd() {
115
+ // Update the errors
116
+ triggerFormValidation();
117
+ },
118
+ onGrabItem,
119
+ onDropItem,
120
+ onCancel,
121
+ });
122
+
123
+ useEffect(() => {
124
+ dragPreviewRef(getEmptyImage(), { captureDraggingState: false });
125
+ }, [dragPreviewRef, index]);
126
+
127
+ const composedAccordionRefs = composeRefs(accordionRef, dragRef);
128
+ const composedBoxRefs = composeRefs(boxRef, dropRef);
129
+
130
+ const { lazyComponentStore } = useLazyComponents();
131
+
132
+ return (
133
+ <Box ref={composedBoxRefs}>
134
+ {isDragging ? (
135
+ <Preview />
136
+ ) : (
137
+ <Accordion expanded={isOpen} onToggle={onClickToggle} id={componentFieldName} size="S">
138
+ <AccordionToggle
139
+ action={
140
+ isReadOnly ? null : (
141
+ <ActionsStack horizontal spacing={0} expanded={isOpen}>
142
+ <CustomIconButton
143
+ expanded={isOpen}
144
+ noBorder
145
+ onClick={() => {
146
+ removeRepeatableField(componentFieldName);
147
+ toggleCollapses();
148
+ }}
149
+ label={formatMessage({
150
+ id: getTrad('containers.Edit.delete'),
151
+ defaultMessage: 'Delete',
152
+ })}
153
+ icon={<Trash />}
154
+ />
155
+ <IconButton
156
+ className="drag-handle"
157
+ ref={composedAccordionRefs}
158
+ forwardedAs="div"
159
+ role="button"
160
+ noBorder
161
+ tabIndex={0}
162
+ onClick={(e) => e.stopPropagation()}
163
+ data-handler-id={handlerId}
164
+ label={formatMessage({
165
+ id: getTrad('components.DragHandle-label'),
166
+ defaultMessage: 'Drag',
167
+ })}
168
+ onKeyDown={handleKeyDown}
169
+ >
170
+ <Drag />
171
+ </IconButton>
172
+ </ActionsStack>
173
+ )
174
+ }
175
+ title={displayedValue}
176
+ togglePosition="left"
177
+ />
178
+ <AccordionContent>
179
+ <Stack background="neutral100" padding={6} spacing={6}>
180
+ {fields.map((fieldRow, key) => {
181
+ return (
182
+ // eslint-disable-next-line react/no-array-index-key
183
+ <Grid gap={4} key={key}>
184
+ {fieldRow.map(({ name, fieldSchema, metadatas, queryInfos, size }) => {
185
+ const isComponent = fieldSchema.type === 'component';
186
+ const keys = `${componentFieldName}.${name}`;
187
+
188
+ if (isComponent) {
189
+ const componentUid = fieldSchema.component;
190
+
191
+ return (
192
+ <GridItem col={size} s={12} xs={12} key={name}>
193
+ <FieldComponent
194
+ componentUid={componentUid}
195
+ intlLabel={{
196
+ id: metadatas.label,
197
+ defaultMessage: metadatas.label,
198
+ }}
199
+ isRepeatable={fieldSchema.repeatable}
200
+ isNested
201
+ name={keys}
202
+ max={fieldSchema.max}
203
+ min={fieldSchema.min}
204
+ required={fieldSchema.required}
205
+ />
206
+ </GridItem>
207
+ );
208
+ }
209
+
210
+ return (
211
+ <GridItem key={keys} col={size} s={12} xs={12}>
212
+ <Inputs
213
+ componentUid={componentUid}
214
+ fieldSchema={fieldSchema}
215
+ keys={keys}
216
+ metadatas={metadatas}
217
+ queryInfos={queryInfos}
218
+ size={size}
219
+ customFieldInputs={lazyComponentStore}
220
+ />
221
+ </GridItem>
222
+ );
223
+ })}
224
+ </Grid>
225
+ );
226
+ })}
227
+ </Stack>
228
+ </AccordionContent>
229
+ </Accordion>
230
+ )}
231
+ </Box>
232
+ );
233
+ };
234
+
235
+ DraggedItem.defaultProps = {
236
+ componentUid: undefined,
237
+ fields: [],
238
+ isReadOnly: false,
239
+ isOpen: false,
240
+ onGrabItem: undefined,
241
+ onDropItem: undefined,
242
+ onCancel: undefined,
243
+ toggleCollapses() {},
244
+ };
245
+
246
+ DraggedItem.propTypes = {
247
+ componentFieldName: PropTypes.string.isRequired,
248
+ componentUid: PropTypes.string,
249
+ fields: PropTypes.array,
250
+ index: PropTypes.number.isRequired,
251
+ isOpen: PropTypes.bool,
252
+ isReadOnly: PropTypes.bool,
253
+ mainField: PropTypes.string.isRequired,
254
+ moveComponentField: PropTypes.func.isRequired,
255
+ onGrabItem: PropTypes.func,
256
+ onDropItem: PropTypes.func,
257
+ onCancel: PropTypes.func,
258
+ onClickToggle: PropTypes.func.isRequired,
259
+ toggleCollapses: PropTypes.func,
260
+ };
261
+
262
+ export default memo(DraggedItem);