@strapi/admin 4.10.1 → 4.10.2

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 (127) hide show
  1. package/admin/src/components/AuthenticatedApp/index.js +19 -24
  2. package/admin/src/components/DragLayer/DragLayer.js +53 -0
  3. package/admin/src/components/DragLayer/index.js +1 -0
  4. package/admin/src/components/LeftMenu/index.js +2 -2
  5. package/admin/src/components/Providers/index.js +11 -7
  6. package/admin/src/content-manager/contexts/index.js +0 -1
  7. package/admin/src/content-manager/hooks/index.js +0 -1
  8. package/admin/src/content-manager/hooks/useLazyComponents/index.js +7 -3
  9. package/admin/src/content-manager/hooks/useRelation/useRelation.js +1 -3
  10. package/admin/src/content-manager/pages/{ListSettingsView/components/CardPreview.js → App/components/CardDragPreview.js} +28 -28
  11. package/admin/src/content-manager/pages/App/components/ComponentDragPreview.js +75 -0
  12. package/admin/src/content-manager/{components/DragLayer → pages/App/components}/RelationDragPreview.js +7 -4
  13. package/admin/src/content-manager/pages/App/index.js +39 -2
  14. package/admin/src/content-manager/pages/EditSettingsView/components/ComponentFieldList.js +1 -1
  15. package/admin/src/content-manager/pages/EditSettingsView/components/DisplayedFieldButton.js +1 -1
  16. package/admin/src/content-manager/pages/EditSettingsView/components/DynamicZoneList.js +1 -1
  17. package/admin/src/content-manager/pages/EditSettingsView/components/FormModal.js +1 -1
  18. package/admin/src/content-manager/{components → pages/EditSettingsView/components}/LayoutDndProvider/index.js +3 -4
  19. package/admin/src/content-manager/pages/EditSettingsView/components/LinkToCTB.js +1 -1
  20. package/admin/src/content-manager/pages/EditSettingsView/components/ModalForm.js +1 -1
  21. package/admin/src/content-manager/pages/EditSettingsView/components/RowItemsLayout.js +1 -1
  22. package/admin/src/content-manager/pages/EditSettingsView/hooks/useLayoutDnd.js +6 -0
  23. package/admin/src/content-manager/pages/EditSettingsView/index.js +1 -1
  24. package/admin/src/content-manager/pages/ListSettingsView/components/DraggableCard.js +6 -6
  25. package/admin/src/hooks/useMenu/index.js +2 -2
  26. package/admin/src/hooks/useReleaseNotification/index.js +2 -2
  27. package/admin/src/hooks/useSettingsMenu/index.js +2 -2
  28. package/admin/src/pages/Admin/Onboarding/index.js +2 -2
  29. package/admin/src/pages/App/index.js +2 -2
  30. package/admin/src/pages/HomePage/SocialLinks.js +2 -2
  31. package/admin/src/pages/MarketplacePage/index.js +2 -2
  32. package/admin/src/pages/ProfilePage/index.js +2 -2
  33. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/index.js +2 -2
  34. package/admin/src/pages/SettingsPage/pages/Roles/EditPage/components/Permissions/utils/updateValues.js +3 -3
  35. package/admin/src/pages/SettingsPage/pages/Users/EditPage/index.js +2 -2
  36. package/admin/src/translations/fr.json +1 -1
  37. package/build/{5563.905daa13.chunk.js → 5563.986609ed.chunk.js} +2 -2
  38. package/build/6858.56d4d528.chunk.js +50 -0
  39. package/build/{7259.b7d00cea.chunk.js → 7259.7a48aa2f.chunk.js} +1 -1
  40. package/build/7725.1633e06f.chunk.js +213 -0
  41. package/build/9703.e590889d.chunk.js +1 -0
  42. package/build/Admin-authenticatedApp.a8373103.chunk.js +79 -0
  43. package/build/{Admin_InternalErrorPage.15c6bf07.chunk.js → Admin_InternalErrorPage.96ceaae1.chunk.js} +1 -1
  44. package/build/{Admin_homePage.f9309c6d.chunk.js → Admin_homePage.9f7c0bb1.chunk.js} +5 -5
  45. package/build/{Admin_marketplace.56bc1008.chunk.js → Admin_marketplace.a60cde15.chunk.js} +5 -5
  46. package/build/{Admin_pluginsPage.f6b52ee9.chunk.js → Admin_pluginsPage.9e6fa51c.chunk.js} +1 -1
  47. package/build/{Admin_profilePage.9112cffc.chunk.js → Admin_profilePage.1b337b73.chunk.js} +2 -2
  48. package/build/{Admin_settingsPage.4604a16c.chunk.js → Admin_settingsPage.5e045f42.chunk.js} +2 -2
  49. package/build/{Upload_ConfigureTheView.eaaec495.chunk.js → Upload_ConfigureTheView.4fc648b5.chunk.js} +1 -1
  50. package/build/admin-app.9bfe4ec7.chunk.js +63 -0
  51. package/build/{admin-edit-roles-page.8a4063f7.chunk.js → admin-edit-roles-page.d0c9497b.chunk.js} +24 -24
  52. package/build/{admin-edit-users.7e14d85f.chunk.js → admin-edit-users.ba27c532.chunk.js} +2 -2
  53. package/build/{admin-roles-list.329c1f63.chunk.js → admin-roles-list.c759daa3.chunk.js} +1 -1
  54. package/build/{admin-users.d02de059.chunk.js → admin-users.ad5dd832.chunk.js} +2 -2
  55. package/build/{api-tokens-create-page.97595e12.chunk.js → api-tokens-create-page.973d2816.chunk.js} +1 -1
  56. package/build/{api-tokens-edit-page.cd36e30e.chunk.js → api-tokens-edit-page.29725c5e.chunk.js} +1 -1
  57. package/build/{api-tokens-list-page.6757c7b9.chunk.js → api-tokens-list-page.66c4fbdd.chunk.js} +2 -2
  58. package/build/{audit-logs-settings-page.19d90bda.chunk.js → audit-logs-settings-page.45cb4fb5.chunk.js} +1 -1
  59. package/build/content-manager.d28eb183.chunk.js +1111 -0
  60. package/build/{content-type-builder-list-view.9c2c020c.chunk.js → content-type-builder-list-view.5ff685ec.chunk.js} +1 -1
  61. package/build/{content-type-builder.68af11d2.chunk.js → content-type-builder.4737a30c.chunk.js} +3 -3
  62. package/build/{email-settings-page.1095e1ab.chunk.js → email-settings-page.dc07d518.chunk.js} +1 -1
  63. package/build/{fr-json.5947cf63.chunk.js → fr-json.73494bf5.chunk.js} +1 -1
  64. package/build/{i18n-settings-page.d95b32df.chunk.js → i18n-settings-page.8219dd99.chunk.js} +1 -1
  65. package/build/index.html +1 -1
  66. package/build/main.41970e4c.js +2597 -0
  67. package/build/review-workflows-settings.7c0b4e73.chunk.js +61 -0
  68. package/build/{runtime~main.d4c8d6a2.js → runtime~main.c20330f1.js} +1 -1
  69. package/build/{sso-settings-page.1dd4886e.chunk.js → sso-settings-page.f44d95d8.chunk.js} +1 -1
  70. package/build/{transfer-tokens-create-page.ec2ca215.chunk.js → transfer-tokens-create-page.170acee6.chunk.js} +1 -1
  71. package/build/{transfer-tokens-edit-page.22bf28e5.chunk.js → transfer-tokens-edit-page.6cf23295.chunk.js} +1 -1
  72. package/build/{transfer-tokens-list-page.cf8c77f2.chunk.js → transfer-tokens-list-page.c3fec4c1.chunk.js} +2 -2
  73. package/build/{upload-settings.945fdcfa.chunk.js → upload-settings.dd2d987c.chunk.js} +1 -1
  74. package/build/{upload.a86b1054.chunk.js → upload.c8479232.chunk.js} +1 -1
  75. package/build/{users-advanced-settings-page.5b5a9baa.chunk.js → users-advanced-settings-page.c36cfd59.chunk.js} +1 -1
  76. package/build/{users-email-settings-page.e5506eb4.chunk.js → users-email-settings-page.2716ce8e.chunk.js} +5 -5
  77. package/build/{users-providers-settings-page.e32089c2.chunk.js → users-providers-settings-page.0d6304a5.chunk.js} +1 -1
  78. package/build/{users-roles-settings-page.20656f92.chunk.js → users-roles-settings-page.eeb3a339.chunk.js} +1 -1
  79. package/build/{webhook-edit-page.a3b62049.chunk.js → webhook-edit-page.f4db86f3.chunk.js} +2 -2
  80. package/build/{webhook-list-page.ca38eeef.chunk.js → webhook-list-page.30d73114.chunk.js} +1 -1
  81. package/ee/admin/content-manager/components/DynamicTable/CellContent/ReviewWorkflowsStage/ReviewWorkflowsStageEE.js +11 -5
  82. package/ee/admin/content-manager/components/DynamicTable/CellContent/ReviewWorkflowsStage/getTableColumn.js +7 -3
  83. package/ee/admin/content-manager/pages/EditView/InformationBox/InformationBoxEE.js +16 -2
  84. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/ReviewWorkflows.js +34 -25
  85. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/actions/index.js +11 -0
  86. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/components/StageDragPreview/StageDragPreview.js +45 -0
  87. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/components/StageDragPreview/index.js +1 -0
  88. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/components/Stages/Stage/Stage.js +287 -63
  89. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/components/Stages/Stage/components/OptionColor/OptionColor.js +27 -0
  90. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/components/Stages/Stage/components/OptionColor/index.js +1 -0
  91. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/components/Stages/Stage/components/SingleValueColor/SingleValueColor.js +31 -0
  92. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/components/Stages/Stage/components/SingleValueColor/index.js +1 -0
  93. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/components/Stages/Stages.js +2 -1
  94. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/constants.js +26 -0
  95. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/reducer/index.js +36 -2
  96. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/utils/colors.js +33 -0
  97. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/utils/getWorkflowValidationSchema.js +9 -0
  98. package/ee/server/constants/workflows.js +1 -0
  99. package/ee/server/content-types/workflow-stage/index.js +7 -0
  100. package/ee/server/controllers/authentication/middlewares.js +1 -1
  101. package/ee/server/migrations/review-workflows-stages-color.js +20 -0
  102. package/ee/server/register.js +2 -0
  103. package/ee/server/services/review-workflows/review-workflows.js +1 -1
  104. package/ee/server/services/review-workflows/stages.js +1 -1
  105. package/ee/server/utils/persisted-tables.js +3 -0
  106. package/ee/server/validation/review-workflows.js +7 -1
  107. package/jest.config.front.js +1 -0
  108. package/package.json +10 -10
  109. package/admin/src/components/AutoReloadOverlayBlockerProvider/Blocker.js +0 -95
  110. package/admin/src/components/AutoReloadOverlayBlockerProvider/Overlay.js +0 -42
  111. package/admin/src/components/AutoReloadOverlayBlockerProvider/index.js +0 -99
  112. package/admin/src/components/Notifications/Notification/index.js +0 -159
  113. package/admin/src/components/Notifications/index.js +0 -46
  114. package/admin/src/components/Notifications/reducer.js +0 -47
  115. package/admin/src/components/OverlayBlocker/index.js +0 -67
  116. package/admin/src/content-manager/components/DragLayer/ComponentDragPreview.js +0 -83
  117. package/admin/src/content-manager/components/DragLayer/index.js +0 -85
  118. package/admin/src/content-manager/contexts/LayoutDnd.js +0 -5
  119. package/admin/src/content-manager/hooks/useCallbackRef.js +0 -23
  120. package/admin/src/content-manager/hooks/useLayoutDnd.js +0 -6
  121. package/admin/src/content-manager/pages/ListSettingsView/utils/ellipsisCardTitle.js +0 -7
  122. package/build/8694.6522968d.chunk.js +0 -247
  123. package/build/Admin-authenticatedApp.5562aedc.chunk.js +0 -79
  124. package/build/admin-app.014adc27.chunk.js +0 -110
  125. package/build/content-manager.84f81966.chunk.js +0 -1130
  126. package/build/main.841e0dcb.js +0 -2280
  127. package/build/review-workflows-settings.f7890c40.chunk.js +0 -106
@@ -1,9 +1,9 @@
1
- import React, { useMemo, useState, useEffect, useRef } from 'react';
1
+ import React, { useState, useEffect } from 'react';
2
2
  // TODO: DS add loader
3
3
  import {
4
4
  auth,
5
5
  LoadingIndicatorPage,
6
- AppInfosContext,
6
+ AppInfoProvider,
7
7
  useGuidedTour,
8
8
  useNotification,
9
9
  } from '@strapi/helper-plugin';
@@ -27,7 +27,6 @@ const strapiVersion = packageJSON.version;
27
27
  const AuthenticatedApp = () => {
28
28
  const { setGuidedTourVisibility } = useGuidedTour();
29
29
  const toggleNotification = useNotification();
30
- const setGuidedTourVisibilityRef = useRef(setGuidedTourVisibility);
31
30
  const userInfo = auth.getUserInfo();
32
31
  const userName = get(userInfo, 'username') || getFullName(userInfo.firstname, userInfo.lastname);
33
32
  const [userDisplayName, setUserDisplayName] = useState(userName);
@@ -35,7 +34,7 @@ const AuthenticatedApp = () => {
35
34
  const { showReleaseNotification } = useConfigurations();
36
35
  const [
37
36
  { data: appInfos, status },
38
- { data: tag_name, isLoading },
37
+ { data: tagName, isLoading },
39
38
  { data: permissions, status: fetchPermissionsStatus, refetch, isFetched, isFetching },
40
39
  { data: userRoles },
41
40
  ] = useQueries([
@@ -57,20 +56,20 @@ const AuthenticatedApp = () => {
57
56
  },
58
57
  ]);
59
58
 
60
- const shouldUpdateStrapi = useMemo(
61
- () => checkLatestStrapiVersion(strapiVersion, tag_name),
62
- [tag_name]
63
- );
59
+ const shouldUpdateStrapi = checkLatestStrapiVersion(strapiVersion, tagName);
64
60
 
61
+ /**
62
+ * TODO: does this actually need to be an effect?
63
+ */
65
64
  useEffect(() => {
66
65
  if (userRoles) {
67
66
  const isUserSuperAdmin = userRoles.find(({ code }) => code === 'strapi-super-admin');
68
67
 
69
68
  if (isUserSuperAdmin && appInfos?.autoReload) {
70
- setGuidedTourVisibilityRef.current(true);
69
+ setGuidedTourVisibility(true);
71
70
  }
72
71
  }
73
- }, [userRoles, appInfos]);
72
+ }, [userRoles, appInfos, setGuidedTourVisibility]);
74
73
 
75
74
  useEffect(() => {
76
75
  const getUserId = async () => {
@@ -88,32 +87,28 @@ const AuthenticatedApp = () => {
88
87
 
89
88
  const shouldShowLoader = isLoading || shouldShowNotDependentQueriesLoader;
90
89
 
91
- const appInfosValue = useMemo(() => {
92
- return {
93
- ...appInfos,
94
- userId,
95
- latestStrapiReleaseTag: tag_name,
96
- setUserDisplayName,
97
- shouldUpdateStrapi,
98
- userDisplayName,
99
- };
100
- }, [appInfos, tag_name, shouldUpdateStrapi, userDisplayName, userId]);
101
-
102
90
  if (shouldShowLoader) {
103
91
  return <LoadingIndicatorPage />;
104
92
  }
105
93
 
106
- // TODO add error state
94
+ // TODO: add error state
107
95
  if (status === 'error') {
108
96
  return <div>error...</div>;
109
97
  }
110
98
 
111
99
  return (
112
- <AppInfosContext.Provider value={appInfosValue}>
100
+ <AppInfoProvider
101
+ {...appInfos}
102
+ userId={userId}
103
+ latestStrapiReleaseTag={tagName}
104
+ setUserDisplayName={setUserDisplayName}
105
+ shouldUpdateStrapi={shouldUpdateStrapi}
106
+ userDisplayName={userDisplayName}
107
+ >
113
108
  <RBACProvider permissions={permissions} refetchPermissions={refetch}>
114
109
  <PluginsInitializer />
115
110
  </RBACProvider>
116
- </AppInfosContext.Provider>
111
+ </AppInfoProvider>
117
112
  );
118
113
  };
119
114
 
@@ -0,0 +1,53 @@
1
+ import * as React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { useDragLayer } from 'react-dnd';
4
+ import { Box } from '@strapi/design-system';
5
+
6
+ function getStyle(initialOffset, currentOffset, mouseOffset) {
7
+ if (!initialOffset || !currentOffset) {
8
+ return { display: 'none' };
9
+ }
10
+
11
+ const { x, y } = mouseOffset;
12
+
13
+ return {
14
+ transform: `translate(${x}px, ${y}px)`,
15
+ };
16
+ }
17
+
18
+ export function DragLayer({ renderItem }) {
19
+ const { itemType, isDragging, item, initialOffset, currentOffset, mouseOffset } = useDragLayer(
20
+ (monitor) => ({
21
+ item: monitor.getItem(),
22
+ itemType: monitor.getItemType(),
23
+ initialOffset: monitor.getInitialSourceClientOffset(),
24
+ currentOffset: monitor.getSourceClientOffset(),
25
+ isDragging: monitor.isDragging(),
26
+ mouseOffset: monitor.getClientOffset(),
27
+ })
28
+ );
29
+
30
+ if (!isDragging) {
31
+ return null;
32
+ }
33
+
34
+ return (
35
+ <Box
36
+ height="100%"
37
+ left={0}
38
+ position="fixed"
39
+ pointerEvents="none"
40
+ top={0}
41
+ zIndex={100}
42
+ width="100%"
43
+ >
44
+ <Box style={getStyle(initialOffset, currentOffset, mouseOffset)}>
45
+ {renderItem({ type: itemType, item })}
46
+ </Box>
47
+ </Box>
48
+ );
49
+ }
50
+
51
+ DragLayer.propTypes = {
52
+ renderItem: PropTypes.func.isRequired,
53
+ };
@@ -0,0 +1 @@
1
+ export * from './DragLayer';
@@ -18,7 +18,7 @@ import { Write, Exit } from '@strapi/icons';
18
18
  import {
19
19
  auth,
20
20
  usePersistentState,
21
- useAppInfos,
21
+ useAppInfo,
22
22
  useTracking,
23
23
  getFetchClient,
24
24
  } from '@strapi/helper-plugin';
@@ -59,7 +59,7 @@ const LeftMenu = ({ generalSectionLinks, pluginsSectionLinks }) => {
59
59
  logos: { menu },
60
60
  } = useConfigurations();
61
61
  const [condensed, setCondensed] = usePersistentState('navbar-condensed', false);
62
- const { userDisplayName } = useAppInfos();
62
+ const { userDisplayName } = useAppInfo();
63
63
  const { formatMessage } = useIntl();
64
64
  const { trackUsage } = useTracking();
65
65
  const { pathname } = useLocation();
@@ -1,15 +1,19 @@
1
1
  import React from 'react';
2
2
  import PropTypes from 'prop-types';
3
3
  import { QueryClientProvider, QueryClient } from 'react-query';
4
- import { LibraryProvider, CustomFieldsProvider, StrapiAppProvider } from '@strapi/helper-plugin';
4
+ import {
5
+ LibraryProvider,
6
+ CustomFieldsProvider,
7
+ StrapiAppProvider,
8
+ AutoReloadOverlayBlockerProvider,
9
+ OverlayBlockerProvider,
10
+ NotificationsProvider,
11
+ } from '@strapi/helper-plugin';
5
12
  import { Provider } from 'react-redux';
6
13
  import { AdminContext } from '../../contexts';
7
14
  import ConfigurationsProvider from '../ConfigurationsProvider';
8
15
  import LanguageProvider from '../LanguageProvider';
9
16
  import GuidedTour from '../GuidedTour';
10
- import AutoReloadOverlayBlockerProvider from '../AutoReloadOverlayBlockerProvider';
11
- import Notifications from '../Notifications';
12
- import OverlayBlocker from '../OverlayBlocker';
13
17
  import ThemeToggleProvider from '../ThemeToggleProvider';
14
18
  import Theme from '../Theme';
15
19
 
@@ -68,11 +72,11 @@ const Providers = ({
68
72
  <CustomFieldsProvider customFields={customFields}>
69
73
  <LanguageProvider messages={messages} localeNames={localeNames}>
70
74
  <AutoReloadOverlayBlockerProvider>
71
- <OverlayBlocker>
75
+ <OverlayBlockerProvider>
72
76
  <GuidedTour>
73
- <Notifications>{children}</Notifications>
77
+ <NotificationsProvider>{children}</NotificationsProvider>
74
78
  </GuidedTour>
75
- </OverlayBlocker>
79
+ </OverlayBlockerProvider>
76
80
  </AutoReloadOverlayBlockerProvider>
77
81
  </LanguageProvider>
78
82
  </CustomFieldsProvider>
@@ -1,3 +1,2 @@
1
1
  export { default as ContentTypeLayoutContext } from './ContentTypeLayout';
2
- export { default as LayoutDndContext } from './LayoutDnd';
3
2
  export { default as WysiwygContext } from './Wysiwyg';
@@ -1,7 +1,6 @@
1
1
  export { default as useContentTypeLayout } from './useContentTypeLayout';
2
2
  export { default as useFetchContentTypeLayout } from './useFetchContentTypeLayout';
3
3
  export { default as useFindRedirectionLink } from './useFindRedirectionLink';
4
- export { default as useLayoutDnd } from './useLayoutDnd';
5
4
  export { default as usePluginsQueryParams } from './usePluginsQueryParams';
6
5
  export { default as useSyncRbac } from './useSyncRbac';
7
6
  export { default as useWysiwyg } from './useWysiwyg';
@@ -38,11 +38,15 @@ const useLazyComponents = (componentUids = []) => {
38
38
  if (newUids.length > 0) {
39
39
  setLoading(true);
40
40
 
41
- const componentPromises = newUids.map((uid) => {
41
+ const componentPromises = newUids.reduce((arrayOfPromises, uid) => {
42
42
  const customField = customFieldsRegistry.get(uid);
43
43
 
44
- return customField.components.Input();
45
- });
44
+ if (customField) {
45
+ arrayOfPromises.push(customField.components.Input());
46
+ }
47
+
48
+ return arrayOfPromises;
49
+ }, []);
46
50
 
47
51
  if (componentPromises.length > 0) {
48
52
  lazyLoadComponents(newUids, componentPromises);
@@ -1,12 +1,10 @@
1
1
  import { useState, useEffect } from 'react';
2
2
  import { useInfiniteQuery } from 'react-query';
3
3
 
4
- import { useFetchClient } from '@strapi/helper-plugin';
4
+ import { useFetchClient, useCallbackRef } from '@strapi/helper-plugin';
5
5
 
6
6
  import { normalizeRelations } from '../../components/RelationInputDataManager/utils';
7
7
 
8
- import { useCallbackRef } from '../useCallbackRef';
9
-
10
8
  export const useRelation = (cacheKey, { relation, search }) => {
11
9
  const [searchParams, setSearchParams] = useState({});
12
10
  const [currentPage, setCurrentPage] = useState(0);
@@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
3
3
  import styled from 'styled-components';
4
4
  import { Flex, Typography } from '@strapi/design-system';
5
5
  import { Pencil, Cross, Drag } from '@strapi/icons';
6
- import ellipsisCardTitle from '../utils/ellipsisCardTitle';
6
+ import { pxToRem } from '@strapi/helper-plugin';
7
7
 
8
8
  const ActionBox = styled(Flex)`
9
9
  height: ${({ theme }) => theme.spaces[7]};
@@ -14,9 +14,8 @@ const ActionBox = styled(Flex)`
14
14
  `;
15
15
 
16
16
  const DragButton = styled(ActionBox)`
17
- padding: 0 ${({ theme }) => theme.spaces[3]};
18
- border-right: 1px solid ${({ theme }) => theme.colors.neutral150};
19
- cursor: all-scroll;
17
+ border-right: 1px solid
18
+ ${({ theme, isSibling }) => (isSibling ? theme.colors.neutral150 : theme.colors.primary200)};
20
19
 
21
20
  svg {
22
21
  width: ${12 / 16}rem;
@@ -25,11 +24,6 @@ const DragButton = styled(ActionBox)`
25
24
  `;
26
25
 
27
26
  const FieldContainer = styled(Flex)`
28
- display: inline-flex;
29
- max-height: ${32 / 16}rem;
30
- opacity: ${({ transparent }) => (transparent ? 0 : 1)};
31
- background-color: ${({ theme, isSibling }) =>
32
- isSibling ? theme.colors.neutral100 : theme.colors.primary100};
33
27
  border: 1px solid
34
28
  ${({ theme, isSibling }) => (isSibling ? theme.colors.neutral150 : theme.colors.primary200)};
35
29
 
@@ -41,54 +35,60 @@ const FieldContainer = styled(Flex)`
41
35
  fill: ${({ theme, isSibling }) => (isSibling ? undefined : theme.colors.primary600)};
42
36
  }
43
37
  }
44
-
45
- ${Typography} {
46
- color: ${({ theme, isSibling }) => (isSibling ? undefined : theme.colors.primary600)};
47
- }
48
-
49
- ${DragButton} {
50
- border-right: 1px solid
51
- ${({ theme, isSibling }) => (isSibling ? theme.colors.neutral150 : theme.colors.primary200)};
52
- }
53
38
  `;
54
39
 
55
- const CardPreview = ({ labelField, transparent, isSibling }) => {
56
- const cardEllipsisTitle = ellipsisCardTitle(labelField);
40
+ const TypographyMaxWidth = styled(Typography)`
41
+ max-width: ${72 / 16}rem;
42
+ `;
57
43
 
44
+ export function CardDragPreview({ labelField, transparent, isSibling }) {
58
45
  return (
59
46
  <FieldContainer
47
+ background={isSibling ? 'neutral100' : 'primary100'}
48
+ display="inline-flex"
49
+ gap={3}
60
50
  hasRadius
61
51
  justifyContent="space-between"
62
52
  transparent={transparent}
63
53
  isSibling={isSibling}
54
+ max-height={pxToRem(32)}
55
+ maxWidth="min-content"
56
+ opacity={transparent ? 0 : 1}
64
57
  >
65
58
  <Flex gap={3}>
66
- <DragButton alignItems="center">
59
+ <DragButton alignItems="center" cursor="all-scroll" padding={3}>
67
60
  <Drag />
68
61
  </DragButton>
69
- <Typography fontWeight="bold">{cardEllipsisTitle}</Typography>
62
+
63
+ <TypographyMaxWidth
64
+ textColor={isSibling ? undefined : 'primary600'}
65
+ fontWeight="bold"
66
+ ellipsis
67
+ >
68
+ {labelField}
69
+ </TypographyMaxWidth>
70
70
  </Flex>
71
- <Flex paddingLeft={3}>
71
+
72
+ <Flex>
72
73
  <ActionBox alignItems="center">
73
74
  <Pencil />
74
75
  </ActionBox>
76
+
75
77
  <ActionBox alignItems="center">
76
78
  <Cross />
77
79
  </ActionBox>
78
80
  </Flex>
79
81
  </FieldContainer>
80
82
  );
81
- };
83
+ }
82
84
 
83
- CardPreview.defaultProps = {
85
+ CardDragPreview.defaultProps = {
84
86
  isSibling: false,
85
87
  transparent: false,
86
88
  };
87
89
 
88
- CardPreview.propTypes = {
90
+ CardDragPreview.propTypes = {
89
91
  isSibling: PropTypes.bool,
90
92
  labelField: PropTypes.string.isRequired,
91
93
  transparent: PropTypes.bool,
92
94
  };
93
-
94
- export default CardPreview;
@@ -0,0 +1,75 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import styled from 'styled-components';
4
+ import { pxToRem } from '@strapi/helper-plugin';
5
+ import { Flex, Typography, IconButton } from '@strapi/design-system';
6
+ import { Trash, Drag, CarretDown } from '@strapi/icons';
7
+
8
+ const DropdownIconWrapper = styled(Flex)`
9
+ border-radius: 50%;
10
+
11
+ svg {
12
+ height: ${6 / 16}rem;
13
+ width: ${11 / 16}rem;
14
+ > path {
15
+ fill: ${({ theme }) => theme.colors.neutral600};
16
+ }
17
+ }
18
+ `;
19
+
20
+ // TODO: we shouldn't have to reset a whole button
21
+ const ToggleButton = styled.button`
22
+ border: none;
23
+ background: transparent;
24
+ display: block;
25
+ width: 100%;
26
+ text-align: unset;
27
+ padding: 0;
28
+ `;
29
+
30
+ export function ComponentDragPreview({ displayedValue }) {
31
+ return (
32
+ <Flex
33
+ background="neutral0"
34
+ borderColor="neutral200"
35
+ justifyContent="space-between"
36
+ gap={3}
37
+ padding={3}
38
+ width={pxToRem(300)}
39
+ >
40
+ <ToggleButton type="button">
41
+ <Flex gap={6}>
42
+ <DropdownIconWrapper
43
+ alignItems="center"
44
+ justifyContent="center"
45
+ background="neutral200"
46
+ height={pxToRem(32)}
47
+ width={pxToRem(32)}
48
+ >
49
+ <CarretDown />
50
+ </DropdownIconWrapper>
51
+
52
+ <Flex maxWidth={pxToRem(150)}>
53
+ <Typography textColor="neutral700" ellipsis>
54
+ {displayedValue}
55
+ </Typography>
56
+ </Flex>
57
+ </Flex>
58
+ </ToggleButton>
59
+
60
+ <Flex gap={2}>
61
+ <IconButton noBorder>
62
+ <Trash />
63
+ </IconButton>
64
+
65
+ <IconButton noBorder>
66
+ <Drag />
67
+ </IconButton>
68
+ </Flex>
69
+ </Flex>
70
+ );
71
+ }
72
+
73
+ ComponentDragPreview.propTypes = {
74
+ displayedValue: PropTypes.string.isRequired,
75
+ };
@@ -4,10 +4,13 @@ import PropTypes from 'prop-types';
4
4
  import { Box, Flex, IconButton, Typography, Status, Icon } from '@strapi/design-system';
5
5
  import { Drag, Cross } from '@strapi/icons';
6
6
 
7
- import { getTrad } from '../../utils';
8
- import { PUBLICATION_STATES } from '../RelationInputDataManager/constants';
9
- import { ChildrenWrapper, FlexWrapper } from '../RelationInput/components/RelationItem';
10
- import { LinkEllipsis, DisconnectButton } from '../RelationInput';
7
+ import { getTrad } from '../../../utils';
8
+ import { PUBLICATION_STATES } from '../../../components/RelationInputDataManager/constants';
9
+ import {
10
+ ChildrenWrapper,
11
+ FlexWrapper,
12
+ } from '../../../components/RelationInput/components/RelationItem';
13
+ import { LinkEllipsis, DisconnectButton } from '../../../components/RelationInput';
11
14
 
12
15
  export const RelationDragPreview = ({ status, displayedValue, width }) => {
13
16
  const { formatMessage } = useIntl();
@@ -12,7 +12,7 @@ import { useIntl } from 'react-intl';
12
12
  import sortBy from 'lodash/sortBy';
13
13
  import permissions from '../../../permissions';
14
14
  import getTrad from '../../utils/getTrad';
15
- import DragLayer from '../../components/DragLayer';
15
+ import { DragLayer } from '../../../components/DragLayer';
16
16
  import ModelsContext from '../../contexts/ModelsContext';
17
17
  import CollectionTypeRecursivePath from '../CollectionTypeRecursivePath';
18
18
  import ComponentSettingsView from '../ComponentSetttingsView';
@@ -22,8 +22,45 @@ import SingleTypeRecursivePath from '../SingleTypeRecursivePath';
22
22
  import LeftMenu from './LeftMenu';
23
23
  import useContentManagerInitData from './useContentManagerInitData';
24
24
 
25
+ import ItemTypes from '../../utils/ItemTypes';
26
+
27
+ import { CardDragPreview } from './components/CardDragPreview';
28
+ import { ComponentDragPreview } from './components/ComponentDragPreview';
29
+ import { RelationDragPreview } from './components/RelationDragPreview';
30
+
25
31
  const cmPermissions = permissions.contentManager;
26
32
 
33
+ function renderDraglayerItem({ type, item }) {
34
+ if ([ItemTypes.EDIT_FIELD, ItemTypes.FIELD].includes(type)) {
35
+ return <CardDragPreview labelField={item.labelField} />;
36
+ }
37
+
38
+ /**
39
+ * Because a user may have multiple relations / dynamic zones / repeable fields in the same content type,
40
+ * we append the fieldName for the item type to make them unique, however, we then want to extract that
41
+ * first type to apply the correct preview.
42
+ */
43
+ const [actualType] = type.split('_');
44
+
45
+ switch (actualType) {
46
+ case ItemTypes.COMPONENT:
47
+ case ItemTypes.DYNAMIC_ZONE:
48
+ return <ComponentDragPreview displayedValue={item.displayedValue} />;
49
+
50
+ case ItemTypes.RELATION:
51
+ return (
52
+ <RelationDragPreview
53
+ displayedValue={item.displayedValue}
54
+ status={item.status}
55
+ width={item.width}
56
+ />
57
+ );
58
+
59
+ default:
60
+ return null;
61
+ }
62
+ }
63
+
27
64
  const App = () => {
28
65
  const contentTypeMatch = useRouteMatch(`/content-manager/:kind/:uid`);
29
66
  const { status, collectionTypeLinks, singleTypeLinks, models, refetchData } =
@@ -85,7 +122,7 @@ const App = () => {
85
122
 
86
123
  return (
87
124
  <Layout sideNav={<LeftMenu />}>
88
- <DragLayer />
125
+ <DragLayer renderItem={renderDraglayerItem} />
89
126
  <ModelsContext.Provider value={{ refetchData }}>
90
127
  <Switch>
91
128
  <Route path="/content-manager/components/:uid/configurations/edit">
@@ -5,7 +5,7 @@ import { Box, Flex, Typography, Grid, GridItem } from '@strapi/design-system';
5
5
  import { Cog } from '@strapi/icons';
6
6
  import { useIntl } from 'react-intl';
7
7
  import get from 'lodash/get';
8
- import useLayoutDnd from '../../../hooks/useLayoutDnd';
8
+ import { useLayoutDnd } from '../hooks/useLayoutDnd';
9
9
  import getTrad from '../../../utils/getTrad';
10
10
 
11
11
  const ComponentFieldList = ({ componentUid }) => {
@@ -7,7 +7,7 @@ import { Flex, Box, GridItem } from '@strapi/design-system';
7
7
  import { Drag } from '@strapi/icons';
8
8
  import { ItemTypes } from '../../../utils';
9
9
  import FieldButtonContent from './FieldButtonContent';
10
- import { useLayoutDnd } from '../../../hooks';
10
+ import { useLayoutDnd } from '../hooks/useLayoutDnd';
11
11
 
12
12
  const Wrapper = styled(Flex)`
13
13
  position: relative;
@@ -5,7 +5,7 @@ import PropTypes from 'prop-types';
5
5
  import { Box, Flex, Typography } from '@strapi/design-system';
6
6
 
7
7
  import { ComponentIcon } from '../../../components/ComponentIcon';
8
- import useLayoutDnd from '../../../hooks/useLayoutDnd';
8
+ import { useLayoutDnd } from '../hooks/useLayoutDnd';
9
9
 
10
10
  const CustomLink = styled(Flex)`
11
11
  text-decoration: none;
@@ -14,7 +14,7 @@ import {
14
14
  } from '@strapi/design-system';
15
15
  import styled from 'styled-components';
16
16
  import { getTrad } from '../../../utils';
17
- import { useLayoutDnd } from '../../../hooks';
17
+ import { useLayoutDnd } from '../hooks/useLayoutDnd';
18
18
  import FieldTypeIcon from '../../../components/FieldTypeIcon';
19
19
  import ModalForm from './ModalForm';
20
20
 
@@ -1,8 +1,9 @@
1
1
  import React from 'react';
2
2
  import PropTypes from 'prop-types';
3
- import LayoutDndContext from '../../contexts/LayoutDnd';
4
3
 
5
- function LayoutDndProvider({
4
+ export const LayoutDndContext = React.createContext();
5
+
6
+ export function LayoutDndProvider({
6
7
  attributes,
7
8
  buttonData,
8
9
  children,
@@ -71,5 +72,3 @@ LayoutDndProvider.propTypes = {
71
72
  selectedItemName: PropTypes.string,
72
73
  setEditFieldToSelect: PropTypes.func,
73
74
  };
74
-
75
- export default LayoutDndProvider;
@@ -10,7 +10,7 @@ import { useIntl } from 'react-intl';
10
10
  import get from 'lodash/get';
11
11
  import { Pencil } from '@strapi/icons';
12
12
  import getTrad from '../../../utils/getTrad';
13
- import useLayoutDnd from '../../../hooks/useLayoutDnd';
13
+ import { useLayoutDnd } from '../hooks/useLayoutDnd';
14
14
 
15
15
  const permissions = [{ action: 'plugin::content-type-builder.read', subject: null }];
16
16
 
@@ -4,7 +4,7 @@ import get from 'lodash/get';
4
4
  import { GridItem, Select, Option } from '@strapi/design-system';
5
5
  import { useSelector, shallowEqual } from 'react-redux';
6
6
  import { useIntl } from 'react-intl';
7
- import { useLayoutDnd } from '../../../hooks';
7
+ import { useLayoutDnd } from '../hooks/useLayoutDnd';
8
8
  import { createPossibleMainFieldsForModelsAndComponents, getInputProps } from '../utils';
9
9
  import { makeSelectModelAndComponentSchemas, selectFieldSizes } from '../../App/selectors';
10
10
  import getTrad from '../../../utils/getTrad';
@@ -1,7 +1,7 @@
1
1
  import React from 'react';
2
2
  import PropTypes from 'prop-types';
3
3
  import get from 'lodash/get';
4
- import { useLayoutDnd } from '../../../hooks';
4
+ import { useLayoutDnd } from '../hooks/useLayoutDnd';
5
5
  import DisplayedFieldButton from './DisplayedFieldButton';
6
6
 
7
7
  const RowItemsLayout = ({ rowItem, onRemoveField, rowId, rowIndex, index, lastIndex }) => {
@@ -0,0 +1,6 @@
1
+ import * as React from 'react';
2
+ import { LayoutDndContext } from '../components/LayoutDndProvider';
3
+
4
+ export function useLayoutDnd() {
5
+ return React.useContext(LayoutDndContext);
6
+ }
@@ -32,7 +32,7 @@ import reducer, { initialState } from './reducer';
32
32
  import init from './init';
33
33
  import DisplayedFields from './components/DisplayedFields';
34
34
  import ModalForm from './components/FormModal';
35
- import LayoutDndProvider from '../../components/LayoutDndProvider';
35
+ import { LayoutDndProvider } from './components/LayoutDndProvider';
36
36
  import { unformatLayout } from './utils/layout';
37
37
  import putCMSettingsEV from './utils/api';
38
38
  import { selectFieldSizes } from '../App/selectors';