@strapi/admin 4.5.4 → 4.6.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/admin/src/components/AuthenticatedApp/index.js +2 -13
- package/admin/src/content-manager/components/ComponentInitializer/index.js +1 -7
- package/admin/src/content-manager/components/{RepeatableComponent/DragPreview.js → DragLayer/ComponentDragPreview.js} +25 -12
- package/admin/src/content-manager/components/DragLayer/RelationDragPreview.js +75 -0
- package/admin/src/content-manager/components/DragLayer/index.js +23 -7
- package/admin/src/content-manager/components/DynamicZone/components/DynamicComponent.js +130 -84
- package/admin/src/content-manager/components/DynamicZone/index.js +99 -24
- package/admin/src/content-manager/components/DynamicZone/utils/select.js +9 -5
- package/admin/src/content-manager/components/EditViewDataManagerProvider/index.js +37 -11
- package/admin/src/content-manager/components/EditViewDataManagerProvider/reducer.js +18 -22
- package/admin/src/content-manager/components/EditViewDataManagerProvider/utils/cleanData.js +24 -5
- package/admin/src/content-manager/components/RelationInput/RelationInput.js +209 -64
- package/admin/src/content-manager/components/RelationInput/components/RelationItem.js +134 -21
- package/admin/src/content-manager/components/RelationInput/components/RelationList.js +1 -2
- package/admin/src/content-manager/components/RelationInput/constants.js +1 -0
- package/admin/src/content-manager/components/RelationInputDataManager/RelationInputDataManager.js +131 -9
- package/admin/src/content-manager/components/RepeatableComponent/components/Accordion.js +77 -0
- package/admin/src/content-manager/components/RepeatableComponent/components/Component.js +262 -0
- package/admin/src/content-manager/components/RepeatableComponent/{DraggedItem → components}/Preview.js +0 -0
- package/admin/src/content-manager/components/RepeatableComponent/index.js +147 -87
- package/admin/src/content-manager/components/RepeatableComponent/utils/getComponentErrorKeys.js +1 -1
- package/admin/src/content-manager/hooks/index.js +2 -0
- package/admin/src/content-manager/hooks/useDragAndDrop.js +120 -0
- package/admin/src/content-manager/hooks/useKeyboardDragAndDrop.js +98 -0
- package/admin/src/content-manager/utils/ItemTypes.js +1 -1
- package/admin/src/content-manager/utils/composeRefs.js +28 -0
- package/admin/src/content-manager/utils/getMaxTempKey.js +1 -1
- package/admin/src/content-manager/utils/index.js +7 -0
- package/admin/src/pages/App/index.js +13 -20
- package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/index.js +3 -2
- package/admin/src/translations/en.json +6 -0
- package/admin/src/translations/tr.json +5 -485
- package/admin/src/utils/index.js +0 -1
- package/build/4318.80bdf035.chunk.js +30 -0
- package/build/{8176.e929d326.chunk.js → 8176.b19bc128.chunk.js} +32 -32
- package/build/{1233.802422fa.chunk.js → 8186.55910742.chunk.js} +96 -96
- package/build/{8633.43ec9042.chunk.js → 8633.59223842.chunk.js} +1 -1
- package/build/Admin-authenticatedApp.f9e74dc0.chunk.js +80 -0
- package/build/{Admin_profilePage.60ab80bb.chunk.js → Admin_profilePage.c07bdf08.chunk.js} +1 -1
- package/build/{Admin_settingsPage.6ef8acc9.chunk.js → Admin_settingsPage.50a8765b.chunk.js} +1 -1
- package/build/admin-app.2861b6d2.chunk.js +112 -0
- package/build/admin-edit-users.85231e4c.chunk.js +10 -0
- package/build/{admin-users.e64fb0f1.chunk.js → admin-users.a2707644.chunk.js} +2 -2
- package/build/api-tokens-create-page.dd4ddfcb.chunk.js +1 -0
- package/build/api-tokens-edit-page.821c5a6c.chunk.js +1 -0
- package/build/content-manager.ee948f75.chunk.js +1186 -0
- package/build/content-type-builder-translation-tr-json.2e52bc60.chunk.js +1 -0
- package/build/email-settings-page.db0d98d1.chunk.js +15 -0
- package/build/email-translation-tr-json.87f2feb3.chunk.js +1 -0
- package/build/{en-json.7dd57947.chunk.js → en-json.4a56dca7.chunk.js} +1 -1
- package/build/index.html +1 -1
- package/build/main.faac89ee.js +2025 -0
- package/build/runtime~main.75a15b8e.js +2 -0
- package/build/sso-settings-page.adb12ac3.chunk.js +1 -0
- package/build/tr-json.9c44ea0c.chunk.js +1 -0
- package/build/{upload.74540aab.chunk.js → upload.e2034370.chunk.js} +3 -3
- package/build/users-permissions-translation-tr-json.cdc49a3c.chunk.js +1 -0
- package/package.json +9 -9
- package/server/controllers/admin.js +0 -2
- package/server/routes/admin.js +1 -1
- package/server/services/metrics.js +2 -5
- package/admin/src/content-manager/components/RepeatableComponent/AccordionGroupCustom/index.js +0 -122
- package/admin/src/content-manager/components/RepeatableComponent/AddFieldButton.js +0 -58
- package/admin/src/content-manager/components/RepeatableComponent/DraggedItem/DraggingSibling.js +0 -72
- package/admin/src/content-manager/components/RepeatableComponent/DraggedItem/IconButtonCustoms.js +0 -32
- package/admin/src/content-manager/components/RepeatableComponent/DraggedItem/index.js +0 -326
- package/admin/src/content-manager/components/RepeatableComponent/DraggedItem/utils/connect.js +0 -11
- package/admin/src/content-manager/components/RepeatableComponent/DraggedItem/utils/index.js +0 -2
- package/admin/src/content-manager/components/RepeatableComponent/DraggedItem/utils/select.js +0 -30
- package/admin/src/content-manager/components/RepeatableComponent/utils/connect.js +0 -11
- package/admin/src/content-manager/components/RepeatableComponent/utils/select.js +0 -12
- package/admin/src/content-manager/hooks/__test__/usePrev.test.js +0 -26
- package/admin/src/utils/uniqueAdminHash.js +0 -22
- package/build/4318.9283c350.chunk.js +0 -30
- package/build/Admin-authenticatedApp.0da578b8.chunk.js +0 -80
- package/build/admin-app.a3277e72.chunk.js +0 -112
- package/build/admin-edit-users.5547b126.chunk.js +0 -10
- package/build/api-tokens-create-page.93dd0689.chunk.js +0 -1
- package/build/api-tokens-edit-page.b0adac81.chunk.js +0 -1
- package/build/content-manager.f9630c3b.chunk.js +0 -1197
- package/build/content-type-builder-translation-tr-json.949e22eb.chunk.js +0 -1
- package/build/email-settings-page.c6e62f6b.chunk.js +0 -15
- package/build/email-translation-tr-json.8aa034bb.chunk.js +0 -1
- package/build/i18n-translation-tr-json.34ca9d61.chunk.js +0 -1
- package/build/main.71f24343.js +0 -2034
- package/build/runtime~main.1115f82b.js +0 -2
- package/build/sso-settings-page.feed2f45.chunk.js +0 -1
- package/build/tr-json.eac8bd79.chunk.js +0 -1
- package/build/upload-translation-tr-json.b173223a.chunk.js +0 -1
- package/build/users-permissions-translation-tr-json.9bebc250.chunk.js +0 -1
|
@@ -20,7 +20,7 @@ import {
|
|
|
20
20
|
fetchUserRoles,
|
|
21
21
|
} from './utils/api';
|
|
22
22
|
import checkLatestStrapiVersion from './utils/checkLatestStrapiVersion';
|
|
23
|
-
import { getFullName
|
|
23
|
+
import { getFullName } from '../../utils';
|
|
24
24
|
|
|
25
25
|
const strapiVersion = packageJSON.version;
|
|
26
26
|
|
|
@@ -31,7 +31,6 @@ 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);
|
|
35
34
|
const { showReleaseNotification } = useConfigurations();
|
|
36
35
|
const [
|
|
37
36
|
{ data: appInfos, status },
|
|
@@ -72,15 +71,6 @@ const AuthenticatedApp = () => {
|
|
|
72
71
|
}
|
|
73
72
|
}, [userRoles, appInfos]);
|
|
74
73
|
|
|
75
|
-
useEffect(() => {
|
|
76
|
-
const getUserId = async () => {
|
|
77
|
-
const userId = await hashAdminUserEmail(userInfo);
|
|
78
|
-
setUserId(userId);
|
|
79
|
-
};
|
|
80
|
-
|
|
81
|
-
getUserId();
|
|
82
|
-
}, [userInfo]);
|
|
83
|
-
|
|
84
74
|
// We don't need to wait for the release query to be fetched before rendering the plugins
|
|
85
75
|
// however, we need the appInfos and the permissions
|
|
86
76
|
const shouldShowNotDependentQueriesLoader =
|
|
@@ -91,13 +81,12 @@ const AuthenticatedApp = () => {
|
|
|
91
81
|
const appInfosValue = useMemo(() => {
|
|
92
82
|
return {
|
|
93
83
|
...appInfos,
|
|
94
|
-
userId,
|
|
95
84
|
latestStrapiReleaseTag: tag_name,
|
|
96
85
|
setUserDisplayName,
|
|
97
86
|
shouldUpdateStrapi,
|
|
98
87
|
userDisplayName,
|
|
99
88
|
};
|
|
100
|
-
}, [appInfos, tag_name, shouldUpdateStrapi, userDisplayName
|
|
89
|
+
}, [appInfos, tag_name, shouldUpdateStrapi, userDisplayName]);
|
|
101
90
|
|
|
102
91
|
if (shouldShowLoader) {
|
|
103
92
|
return <LoadingIndicatorPage />;
|
|
@@ -57,13 +57,7 @@ const ComponentInitializer = ({ error, isReadOnly, onClick }) => {
|
|
|
57
57
|
</Box>
|
|
58
58
|
{error?.id && (
|
|
59
59
|
<Typography textColor="danger600" variant="pi">
|
|
60
|
-
{formatMessage(
|
|
61
|
-
{
|
|
62
|
-
id: error.id,
|
|
63
|
-
defaultMessage: error.id,
|
|
64
|
-
},
|
|
65
|
-
{ ...error.values }
|
|
66
|
-
)}
|
|
60
|
+
{formatMessage(error, { ...error.values })}
|
|
67
61
|
</Typography>
|
|
68
62
|
)}
|
|
69
63
|
</>
|
|
@@ -2,13 +2,9 @@ import React from 'react';
|
|
|
2
2
|
import PropTypes from 'prop-types';
|
|
3
3
|
import styled from 'styled-components';
|
|
4
4
|
import { pxToRem } from '@strapi/helper-plugin';
|
|
5
|
-
import { Box } from '@strapi/design-system
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import { IconButton } from '@strapi/design-system/IconButton';
|
|
9
|
-
import Trash from '@strapi/icons/Trash';
|
|
10
|
-
import DragHandle from '@strapi/icons/Drag';
|
|
11
|
-
import CarretDown from '@strapi/icons/CarretDown';
|
|
5
|
+
import { Box, Flex, Typography, IconButton } from '@strapi/design-system';
|
|
6
|
+
import { Trash, Drag, CarretDown } from '@strapi/icons';
|
|
7
|
+
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
|
12
8
|
|
|
13
9
|
const DragPreviewBox = styled(Box)`
|
|
14
10
|
border: 1px solid ${({ theme }) => theme.colors.neutral200};
|
|
@@ -31,6 +27,13 @@ const DropdownIconWrapper = styled(Box)`
|
|
|
31
27
|
}
|
|
32
28
|
`;
|
|
33
29
|
|
|
30
|
+
const Icon = styled(FontAwesomeIcon)`
|
|
31
|
+
width: ${pxToRem(12)};
|
|
32
|
+
height: ${pxToRem(12)};
|
|
33
|
+
|
|
34
|
+
color: ${({ theme }) => theme.colors.neutral600};
|
|
35
|
+
`;
|
|
36
|
+
|
|
34
37
|
const ToggleButton = styled.button`
|
|
35
38
|
border: none;
|
|
36
39
|
background: transparent;
|
|
@@ -40,7 +43,7 @@ const ToggleButton = styled.button`
|
|
|
40
43
|
padding: 0;
|
|
41
44
|
`;
|
|
42
45
|
|
|
43
|
-
const DragPreview = ({ displayedValue }) => {
|
|
46
|
+
const DragPreview = ({ displayedValue, icon }) => {
|
|
44
47
|
return (
|
|
45
48
|
<DragPreviewBox
|
|
46
49
|
paddingLeft={3}
|
|
@@ -57,18 +60,23 @@ const DragPreview = ({ displayedValue }) => {
|
|
|
57
60
|
<DropdownIconWrapper background="neutral200">
|
|
58
61
|
<CarretDown />
|
|
59
62
|
</DropdownIconWrapper>
|
|
60
|
-
<
|
|
63
|
+
<Flex gap={2} paddingLeft={icon ? 3 : 6} maxWidth={pxToRem(150)}>
|
|
64
|
+
{icon ? <Icon icon={icon} /> : null}
|
|
61
65
|
<Typography textColor="neutral700" ellipsis>
|
|
62
66
|
{displayedValue}
|
|
63
67
|
</Typography>
|
|
64
|
-
</
|
|
68
|
+
</Flex>
|
|
65
69
|
</Flex>
|
|
66
70
|
</ToggleButton>
|
|
67
71
|
<Box paddingLeft={3}>
|
|
68
72
|
<Flex>
|
|
69
|
-
<IconButton
|
|
73
|
+
<IconButton noBorder>
|
|
74
|
+
<Trash />
|
|
75
|
+
</IconButton>
|
|
70
76
|
<Box paddingLeft={2}>
|
|
71
|
-
<IconButton
|
|
77
|
+
<IconButton noBorder>
|
|
78
|
+
<Drag />
|
|
79
|
+
</IconButton>
|
|
72
80
|
</Box>
|
|
73
81
|
</Flex>
|
|
74
82
|
</Box>
|
|
@@ -77,8 +85,13 @@ const DragPreview = ({ displayedValue }) => {
|
|
|
77
85
|
);
|
|
78
86
|
};
|
|
79
87
|
|
|
88
|
+
DragPreview.defaultProps = {
|
|
89
|
+
icon: undefined,
|
|
90
|
+
};
|
|
91
|
+
|
|
80
92
|
DragPreview.propTypes = {
|
|
81
93
|
displayedValue: PropTypes.string.isRequired,
|
|
94
|
+
icon: PropTypes.string,
|
|
82
95
|
};
|
|
83
96
|
|
|
84
97
|
export default DragPreview;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { useIntl } from 'react-intl';
|
|
3
|
+
import PropTypes from 'prop-types';
|
|
4
|
+
import { Box, Flex, IconButton, Typography, Status, Icon } from '@strapi/design-system';
|
|
5
|
+
import { Drag, Cross } from '@strapi/icons';
|
|
6
|
+
|
|
7
|
+
import { getTrad } from '../../utils';
|
|
8
|
+
import { PUBLICATION_STATES } from '../RelationInputDataManager/constants';
|
|
9
|
+
import { ChildrenWrapper, StackWrapper } from '../RelationInput/components/RelationItem';
|
|
10
|
+
import { BoxEllipsis, DisconnectButton } from '../RelationInput/RelationInput';
|
|
11
|
+
|
|
12
|
+
export const RelationDragPreview = ({ status, displayedValue, width }) => {
|
|
13
|
+
const { formatMessage } = useIntl();
|
|
14
|
+
|
|
15
|
+
const stateMessage = {
|
|
16
|
+
[PUBLICATION_STATES.DRAFT]: formatMessage({
|
|
17
|
+
id: getTrad('relation.publicationState.draft'),
|
|
18
|
+
defaultMessage: 'Draft',
|
|
19
|
+
}),
|
|
20
|
+
|
|
21
|
+
[PUBLICATION_STATES.PUBLISHED]: formatMessage({
|
|
22
|
+
id: getTrad('relation.publicationState.published'),
|
|
23
|
+
defaultMessage: 'Published',
|
|
24
|
+
}),
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
const statusColor = status === PUBLICATION_STATES.DRAFT ? 'secondary' : 'success';
|
|
28
|
+
|
|
29
|
+
return (
|
|
30
|
+
<Box style={{ width }}>
|
|
31
|
+
<Flex
|
|
32
|
+
paddingTop={2}
|
|
33
|
+
paddingBottom={2}
|
|
34
|
+
paddingLeft={2}
|
|
35
|
+
paddingRight={4}
|
|
36
|
+
hasRadius
|
|
37
|
+
borderSize={1}
|
|
38
|
+
background="neutral0"
|
|
39
|
+
borderColor="neutral200"
|
|
40
|
+
justifyContent="space-between"
|
|
41
|
+
>
|
|
42
|
+
<StackWrapper spacing={1} horizontal>
|
|
43
|
+
<IconButton noBorder>
|
|
44
|
+
<Drag />
|
|
45
|
+
</IconButton>
|
|
46
|
+
<ChildrenWrapper justifyContent="space-between">
|
|
47
|
+
<BoxEllipsis minWidth={0} paddingTop={1} paddingBottom={1} paddingRight={4}>
|
|
48
|
+
<Typography textColor="primary600" ellipsis>
|
|
49
|
+
{displayedValue}
|
|
50
|
+
</Typography>
|
|
51
|
+
</BoxEllipsis>
|
|
52
|
+
{status && (
|
|
53
|
+
<Status variant={statusColor} showBullet={false} size="S">
|
|
54
|
+
<Typography fontWeight="bold" textColor={`${statusColor}700`}>
|
|
55
|
+
{stateMessage[status]}
|
|
56
|
+
</Typography>
|
|
57
|
+
</Status>
|
|
58
|
+
)}
|
|
59
|
+
</ChildrenWrapper>
|
|
60
|
+
</StackWrapper>
|
|
61
|
+
<Box paddingLeft={4}>
|
|
62
|
+
<DisconnectButton type="button">
|
|
63
|
+
<Icon width="12px" as={Cross} />
|
|
64
|
+
</DisconnectButton>
|
|
65
|
+
</Box>
|
|
66
|
+
</Flex>
|
|
67
|
+
</Box>
|
|
68
|
+
);
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
RelationDragPreview.propTypes = {
|
|
72
|
+
status: PropTypes.string.isRequired,
|
|
73
|
+
displayedValue: PropTypes.string.isRequired,
|
|
74
|
+
width: PropTypes.number.isRequired,
|
|
75
|
+
};
|
|
@@ -3,11 +3,10 @@ import { useDragLayer } from 'react-dnd';
|
|
|
3
3
|
import LayoutDndProvider from '../LayoutDndProvider';
|
|
4
4
|
|
|
5
5
|
import ItemTypes from '../../utils/ItemTypes';
|
|
6
|
-
import RepeatableComponentPreview from '../RepeatableComponent/DragPreview';
|
|
7
6
|
import CardPreview from '../../pages/ListSettingsView/components/CardPreview';
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
7
|
+
|
|
8
|
+
import ComponentPreview from './ComponentDragPreview';
|
|
9
|
+
import { RelationDragPreview } from './RelationDragPreview';
|
|
11
10
|
|
|
12
11
|
const layerStyles = {
|
|
13
12
|
position: 'fixed',
|
|
@@ -50,15 +49,32 @@ const CustomDragLayer = () => {
|
|
|
50
49
|
return null;
|
|
51
50
|
}
|
|
52
51
|
|
|
52
|
+
/**
|
|
53
|
+
* Because a user may have multiple relations / dynamic zones / repeable fields in the same content type,
|
|
54
|
+
* we append the fieldName for the item type to make them unique, however, we then want to extract that
|
|
55
|
+
* first type to apply the correct preview.
|
|
56
|
+
*/
|
|
57
|
+
const [actualType] = itemType.split('_');
|
|
58
|
+
|
|
53
59
|
return (
|
|
54
60
|
<LayoutDndProvider>
|
|
55
61
|
<div style={layerStyles}>
|
|
56
62
|
<div style={getItemStyles(initialOffset, currentOffset, mouseOffset)} className="col-md-2">
|
|
57
|
-
{[ItemTypes.
|
|
63
|
+
{[ItemTypes.EDIT_FIELD, ItemTypes.FIELD].includes(itemType) && (
|
|
58
64
|
<CardPreview labelField={item.labelField} />
|
|
59
65
|
)}
|
|
60
|
-
{
|
|
61
|
-
<
|
|
66
|
+
{actualType === ItemTypes.COMPONENT && (
|
|
67
|
+
<ComponentPreview displayedValue={item.displayedValue} />
|
|
68
|
+
)}
|
|
69
|
+
{actualType === ItemTypes.DYNAMIC_ZONE && (
|
|
70
|
+
<ComponentPreview icon={item.icon} displayedValue={item.displayedValue} />
|
|
71
|
+
)}
|
|
72
|
+
{actualType === ItemTypes.RELATION && (
|
|
73
|
+
<RelationDragPreview
|
|
74
|
+
displayedValue={item.displayedValue}
|
|
75
|
+
status={item.status}
|
|
76
|
+
width={item.width}
|
|
77
|
+
/>
|
|
62
78
|
)}
|
|
63
79
|
</div>
|
|
64
80
|
</div>
|
|
@@ -1,27 +1,39 @@
|
|
|
1
|
-
import React, { useMemo, useState } from 'react';
|
|
1
|
+
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
5
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
|
6
6
|
import get from 'lodash/get';
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
import {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
7
|
+
import { getEmptyImage } from 'react-dnd-html5-backend';
|
|
8
|
+
|
|
9
|
+
import {
|
|
10
|
+
Accordion,
|
|
11
|
+
AccordionToggle,
|
|
12
|
+
AccordionContent,
|
|
13
|
+
IconButton,
|
|
14
|
+
Box,
|
|
15
|
+
Flex,
|
|
16
|
+
Stack,
|
|
17
|
+
} from '@strapi/design-system';
|
|
14
18
|
import { useCMEditViewDataManager } from '@strapi/helper-plugin';
|
|
19
|
+
import { Trash, Drag } from '@strapi/icons';
|
|
15
20
|
|
|
16
|
-
import
|
|
17
|
-
import
|
|
18
|
-
import ArrowUp from '@strapi/icons/ArrowUp';
|
|
19
|
-
|
|
20
|
-
import { useContentTypeLayout } from '../../../hooks';
|
|
21
|
-
import { getTrad } from '../../../utils';
|
|
21
|
+
import { useContentTypeLayout, useDragAndDrop } from '../../../hooks';
|
|
22
|
+
import { composeRefs, getTrad, ItemTypes } from '../../../utils';
|
|
22
23
|
|
|
23
24
|
import FieldComponent from '../../FieldComponent';
|
|
24
25
|
|
|
26
|
+
const ActionsStack = styled(Stack)`
|
|
27
|
+
/*
|
|
28
|
+
we need to remove the background from the button but we can't
|
|
29
|
+
wrap the element in styled because it breaks the forwardedAs which
|
|
30
|
+
we need for drag handler to work on firefox
|
|
31
|
+
*/
|
|
32
|
+
div[role='button'] {
|
|
33
|
+
background: transparent;
|
|
34
|
+
}
|
|
35
|
+
`;
|
|
36
|
+
|
|
25
37
|
const IconButtonCustom = styled(IconButton)`
|
|
26
38
|
background-color: transparent;
|
|
27
39
|
|
|
@@ -46,17 +58,31 @@ const Rectangle = styled(Box)`
|
|
|
46
58
|
height: ${({ theme }) => theme.spaces[4]};
|
|
47
59
|
`;
|
|
48
60
|
|
|
61
|
+
const Preview = styled.span`
|
|
62
|
+
display: block;
|
|
63
|
+
background-color: ${({ theme }) => theme.colors.primary100};
|
|
64
|
+
outline: 1px dashed ${({ theme }) => theme.colors.primary500};
|
|
65
|
+
outline-offset: -1px;
|
|
66
|
+
padding: ${({ theme }) => theme.spaces[6]};
|
|
67
|
+
`;
|
|
68
|
+
|
|
69
|
+
const ComponentContainer = styled(Box)`
|
|
70
|
+
list-style: none;
|
|
71
|
+
padding: 0;
|
|
72
|
+
margin: 0;
|
|
73
|
+
`;
|
|
74
|
+
|
|
49
75
|
const DynamicZoneComponent = ({
|
|
50
76
|
componentUid,
|
|
51
77
|
formErrors,
|
|
52
78
|
index,
|
|
53
79
|
isFieldAllowed,
|
|
54
|
-
onMoveComponentDownClick,
|
|
55
|
-
onMoveComponentUpClick,
|
|
56
80
|
name,
|
|
57
81
|
onRemoveComponentClick,
|
|
58
|
-
|
|
59
|
-
|
|
82
|
+
onMoveComponent,
|
|
83
|
+
onGrabItem,
|
|
84
|
+
onDropItem,
|
|
85
|
+
onCancel,
|
|
60
86
|
}) => {
|
|
61
87
|
const [isOpen, setIsOpen] = useState(true);
|
|
62
88
|
const { formatMessage } = useIntl();
|
|
@@ -103,71 +129,90 @@ const DynamicZoneComponent = ({
|
|
|
103
129
|
setIsOpen((s) => !s);
|
|
104
130
|
};
|
|
105
131
|
|
|
132
|
+
const [{ handlerId, isDragging, handleKeyDown }, boxRef, dropRef, dragRef, dragPreviewRef] =
|
|
133
|
+
useDragAndDrop(isFieldAllowed, {
|
|
134
|
+
type: `${ItemTypes.DYNAMIC_ZONE}_${name}`,
|
|
135
|
+
index,
|
|
136
|
+
item: {
|
|
137
|
+
displayedValue: `${friendlyName}${mainValue}`,
|
|
138
|
+
icon,
|
|
139
|
+
},
|
|
140
|
+
onMoveItem: onMoveComponent,
|
|
141
|
+
onGrabItem,
|
|
142
|
+
onDropItem,
|
|
143
|
+
onCancel,
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
useEffect(() => {
|
|
147
|
+
dragPreviewRef(getEmptyImage(), { captureDraggingState: false });
|
|
148
|
+
}, [dragPreviewRef, index]);
|
|
149
|
+
|
|
150
|
+
const composedBoxRefs = composeRefs(boxRef, dropRef);
|
|
151
|
+
|
|
152
|
+
const accordionActions = !isFieldAllowed ? null : (
|
|
153
|
+
<ActionsStack horizontal spacing={0} expanded={isOpen}>
|
|
154
|
+
<IconButtonCustom
|
|
155
|
+
noBorder
|
|
156
|
+
label={formatMessage(
|
|
157
|
+
{
|
|
158
|
+
id: getTrad('components.DynamicZone.delete-label'),
|
|
159
|
+
defaultMessage: 'Delete {name}',
|
|
160
|
+
},
|
|
161
|
+
{ name: friendlyName }
|
|
162
|
+
)}
|
|
163
|
+
onClick={onRemoveComponentClick}
|
|
164
|
+
>
|
|
165
|
+
<Trash />
|
|
166
|
+
</IconButtonCustom>
|
|
167
|
+
<IconButton
|
|
168
|
+
forwardedAs="div"
|
|
169
|
+
role="button"
|
|
170
|
+
noBorder
|
|
171
|
+
tabIndex={0}
|
|
172
|
+
onClick={(e) => e.stopPropagation()}
|
|
173
|
+
data-handler-id={handlerId}
|
|
174
|
+
ref={dragRef}
|
|
175
|
+
label={formatMessage({
|
|
176
|
+
id: getTrad('components.DragHandle-label'),
|
|
177
|
+
defaultMessage: 'Drag',
|
|
178
|
+
})}
|
|
179
|
+
onKeyDown={handleKeyDown}
|
|
180
|
+
>
|
|
181
|
+
<Drag />
|
|
182
|
+
</IconButton>
|
|
183
|
+
</ActionsStack>
|
|
184
|
+
);
|
|
185
|
+
|
|
106
186
|
return (
|
|
107
|
-
<
|
|
187
|
+
<ComponentContainer as="li">
|
|
108
188
|
<Flex justifyContent="center">
|
|
109
189
|
<Rectangle background="neutral200" />
|
|
110
190
|
</Flex>
|
|
111
|
-
<StyledBox hasRadius>
|
|
112
|
-
|
|
113
|
-
<
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
})}
|
|
135
|
-
onClick={onMoveComponentUpClick}
|
|
136
|
-
icon={<ArrowUp />}
|
|
137
|
-
/>
|
|
138
|
-
)}
|
|
139
|
-
{isFieldAllowed && (
|
|
140
|
-
<IconButtonCustom
|
|
141
|
-
noBorder
|
|
142
|
-
label={formatMessage(
|
|
143
|
-
{
|
|
144
|
-
id: getTrad('components.DynamicZone.delete-label'),
|
|
145
|
-
defaultMessage: 'Delete {name}',
|
|
146
|
-
},
|
|
147
|
-
{ name: friendlyName }
|
|
148
|
-
)}
|
|
149
|
-
onClick={onRemoveComponentClick}
|
|
150
|
-
icon={<Trash />}
|
|
151
|
-
/>
|
|
152
|
-
)}
|
|
153
|
-
</Stack>
|
|
154
|
-
}
|
|
155
|
-
title={`${friendlyName}${mainValue}`}
|
|
156
|
-
togglePosition="left"
|
|
157
|
-
/>
|
|
158
|
-
<AccordionContent>
|
|
159
|
-
<AccordionContentRadius background="neutral0">
|
|
160
|
-
<FieldComponent
|
|
161
|
-
componentUid={componentUid}
|
|
162
|
-
icon={icon}
|
|
163
|
-
name={`${name}.${index}`}
|
|
164
|
-
isFromDynamicZone
|
|
165
|
-
/>
|
|
166
|
-
</AccordionContentRadius>
|
|
167
|
-
</AccordionContent>
|
|
168
|
-
</Accordion>
|
|
191
|
+
<StyledBox ref={composedBoxRefs} hasRadius>
|
|
192
|
+
{isDragging ? (
|
|
193
|
+
<Preview padding={6} background="primary100" />
|
|
194
|
+
) : (
|
|
195
|
+
<Accordion expanded={isOpen} onToggle={handleToggle} size="S" error={errorMessage}>
|
|
196
|
+
<AccordionToggle
|
|
197
|
+
startIcon={icon && <FontAwesomeIcon icon={icon} />}
|
|
198
|
+
action={accordionActions}
|
|
199
|
+
title={`${friendlyName}${mainValue}`}
|
|
200
|
+
togglePosition="left"
|
|
201
|
+
/>
|
|
202
|
+
<AccordionContent>
|
|
203
|
+
<AccordionContentRadius background="neutral0">
|
|
204
|
+
<FieldComponent
|
|
205
|
+
componentUid={componentUid}
|
|
206
|
+
icon={icon}
|
|
207
|
+
name={`${name}.${index}`}
|
|
208
|
+
isFromDynamicZone
|
|
209
|
+
/>
|
|
210
|
+
</AccordionContentRadius>
|
|
211
|
+
</AccordionContent>
|
|
212
|
+
</Accordion>
|
|
213
|
+
)}
|
|
169
214
|
</StyledBox>
|
|
170
|
-
</
|
|
215
|
+
</ComponentContainer>
|
|
171
216
|
);
|
|
172
217
|
};
|
|
173
218
|
|
|
@@ -175,8 +220,9 @@ DynamicZoneComponent.defaultProps = {
|
|
|
175
220
|
formErrors: {},
|
|
176
221
|
index: 0,
|
|
177
222
|
isFieldAllowed: true,
|
|
178
|
-
|
|
179
|
-
|
|
223
|
+
onGrabItem: undefined,
|
|
224
|
+
onDropItem: undefined,
|
|
225
|
+
onCancel: undefined,
|
|
180
226
|
};
|
|
181
227
|
|
|
182
228
|
DynamicZoneComponent.propTypes = {
|
|
@@ -185,11 +231,11 @@ DynamicZoneComponent.propTypes = {
|
|
|
185
231
|
index: PropTypes.number,
|
|
186
232
|
isFieldAllowed: PropTypes.bool,
|
|
187
233
|
name: PropTypes.string.isRequired,
|
|
188
|
-
|
|
189
|
-
|
|
234
|
+
onGrabItem: PropTypes.func,
|
|
235
|
+
onDropItem: PropTypes.func,
|
|
236
|
+
onCancel: PropTypes.func,
|
|
237
|
+
onMoveComponent: PropTypes.func.isRequired,
|
|
190
238
|
onRemoveComponentClick: PropTypes.func.isRequired,
|
|
191
|
-
showDownIcon: PropTypes.bool,
|
|
192
|
-
showUpIcon: PropTypes.bool,
|
|
193
239
|
};
|
|
194
240
|
|
|
195
241
|
export default DynamicZoneComponent;
|