@strapi/admin 4.6.0-beta.0 → 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 (181) 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/DragLayer/ComponentDragPreview.js +2 -16
  6. package/admin/src/content-manager/components/DragLayer/RelationDragPreview.js +3 -3
  7. package/admin/src/content-manager/components/DragLayer/index.js +1 -1
  8. package/admin/src/content-manager/components/DynamicZone/components/ComponentCard.js +17 -31
  9. package/admin/src/content-manager/components/DynamicZone/components/ComponentCategory.js +2 -2
  10. package/admin/src/content-manager/components/DynamicZone/components/DynamicComponent.js +0 -2
  11. package/admin/src/content-manager/components/EditViewDataManagerProvider/reducer.js +19 -2
  12. package/admin/src/content-manager/components/InputJSON/FieldWrapper.js +10 -2
  13. package/admin/src/content-manager/components/InputJSON/Label.js +2 -18
  14. package/admin/src/content-manager/components/InputJSON/index.js +7 -3
  15. package/admin/src/content-manager/components/RelationInput/RelationInput.js +8 -17
  16. package/admin/src/content-manager/components/RelationInput/components/RelationItem.js +2 -0
  17. package/admin/src/content-manager/components/RelationInput/index.js +1 -0
  18. package/admin/src/content-manager/components/RepeatableComponent/index.js +1 -3
  19. package/admin/src/content-manager/hooks/useDragAndDrop.js +25 -11
  20. package/admin/src/content-manager/pages/EditSettingsView/components/DynamicZoneList.js +18 -38
  21. package/admin/src/pages/Admin/Onboarding/index.js +42 -44
  22. package/admin/src/pages/App/index.js +20 -13
  23. package/admin/src/pages/AuthPage/components/Register/index.js +1 -1
  24. package/admin/src/pages/AuthPage/components/ResetPassword/index.js +1 -1
  25. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/index.js +2 -3
  26. package/admin/src/translations/en.json +2 -1
  27. package/admin/src/translations/sk.json +274 -52
  28. package/admin/src/translations/tr.json +485 -5
  29. package/admin/src/utils/index.js +1 -0
  30. package/admin/src/utils/uniqueAdminHash.js +22 -0
  31. package/build/2235.06c13219.chunk.js +106 -0
  32. package/build/2598.962797b2.chunk.js +159 -0
  33. package/build/4318.0bbd3f4b.chunk.js +30 -0
  34. package/build/4958.7c118f5e.chunk.js +276 -0
  35. package/build/5052.712419ea.chunk.js +65 -0
  36. package/build/7295.04ac49dc.chunk.js +114 -0
  37. package/build/805.ddcead70.chunk.js +138 -0
  38. package/build/874.bde3ea04.chunk.js +104 -0
  39. package/build/9159.ac968e72.chunk.js +169 -0
  40. package/build/9707.77e475ee.chunk.js +101 -0
  41. package/build/Admin-authenticatedApp.9dd415b8.chunk.js +72 -0
  42. package/build/Admin_pluginsPage.67728975.chunk.js +6 -0
  43. package/build/{Admin_profilePage.c07bdf08.chunk.js → Admin_profilePage.60ab80bb.chunk.js} +1 -1
  44. package/build/{Admin_settingsPage.50a8765b.chunk.js → Admin_settingsPage.9ce40fed.chunk.js} +3 -3
  45. package/build/Upload_ConfigureTheView.7cb2a3fd.chunk.js +1 -0
  46. package/build/admin-app.d8fc7c4d.chunk.js +112 -0
  47. package/build/admin-edit-users.5547b126.chunk.js +10 -0
  48. package/build/{admin-users.a2707644.chunk.js → admin-users.4b6b47f8.chunk.js} +1 -1
  49. package/build/{api-tokens-list-page.700e575f.chunk.js → api-tokens-list-page.50519ed7.chunk.js} +1 -1
  50. package/build/content-manager.f2214e32.chunk.js +1166 -0
  51. package/build/content-type-builder-list-view.4aea46fa.chunk.js +198 -0
  52. package/build/content-type-builder-translation-de-json.a52482c7.chunk.js +1 -0
  53. package/build/content-type-builder-translation-dk-json.a8616510.chunk.js +1 -0
  54. package/build/content-type-builder-translation-en-json.1d9a3c14.chunk.js +1 -0
  55. package/build/content-type-builder-translation-es-json.c3ea46fb.chunk.js +1 -0
  56. package/build/content-type-builder-translation-ko-json.3fb7ddc8.chunk.js +1 -0
  57. package/build/content-type-builder-translation-pl-json.9b2993b2.chunk.js +1 -0
  58. package/build/content-type-builder-translation-pt-BR-json.6d255441.chunk.js +1 -0
  59. package/build/content-type-builder-translation-sv-json.c608b9ca.chunk.js +1 -0
  60. package/build/content-type-builder-translation-tr-json.949e22eb.chunk.js +1 -0
  61. package/build/content-type-builder-translation-zh-json.b79513e4.chunk.js +1 -0
  62. package/build/content-type-builder.8a9a77f9.chunk.js +127 -0
  63. package/build/email-settings-page.c6e62f6b.chunk.js +15 -0
  64. package/build/email-translation-tr-json.8aa034bb.chunk.js +1 -0
  65. package/build/en-json.1abdade9.chunk.js +1 -0
  66. package/build/{i18n-settings-page.195d42fe.chunk.js → i18n-settings-page.ee572037.chunk.js} +1 -1
  67. package/build/i18n-translation-tr-json.34ca9d61.chunk.js +1 -0
  68. package/build/index.html +1 -1
  69. package/build/main.91f6e21e.js +4099 -0
  70. package/build/runtime~main.447b0382.js +2 -0
  71. package/build/sk-json.2af48064.chunk.js +1 -0
  72. package/build/sso-settings-page.91924df1.chunk.js +41 -0
  73. package/build/tr-json.eac8bd79.chunk.js +1 -0
  74. package/build/upload-settings.326cd9fd.chunk.js +89 -0
  75. package/build/upload-translation-en-json.32cf9aff.chunk.js +1 -0
  76. package/build/upload-translation-sk-json.fe86c53b.chunk.js +1 -0
  77. package/build/upload-translation-tr-json.b173223a.chunk.js +1 -0
  78. package/build/upload.2977cb13.chunk.js +38 -0
  79. package/build/users-email-settings-page.18d4a475.chunk.js +28 -0
  80. package/build/{users-permissions-translation-dk-json.fe39c74b.chunk.js → users-permissions-translation-dk-json.bad0b786.chunk.js} +1 -1
  81. package/build/{users-permissions-translation-en-json.765abf48.chunk.js → users-permissions-translation-en-json.aeab388a.chunk.js} +1 -1
  82. package/build/{users-permissions-translation-es-json.1bb9cde2.chunk.js → users-permissions-translation-es-json.152a923f.chunk.js} +1 -1
  83. package/build/{users-permissions-translation-ko-json.3be77775.chunk.js → users-permissions-translation-ko-json.6bd0ae22.chunk.js} +1 -1
  84. package/build/{users-permissions-translation-pl-json.1dbdd4a1.chunk.js → users-permissions-translation-pl-json.c6a02992.chunk.js} +1 -1
  85. package/build/{users-permissions-translation-sv-json.d5d11648.chunk.js → users-permissions-translation-sv-json.370d6eee.chunk.js} +1 -1
  86. package/build/users-permissions-translation-tr-json.9bebc250.chunk.js +1 -0
  87. package/build/{users-permissions-translation-zh-json.92f406f9.chunk.js → users-permissions-translation-zh-json.1fea833f.chunk.js} +1 -1
  88. package/build/users-providers-settings-page.25dd858e.chunk.js +1 -0
  89. package/build/{users-roles-settings-page.ce5b582d.chunk.js → users-roles-settings-page.8482a999.chunk.js} +1 -1
  90. package/build/{webhook-edit-page.1215a6b7.chunk.js → webhook-edit-page.dcc3d145.chunk.js} +4 -4
  91. package/build/{webhook-list-page.b87821f2.chunk.js → webhook-list-page.894e6959.chunk.js} +1 -1
  92. package/ee/server/services/passport/provider-registry.js +1 -1
  93. package/package.json +10 -16
  94. package/server/controllers/admin.js +2 -0
  95. package/server/routes/admin.js +1 -1
  96. package/server/services/metrics.js +5 -2
  97. package/server/services/role.js +1 -0
  98. package/webpack.alias.js +0 -2
  99. package/admin/src/content-manager/components/BackHeader/index.js +0 -8
  100. package/admin/src/content-manager/components/Block/components.js +0 -28
  101. package/admin/src/content-manager/components/Block/index.js +0 -43
  102. package/admin/src/content-manager/components/Container/index.js +0 -7
  103. package/admin/src/content-manager/components/CustomInputCheckbox/components.js +0 -77
  104. package/admin/src/content-manager/components/CustomInputCheckbox/index.js +0 -53
  105. package/admin/src/content-manager/components/DynamicComponentCard/Wrapper.js +0 -63
  106. package/admin/src/content-manager/components/FilterOptionsCTA/index.js +0 -14
  107. package/admin/src/content-manager/components/FormTitle/index.js +0 -22
  108. package/admin/src/content-manager/components/FormWrapper/index.js +0 -20
  109. package/admin/src/content-manager/components/InputJSON/FieldError.js +0 -38
  110. package/admin/src/content-manager/components/LayoutTitle/index.js +0 -19
  111. package/admin/src/content-manager/components/PlusButton/index.js +0 -52
  112. package/admin/src/content-manager/components/PreviewCarret/components.js +0 -27
  113. package/admin/src/content-manager/components/PreviewCarret/index.js +0 -22
  114. package/admin/src/content-manager/components/SectionTitle/Title.js +0 -11
  115. package/admin/src/content-manager/components/SectionTitle/index.js +0 -26
  116. package/build/1551f4f60c37af51121f.woff2 +0 -0
  117. package/build/1e59d2330b4c6deb84b3.ttf +0 -0
  118. package/build/20fd1704ea223900efa9.woff2 +0 -0
  119. package/build/2285773e6b4b172f07d9.woff +0 -0
  120. package/build/23f19bb08961f37aaf69.eot +0 -0
  121. package/build/2f517e09eb2ca6650ff5.svg +0 -3717
  122. package/build/4306.df40a798.chunk.js +0 -98
  123. package/build/4318.80bdf035.chunk.js +0 -30
  124. package/build/4689f52cc96215721344.svg +0 -801
  125. package/build/491974d108fe4002b2aa.ttf +0 -0
  126. package/build/504.9aeff724.chunk.js +0 -758
  127. package/build/5057.195a59ff.chunk.js +0 -65
  128. package/build/527940b104eb2ea366c8.ttf +0 -0
  129. package/build/77206a6bb316fa0aded5.eot +0 -0
  130. package/build/7a3337626410ca2f4071.woff2 +0 -0
  131. package/build/7a8b4f130182d19a2d7c.svg +0 -5034
  132. package/build/805.e991a370.chunk.js +0 -138
  133. package/build/8176.b19bc128.chunk.js +0 -145
  134. package/build/8186.55910742.chunk.js +0 -169
  135. package/build/8881.c693411a.chunk.js +0 -245
  136. package/build/8b43027f47b20503057d.eot +0 -0
  137. package/build/9161.4a0ab137.chunk.js +0 -2119
  138. package/build/9279.6290c87a.chunk.js +0 -117
  139. package/build/9707.a0cc4ad8.chunk.js +0 -70
  140. package/build/9bbb245e67a133f6e486.eot +0 -0
  141. package/build/Admin-authenticatedApp.f9e74dc0.chunk.js +0 -80
  142. package/build/Admin_pluginsPage.3c872de7.chunk.js +0 -6
  143. package/build/admin-app.2861b6d2.chunk.js +0 -112
  144. package/build/admin-edit-users.85231e4c.chunk.js +0 -10
  145. package/build/bb58e57c48a3e911f15f.woff +0 -0
  146. package/build/be9ee23c0c6390141475.ttf +0 -0
  147. package/build/c1e38fd9e0e74ba58f7a.svg +0 -2671
  148. package/build/content-manager.ee948f75.chunk.js +0 -1186
  149. package/build/content-type-builder-list-view.4412efc3.chunk.js +0 -201
  150. package/build/content-type-builder-translation-de-json.0d7696b9.chunk.js +0 -1
  151. package/build/content-type-builder-translation-dk-json.4729f055.chunk.js +0 -1
  152. package/build/content-type-builder-translation-en-json.f985c9c4.chunk.js +0 -1
  153. package/build/content-type-builder-translation-es-json.333cf47f.chunk.js +0 -1
  154. package/build/content-type-builder-translation-ko-json.51201b12.chunk.js +0 -1
  155. package/build/content-type-builder-translation-pl-json.4a42349b.chunk.js +0 -1
  156. package/build/content-type-builder-translation-pt-BR-json.6fe3b8d1.chunk.js +0 -1
  157. package/build/content-type-builder-translation-sv-json.6deff030.chunk.js +0 -1
  158. package/build/content-type-builder-translation-tr-json.2e52bc60.chunk.js +0 -1
  159. package/build/content-type-builder-translation-zh-json.3b0afd31.chunk.js +0 -1
  160. package/build/content-type-builder.b132b5f4.chunk.js +0 -145
  161. package/build/d878b0a6a1144760244f.woff2 +0 -0
  162. package/build/eeccf4f66002c6f2ba24.woff +0 -0
  163. package/build/email-settings-page.db0d98d1.chunk.js +0 -15
  164. package/build/email-translation-tr-json.87f2feb3.chunk.js +0 -1
  165. package/build/en-json.4a56dca7.chunk.js +0 -1
  166. package/build/f691f37e57f04c152e23.woff +0 -0
  167. package/build/fontawesome-css-all.15068c6e.chunk.js +0 -4618
  168. package/build/fontawesome-css.418f40da.chunk.js +0 -6
  169. package/build/fontawesome-js.252cc5f3.chunk.js +0 -7
  170. package/build/main.faac89ee.js +0 -2025
  171. package/build/runtime~main.75a15b8e.js +0 -2
  172. package/build/sk-json.7ba4b330.chunk.js +0 -1
  173. package/build/sso-settings-page.adb12ac3.chunk.js +0 -1
  174. package/build/tr-json.9c44ea0c.chunk.js +0 -1
  175. package/build/upload-settings.450cab1a.chunk.js +0 -18
  176. package/build/upload-translation-en-json.86da7b0a.chunk.js +0 -1
  177. package/build/upload-translation-sk-json.b03d4904.chunk.js +0 -1
  178. package/build/upload.e2034370.chunk.js +0 -64
  179. package/build/users-email-settings-page.3126ff8c.chunk.js +0 -28
  180. package/build/users-permissions-translation-tr-json.cdc49a3c.chunk.js +0 -1
  181. package/build/users-providers-settings-page.b7b602e2.chunk.js +0 -33
@@ -20,7 +20,7 @@ import {
20
20
  fetchUserRoles,
21
21
  } from './utils/api';
22
22
  import checkLatestStrapiVersion from './utils/checkLatestStrapiVersion';
23
- import { getFullName } from '../../utils';
23
+ import { getFullName, hashAdminUserEmail } from '../../utils';
24
24
 
25
25
  const strapiVersion = packageJSON.version;
26
26
 
@@ -31,6 +31,7 @@ const AuthenticatedApp = () => {
31
31
  const userInfo = auth.getUserInfo();
32
32
  const userName = get(userInfo, 'username') || getFullName(userInfo.firstname, userInfo.lastname);
33
33
  const [userDisplayName, setUserDisplayName] = useState(userName);
34
+ const [userId, setUserId] = useState(null);
34
35
  const { showReleaseNotification } = useConfigurations();
35
36
  const [
36
37
  { data: appInfos, status },
@@ -71,6 +72,15 @@ const AuthenticatedApp = () => {
71
72
  }
72
73
  }, [userRoles, appInfos]);
73
74
 
75
+ useEffect(() => {
76
+ const getUserId = async () => {
77
+ const userId = await hashAdminUserEmail(userInfo);
78
+ setUserId(userId);
79
+ };
80
+
81
+ getUserId();
82
+ }, [userInfo]);
83
+
74
84
  // We don't need to wait for the release query to be fetched before rendering the plugins
75
85
  // however, we need the appInfos and the permissions
76
86
  const shouldShowNotDependentQueriesLoader =
@@ -81,12 +91,13 @@ const AuthenticatedApp = () => {
81
91
  const appInfosValue = useMemo(() => {
82
92
  return {
83
93
  ...appInfos,
94
+ userId,
84
95
  latestStrapiReleaseTag: tag_name,
85
96
  setUserDisplayName,
86
97
  shouldUpdateStrapi,
87
98
  userDisplayName,
88
99
  };
89
- }, [appInfos, tag_name, shouldUpdateStrapi, userDisplayName]);
100
+ }, [appInfos, tag_name, shouldUpdateStrapi, userDisplayName, userId]);
90
101
 
91
102
  if (shouldShowLoader) {
92
103
  return <LoadingIndicatorPage />;
@@ -1,11 +1,6 @@
1
1
  import { createGlobalStyle } from 'styled-components';
2
2
 
3
3
  const loadCss = async () => {
4
- await import(/* webpackChunkName: "fontawesome-css" */ 'font-awesome/css/font-awesome.min.css');
5
- await import(
6
- /* webpackChunkName: "fontawesome-css-all" */ '@fortawesome/fontawesome-free/css/all.css'
7
- );
8
- await import(/* webpackChunkName: "fontawesome-js" */ '@fortawesome/fontawesome-free/js/all.min');
9
4
  await import(/* webpackChunkName: "cropper-css" */ 'cropperjs/dist/cropper.css');
10
5
  };
11
6
 
@@ -0,0 +1,49 @@
1
+ import PropTypes from 'prop-types';
2
+ import React from 'react';
3
+ import styled from 'styled-components';
4
+
5
+ import { Flex } from '@strapi/design-system';
6
+
7
+ const WIDTH_S = 5;
8
+ const WIDTH_M = 8;
9
+
10
+ const Wrapper = styled(Flex)`
11
+ border-radius: ${({ showBackground }) => (showBackground ? `50%` : 0)};
12
+ color: ${({ theme }) => theme.colors.neutral600};
13
+ height: ${({ theme, size }) => theme.spaces[size === 'S' ? WIDTH_S : WIDTH_M]};
14
+ width: ${({ theme, size }) => theme.spaces[size === 'S' ? WIDTH_S : WIDTH_M]};
15
+
16
+ svg {
17
+ height: ${({ theme, size }) => theme.spaces[size === 'S' ? WIDTH_S - 2 : WIDTH_M - 3]};
18
+ width: ${({ theme, size }) => theme.spaces[size === 'S' ? WIDTH_S - 2 : WIDTH_M - 3]};
19
+ }
20
+ `;
21
+
22
+ export function ComponentIcon({ showBackground = true, size = 'M' }) {
23
+ return (
24
+ <Wrapper
25
+ alignItems="center"
26
+ background={showBackground ? 'neutral200' : null}
27
+ justifyContent="center"
28
+ size={size}
29
+ showBackground={showBackground}
30
+ >
31
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512">
32
+ <path
33
+ d="M216.3 2c4.8-2.6 10.5-2.6 15.3 0L422.3 106c5.1 2.8 8.3 8.2 8.3 14s-3.2 11.2-8.3 14L231.7 238c-4.8 2.6-10.5 2.6-15.3 0L25.7 134c-5.1-2.8-8.3-8.2-8.3-14s3.2-11.2 8.3-14L216.3 2zM23.7 170l176 96c5.1 2.8 8.3 8.2 8.3 14V496c0 5.6-3 10.9-7.8 13.8s-10.9 3-15.8 .3L8.3 414C3.2 411.2 0 405.9 0 400V184c0-5.6 3-10.9 7.8-13.8s10.9-3 15.8-.3zm400.7 0c5-2.7 11-2.6 15.8 .3s7.8 8.1 7.8 13.8V400c0 5.9-3.2 11.2-8.3 14l-176 96c-5 2.7-11 2.6-15.8-.3s-7.8-8.1-7.8-13.8V280c0-5.9 3.2-11.2 8.3-14l176-96z"
34
+ fill="currentColor"
35
+ />
36
+ </svg>
37
+ </Wrapper>
38
+ );
39
+ }
40
+
41
+ ComponentIcon.defaultProps = {
42
+ showBackground: true,
43
+ size: 'M',
44
+ };
45
+
46
+ ComponentIcon.propTypes = {
47
+ showBackground: PropTypes.bool,
48
+ size: PropTypes.string,
49
+ };
@@ -0,0 +1 @@
1
+ export * from './ComponentIcon';
@@ -4,7 +4,6 @@ import styled from 'styled-components';
4
4
  import { pxToRem } from '@strapi/helper-plugin';
5
5
  import { Box, Flex, Typography, IconButton } from '@strapi/design-system';
6
6
  import { Trash, Drag, CarretDown } from '@strapi/icons';
7
- import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
8
7
 
9
8
  const DragPreviewBox = styled(Box)`
10
9
  border: 1px solid ${({ theme }) => theme.colors.neutral200};
@@ -27,13 +26,6 @@ const DropdownIconWrapper = styled(Box)`
27
26
  }
28
27
  `;
29
28
 
30
- const Icon = styled(FontAwesomeIcon)`
31
- width: ${pxToRem(12)};
32
- height: ${pxToRem(12)};
33
-
34
- color: ${({ theme }) => theme.colors.neutral600};
35
- `;
36
-
37
29
  const ToggleButton = styled.button`
38
30
  border: none;
39
31
  background: transparent;
@@ -43,7 +35,7 @@ const ToggleButton = styled.button`
43
35
  padding: 0;
44
36
  `;
45
37
 
46
- const DragPreview = ({ displayedValue, icon }) => {
38
+ const DragPreview = ({ displayedValue }) => {
47
39
  return (
48
40
  <DragPreviewBox
49
41
  paddingLeft={3}
@@ -60,8 +52,7 @@ const DragPreview = ({ displayedValue, icon }) => {
60
52
  <DropdownIconWrapper background="neutral200">
61
53
  <CarretDown />
62
54
  </DropdownIconWrapper>
63
- <Flex gap={2} paddingLeft={icon ? 3 : 6} maxWidth={pxToRem(150)}>
64
- {icon ? <Icon icon={icon} /> : null}
55
+ <Flex gap={2} paddingLeft={6} maxWidth={pxToRem(150)}>
65
56
  <Typography textColor="neutral700" ellipsis>
66
57
  {displayedValue}
67
58
  </Typography>
@@ -85,13 +76,8 @@ const DragPreview = ({ displayedValue, icon }) => {
85
76
  );
86
77
  };
87
78
 
88
- DragPreview.defaultProps = {
89
- icon: undefined,
90
- };
91
-
92
79
  DragPreview.propTypes = {
93
80
  displayedValue: PropTypes.string.isRequired,
94
- icon: PropTypes.string,
95
81
  };
96
82
 
97
83
  export default DragPreview;
@@ -7,7 +7,7 @@ import { Drag, Cross } from '@strapi/icons';
7
7
  import { getTrad } from '../../utils';
8
8
  import { PUBLICATION_STATES } from '../RelationInputDataManager/constants';
9
9
  import { ChildrenWrapper, StackWrapper } from '../RelationInput/components/RelationItem';
10
- import { BoxEllipsis, DisconnectButton } from '../RelationInput/RelationInput';
10
+ import { LinkEllipsis, DisconnectButton } from '../RelationInput';
11
11
 
12
12
  export const RelationDragPreview = ({ status, displayedValue, width }) => {
13
13
  const { formatMessage } = useIntl();
@@ -44,11 +44,11 @@ export const RelationDragPreview = ({ status, displayedValue, width }) => {
44
44
  <Drag />
45
45
  </IconButton>
46
46
  <ChildrenWrapper justifyContent="space-between">
47
- <BoxEllipsis minWidth={0} paddingTop={1} paddingBottom={1} paddingRight={4}>
47
+ <LinkEllipsis minWidth={0} paddingTop={1} paddingBottom={1} paddingRight={4}>
48
48
  <Typography textColor="primary600" ellipsis>
49
49
  {displayedValue}
50
50
  </Typography>
51
- </BoxEllipsis>
51
+ </LinkEllipsis>
52
52
  {status && (
53
53
  <Status variant={statusColor} showBullet={false} size="S">
54
54
  <Typography fontWeight="bold" textColor={`${statusColor}700`}>
@@ -67,7 +67,7 @@ const CustomDragLayer = () => {
67
67
  <ComponentPreview displayedValue={item.displayedValue} />
68
68
  )}
69
69
  {actualType === ItemTypes.DYNAMIC_ZONE && (
70
- <ComponentPreview icon={item.icon} displayedValue={item.displayedValue} />
70
+ <ComponentPreview displayedValue={item.displayedValue} />
71
71
  )}
72
72
  {actualType === ItemTypes.RELATION && (
73
73
  <RelationDragPreview
@@ -7,23 +7,13 @@
7
7
  import React from 'react';
8
8
  import PropTypes from 'prop-types';
9
9
  import styled from 'styled-components';
10
- import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
11
10
 
12
11
  import { Box } from '@strapi/design-system/Box';
13
12
  import { Typography } from '@strapi/design-system/Typography';
14
13
  import { Stack } from '@strapi/design-system/Stack';
15
14
  import { pxToRem } from '@strapi/helper-plugin';
16
15
 
17
- const StyledFontAwesomeIcon = styled(FontAwesomeIcon)`
18
- width: ${pxToRem(32)} !important;
19
- height: ${pxToRem(32)} !important;
20
- padding: ${pxToRem(9)};
21
- border-radius: ${pxToRem(64)};
22
- background: ${({ theme }) => theme.colors.neutral150};
23
- path {
24
- fill: ${({ theme }) => theme.colors.neutral500};
25
- }
26
- `;
16
+ import { ComponentIcon } from '../../ComponentIcon';
27
17
 
28
18
  const ComponentBox = styled(Box)`
29
19
  flex-shrink: 0;
@@ -35,46 +25,42 @@ const ComponentBox = styled(Box)`
35
25
  justify-content: center;
36
26
  align-items: center;
37
27
 
38
- &.active,
28
+ &:focus,
39
29
  &:hover {
40
30
  border: 1px solid ${({ theme }) => theme.colors.primary200};
41
31
  background: ${({ theme }) => theme.colors.primary100};
42
32
 
43
- ${StyledFontAwesomeIcon} {
44
- background: ${({ theme }) => theme.colors.primary200};
45
- path {
46
- fill: ${({ theme }) => theme.colors.primary600};
47
- }
33
+ ${Typography} {
34
+ color: ${({ theme }) => theme.colors.primary600};
48
35
  }
49
36
 
50
- ${Typography} {
37
+ /* > Stack > ComponentIcon */
38
+ > div > div:first-child {
39
+ background: ${({ theme }) => theme.colors.primary200};
51
40
  color: ${({ theme }) => theme.colors.primary600};
52
41
  }
53
42
  }
54
43
  `;
55
44
 
56
- export default function ComponentCard({ children, icon, onClick }) {
45
+ export default function ComponentCard({ children, onClick }) {
57
46
  return (
58
- <button type="button" onClick={onClick}>
59
- <ComponentBox borderRadius="borderRadius">
60
- <Stack spacing={1} style={{ justifyContent: 'center', alignItems: 'center' }}>
61
- <StyledFontAwesomeIcon data-testid="component-card-icon" icon={icon} />
62
- <Typography variant="pi" fontWeight="bold" textColor="neutral600">
63
- {children}
64
- </Typography>
65
- </Stack>
66
- </ComponentBox>
67
- </button>
47
+ <ComponentBox as="button" type="button" onClick={onClick} hasRadius>
48
+ <Stack spacing={1} alignItems="center" justifyContent="center">
49
+ <ComponentIcon />
50
+
51
+ <Typography variant="pi" fontWeight="bold" textColor="neutral600">
52
+ {children}
53
+ </Typography>
54
+ </Stack>
55
+ </ComponentBox>
68
56
  );
69
57
  }
70
58
 
71
59
  ComponentCard.defaultProps = {
72
- icon: 'dice-d6',
73
60
  onClick() {},
74
61
  };
75
62
 
76
63
  ComponentCard.propTypes = {
77
64
  children: PropTypes.node.isRequired,
78
- icon: PropTypes.string,
79
65
  onClick: PropTypes.func,
80
66
  };
@@ -30,8 +30,8 @@ const ComponentCategory = ({ category, components, variant, isOpen, onAddCompone
30
30
  <AccordionContent>
31
31
  <Box paddingTop={4} paddingBottom={4} paddingLeft={3} paddingRight={3}>
32
32
  <Grid>
33
- {components.map(({ componentUid, info: { displayName, icon } }) => (
34
- <ComponentCard key={componentUid} icon={icon} onClick={onAddComponent(componentUid)}>
33
+ {components.map(({ componentUid, info: { displayName } }) => (
34
+ <ComponentCard key={componentUid} onClick={onAddComponent(componentUid)}>
35
35
  {formatMessage({ id: displayName, defaultMessage: displayName })}
36
36
  </ComponentCard>
37
37
  ))}
@@ -2,7 +2,6 @@ import React, { useEffect, useMemo, useState } from 'react';
2
2
  import PropTypes from 'prop-types';
3
3
  import styled from 'styled-components';
4
4
  import { useIntl } from 'react-intl';
5
- import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
6
5
  import get from 'lodash/get';
7
6
  import { getEmptyImage } from 'react-dnd-html5-backend';
8
7
 
@@ -194,7 +193,6 @@ const DynamicZoneComponent = ({
194
193
  ) : (
195
194
  <Accordion expanded={isOpen} onToggle={handleToggle} size="S" error={errorMessage}>
196
195
  <AccordionToggle
197
- startIcon={icon && <FontAwesomeIcon icon={icon} />}
198
196
  action={accordionActions}
199
197
  title={`${friendlyName}${mainValue}`}
200
198
  togglePosition="left"
@@ -105,6 +105,11 @@ const reducer = (state, action) =>
105
105
  (value) => value.type === 'component' && value.repeatable
106
106
  )(componentLayoutData.attributes);
107
107
 
108
+ const nonRepeatableComponentPaths = recursivelyFindPathsBasedOnCondition(
109
+ allComponents,
110
+ (value) => value.type === 'component' && !value.repeatable
111
+ )(componentLayoutData.attributes);
112
+
108
113
  const componentDataStructure = relationPaths.reduce((acc, current) => {
109
114
  const [componentName] = current.split('.');
110
115
 
@@ -113,8 +118,21 @@ const reducer = (state, action) =>
113
118
  * has another repeatable component inside of it we
114
119
  * don't need to attach the array at this point because that will be
115
120
  * done again deeper in the nest.
121
+ *
122
+ * We also need to handle cases with single components nested within
123
+ * repeatables by checking that the relation path does not match a
124
+ * non-repeatable component path. This accounts for component
125
+ * structures such as:
126
+ * - outer_single_compo
127
+ * - level_one_repeatable
128
+ * - level_two_single_component
129
+ * - level_three_repeatable
116
130
  */
117
- if (!repeatableFields.includes(componentName)) {
131
+
132
+ if (
133
+ !repeatableFields.includes(componentName) &&
134
+ !nonRepeatableComponentPaths.includes(componentName)
135
+ ) {
118
136
  set(acc, current, []);
119
137
  }
120
138
 
@@ -129,7 +147,6 @@ const reducer = (state, action) =>
129
147
 
130
148
  break;
131
149
  }
132
-
133
150
  case 'LOAD_RELATION': {
134
151
  const initialDataPath = ['initialData', ...action.keys];
135
152
  const modifiedDataPath = ['modifiedData', ...action.keys];
@@ -3,12 +3,18 @@ import PropTypes from 'prop-types';
3
3
  import { useIntl } from 'react-intl';
4
4
  import { Field } from '@strapi/design-system/Field';
5
5
 
6
- const FieldWrapper = ({ name, hint, error, children }) => {
6
+ const FieldWrapper = ({ name, hint, error, children, required }) => {
7
7
  const { formatMessage } = useIntl();
8
8
  const errorMessage = error ? formatMessage({ id: error, defaultMessage: error }) : '';
9
9
 
10
10
  return (
11
- <Field name={name} hint={hint && formatMessage(hint)} error={errorMessage} id={name}>
11
+ <Field
12
+ name={name}
13
+ hint={hint && formatMessage(hint)}
14
+ error={errorMessage}
15
+ id={name}
16
+ required={required}
17
+ >
12
18
  {children}
13
19
  </Field>
14
20
  );
@@ -17,6 +23,7 @@ const FieldWrapper = ({ name, hint, error, children }) => {
17
23
  FieldWrapper.defaultProps = {
18
24
  hint: undefined,
19
25
  error: '',
26
+ required: false,
20
27
  };
21
28
 
22
29
  FieldWrapper.propTypes = {
@@ -27,6 +34,7 @@ FieldWrapper.propTypes = {
27
34
  }),
28
35
  error: PropTypes.string,
29
36
  children: PropTypes.node.isRequired,
37
+ required: PropTypes.bool,
30
38
  };
31
39
 
32
40
  export default FieldWrapper;
@@ -1,18 +1,9 @@
1
1
  import React from 'react';
2
2
  import PropTypes from 'prop-types';
3
- import styled from 'styled-components';
4
3
  import { useIntl } from 'react-intl';
5
4
  import { FieldLabel } from '@strapi/design-system/Field';
6
- import { Box } from '@strapi/design-system/Box';
7
- import { Flex } from '@strapi/design-system/Flex';
8
5
 
9
- const LabelAction = styled(Box)`
10
- svg path {
11
- fill: ${({ theme }) => theme.colors.neutral500};
12
- }
13
- `;
14
-
15
- const Label = ({ intlLabel, labelAction, name, required }) => {
6
+ const Label = ({ intlLabel, labelAction, name }) => {
16
7
  const { formatMessage } = useIntl();
17
8
  const label = intlLabel?.id
18
9
  ? formatMessage(
@@ -21,19 +12,13 @@ const Label = ({ intlLabel, labelAction, name, required }) => {
21
12
  )
22
13
  : name;
23
14
 
24
- return (
25
- <Flex>
26
- <FieldLabel required={required}>{label}</FieldLabel>
27
- {labelAction && <LabelAction paddingLeft={1}>{labelAction}</LabelAction>}
28
- </Flex>
29
- );
15
+ return <FieldLabel action={labelAction}>{label}</FieldLabel>;
30
16
  };
31
17
 
32
18
  Label.defaultProps = {
33
19
  id: undefined,
34
20
  intlLabel: undefined,
35
21
  labelAction: undefined,
36
- required: false,
37
22
  };
38
23
 
39
24
  Label.propTypes = {
@@ -45,7 +30,6 @@ Label.propTypes = {
45
30
  }),
46
31
  labelAction: PropTypes.element,
47
32
  name: PropTypes.string.isRequired,
48
- required: PropTypes.bool,
49
33
  };
50
34
 
51
35
  export default Label;
@@ -157,13 +157,17 @@ class InputJSON extends React.Component {
157
157
  }
158
158
 
159
159
  return (
160
- <FieldWrapper name={this.props.name} hint={this.props.description} error={this.props.error}>
160
+ <FieldWrapper
161
+ name={this.props.name}
162
+ hint={this.props.description}
163
+ error={this.props.error}
164
+ required={this.props.required}
165
+ >
161
166
  <Stack spacing={1}>
162
167
  <Label
163
168
  intlLabel={this.props.intlLabel}
164
- labelAction={this.props.labelAction}
165
169
  name={this.props.name}
166
- required={this.props.required}
170
+ labelAction={this.props.labelAction}
167
171
  />
168
172
  <StyledBox error={this.props.error}>
169
173
  <EditorWrapper disabled={this.props.disabled}>
@@ -25,19 +25,14 @@ import { RELATION_GUTTER, RELATION_ITEM_HEIGHT } from './constants';
25
25
 
26
26
  import { usePrev } from '../../hooks';
27
27
 
28
- const LinkEllipsis = styled(Link)`
29
- white-space: nowrap;
30
- overflow: hidden;
31
- text-overflow: ellipsis;
32
- display: inherit;
33
- `;
28
+ export const LinkEllipsis = styled(Link)`
29
+ display: block;
34
30
 
35
- export const BoxEllipsis = styled(Box)`
36
31
  > span {
37
32
  white-space: nowrap;
38
33
  overflow: hidden;
39
34
  text-overflow: ellipsis;
40
- display: inherit;
35
+ display: block;
41
36
  }
42
37
  `;
43
38
 
@@ -267,15 +262,13 @@ const RelationInput = ({
267
262
  const ariaDescriptionId = `${name}-item-instructions`;
268
263
 
269
264
  return (
270
- <Field error={error} name={name} hint={description} id={id}>
265
+ <Field error={error} name={name} hint={description} id={id} required={required}>
271
266
  <Relation
272
267
  totalNumberOfRelations={totalNumberOfRelations}
273
268
  size={size}
274
269
  search={
275
270
  <>
276
- <FieldLabel action={labelAction} required={required}>
277
- {label}
278
- </FieldLabel>
271
+ <FieldLabel action={labelAction}>{label}</FieldLabel>
279
272
  <ReactSelect
280
273
  // position fixed doesn't update position on scroll
281
274
  // react select doesn't update menu position on options change
@@ -352,9 +345,7 @@ const RelationInput = ({
352
345
  relations,
353
346
  updatePositionOfRelation: handleUpdatePositionOfRelation,
354
347
  }}
355
- itemKey={(index, { relations: relationsItems }) =>
356
- `${relationsItems[index].mainField}_${relationsItems[index].id}`
357
- }
348
+ itemKey={(index) => `${relations[index].mainField}_${relations[index].id}`}
358
349
  innerElementType="ol"
359
350
  >
360
351
  {ListItem}
@@ -509,7 +500,7 @@ const ListItem = ({ data, index, style }) => {
509
500
  }}
510
501
  updatePositionOfRelation={updatePositionOfRelation}
511
502
  >
512
- <BoxEllipsis minWidth={0} paddingTop={1} paddingBottom={1} paddingRight={4}>
503
+ <Box minWidth={0} paddingTop={1} paddingBottom={1} paddingRight={4}>
513
504
  <Tooltip description={mainField ?? `${id}`}>
514
505
  {href ? (
515
506
  <LinkEllipsis to={href} disabled={disabled}>
@@ -521,7 +512,7 @@ const ListItem = ({ data, index, style }) => {
521
512
  </Typography>
522
513
  )}
523
514
  </Tooltip>
524
- </BoxEllipsis>
515
+ </Box>
525
516
 
526
517
  {publicationState && (
527
518
  <Status variant={statusColor} showBullet={false} size="S">
@@ -50,11 +50,13 @@ export const RelationItem = ({
50
50
  item: {
51
51
  displayedValue: displayValue,
52
52
  status,
53
+ id,
53
54
  },
54
55
  onGrabItem,
55
56
  onDropItem,
56
57
  onCancel,
57
58
  onMoveItem: updatePositionOfRelation,
59
+ dropSensitivity: 'immediate',
58
60
  });
59
61
 
60
62
  const composedRefs = composeRefs(relationRef, dragRef);
@@ -1 +1,2 @@
1
1
  export { default as RelationInput } from './RelationInput';
2
+ export * from './RelationInput';
@@ -51,9 +51,7 @@ const RepeatableComponent = ({
51
51
  [componentUid, getComponentLayout]
52
52
  );
53
53
 
54
- const nextTempKey = useMemo(() => {
55
- return getMaxTempKey(componentValue || []) + 1;
56
- }, [componentValue]);
54
+ const nextTempKey = useMemo(() => getMaxTempKey(componentValue || []) + 1, [componentValue]);
57
55
 
58
56
  const componentErrorKeys = getComponentErrorKeys(name, formErrors);
59
57
 
@@ -12,6 +12,7 @@ import { useKeyboardDragAndDrop } from './useKeyboardDragAndDrop';
12
12
  * item?: object,
13
13
  * onStart?: () => void,
14
14
  * onEnd?: () => void,
15
+ * dropSensitivity?: 'regular' | 'immediate'
15
16
  * } & import('./useKeyboardDragAndDrop').UseKeyboardDragAndDropCallbacks}
16
17
  */
17
18
 
@@ -39,6 +40,7 @@ export const useDragAndDrop = (
39
40
  onDropItem,
40
41
  onCancel,
41
42
  onMoveItem,
43
+ dropSensitivity = 'regular',
42
44
  }
43
45
  ) => {
44
46
  const objectRef = useRef(null);
@@ -62,19 +64,21 @@ export const useDragAndDrop = (
62
64
  return;
63
65
  }
64
66
 
65
- const hoverBoundingRect = objectRef.current.getBoundingClientRect();
66
- const hoverMiddleY = (hoverBoundingRect.bottom - hoverBoundingRect.top) / 2;
67
- const clientOffset = monitor.getClientOffset();
68
- const hoverClientY = clientOffset.y - hoverBoundingRect.top;
67
+ if (dropSensitivity === 'regular') {
68
+ const hoverBoundingRect = objectRef.current.getBoundingClientRect();
69
+ const hoverMiddleY = (hoverBoundingRect.bottom - hoverBoundingRect.top) / 2;
70
+ const clientOffset = monitor.getClientOffset();
71
+ const hoverClientY = clientOffset.y - hoverBoundingRect.top;
69
72
 
70
- // Dragging downwards
71
- if (dragIndex < newInd && hoverClientY < hoverMiddleY) {
72
- return;
73
- }
73
+ // Dragging downwards
74
+ if (dragIndex < newInd && hoverClientY < hoverMiddleY) {
75
+ return;
76
+ }
74
77
 
75
- // Dragging upwards
76
- if (dragIndex > newInd && hoverClientY > hoverMiddleY) {
77
- return;
78
+ // Dragging upwards
79
+ if (dragIndex > newInd && hoverClientY > hoverMiddleY) {
80
+ return;
81
+ }
78
82
  }
79
83
 
80
84
  // Time to actually perform the action
@@ -104,6 +108,16 @@ export const useDragAndDrop = (
104
108
  }
105
109
  },
106
110
  canDrag: active,
111
+ /**
112
+ * This is for useful when the item is in a virtualized list.
113
+ * However, if we don't have an ID then we want the libraries
114
+ * defaults to take care of this.
115
+ */
116
+ isDragging: item.id
117
+ ? (monitor) => {
118
+ return item.id === monitor.getItem().id;
119
+ }
120
+ : undefined,
107
121
  collect: (monitor) => ({
108
122
  isDragging: monitor.isDragging(),
109
123
  }),