diff --git a/packages/core/admin/admin/src/content-manager/components/DynamicZone/components/AddComponentButton/index.js b/packages/core/admin/admin/src/content-manager/components/DynamicZone/components/AddComponentButton.js similarity index 98% rename from packages/core/admin/admin/src/content-manager/components/DynamicZone/components/AddComponentButton/index.js rename to packages/core/admin/admin/src/content-manager/components/DynamicZone/components/AddComponentButton.js index cd3cbf3800..57a4e352a7 100644 --- a/packages/core/admin/admin/src/content-manager/components/DynamicZone/components/AddComponentButton/index.js +++ b/packages/core/admin/admin/src/content-manager/components/DynamicZone/components/AddComponentButton.js @@ -13,7 +13,8 @@ import { BaseButton } from '@strapi/design-system/BaseButton'; import { Box } from '@strapi/design-system/Box'; import { Flex } from '@strapi/design-system/Flex'; import { Typography } from '@strapi/design-system/Typography'; -import { getTrad } from '../../../../utils'; + +import { getTrad } from '../../../utils'; const StyledAddIcon = styled(PlusCircle)` transform: ${({ $isOpen }) => ($isOpen ? 'rotate(45deg)' : 'rotate(0deg)')}; diff --git a/packages/core/admin/admin/src/content-manager/components/DynamicZone/components/AddComponentButton/tests/__snapshots__/index.test.js.snap b/packages/core/admin/admin/src/content-manager/components/DynamicZone/components/AddComponentButton/tests/__snapshots__/index.test.js.snap deleted file mode 100644 index 07f1ec7652..0000000000 --- a/packages/core/admin/admin/src/content-manager/components/DynamicZone/components/AddComponentButton/tests/__snapshots__/index.test.js.snap +++ /dev/null @@ -1,763 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[` displays the name of the dz when the label is empty 1`] = ` -.c10 { - border: 0; - -webkit-clip: rect(0 0 0 0); - clip: rect(0 0 0 0); - height: 1px; - margin: -1px; - overflow: hidden; - padding: 0; - position: absolute; - width: 1px; -} - -.c1 { - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - cursor: pointer; - padding: 8px; - border-radius: 4px; - background: #ffffff; - border: 1px solid #dcdce4; - position: relative; - outline: none; -} - -.c1 svg { - height: 12px; - width: 12px; -} - -.c1 svg > g, -.c1 svg path { - fill: #ffffff; -} - -.c1[aria-disabled='true'] { - pointer-events: none; -} - -.c1:after { - -webkit-transition-property: all; - transition-property: all; - -webkit-transition-duration: 0.2s; - transition-duration: 0.2s; - border-radius: 8px; - content: ''; - position: absolute; - top: -4px; - bottom: -4px; - left: -4px; - right: -4px; - border: 2px solid transparent; -} - -.c1:focus-visible { - outline: none; -} - -.c1:focus-visible:after { - border-radius: 8px; - content: ''; - position: absolute; - top: -5px; - bottom: -5px; - left: -5px; - right: -5px; - border: 2px solid #4945ff; -} - -.c4 { - padding-right: 8px; -} - -.c0 { - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-flex-direction: row; - -ms-flex-direction: row; - flex-direction: row; - -webkit-box-pack: center; - -webkit-justify-content: center; - -ms-flex-pack: center; - justify-content: center; -} - -.c3 { - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-flex-direction: row; - -ms-flex-direction: row; - flex-direction: row; -} - -.c9 { - font-weight: 600; - color: #8e8ea9; - font-size: 0.75rem; - line-height: 1.33; -} - -.c7 { - -webkit-transform: rotate(0deg); - -ms-transform: rotate(0deg); - transform: rotate(0deg); -} - -.c7 > circle { - fill: #eaeaef; -} - -.c7 > path { - fill: #666687; -} - -.c2 { - border-radius: 26px; - border-color: #eaeaef; - background: #ffffff; - padding-top: 12px; - padding-right: 16px; - padding-bottom: 12px; - padding-left: 16px; - box-shadow: 0px 1px 4px rgba(33,33,52,0.1); -} - -.c2 svg { - height: 24px; - width: 24px; -} - -.c2 svg > path { - fill: #666687; -} - -.c2:hover { - color: #4945ff !important; -} - -.c2:hover .c8 { - color: #4945ff !important; -} - -.c2:hover .c6 > circle { - fill: #4945ff; -} - -.c2:hover .c6 > path { - fill: #f6f6f9; -} - -.c2:active .c8 { - color: #4945ff; -} - -.c2:active .c6 > circle { - fill: #4945ff; -} - -.c2:active .c6 > path { - fill: #f6f6f9; -} - -.c5 { - height: 100%; -} - -
-
-
- -
-
-
-

-

-

-
-`; - -exports[` renders and matches the snapshot 1`] = ` -.c10 { - border: 0; - -webkit-clip: rect(0 0 0 0); - clip: rect(0 0 0 0); - height: 1px; - margin: -1px; - overflow: hidden; - padding: 0; - position: absolute; - width: 1px; -} - -.c1 { - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - cursor: pointer; - padding: 8px; - border-radius: 4px; - background: #ffffff; - border: 1px solid #dcdce4; - position: relative; - outline: none; -} - -.c1 svg { - height: 12px; - width: 12px; -} - -.c1 svg > g, -.c1 svg path { - fill: #ffffff; -} - -.c1[aria-disabled='true'] { - pointer-events: none; -} - -.c1:after { - -webkit-transition-property: all; - transition-property: all; - -webkit-transition-duration: 0.2s; - transition-duration: 0.2s; - border-radius: 8px; - content: ''; - position: absolute; - top: -4px; - bottom: -4px; - left: -4px; - right: -4px; - border: 2px solid transparent; -} - -.c1:focus-visible { - outline: none; -} - -.c1:focus-visible:after { - border-radius: 8px; - content: ''; - position: absolute; - top: -5px; - bottom: -5px; - left: -5px; - right: -5px; - border: 2px solid #4945ff; -} - -.c4 { - padding-right: 8px; -} - -.c0 { - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-flex-direction: row; - -ms-flex-direction: row; - flex-direction: row; - -webkit-box-pack: center; - -webkit-justify-content: center; - -ms-flex-pack: center; - justify-content: center; -} - -.c3 { - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-flex-direction: row; - -ms-flex-direction: row; - flex-direction: row; -} - -.c9 { - font-weight: 600; - color: #8e8ea9; - font-size: 0.75rem; - line-height: 1.33; -} - -.c7 { - -webkit-transform: rotate(0deg); - -ms-transform: rotate(0deg); - transform: rotate(0deg); -} - -.c7 > circle { - fill: #eaeaef; -} - -.c7 > path { - fill: #666687; -} - -.c2 { - border-radius: 26px; - border-color: #eaeaef; - background: #ffffff; - padding-top: 12px; - padding-right: 16px; - padding-bottom: 12px; - padding-left: 16px; - box-shadow: 0px 1px 4px rgba(33,33,52,0.1); -} - -.c2 svg { - height: 24px; - width: 24px; -} - -.c2 svg > path { - fill: #666687; -} - -.c2:hover { - color: #4945ff !important; -} - -.c2:hover .c8 { - color: #4945ff !important; -} - -.c2:hover .c6 > circle { - fill: #4945ff; -} - -.c2:hover .c6 > path { - fill: #f6f6f9; -} - -.c2:active .c8 { - color: #4945ff; -} - -.c2:active .c6 > circle { - fill: #4945ff; -} - -.c2:active .c6 > path { - fill: #f6f6f9; -} - -.c5 { - height: 100%; -} - -
-
-
- -
-
-
-

-

-

-
-`; - -exports[` renders and matches the snapshot when the isOpen prop is truthy 1`] = ` -.c10 { - border: 0; - -webkit-clip: rect(0 0 0 0); - clip: rect(0 0 0 0); - height: 1px; - margin: -1px; - overflow: hidden; - padding: 0; - position: absolute; - width: 1px; -} - -.c1 { - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - cursor: pointer; - padding: 8px; - border-radius: 4px; - background: #ffffff; - border: 1px solid #dcdce4; - position: relative; - outline: none; -} - -.c1 svg { - height: 12px; - width: 12px; -} - -.c1 svg > g, -.c1 svg path { - fill: #ffffff; -} - -.c1[aria-disabled='true'] { - pointer-events: none; -} - -.c1:after { - -webkit-transition-property: all; - transition-property: all; - -webkit-transition-duration: 0.2s; - transition-duration: 0.2s; - border-radius: 8px; - content: ''; - position: absolute; - top: -4px; - bottom: -4px; - left: -4px; - right: -4px; - border: 2px solid transparent; -} - -.c1:focus-visible { - outline: none; -} - -.c1:focus-visible:after { - border-radius: 8px; - content: ''; - position: absolute; - top: -5px; - bottom: -5px; - left: -5px; - right: -5px; - border: 2px solid #4945ff; -} - -.c4 { - padding-right: 8px; -} - -.c0 { - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-flex-direction: row; - -ms-flex-direction: row; - flex-direction: row; - -webkit-box-pack: center; - -webkit-justify-content: center; - -ms-flex-pack: center; - justify-content: center; -} - -.c3 { - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-flex-direction: row; - -ms-flex-direction: row; - flex-direction: row; -} - -.c9 { - font-weight: 600; - color: #8e8ea9; - font-size: 0.75rem; - line-height: 1.33; -} - -.c7 { - -webkit-transform: rotate(45deg); - -ms-transform: rotate(45deg); - transform: rotate(45deg); -} - -.c7 > circle { - fill: #eaeaef; -} - -.c7 > path { - fill: #666687; -} - -.c2 { - border-radius: 26px; - border-color: #eaeaef; - background: #ffffff; - padding-top: 12px; - padding-right: 16px; - padding-bottom: 12px; - padding-left: 16px; - box-shadow: 0px 1px 4px rgba(33,33,52,0.1); -} - -.c2 svg { - height: 24px; - width: 24px; -} - -.c2 svg > path { - fill: #666687; -} - -.c2:hover { - color: #4945ff !important; -} - -.c2:hover .c8 { - color: #4945ff !important; -} - -.c2:hover .c6 > circle { - fill: #4945ff; -} - -.c2:hover .c6 > path { - fill: #f6f6f9; -} - -.c2:active .c8 { - color: #4945ff; -} - -.c2:active .c6 > circle { - fill: #4945ff; -} - -.c2:active .c6 > path { - fill: #f6f6f9; -} - -.c5 { - height: 100%; -} - -
-
-
- -
-
-
-

-

-

-
-`; diff --git a/packages/core/admin/admin/src/content-manager/components/DynamicZone/components/Component/index.js b/packages/core/admin/admin/src/content-manager/components/DynamicZone/components/Component.js similarity index 56% rename from packages/core/admin/admin/src/content-manager/components/DynamicZone/components/Component/index.js rename to packages/core/admin/admin/src/content-manager/components/DynamicZone/components/Component.js index 599d01a1e4..0fac57e5b1 100644 --- a/packages/core/admin/admin/src/content-manager/components/DynamicZone/components/Component/index.js +++ b/packages/core/admin/admin/src/content-manager/components/DynamicZone/components/Component.js @@ -1,23 +1,23 @@ -import React, { memo, Suspense, useMemo } from 'react'; +import React, { useMemo, useState } from 'react'; import PropTypes from 'prop-types'; import styled from 'styled-components'; -import isEqual from 'react-fast-compare'; import { useIntl } from 'react-intl'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; + import { Accordion, AccordionToggle, AccordionContent } from '@strapi/design-system/Accordion'; import { IconButton } from '@strapi/design-system/IconButton'; -import { FocusTrap } from '@strapi/design-system/FocusTrap'; import { Box } from '@strapi/design-system/Box'; import { Flex } from '@strapi/design-system/Flex'; import { Stack } from '@strapi/design-system/Stack'; -import { Loader } from '@strapi/design-system/Loader'; + import Trash from '@strapi/icons/Trash'; import ArrowDown from '@strapi/icons/ArrowDown'; import ArrowUp from '@strapi/icons/ArrowUp'; -import { useContentTypeLayout } from '../../../../hooks'; -import { getTrad } from '../../../../utils'; -import FieldComponent from '../../../FieldComponent'; -import Rectangle from './Rectangle'; + +import { useContentTypeLayout } from '../../../hooks'; +import { getTrad } from '../../../utils'; + +import FieldComponent from '../../FieldComponent'; const ActionStack = styled(Stack)` svg { @@ -42,20 +42,24 @@ const AccordionContentRadius = styled(Box)` border-radius: 0 0 ${({ theme }) => theme.spaces[1]} ${({ theme }) => theme.spaces[1]}; `; -const Component = ({ +const Rectangle = styled(Box)` + width: ${({ theme }) => theme.spaces[2]}; + height: ${({ theme }) => theme.spaces[4]}; +`; + +const DynamicZoneComponent = ({ componentUid, formErrors, index, - isOpen, isFieldAllowed, - moveComponentDown, - moveComponentUp, + onMoveComponentDownClick, + onMoveComponentUpClick, name, - onToggle, - removeComponentFromDynamicZone, + onRemoveComponentClick, showDownIcon, showUpIcon, }) => { + const [isOpen, setIsOpen] = useState(true); const { formatMessage } = useIntl(); const { getComponentLayout } = useContentTypeLayout(); const { icon, friendlyName } = useMemo(() => { @@ -66,31 +70,7 @@ const Component = ({ return { friendlyName: displayName, icon }; }, [componentUid, getComponentLayout]); - const handleMoveComponentDown = () => moveComponentDown(name, index); - - const handleMoveComponentUp = () => moveComponentUp(name, index); - - const handleRemove = () => removeComponentFromDynamicZone(name, index); - - const downLabel = formatMessage({ - id: getTrad('components.DynamicZone.move-down-label'), - defaultMessage: 'Move component down', - }); - const upLabel = formatMessage({ - id: getTrad('components.DynamicZone.move-up-label'), - defaultMessage: 'Move component down', - }); - const deleteLabel = formatMessage( - { - id: getTrad('components.DynamicZone.delete-label'), - defaultMessage: 'Delete {name}', - }, - { name: friendlyName } - ); - - const formErrorsKeys = Object.keys(formErrors); - - const fieldsErrors = formErrorsKeys.filter((errorKey) => { + const fieldsErrors = Object.keys(formErrors).filter((errorKey) => { const errorKeysArray = errorKey.split('.'); if (`${errorKeysArray[0]}.${errorKeysArray[1]}` === `${name}.${index}`) { @@ -109,11 +89,17 @@ const Component = ({ }); } + const handleToggle = () => { + setIsOpen((s) => !s); + }; + return ( - + + + - onToggle(index)} size="S" error={errorMessage}> + } action={ @@ -121,24 +107,36 @@ const Component = ({ {showDownIcon && ( } /> )} {showUpIcon && ( } /> )} {isFieldAllowed && ( } /> )} @@ -149,22 +147,12 @@ const Component = ({ /> - - Loading content. - - } - > - onToggle(index)}> - - - + @@ -173,19 +161,17 @@ const Component = ({ ); }; -Component.propTypes = { +DynamicZoneComponent.propTypes = { componentUid: PropTypes.string.isRequired, formErrors: PropTypes.object.isRequired, index: PropTypes.number.isRequired, isFieldAllowed: PropTypes.bool.isRequired, - isOpen: PropTypes.bool.isRequired, - moveComponentDown: PropTypes.func.isRequired, - moveComponentUp: PropTypes.func.isRequired, + onMoveComponentDownClick: PropTypes.func.isRequired, + onMoveComponentUpClick: PropTypes.func.isRequired, name: PropTypes.string.isRequired, - onToggle: PropTypes.func.isRequired, - removeComponentFromDynamicZone: PropTypes.func.isRequired, + onRemoveComponentClick: PropTypes.func.isRequired, showDownIcon: PropTypes.bool.isRequired, showUpIcon: PropTypes.bool.isRequired, }; -export default memo(Component, isEqual); +export default DynamicZoneComponent; diff --git a/packages/core/admin/admin/src/content-manager/components/DynamicZone/components/Component/Rectangle.js b/packages/core/admin/admin/src/content-manager/components/DynamicZone/components/Component/Rectangle.js deleted file mode 100644 index 528af02f42..0000000000 --- a/packages/core/admin/admin/src/content-manager/components/DynamicZone/components/Component/Rectangle.js +++ /dev/null @@ -1,19 +0,0 @@ -import React from 'react'; -import styled from 'styled-components'; -import { Box } from '@strapi/design-system/Box'; -import { Flex } from '@strapi/design-system/Flex'; - -const StyledBox = styled(Box)` - width: ${({ theme }) => theme.spaces[2]}; - height: ${({ theme }) => theme.spaces[4]}; -`; - -const Rectangle = () => { - return ( - - - - ); -}; - -export default Rectangle; diff --git a/packages/core/admin/admin/src/content-manager/components/DynamicZone/components/ComponentPicker/Category/ComponentCard/index.js b/packages/core/admin/admin/src/content-manager/components/DynamicZone/components/ComponentCard.js similarity index 79% rename from packages/core/admin/admin/src/content-manager/components/DynamicZone/components/ComponentPicker/Category/ComponentCard/index.js rename to packages/core/admin/admin/src/content-manager/components/DynamicZone/components/ComponentCard.js index 6f9ab169a2..99270c2306 100644 --- a/packages/core/admin/admin/src/content-manager/components/DynamicZone/components/ComponentPicker/Category/ComponentCard/index.js +++ b/packages/core/admin/admin/src/content-manager/components/DynamicZone/components/ComponentCard.js @@ -6,13 +6,13 @@ import React from 'react'; import PropTypes from 'prop-types'; +import styled from 'styled-components'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; + import { Box } from '@strapi/design-system/Box'; import { Typography } from '@strapi/design-system/Typography'; import { Stack } from '@strapi/design-system/Stack'; import { pxToRem } from '@strapi/helper-plugin'; -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import styled from 'styled-components'; -import { useIntl } from 'react-intl'; const StyledFontAwesomeIcon = styled(FontAwesomeIcon)` width: ${pxToRem(32)} !important; @@ -53,19 +53,14 @@ const ComponentBox = styled(Box)` } `; -function ComponentCard({ componentUid, intlLabel, icon, onClick }) { - const { formatMessage } = useIntl(); - const handleClick = () => { - onClick(componentUid); - }; - +export default function ComponentCard({ children, icon, onClick }) { return ( - - - - - - - - -
-

-

-

- -`; - -exports[` displays the name of the dz when the label is empty 1`] = ` -.c8 { - border: 0; - -webkit-clip: rect(0 0 0 0); - clip: rect(0 0 0 0); - height: 1px; - margin: -1px; - overflow: hidden; - padding: 0; - position: absolute; - width: 1px; -} - -.c4 { - max-width: 22.25rem; -} - -.c0 { - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-flex-direction: row; - -ms-flex-direction: row; - flex-direction: row; - -webkit-box-pack: center; - -webkit-justify-content: center; - -ms-flex-pack: center; - justify-content: center; -} - -.c3 { - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-flex-direction: column; - -ms-flex-direction: column; - flex-direction: column; - -webkit-box-pack: center; - -webkit-justify-content: center; - -ms-flex-pack: center; - justify-content: center; -} - -.c5 { - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-flex-direction: row; - -ms-flex-direction: row; - flex-direction: row; -} - -.c6 { - font-weight: 600; - color: #666687; - display: block; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - font-size: 0.75rem; - line-height: 1.33; -} - -.c7 { - font-weight: 600; - color: #666687; - font-size: 0.75rem; - line-height: 1.33; -} - -.c1 { - background: #ffffff; - color: #8e8ea9; - padding-top: 12px; - padding-right: 16px; - padding-bottom: 12px; - padding-left: 16px; - box-shadow: 0px 1px 4px rgba(33,33,52,0.1); -} - -.c2 { - border-radius: 1.625rem; -} - -
-
-
-
-
-
- - test -   - - - ( - 1 - ) - -
-
-
-
-
-
-

-

-

-
-`; - -exports[` renders and matches the snapshot 1`] = ` -.c8 { - border: 0; - -webkit-clip: rect(0 0 0 0); - clip: rect(0 0 0 0); - height: 1px; - margin: -1px; - overflow: hidden; - padding: 0; - position: absolute; - width: 1px; -} - -.c4 { - max-width: 22.25rem; -} - -.c0 { - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-flex-direction: row; - -ms-flex-direction: row; - flex-direction: row; - -webkit-box-pack: center; - -webkit-justify-content: center; - -ms-flex-pack: center; - justify-content: center; -} - -.c3 { - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-flex-direction: column; - -ms-flex-direction: column; - flex-direction: column; - -webkit-box-pack: center; - -webkit-justify-content: center; - -ms-flex-pack: center; - justify-content: center; -} - -.c5 { - -webkit-align-items: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - display: -webkit-box; - display: -webkit-flex; - display: -ms-flexbox; - display: flex; - -webkit-flex-direction: row; - -ms-flex-direction: row; - flex-direction: row; -} - -.c6 { - font-weight: 600; - color: #666687; - display: block; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - font-size: 0.75rem; - line-height: 1.33; -} - -.c7 { - font-weight: 600; - color: #666687; - font-size: 0.75rem; - line-height: 1.33; -} - -.c1 { - background: #ffffff; - color: #8e8ea9; - padding-top: 12px; - padding-right: 16px; - padding-bottom: 12px; - padding-left: 16px; - box-shadow: 0px 1px 4px rgba(33,33,52,0.1); -} - -.c2 { - border-radius: 1.625rem; -} - -
-
-
-
-
-
- - dz -   - - - ( - 1 - ) - -
-
-
-
-
-
-

-

-

-
-`; diff --git a/packages/core/admin/admin/src/content-manager/components/DynamicZone/components/AddComponentButton/tests/index.test.js b/packages/core/admin/admin/src/content-manager/components/DynamicZone/components/tests/AddComponentButton.test.js similarity index 97% rename from packages/core/admin/admin/src/content-manager/components/DynamicZone/components/AddComponentButton/tests/index.test.js rename to packages/core/admin/admin/src/content-manager/components/DynamicZone/components/tests/AddComponentButton.test.js index 736b473757..eb73cae3ff 100644 --- a/packages/core/admin/admin/src/content-manager/components/DynamicZone/components/AddComponentButton/tests/index.test.js +++ b/packages/core/admin/admin/src/content-manager/components/DynamicZone/components/tests/AddComponentButton.test.js @@ -8,7 +8,7 @@ import React from 'react'; import { render } from '@testing-library/react'; import { ThemeProvider, lightTheme } from '@strapi/design-system'; import { IntlProvider } from 'react-intl'; -import AddComponentButton from '../index'; +import AddComponentButton from '../AddComponentButton'; describe('', () => { it('renders and matches the snapshot', () => { diff --git a/packages/core/admin/admin/src/content-manager/components/DynamicZone/components/DzLabel/tests/index.test.js b/packages/core/admin/admin/src/content-manager/components/DynamicZone/components/tests/DynamicZoneLabel.test.js similarity index 80% rename from packages/core/admin/admin/src/content-manager/components/DynamicZone/components/DzLabel/tests/index.test.js rename to packages/core/admin/admin/src/content-manager/components/DynamicZone/components/tests/DynamicZoneLabel.test.js index eb9bb7437d..1fb177f3ee 100644 --- a/packages/core/admin/admin/src/content-manager/components/DynamicZone/components/DzLabel/tests/index.test.js +++ b/packages/core/admin/admin/src/content-manager/components/DynamicZone/components/tests/DynamicZoneLabel.test.js @@ -10,7 +10,7 @@ import { ThemeProvider, lightTheme, Tooltip } from '@strapi/design-system'; import Earth from '@strapi/icons/Earth'; import { IntlProvider } from 'react-intl'; import styled from 'styled-components'; -import DzLabel from '../index'; +import DynamicZoneLabel from '../DynamicZoneLabel'; const Button = styled.button` border: none; @@ -36,12 +36,12 @@ const LabelAction = () => { ); }; -describe('', () => { +describe('DynamicZoneLabel', () => { it('renders and matches the snapshot', () => { const { container } = render( - + ); @@ -53,7 +53,7 @@ describe('', () => { const { container } = render( - + ); @@ -65,7 +65,12 @@ describe('', () => { const { container } = render( - } /> + } + /> ); diff --git a/packages/core/admin/admin/src/content-manager/components/DynamicZone/index.js b/packages/core/admin/admin/src/content-manager/components/DynamicZone/index.js index faac4490f5..a1cbf0b8e7 100644 --- a/packages/core/admin/admin/src/content-manager/components/DynamicZone/index.js +++ b/packages/core/admin/admin/src/content-manager/components/DynamicZone/index.js @@ -1,25 +1,23 @@ -import React, { memo, useCallback, useMemo, useState, useEffect } from 'react'; +import React, { memo, useMemo, useState } from 'react'; import get from 'lodash/get'; import isEqual from 'react-fast-compare'; import PropTypes from 'prop-types'; import { Stack } from '@strapi/design-system/Stack'; import { Box } from '@strapi/design-system/Box'; import { NotAllowedInput, useNotification } from '@strapi/helper-plugin'; + import { getTrad } from '../../utils'; + import connect from './utils/connect'; import select from './utils/select'; + +import DynamicZoneComponent from './components/Component'; import AddComponentButton from './components/AddComponentButton'; -import DzLabel from './components/DzLabel'; -import Component from './components/Component'; - +import DynamicZoneLabel from './components/DynamicZoneLabel'; import ComponentPicker from './components/ComponentPicker'; + import { useContentTypeLayout } from '../../hooks'; -/* eslint-disable react/no-array-index-key */ - -const createCollapses = (arrayLength) => - Array.from({ length: arrayLength }).map(() => ({ isOpen: false })); - const DynamicZone = ({ name, // Passed with the select function @@ -36,39 +34,16 @@ const DynamicZone = ({ fieldSchema, metadatas, }) => { + const [addComponentIsOpen, setAddComponentIsOpen] = useState(false); + const toggleNotification = useNotification(); - const [isOpen, setIsOpen] = useState(false); - const [shouldOpenAddedComponent, setShouldOpenAddedComponent] = useState(false); const { getComponentLayout, components } = useContentTypeLayout(); + const dynamicDisplayedComponentsLength = dynamicDisplayedComponents.length; const intlDescription = metadatas.description ? { id: metadatas.description, defaultMessage: metadatas.description } : null; - const [componentCollapses, setComponentsCollapses] = useState( - createCollapses(dynamicDisplayedComponentsLength) - ); - - useEffect(() => { - setComponentsCollapses(createCollapses(dynamicDisplayedComponentsLength)); - }, [dynamicDisplayedComponentsLength]); - - useEffect(() => { - if (shouldOpenAddedComponent) { - setComponentsCollapses((prev) => - prev.map((collapse, index) => { - if (index === prev.length - 1) { - return { ...collapse, isOpen: true }; - } - - return collapse; - }) - ); - - setShouldOpenAddedComponent(false); - } - }, [shouldOpenAddedComponent]); - // We cannot use the default props here const { max = Infinity, min = -Infinity } = fieldSchema; const dynamicZoneErrors = useMemo(() => { @@ -79,8 +54,6 @@ const DynamicZone = ({ .map((key) => formErrors[key]); }, [formErrors, name]); - const dynamicZoneAvailableComponents = useMemo(() => fieldSchema.components || [], [fieldSchema]); - const missingComponentNumber = min - dynamicDisplayedComponentsLength; const hasError = dynamicZoneErrors.length > 0; @@ -90,21 +63,17 @@ const DynamicZone = ({ const hasMaxError = hasError && get(dynamicZoneErrors, [0, 'id'], '') === 'components.Input.error.validation.max'; - const handleAddComponent = useCallback( - (componentUid) => { - setIsOpen(false); + const handleAddComponent = (componentUid) => { + setAddComponentIsOpen(false); - const componentLayoutData = getComponentLayout(componentUid); + const componentLayoutData = getComponentLayout(componentUid); - addComponentToDynamicZone(name, componentLayoutData, components, hasError); - setShouldOpenAddedComponent(true); - }, - [addComponentToDynamicZone, hasError, name, components, getComponentLayout] - ); + addComponentToDynamicZone(name, componentLayoutData, components, hasError); + }; const handleClickOpenPicker = () => { if (dynamicDisplayedComponentsLength < max) { - setIsOpen((prev) => !prev); + setAddComponentIsOpen((prev) => !prev); } else { toggleNotification({ type: 'info', @@ -113,68 +82,19 @@ const DynamicZone = ({ } }; - const handleToggleComponent = (indexToToggle) => { - setComponentsCollapses((prev) => - prev.map(({ isOpen }, index) => { - if (index === indexToToggle) { - return { isOpen: !isOpen }; - } - - return { isOpen }; - }) - ); + const handleMoveComponentDown = (name, componentIndex) => () => { + moveComponentDown(name, componentIndex); }; - const handleMoveComponentDown = (name, currentIndex) => { - moveComponentDown(name, currentIndex); - setComponentsCollapses((prev) => { - return prev.map(({ isOpen }, index, refArray) => { - if (index === currentIndex + 1) { - return { isOpen: refArray[currentIndex].isOpen }; - } - - if (index === currentIndex) { - return { isOpen: refArray[index + 1].isOpen }; - } - - return { isOpen }; - }); - }); + const handleMoveComponentUp = (name, componentIndex) => () => { + moveComponentUp(name, componentIndex); }; - const handleMoveComponentUp = (name, currentIndex) => { - moveComponentUp(name, currentIndex); - setComponentsCollapses((prev) => { - return prev.map(({ isOpen }, index, refArray) => { - if (index === currentIndex - 1) { - return { isOpen: refArray[currentIndex].isOpen }; - } - - if (index === currentIndex) { - return { isOpen: refArray[index - 1].isOpen }; - } - - return { isOpen }; - }); - }); - }; - - const handleRemoveComponent = (name, currentIndex) => { + const handleRemoveComponent = (name, currentIndex) => () => { removeComponentFromDynamicZone(name, currentIndex); }; - if (!isFieldAllowed && isCreatingEntry) { - return ( - - ); - } - - if (!isFieldAllowed && !isFieldReadable && !isCreatingEntry) { + if (!isFieldAllowed && (isCreatingEntry || (!isFieldReadable && !isCreatingEntry))) { return ( {dynamicDisplayedComponentsLength > 0 && ( - {dynamicDisplayedComponents.map((componentUid, index) => { - const showDownIcon = - isFieldAllowed && - dynamicDisplayedComponentsLength > 0 && - index < dynamicDisplayedComponentsLength - 1; - const showUpIcon = isFieldAllowed && dynamicDisplayedComponentsLength > 0 && index > 0; - const isOpen = componentCollapses[index]?.isOpen || false; + const showDownIcon = isFieldAllowed && index < dynamicDisplayedComponentsLength - 1; + const showUpIcon = isFieldAllowed && index > 0; return ( - @@ -233,13 +148,13 @@ const DynamicZone = ({ isDisabled={!isFieldAllowed} label={metadatas.label} missingComponentNumber={missingComponentNumber} - isOpen={isOpen} + isOpen={addComponentIsOpen} name={name} onClick={handleClickOpenPicker} />