mirror of
https://github.com/strapi/strapi.git
synced 2025-08-24 16:49:28 +00:00
Add component picker
Signed-off-by: soupette <cyril@strapi.io>
This commit is contained in:
parent
fa479708d7
commit
ddffdf947d
@ -49,7 +49,9 @@
|
|||||||
"default.dish",
|
"default.dish",
|
||||||
"default.openingtimes",
|
"default.openingtimes",
|
||||||
"default.restaurantservice",
|
"default.restaurantservice",
|
||||||
"default.temp"
|
"default.temp",
|
||||||
|
"default.apple",
|
||||||
|
"default.car"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
13
examples/getstarted/src/components/default/apple.json
Normal file
13
examples/getstarted/src/components/default/apple.json
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"collectionName": "components_default_apples",
|
||||||
|
"info": {
|
||||||
|
"name": "apple",
|
||||||
|
"icon": "apple-alt"
|
||||||
|
},
|
||||||
|
"options": {},
|
||||||
|
"attributes": {
|
||||||
|
"name": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
13
examples/getstarted/src/components/default/car.json
Normal file
13
examples/getstarted/src/components/default/car.json
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"collectionName": "components_default_cars",
|
||||||
|
"info": {
|
||||||
|
"name": "car",
|
||||||
|
"icon": "align-right"
|
||||||
|
},
|
||||||
|
"options": {},
|
||||||
|
"attributes": {
|
||||||
|
"name": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,90 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
* ComponentCard
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import { Text, Stack, Box } from '@strapi/parts';
|
||||||
|
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;
|
||||||
|
height: ${pxToRem(32)} !important;
|
||||||
|
padding: ${pxToRem(9)};
|
||||||
|
border-radius: ${pxToRem(64)};
|
||||||
|
background: ${({ theme }) => theme.colors.neutral150};
|
||||||
|
path {
|
||||||
|
fill: ${({ theme }) => theme.colors.neutral500};
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const ComponentBox = styled(Box)`
|
||||||
|
flex-shrink: 0;
|
||||||
|
width: ${pxToRem(140)};
|
||||||
|
height: ${pxToRem(84)};
|
||||||
|
border: 1px solid ${({ theme }) => theme.colors.neutral200};
|
||||||
|
background: ${({ theme }) => theme.colors.neutral100};
|
||||||
|
border-radius: ${({ theme }) => theme.borderRadius};
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
&.active,
|
||||||
|
&:hover {
|
||||||
|
border: 1px solid ${({ theme }) => theme.colors.primary200};
|
||||||
|
background: ${({ theme }) => theme.colors.primary100};
|
||||||
|
|
||||||
|
${StyledFontAwesomeIcon} {
|
||||||
|
background: ${({ theme }) => theme.colors.primary200};
|
||||||
|
path {
|
||||||
|
fill: ${({ theme }) => theme.colors.primary600};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
${Text} {
|
||||||
|
color: ${({ theme }) => theme.colors.primary600};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
function ComponentCard({ componentUid, intlLabel, icon, onClick }) {
|
||||||
|
const { formatMessage } = useIntl();
|
||||||
|
const handleClick = () => {
|
||||||
|
onClick(componentUid);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<button type="button" onClick={handleClick}>
|
||||||
|
<ComponentBox borderRadius="borderRadius">
|
||||||
|
<Stack size={1} style={{ justifyContent: 'center', alignItems: 'center' }}>
|
||||||
|
<StyledFontAwesomeIcon icon={icon} />
|
||||||
|
<Text small bold textColor="neutral600">
|
||||||
|
{formatMessage(intlLabel)}
|
||||||
|
</Text>
|
||||||
|
</Stack>
|
||||||
|
</ComponentBox>
|
||||||
|
</button>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
ComponentCard.defaultProps = {
|
||||||
|
icon: 'smile',
|
||||||
|
onClick: () => {},
|
||||||
|
};
|
||||||
|
|
||||||
|
ComponentCard.propTypes = {
|
||||||
|
componentUid: PropTypes.string.isRequired,
|
||||||
|
intlLabel: PropTypes.shape({
|
||||||
|
id: PropTypes.string.isRequired,
|
||||||
|
defaultMessage: PropTypes.string.isRequired,
|
||||||
|
}).isRequired,
|
||||||
|
icon: PropTypes.string,
|
||||||
|
onClick: PropTypes.func,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ComponentCard;
|
@ -0,0 +1,51 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import { Accordion, AccordionToggle, AccordionContent } from '@strapi/parts/Accordion';
|
||||||
|
import { Box } from '@strapi/parts/Box';
|
||||||
|
import { Grid, GridItem } from '@strapi/parts/Grid';
|
||||||
|
import ComponentCard from './ComponentCard';
|
||||||
|
|
||||||
|
const Category = ({ category, components, isOdd, isOpen, onAddComponent, onToggle }) => {
|
||||||
|
const handleToggle = () => {
|
||||||
|
onToggle(category);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Accordion expanded={isOpen} toggle={handleToggle}>
|
||||||
|
<AccordionToggle
|
||||||
|
variant={isOdd ? 'primary' : 'secondary'}
|
||||||
|
title={category}
|
||||||
|
togglePosition="left"
|
||||||
|
/>
|
||||||
|
<AccordionContent>
|
||||||
|
<Box paddingTop={4} paddingBottom={4}>
|
||||||
|
<Grid gap={2}>
|
||||||
|
{components.map(({ componentUid, info: { label, icon, name } }) => {
|
||||||
|
return (
|
||||||
|
<GridItem col={2} key={componentUid}>
|
||||||
|
<ComponentCard
|
||||||
|
componentUid={componentUid}
|
||||||
|
intlLabel={{ id: label || name, defaultMessage: label || name }}
|
||||||
|
icon={icon}
|
||||||
|
onClick={onAddComponent}
|
||||||
|
/>
|
||||||
|
</GridItem>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</Grid>
|
||||||
|
</Box>
|
||||||
|
</AccordionContent>
|
||||||
|
</Accordion>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
Category.propTypes = {
|
||||||
|
category: PropTypes.string.isRequired,
|
||||||
|
components: PropTypes.array.isRequired,
|
||||||
|
isOdd: PropTypes.bool.isRequired,
|
||||||
|
isOpen: PropTypes.bool.isRequired,
|
||||||
|
onAddComponent: PropTypes.func.isRequired,
|
||||||
|
onToggle: PropTypes.func.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Category;
|
@ -1,14 +1,17 @@
|
|||||||
import React, { memo, useCallback, useEffect, useMemo, useState } from 'react';
|
import React, { memo, useCallback, useEffect, useMemo, useState } from 'react';
|
||||||
import { groupBy } from 'lodash';
|
import groupBy from 'lodash/groupBy';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { Collapse } from 'reactstrap';
|
import { useIntl } from 'react-intl';
|
||||||
import { FormattedMessage } from 'react-intl';
|
import { KeyboardNavigable } from '@strapi/parts/KeyboardNavigable';
|
||||||
|
import { Box } from '@strapi/parts/Box';
|
||||||
|
import { Row } from '@strapi/parts/Row';
|
||||||
|
import { Text } from '@strapi/parts/Text';
|
||||||
import { getTrad } from '../../../../utils';
|
import { getTrad } from '../../../../utils';
|
||||||
import { useContentTypeLayout } from '../../../../hooks';
|
import { useContentTypeLayout } from '../../../../hooks';
|
||||||
import Category from './Category';
|
import Category from './Category';
|
||||||
import Wrapper from './Wrapper';
|
|
||||||
|
|
||||||
const Picker = ({ components, isOpen, onClickAddComponent }) => {
|
const ComponentPicker = ({ components, isOpen, onClickAddComponent }) => {
|
||||||
|
const { formatMessage } = useIntl();
|
||||||
const { getComponentLayout } = useContentTypeLayout();
|
const { getComponentLayout } = useContentTypeLayout();
|
||||||
const [categoryToOpen, setCategoryToOpen] = useState('');
|
const [categoryToOpen, setCategoryToOpen] = useState('');
|
||||||
|
|
||||||
@ -51,38 +54,58 @@ const Picker = ({ components, isOpen, onClickAddComponent }) => {
|
|||||||
[categoryToOpen]
|
[categoryToOpen]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (!isOpen) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Collapse isOpen={isOpen}>
|
<Box paddingBottom={6}>
|
||||||
<Wrapper>
|
<Box
|
||||||
<div>
|
paddingTop={6}
|
||||||
<p className="componentPickerTitle">
|
paddingBottom={6}
|
||||||
<FormattedMessage id={getTrad('components.DynamicZone.pick-compo')} />
|
paddingLeft={5}
|
||||||
</p>
|
paddingRight={5}
|
||||||
<div className="categoriesList">
|
background="neutral0"
|
||||||
|
shadox="tableShadow"
|
||||||
|
borderColor="neutral150"
|
||||||
|
hasRadius
|
||||||
|
>
|
||||||
|
<Row justifyContent="center">
|
||||||
|
<Text bold textColor="neutral600">
|
||||||
|
{formatMessage({
|
||||||
|
id: getTrad('components.DynamicZone.ComponentPicker-label'),
|
||||||
|
defaultMessage: 'Pick one component',
|
||||||
|
})}
|
||||||
|
</Text>
|
||||||
|
</Row>
|
||||||
|
<Box paddingTop={2}>
|
||||||
|
<KeyboardNavigable attributeName="data-strapi-accordion-toggle">
|
||||||
{dynamicComponentCategories.map(({ category, components }, index) => {
|
{dynamicComponentCategories.map(({ category, components }, index) => {
|
||||||
return (
|
return (
|
||||||
<Category
|
<Category
|
||||||
key={category}
|
key={category}
|
||||||
category={category}
|
category={category}
|
||||||
components={components}
|
components={components}
|
||||||
|
isOdd={index % 2 === 1}
|
||||||
isOpen={category === categoryToOpen}
|
isOpen={category === categoryToOpen}
|
||||||
isFirst={index === 0}
|
// TODO?
|
||||||
|
// isFirst={index === 0}
|
||||||
onAddComponent={handleAddComponentToDz}
|
onAddComponent={handleAddComponentToDz}
|
||||||
onToggle={handleClickToggle}
|
onToggle={handleClickToggle}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</div>
|
</KeyboardNavigable>
|
||||||
</div>
|
</Box>
|
||||||
</Wrapper>
|
</Box>
|
||||||
</Collapse>
|
</Box>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
Picker.propTypes = {
|
ComponentPicker.propTypes = {
|
||||||
components: PropTypes.array.isRequired,
|
components: PropTypes.array.isRequired,
|
||||||
isOpen: PropTypes.bool.isRequired,
|
isOpen: PropTypes.bool.isRequired,
|
||||||
onClickAddComponent: PropTypes.func.isRequired,
|
onClickAddComponent: PropTypes.func.isRequired,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default memo(Picker);
|
export default memo(ComponentPicker);
|
@ -1,78 +0,0 @@
|
|||||||
import styled from 'styled-components';
|
|
||||||
|
|
||||||
/* eslint-disable */
|
|
||||||
|
|
||||||
const BannerWrapper = styled.button`
|
|
||||||
display: flex;
|
|
||||||
height: 36px;
|
|
||||||
width: 100%;
|
|
||||||
padding: 0 15px;
|
|
||||||
border-bottom: 0;
|
|
||||||
border: 1px solid rgba(227, 233, 243, 0.75);
|
|
||||||
background-color: ${({ theme }) => theme.main.colors.white};
|
|
||||||
font-size: ${({ theme }) => theme.main.sizes.fonts.md};
|
|
||||||
font-weight: ${({ theme }) => theme.main.fontWeights.semiBold};
|
|
||||||
cursor: pointer;
|
|
||||||
|
|
||||||
&:focus {
|
|
||||||
outline: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.img-wrapper {
|
|
||||||
width: 19px;
|
|
||||||
height: 19px;
|
|
||||||
margin-right: 19px;
|
|
||||||
border-radius: 50%;
|
|
||||||
background-color: ${({ theme }) => theme.main.colors.mediumGrey};
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
.label {
|
|
||||||
text-transform: capitalize;
|
|
||||||
}
|
|
||||||
|
|
||||||
svg {
|
|
||||||
path {
|
|
||||||
fill: ${({ theme }) => theme.main.colors.leftMenu['link-color']} !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
-webkit-font-smoothing: antialiased;
|
|
||||||
|
|
||||||
> div {
|
|
||||||
align-self: center;
|
|
||||||
margin-top: -2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
${({ isFirst, theme }) => {
|
|
||||||
if (isFirst) {
|
|
||||||
return `
|
|
||||||
border-top-right-radius: ${theme.main.sizes.borderRadius};
|
|
||||||
border-top-left-radius: ${theme.main.sizes.borderRadius};
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
|
|
||||||
${({ isOpen, theme }) => {
|
|
||||||
if (isOpen) {
|
|
||||||
return `
|
|
||||||
border: 1px solid ${theme.main.colors.darkBlue};
|
|
||||||
background-color: ${theme.main.colors.lightBlue};
|
|
||||||
color: ${theme.main.colors.mediumBlue};
|
|
||||||
font-weight: ${theme.main.fontWeights.bold};
|
|
||||||
|
|
||||||
.img-wrapper {
|
|
||||||
background-color: ${theme.main.colors.darkBlue};
|
|
||||||
transform: rotate(180deg);
|
|
||||||
}
|
|
||||||
|
|
||||||
svg {
|
|
||||||
path {
|
|
||||||
fill: ${theme.main.colors.mediumBlue} !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
`;
|
|
||||||
|
|
||||||
export default BannerWrapper;
|
|
@ -1,33 +0,0 @@
|
|||||||
/* eslint-disable jsx-a11y/click-events-have-key-events */
|
|
||||||
import React from 'react';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import { Carret } from '@buffetjs/icons';
|
|
||||||
import Wrapper from './Wrapper';
|
|
||||||
|
|
||||||
/* eslint-disable jsx-a11y/no-static-element-interactions */
|
|
||||||
|
|
||||||
const Banner = ({ category, isOpen, onToggle, isFirst }) => {
|
|
||||||
const handleClick = () => {
|
|
||||||
onToggle(category);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Wrapper type="button" isFirst={isFirst} isOpen={isOpen} onClick={handleClick}>
|
|
||||||
<div className="img-wrapper">
|
|
||||||
<Carret />
|
|
||||||
</div>
|
|
||||||
<div className="label">{category}</div>
|
|
||||||
</Wrapper>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
Banner.propTypes = {
|
|
||||||
category: PropTypes.string.isRequired,
|
|
||||||
isFirst: PropTypes.bool.isRequired,
|
|
||||||
isOpen: PropTypes.bool.isRequired,
|
|
||||||
onToggle: PropTypes.func.isRequired,
|
|
||||||
};
|
|
||||||
|
|
||||||
Banner.displayName = 'Banner';
|
|
||||||
|
|
||||||
export default Banner;
|
|
@ -1,53 +0,0 @@
|
|||||||
import React, { memo, useEffect, useState } from 'react';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import { Collapse } from 'reactstrap';
|
|
||||||
import DynamicComponentCard from '../../../../DynamicComponentCard';
|
|
||||||
import Banner from './Banner';
|
|
||||||
|
|
||||||
const Category = ({ category, components, isFirst, isOpen, onAddComponent, onToggle }) => {
|
|
||||||
const [showComponents, setShowComponents] = useState(false);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (isOpen) {
|
|
||||||
setShowComponents(true);
|
|
||||||
}
|
|
||||||
}, [isOpen]);
|
|
||||||
|
|
||||||
const handleExited = () => setShowComponents(false);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Banner isFirst={isFirst} isOpen={isOpen} category={category} onToggle={onToggle} />
|
|
||||||
<Collapse isOpen={isOpen} onExited={handleExited}>
|
|
||||||
{showComponents && (
|
|
||||||
<div className="componentsList">
|
|
||||||
{components.map(({ componentUid, info: { name, icon } }) => {
|
|
||||||
return (
|
|
||||||
<DynamicComponentCard
|
|
||||||
key={componentUid}
|
|
||||||
componentUid={componentUid}
|
|
||||||
friendlyName={name}
|
|
||||||
icon={icon}
|
|
||||||
onClick={() => {
|
|
||||||
onAddComponent(componentUid);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</Collapse>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
Category.propTypes = {
|
|
||||||
category: PropTypes.string.isRequired,
|
|
||||||
components: PropTypes.array.isRequired,
|
|
||||||
isFirst: PropTypes.bool.isRequired,
|
|
||||||
isOpen: PropTypes.bool.isRequired,
|
|
||||||
onAddComponent: PropTypes.func.isRequired,
|
|
||||||
onToggle: PropTypes.func.isRequired,
|
|
||||||
};
|
|
||||||
|
|
||||||
export default memo(Category);
|
|
@ -1,32 +0,0 @@
|
|||||||
import styled from 'styled-components';
|
|
||||||
|
|
||||||
const Wrapper = styled.div`
|
|
||||||
overflow: hidden;
|
|
||||||
|
|
||||||
> div {
|
|
||||||
margin-top: 15px;
|
|
||||||
padding: 23px 18px 21px 18px;
|
|
||||||
background-color: #f2f3f4;
|
|
||||||
}
|
|
||||||
|
|
||||||
.componentPickerTitle {
|
|
||||||
margin-bottom: 10px;
|
|
||||||
color: #919bae;
|
|
||||||
font-weight: 600;
|
|
||||||
font-size: 13px;
|
|
||||||
line-height: normal;
|
|
||||||
}
|
|
||||||
.componentsList {
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
padding-top: 10px;
|
|
||||||
padding-left: 15px;
|
|
||||||
padding-right: 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.categoriesList {
|
|
||||||
padding-bottom: 4px;
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
export default Wrapper;
|
|
@ -4,7 +4,6 @@ import isEqual from 'react-fast-compare';
|
|||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { FormattedMessage } from 'react-intl';
|
import { FormattedMessage } from 'react-intl';
|
||||||
import { Box } from '@strapi/parts/Box';
|
import { Box } from '@strapi/parts/Box';
|
||||||
import { Stack } from '@strapi/parts/Stack';
|
|
||||||
import { Flex } from '@buffetjs/core';
|
import { Flex } from '@buffetjs/core';
|
||||||
import { LabelIconWrapper, NotAllowedInput, useNotification } from '@strapi/helper-plugin';
|
import { LabelIconWrapper, NotAllowedInput, useNotification } from '@strapi/helper-plugin';
|
||||||
import { getTrad } from '../../utils';
|
import { getTrad } from '../../utils';
|
||||||
@ -19,7 +18,7 @@ import ComponentWrapper from './ComponentWrapper';
|
|||||||
import DynamicZoneWrapper from './DynamicZoneWrapper';
|
import DynamicZoneWrapper from './DynamicZoneWrapper';
|
||||||
import Label from './Label';
|
import Label from './Label';
|
||||||
import Wrapper from './Wrapper';
|
import Wrapper from './Wrapper';
|
||||||
import Picker from './components/Picker';
|
import ComponentPicker from './components/ComponentPicker';
|
||||||
|
|
||||||
/* eslint-disable react/no-array-index-key */
|
/* eslint-disable react/no-array-index-key */
|
||||||
|
|
||||||
@ -131,6 +130,11 @@ const DynamicZone = ({
|
|||||||
name={name}
|
name={name}
|
||||||
onClick={handleClickOpenPicker}
|
onClick={handleClickOpenPicker}
|
||||||
/>
|
/>
|
||||||
|
<ComponentPicker
|
||||||
|
isOpen={isOpen}
|
||||||
|
components={dynamicZoneAvailableComponents}
|
||||||
|
onClickAddComponent={handleAddComponent}
|
||||||
|
/>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
@ -215,7 +219,7 @@ const DynamicZone = ({
|
|||||||
values={{ componentName: metadatas.label }}
|
values={{ componentName: metadatas.label }}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<Picker
|
<ComponentPicker
|
||||||
isOpen={isOpen}
|
isOpen={isOpen}
|
||||||
components={dynamicZoneAvailableComponents}
|
components={dynamicZoneAvailableComponents}
|
||||||
onClickAddComponent={handleAddComponent}
|
onClickAddComponent={handleAddComponent}
|
||||||
|
@ -630,5 +630,6 @@
|
|||||||
"clearLabel": "Clear",
|
"clearLabel": "Clear",
|
||||||
"submit": "Submit",
|
"submit": "Submit",
|
||||||
"anErrorOccurred": "Woops! Something went wrong. Please, try again.",
|
"anErrorOccurred": "Woops! Something went wrong. Please, try again.",
|
||||||
"app.utils.close-label": "Close"
|
"app.utils.close-label": "Close",
|
||||||
|
"content-manager.components.DynamicZone.ComponentPicker-label": "Pick one component"
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user