mirror of
https://github.com/strapi/strapi.git
synced 2025-12-29 08:04:51 +00:00
Fix all single types feedback
Signed-off-by: HichamELBSI <elabbassih@gmail.com>
This commit is contained in:
parent
d5d5c0fb4f
commit
92632be70d
@ -8,7 +8,8 @@ const FaIcon = styled(({ small, ...props }) => <FontAwesomeIcon {...props} />)`
|
||||
top: calc(50% - 0.9rem + 0.3rem);
|
||||
left: 1.6rem;
|
||||
margin-right: 1.2rem;
|
||||
font-size: ${props => (props.small ? '1rem' : '1.4rem')};
|
||||
margin-top: ${({ small }) => (small ? '.3rem' : null)};
|
||||
font-size: ${({ small }) => (small ? '.9rem' : '1.4rem')};
|
||||
width: 1.4rem;
|
||||
padding-bottom: 0.2rem;
|
||||
text-align: center;
|
||||
|
||||
@ -4,8 +4,8 @@ const Search = styled.input`
|
||||
width: 100%;
|
||||
padding: 0 15px;
|
||||
outline: 0;
|
||||
font-size: 1.2rem;
|
||||
color: ${props => props.theme.main.colors.white};
|
||||
font-size: 1.1rem;
|
||||
color: ${({ theme }) => theme.main.colors.white};
|
||||
`;
|
||||
|
||||
export default Search;
|
||||
|
||||
@ -2,6 +2,7 @@ import styled from 'styled-components';
|
||||
|
||||
const SearchButton = styled.button`
|
||||
padding: 0 10px;
|
||||
line-height: normal;
|
||||
`;
|
||||
|
||||
export default SearchButton;
|
||||
|
||||
@ -0,0 +1,10 @@
|
||||
import styled from 'styled-components';
|
||||
|
||||
const SearchWrapper = styled.div`
|
||||
display: flex;
|
||||
width: 100%;
|
||||
justify-content: space-between;
|
||||
border-bottom: 1px solid;
|
||||
`;
|
||||
|
||||
export default SearchWrapper;
|
||||
@ -6,13 +6,13 @@ const Title = styled.div`
|
||||
padding-left: 2rem;
|
||||
padding-right: 1.6rem;
|
||||
padding-top: 1rem;
|
||||
margin-bottom: 0.8rem;
|
||||
margin-bottom: 0.9rem;
|
||||
color: ${props => props.theme.main.colors.leftMenu['title-color']};
|
||||
text-transform: uppercase;
|
||||
font-size: 1.2rem;
|
||||
font-size: 1.1rem;
|
||||
letter-spacing: 0.1rem;
|
||||
font-weight: 800;
|
||||
max-height: 28px;
|
||||
max-height: 26px;
|
||||
`;
|
||||
|
||||
Title.defaultProps = {
|
||||
|
||||
@ -8,6 +8,7 @@ import messages from '../LeftMenuLinkContainer/messages.json';
|
||||
import Search from './Search';
|
||||
import Title from './Title';
|
||||
import SearchButton from './SearchButton';
|
||||
import SearchWrapper from './SearchWrapper';
|
||||
|
||||
const LeftMenuLinkHeader = ({ section, searchable, setSearch, search }) => {
|
||||
const [showSearch, setShowSearch] = useState(false);
|
||||
@ -33,34 +34,33 @@ const LeftMenuLinkHeader = ({ section, searchable, setSearch, search }) => {
|
||||
setShowSearch(false);
|
||||
};
|
||||
|
||||
return !showSearch ? (
|
||||
return (
|
||||
<Title>
|
||||
<FormattedMessage id={id} defaultMessage={defaultMessage} />
|
||||
{searchable && (
|
||||
<SearchButton onClick={toggleSearch}>
|
||||
<FontAwesomeIcon icon="search" />
|
||||
</SearchButton>
|
||||
{!showSearch ? (
|
||||
<>
|
||||
<FormattedMessage id={id} defaultMessage={defaultMessage} />
|
||||
{searchable && (
|
||||
<SearchButton onClick={toggleSearch}>
|
||||
<FontAwesomeIcon icon="search" />
|
||||
</SearchButton>
|
||||
)}
|
||||
</>
|
||||
) : (
|
||||
<SearchWrapper>
|
||||
<div>
|
||||
<FontAwesomeIcon style={{ fontSize: 12 }} icon="search" />
|
||||
</div>
|
||||
<FormattedMessage id="components.Search.placeholder">
|
||||
{message => (
|
||||
<Search ref={ref} onChange={handleChange} value={search} placeholder={message} />
|
||||
)}
|
||||
</FormattedMessage>
|
||||
<SearchButton onClick={clearSearch}>
|
||||
<FontAwesomeIcon icon="times" />
|
||||
</SearchButton>
|
||||
</SearchWrapper>
|
||||
)}
|
||||
</Title>
|
||||
) : (
|
||||
<Title>
|
||||
<div>
|
||||
<FontAwesomeIcon icon="search" />
|
||||
</div>
|
||||
<FormattedMessage id="components.Search.placeholder">
|
||||
{message => (
|
||||
<Search
|
||||
ref={ref}
|
||||
onChange={handleChange}
|
||||
value={search}
|
||||
placeholder={message}
|
||||
/>
|
||||
)}
|
||||
</FormattedMessage>
|
||||
<SearchButton onClick={clearSearch}>
|
||||
<FontAwesomeIcon icon="times" />
|
||||
</SearchButton>
|
||||
</Title>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@ -1,12 +1,11 @@
|
||||
import styled from 'styled-components';
|
||||
|
||||
const EmptyLinksList = styled.div`
|
||||
color: ${props => props.theme.main.colors.white};
|
||||
padding-left: 1.6rem;
|
||||
padding-right: 1.6rem;
|
||||
font-weight: 300;
|
||||
const EmptyLinksList = styled.span`
|
||||
min-height: 3.6rem;
|
||||
padding-top: 0.6rem;
|
||||
padding: 0.6rem 1.6rem 2.6rem 0;
|
||||
font-size: 1.4rem;
|
||||
font-weight: 400;
|
||||
color: ${({ theme }) => theme.main.colors.leftMenu['link-color']};
|
||||
`;
|
||||
|
||||
EmptyLinksList.defaultProps = {
|
||||
|
||||
@ -0,0 +1,8 @@
|
||||
import styled from 'styled-components';
|
||||
|
||||
const EmptyLinksListWrapper = styled.div`
|
||||
padding: 0.7rem 0;
|
||||
margin-bottom: 0.1rem;
|
||||
`;
|
||||
|
||||
export default EmptyLinksListWrapper;
|
||||
@ -2,6 +2,7 @@ import styled from 'styled-components';
|
||||
|
||||
const LeftMenuListLink = styled.div`
|
||||
max-height: 180px;
|
||||
margin-bottom: 0.1rem;
|
||||
overflow: auto;
|
||||
`;
|
||||
|
||||
|
||||
@ -6,16 +6,11 @@ import { FormattedMessage } from 'react-intl';
|
||||
|
||||
import LeftMenuLink from '../LeftMenuLink';
|
||||
import LeftMenuLinkHeader from '../LeftMenuLinkHeader';
|
||||
import EmptyLinksList from './EmptyLinksList';
|
||||
import LeftMenuListLink from './LeftMenuListLink';
|
||||
import EmptyLinksList from './EmptyLinksList';
|
||||
import EmptyLinksListWrapper from './EmptyLinksListWrapper';
|
||||
|
||||
const LeftMenuLinksSection = ({
|
||||
section,
|
||||
searchable,
|
||||
location,
|
||||
links,
|
||||
emptyLinksListMessage,
|
||||
}) => {
|
||||
const LeftMenuLinksSection = ({ section, searchable, location, links, emptyLinksListMessage }) => {
|
||||
const [search, setSearch] = useState('');
|
||||
|
||||
const filteredList = sortBy(
|
||||
@ -30,8 +25,7 @@ const LeftMenuLinksSection = ({
|
||||
return link.destination;
|
||||
}
|
||||
if (link.schema && link.schema.kind) {
|
||||
return `/plugins/${link.plugin}/${link.schema.kind}/${link.destination ||
|
||||
link.uid}`;
|
||||
return `/plugins/${link.plugin}/${link.schema.kind}/${link.destination || link.uid}`;
|
||||
}
|
||||
|
||||
return `/plugins/${link.plugin}/${link.destination || link.uid}`;
|
||||
@ -59,12 +53,11 @@ const LeftMenuLinksSection = ({
|
||||
/>
|
||||
))
|
||||
) : (
|
||||
<EmptyLinksList>
|
||||
<FormattedMessage
|
||||
id={emptyLinksListMessage}
|
||||
defaultMessage="No plugins installed yet"
|
||||
/>
|
||||
</EmptyLinksList>
|
||||
<EmptyLinksListWrapper>
|
||||
<FormattedMessage id={emptyLinksListMessage} defaultMessage="No plugins installed yet">
|
||||
{msg => <EmptyLinksList>{msg}</EmptyLinksList>}
|
||||
</FormattedMessage>
|
||||
</EmptyLinksListWrapper>
|
||||
)}
|
||||
</LeftMenuListLink>
|
||||
</>
|
||||
|
||||
@ -105,7 +105,7 @@ const GlobalNotification = createGlobalStyle`
|
||||
const Li = styled.li`
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
align-items: center;
|
||||
width: 300px;
|
||||
min-height: 60px;
|
||||
margin-bottom: 14px;
|
||||
@ -116,6 +116,7 @@ const Li = styled.li`
|
||||
transition: all 0.15s ease;
|
||||
overflow: hidden;
|
||||
z-index: 10;
|
||||
padding: 1rem;
|
||||
|
||||
// The last notification must appear from
|
||||
// the background of the previous one.
|
||||
|
||||
@ -11,15 +11,7 @@ import { auth } from 'strapi-helper-plugin';
|
||||
import PageTitle from '../../components/PageTitle';
|
||||
|
||||
import useFetch from './hooks';
|
||||
import {
|
||||
ALink,
|
||||
Block,
|
||||
Container,
|
||||
LinkWrapper,
|
||||
P,
|
||||
Wave,
|
||||
Separator,
|
||||
} from './components';
|
||||
import { ALink, Block, Container, LinkWrapper, P, Wave, Separator } from './components';
|
||||
import BlogPost from './BlogPost';
|
||||
import SocialLink from './SocialLink';
|
||||
|
||||
@ -74,11 +66,9 @@ const HomePage = ({ global: { plugins }, history: { push } }) => {
|
||||
);
|
||||
};
|
||||
const hasAlreadyCreatedContentTypes =
|
||||
get(
|
||||
plugins,
|
||||
['content-manager', 'leftMenuSections', '0', 'links'],
|
||||
[]
|
||||
).filter(contentType => contentType.isDisplayed === true).length > 1;
|
||||
get(plugins, ['content-manager', 'leftMenuSections', '0', 'links'], []).filter(
|
||||
contentType => contentType.isDisplayed === true
|
||||
).length > 1;
|
||||
|
||||
const headerId = hasAlreadyCreatedContentTypes
|
||||
? 'HomePage.greetings'
|
||||
@ -133,7 +123,7 @@ const HomePage = ({ global: { plugins }, history: { push } }) => {
|
||||
return (
|
||||
<P>
|
||||
<b>{congrats}</b>
|
||||
{content}
|
||||
{content}
|
||||
<b>{boldContent}</b>
|
||||
</P>
|
||||
);
|
||||
@ -176,12 +166,7 @@ const HomePage = ({ global: { plugins }, history: { push } }) => {
|
||||
const type = index === 0 ? 'doc' : 'code';
|
||||
|
||||
return (
|
||||
<LinkWrapper
|
||||
href={data.link}
|
||||
target="_blank"
|
||||
key={data.link}
|
||||
type={type}
|
||||
>
|
||||
<LinkWrapper href={data.link} target="_blank" key={data.link} type={type}>
|
||||
<FormattedMessage id={data.titleId}>
|
||||
{title => <p className="bold">{title}</p>}
|
||||
</FormattedMessage>
|
||||
@ -197,13 +182,9 @@ const HomePage = ({ global: { plugins }, history: { push } }) => {
|
||||
|
||||
<div className="col-md-12 col-lg-4">
|
||||
<Block style={{ paddingRight: 30, paddingBottom: 0 }}>
|
||||
<FormattedMessage id="HomePage.community">
|
||||
{msg => <h2>{msg}</h2>}
|
||||
</FormattedMessage>
|
||||
<FormattedMessage id="HomePage.community">{msg => <h2>{msg}</h2>}</FormattedMessage>
|
||||
<FormattedMessage id="app.components.HomePage.community.content">
|
||||
{content => (
|
||||
<P style={{ marginTop: 7, marginBottom: 0 }}>{content}</P>
|
||||
)}
|
||||
{content => <P style={{ marginTop: 7, marginBottom: 0 }}>{content}</P>}
|
||||
</FormattedMessage>
|
||||
<FormattedMessage id="HomePage.roadmap">
|
||||
{msg => (
|
||||
|
||||
@ -1,25 +1,31 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { isObject } from 'lodash';
|
||||
import { Collapse } from 'reactstrap';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import useFormattedMessage from '../../hooks/useFormattedMessage';
|
||||
import { useGlobalContext } from '../../contexts/GlobalContext';
|
||||
import LeftMenuLink from '../LeftMenuLink';
|
||||
import Dropdown from './Dropdown';
|
||||
|
||||
const LeftMenuSubList = ({
|
||||
isEditable,
|
||||
isFirstItem,
|
||||
isSearching,
|
||||
links,
|
||||
name,
|
||||
onClickEdit,
|
||||
}) => {
|
||||
const LeftMenuSubList = ({ isEditable, isFirstItem, isSearching, links, name, onClickEdit }) => {
|
||||
const [collapse, setCollapse] = useState(isFirstItem);
|
||||
const { formatMessage } = useGlobalContext();
|
||||
|
||||
const toggle = () => {
|
||||
setCollapse(!collapse);
|
||||
};
|
||||
|
||||
const getLabel = message => {
|
||||
if (isObject(message) && message.id) {
|
||||
return formatMessage({
|
||||
...message,
|
||||
defaultMessage: message.defaultMessage || message.id,
|
||||
});
|
||||
}
|
||||
|
||||
return message;
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (isSearching) {
|
||||
setCollapse(true);
|
||||
@ -32,10 +38,7 @@ const LeftMenuSubList = ({
|
||||
return (
|
||||
links.length > 0 && (
|
||||
<Dropdown>
|
||||
<button
|
||||
onClick={toggle}
|
||||
className={`editable ${collapse ? 'is-open' : ''}`}
|
||||
>
|
||||
<button onClick={toggle} className={`editable ${collapse ? 'is-open' : ''}`}>
|
||||
{name}
|
||||
{isEditable && (
|
||||
<FontAwesomeIcon
|
||||
@ -53,9 +56,7 @@ const LeftMenuSubList = ({
|
||||
|
||||
return (
|
||||
<li key={name}>
|
||||
<LeftMenuLink {...link}>
|
||||
{useFormattedMessage(title)}
|
||||
</LeftMenuLink>
|
||||
<LeftMenuLink {...link}>{getLabel(title)}</LeftMenuLink>
|
||||
</li>
|
||||
);
|
||||
})}
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
*
|
||||
*/
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import styled, { keyframes } from 'styled-components';
|
||||
|
||||
const spin = keyframes`
|
||||
@ -20,8 +21,8 @@ const Loader = styled.div`
|
||||
justify-content: space-around;
|
||||
width: 100%;
|
||||
> div {
|
||||
width: 26px;
|
||||
height: 26px;
|
||||
width: ${({ small }) => (small ? '11px' : '26px')};
|
||||
height: ${({ small }) => (small ? '11px' : '26px')};
|
||||
border: 4px solid #f3f3f3;
|
||||
border-top: 4px solid #555555 !important;
|
||||
border-radius: 50%;
|
||||
@ -29,10 +30,18 @@ const Loader = styled.div`
|
||||
}
|
||||
`;
|
||||
|
||||
const LoadingIndicator = () => (
|
||||
<Loader>
|
||||
const LoadingIndicator = ({ small }) => (
|
||||
<Loader small={small}>
|
||||
<div />
|
||||
</Loader>
|
||||
);
|
||||
|
||||
LoadingIndicator.propTypes = {
|
||||
small: PropTypes.bool,
|
||||
};
|
||||
|
||||
LoadingIndicator.defaultProps = {
|
||||
small: false,
|
||||
};
|
||||
|
||||
export default LoadingIndicator;
|
||||
|
||||
@ -1,20 +1,21 @@
|
||||
import styled from 'styled-components';
|
||||
|
||||
const Option = styled.div`
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: baseline;
|
||||
padding: 0.5rem 1rem;
|
||||
font-size: 1.5rem;
|
||||
line-height: 3rem;
|
||||
cursor: pointer;
|
||||
&:hover {
|
||||
background-color: #e4f0fc;
|
||||
.right-label {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
cursor: pointer;
|
||||
line-height: 2.6rem;
|
||||
font-size: 1.5rem;
|
||||
padding: 5px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
.right-label {
|
||||
display: none;
|
||||
display: block;
|
||||
}
|
||||
`;
|
||||
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
import styled from 'styled-components';
|
||||
|
||||
const OptionsTitle = styled.div`
|
||||
line-height: 2.1rem;
|
||||
padding: 0.7rem 1rem;
|
||||
font-size: 1.2rem;
|
||||
padding: 5px;
|
||||
font-weight: bold;
|
||||
line-height: 2.1rem;
|
||||
text-transform: uppercase;
|
||||
color: ${({ theme }) => theme.main.colors.grayLight};
|
||||
border-bottom: 1px solid ${({ theme }) => theme.main.colors.border};
|
||||
color: #9ea7b8;
|
||||
`;
|
||||
|
||||
export default OptionsTitle;
|
||||
|
||||
@ -1,9 +1,10 @@
|
||||
import styled from 'styled-components';
|
||||
|
||||
const RightOptionLabel = styled.div`
|
||||
color: ${({ theme }) => theme.main.colors.strapi.blue};
|
||||
color: #007dff;
|
||||
text-transform: uppercase;
|
||||
font-weight: bold;
|
||||
font-size: 1.1rem;
|
||||
`;
|
||||
|
||||
export default RightOptionLabel;
|
||||
|
||||
@ -14,7 +14,6 @@ const Options = ({ options, title }) => (
|
||||
{options.map(option => (
|
||||
<Option key={option.id} onClick={option.onClick}>
|
||||
<div>{option.label}</div>
|
||||
|
||||
<FormattedMessage id={getTrad('components.uid.apply')}>
|
||||
{msg => <RightOptionLabel className="right-label">{msg}</RightOptionLabel>}
|
||||
</FormattedMessage>
|
||||
|
||||
@ -7,7 +7,7 @@ const wrapper = styled.div`
|
||||
border: 1px solid ${props => props.theme.main.colors.border};
|
||||
border-radius: 2px;
|
||||
background-color: white;
|
||||
z-index: 10;
|
||||
z-index: 11;
|
||||
`;
|
||||
|
||||
export default wrapper;
|
||||
|
||||
@ -12,6 +12,7 @@ import getTrad from '../../utils/getTrad';
|
||||
const RightContentLabel = styled.div`
|
||||
padding: 0 5px;
|
||||
text-transform: capitalize;
|
||||
font-size: 1.3rem;
|
||||
color: ${({ theme, color }) => theme.main.colors[color]};
|
||||
`;
|
||||
|
||||
@ -41,7 +42,7 @@ const RightLabel = ({ label, availability }) => {
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<Remove fill="#ff203c" width="12px" height="12px" />
|
||||
<Remove fill="#ff203c" width="9px" height="9px" />
|
||||
<RightContentLabel color="red">
|
||||
{formatMessage({
|
||||
id: getTrad('components.uid.unavailable'),
|
||||
|
||||
@ -0,0 +1,9 @@
|
||||
import styled from 'styled-components';
|
||||
|
||||
const SubLabel = styled.p`
|
||||
padding-top: 10px;
|
||||
line-height: normal;
|
||||
font-size: 1.3rem;
|
||||
`;
|
||||
|
||||
export default SubLabel;
|
||||
@ -0,0 +1,8 @@
|
||||
import styled from 'styled-components';
|
||||
|
||||
const Wrapper = styled.div`
|
||||
position: relative;
|
||||
padding-bottom: 23px;
|
||||
`;
|
||||
|
||||
export default Wrapper;
|
||||
@ -1,7 +1,7 @@
|
||||
import React, { useEffect, useState, useRef } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Sync } from '@buffetjs/icons';
|
||||
import { ErrorMessage as BaseErrorMessage } from '@buffetjs/styles';
|
||||
import { ErrorMessage, Description } from '@buffetjs/styles';
|
||||
import { Label, Error } from '@buffetjs/core';
|
||||
import { useDebounce, useClickAwayListener } from '@buffetjs/hooks';
|
||||
import styled from 'styled-components';
|
||||
@ -17,18 +17,13 @@ import Options from './Options';
|
||||
import RegenerateButton from './RegenerateButton';
|
||||
import RightContent from './RightContent';
|
||||
import Input from './InputUID';
|
||||
import Wrapper from './Wrapper';
|
||||
import SubLabel from './SubLabel';
|
||||
import UID_REGEX from './regex';
|
||||
|
||||
// There is no need to create additional files for those little components.
|
||||
const Wrapper = styled.div`
|
||||
position: relative;
|
||||
padding-bottom: 23px;
|
||||
`;
|
||||
const InputContainer = styled.div`
|
||||
position: relative;
|
||||
`;
|
||||
const ErrorMessage = styled(BaseErrorMessage)`
|
||||
padding-top: 10px;
|
||||
`;
|
||||
const Name = styled(Label)`
|
||||
display: block;
|
||||
text-transform: capitalize;
|
||||
@ -43,12 +38,15 @@ const Name = styled(Label)`
|
||||
const InputUID = ({
|
||||
attribute,
|
||||
contentTypeUID,
|
||||
description,
|
||||
error: inputError,
|
||||
name,
|
||||
onChange,
|
||||
required,
|
||||
validations,
|
||||
value,
|
||||
editable,
|
||||
...inputProps
|
||||
}) => {
|
||||
const { modifiedData, initialData } = useDataManager();
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
@ -92,7 +90,7 @@ const InputUID = ({
|
||||
body: {
|
||||
contentTypeUID,
|
||||
field: name,
|
||||
value: value || null,
|
||||
value: value ? value.trim() : null,
|
||||
},
|
||||
});
|
||||
setAvailability(data);
|
||||
@ -115,7 +113,11 @@ const InputUID = ({
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (debouncedValue && debouncedValue !== initialValue) {
|
||||
if (
|
||||
debouncedValue &&
|
||||
debouncedValue.trim().match(UID_REGEX) &&
|
||||
debouncedValue !== initialValue
|
||||
) {
|
||||
checkAvailability();
|
||||
}
|
||||
if (!debouncedValue) {
|
||||
@ -187,7 +189,12 @@ const InputUID = ({
|
||||
};
|
||||
|
||||
return (
|
||||
<Error name={name} inputError={inputError} type="text" validations={validations}>
|
||||
<Error
|
||||
name={name}
|
||||
inputError={inputError}
|
||||
type="text"
|
||||
validations={{ ...validations, regex: UID_REGEX }}
|
||||
>
|
||||
{({ canCheck, onBlur, error, dispatch }) => {
|
||||
const hasError = error && error !== null;
|
||||
|
||||
@ -196,6 +203,8 @@ const InputUID = ({
|
||||
<Name htmlFor={name}>{name}</Name>
|
||||
<InputContainer>
|
||||
<Input
|
||||
{...inputProps}
|
||||
editable={editable}
|
||||
error={hasError}
|
||||
onFocus={handleFocus}
|
||||
name={name}
|
||||
@ -207,17 +216,19 @@ const InputUID = ({
|
||||
/>
|
||||
<RightContent>
|
||||
<RightLabel availability={availability} label={label} />
|
||||
<RegenerateButton
|
||||
onMouseEnter={handleGenerateMouseEnter}
|
||||
onMouseLeave={handleGenerateMouseLeave}
|
||||
onClick={generateUid.current}
|
||||
>
|
||||
{isLoading ? (
|
||||
<LoadingIndicator />
|
||||
) : (
|
||||
<Sync fill={label ? '#007EFF' : '#B5B7BB'} width="15px" height="15px" />
|
||||
)}
|
||||
</RegenerateButton>
|
||||
{editable && (
|
||||
<RegenerateButton
|
||||
onMouseEnter={handleGenerateMouseEnter}
|
||||
onMouseLeave={handleGenerateMouseLeave}
|
||||
onClick={generateUid.current}
|
||||
>
|
||||
{isLoading ? (
|
||||
<LoadingIndicator small />
|
||||
) : (
|
||||
<Sync fill={label ? '#007EFF' : '#B5B7BB'} width="11px" height="11px" />
|
||||
)}
|
||||
</RegenerateButton>
|
||||
)}
|
||||
</RightContent>
|
||||
{availability && availability.suggestion && isSuggestionOpen && (
|
||||
<FormattedMessage id={`${pluginId}.components.uid.suggested`}>
|
||||
@ -236,7 +247,8 @@ const InputUID = ({
|
||||
</FormattedMessage>
|
||||
)}
|
||||
</InputContainer>
|
||||
{hasError && <ErrorMessage>{error}</ErrorMessage>}
|
||||
{!hasError && description && <SubLabel as={Description}>{description}</SubLabel>}
|
||||
{hasError && <SubLabel as={ErrorMessage}>{error}</SubLabel>}
|
||||
</Wrapper>
|
||||
);
|
||||
}}
|
||||
@ -247,6 +259,8 @@ const InputUID = ({
|
||||
InputUID.propTypes = {
|
||||
attribute: PropTypes.object.isRequired,
|
||||
contentTypeUID: PropTypes.string.isRequired,
|
||||
description: PropTypes.string,
|
||||
editable: PropTypes.bool,
|
||||
error: PropTypes.string,
|
||||
name: PropTypes.string.isRequired,
|
||||
onChange: PropTypes.func.isRequired,
|
||||
@ -256,6 +270,8 @@ InputUID.propTypes = {
|
||||
};
|
||||
|
||||
InputUID.defaultProps = {
|
||||
description: '',
|
||||
editable: false,
|
||||
error: null,
|
||||
required: false,
|
||||
validations: {},
|
||||
|
||||
@ -0,0 +1,3 @@
|
||||
const UID_REGEX = new RegExp(/^[A-Za-z0-9-_.~]*$/);
|
||||
|
||||
export default UID_REGEX;
|
||||
@ -3,7 +3,7 @@ import styled, { css } from 'styled-components';
|
||||
/* eslint-disable */
|
||||
|
||||
const SelectWrapper = styled.div`
|
||||
min-width: ${({ isFullScreen }) => (isFullScreen ? '161px' : '115px')}
|
||||
min-width: ${({ isFullScreen }) => (isFullScreen ? '161px' : '115px')};
|
||||
margin-left: 15px;
|
||||
> select {
|
||||
${({ isFullScreen }) => {
|
||||
|
||||
@ -11,14 +11,7 @@ import Wrapper from './Wrapper';
|
||||
|
||||
/* eslint-disable jsx-a11y/control-has-associated-label */
|
||||
|
||||
const ComponentIconPicker = ({
|
||||
error,
|
||||
isCreating,
|
||||
label,
|
||||
name,
|
||||
onChange,
|
||||
value,
|
||||
}) => {
|
||||
const ComponentIconPicker = ({ error, isCreating, label, name, onChange, value }) => {
|
||||
const { allIcons, allComponentsIconAlreadyTaken } = useDataManager();
|
||||
const initialIcons = allIcons.filter(ico => {
|
||||
if (isCreating) {
|
||||
@ -26,9 +19,7 @@ const ComponentIconPicker = ({
|
||||
}
|
||||
|
||||
// Edition
|
||||
return !allComponentsIconAlreadyTaken
|
||||
.filter(icon => icon !== originalIcon)
|
||||
.includes(ico);
|
||||
return !allComponentsIconAlreadyTaken.filter(icon => icon !== originalIcon).includes(ico);
|
||||
});
|
||||
const ref = createRef();
|
||||
const [originalIcon] = useState(value);
|
||||
@ -85,12 +76,10 @@ const ComponentIconPicker = ({
|
||||
ref={ref}
|
||||
onChange={({ target: { value } }) => {
|
||||
setSearch(value);
|
||||
setIcons(() =>
|
||||
initialIcons.filter(icon => icon.includes(value))
|
||||
);
|
||||
setIcons(() => initialIcons.filter(icon => icon.includes(value)));
|
||||
}}
|
||||
value={search}
|
||||
placeholder="search…"
|
||||
placeholder="Search…"
|
||||
/>
|
||||
<button
|
||||
onClick={() => {
|
||||
@ -130,11 +119,7 @@ const ComponentIconPicker = ({
|
||||
);
|
||||
}}
|
||||
</AutoSizer>
|
||||
{error && (
|
||||
<ErrorMessage style={{ marginTop: 5, marginBottom: 16 }}>
|
||||
{error}
|
||||
</ErrorMessage>
|
||||
)}
|
||||
{error && <ErrorMessage style={{ marginTop: 5, marginBottom: 16 }}>{error}</ErrorMessage>}
|
||||
</Wrapper>
|
||||
);
|
||||
};
|
||||
|
||||
@ -420,7 +420,7 @@ const DataManagerProvider = ({ allIcons, children }) => {
|
||||
emitEvent('didNotSaveComponent');
|
||||
}
|
||||
console.error({ err });
|
||||
strapi.notification.error('notification.error');
|
||||
strapi.notification.error(err.response.payload.error || 'notification.error');
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -11,7 +11,6 @@ const getAttributes = (dataTarget = '', targetUid, nestedComponents) => {
|
||||
'media',
|
||||
'boolean',
|
||||
'json',
|
||||
'uid',
|
||||
'relation',
|
||||
],
|
||||
];
|
||||
@ -23,6 +22,7 @@ const getAttributes = (dataTarget = '', targetUid, nestedComponents) => {
|
||||
const items = defaultAttributes.slice();
|
||||
|
||||
if (isPickingAttributeForAContentType) {
|
||||
items[0].push('uid');
|
||||
items.push(['component', 'dynamiczone']);
|
||||
}
|
||||
|
||||
|
||||
@ -716,28 +716,40 @@ const forms = {
|
||||
.filter(key => ['string', 'text'].includes(attributes[key].type))
|
||||
.map(key => ({ id: key, value: key }));
|
||||
|
||||
items[0].push({
|
||||
label: {
|
||||
id: getTrad('modalForm.attribute.target-field'),
|
||||
},
|
||||
name: 'targetField',
|
||||
type: 'select',
|
||||
options: [{ id: getTrad('none'), value: '' }, ...options].map((option, index) => (
|
||||
// eslint-disable-next-line react/no-array-index-key
|
||||
<Fragment key={index}>
|
||||
{index === 0 ? (
|
||||
<FormattedMessage id={option.id}>
|
||||
{msg => <option value={option.value}>{msg}</option>}
|
||||
</FormattedMessage>
|
||||
) : (
|
||||
<option value={option.value}>{option.value}</option>
|
||||
)}
|
||||
</Fragment>
|
||||
)),
|
||||
validations: {
|
||||
required: true,
|
||||
},
|
||||
});
|
||||
return {
|
||||
items: [
|
||||
[
|
||||
{
|
||||
...fields.name,
|
||||
placeholder: {
|
||||
id: getTrad('modalForm.attribute.form.base.name.placeholder'),
|
||||
},
|
||||
},
|
||||
{
|
||||
label: {
|
||||
id: getTrad('modalForm.attribute.target-field'),
|
||||
},
|
||||
name: 'targetField',
|
||||
type: 'select',
|
||||
options: [{ id: getTrad('none'), value: '' }, ...options].map((option, index) => (
|
||||
// eslint-disable-next-line react/no-array-index-key
|
||||
<Fragment key={index}>
|
||||
{index === 0 ? (
|
||||
<FormattedMessage id={option.id}>
|
||||
{msg => <option value={option.value}>{msg}</option>}
|
||||
</FormattedMessage>
|
||||
) : (
|
||||
<option value={option.value}>{option.value}</option>
|
||||
)}
|
||||
</Fragment>
|
||||
)),
|
||||
validations: {
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
|
||||
@ -28,7 +28,7 @@
|
||||
"attribute.text": "Text",
|
||||
"attribute.text.description": "Krátký nebo delší text",
|
||||
"attribute.time": "Čas",
|
||||
"attribute.uid": "Uid",
|
||||
"attribute.uid": "UID",
|
||||
"attribute.uid.description": "Unikátní identifikátor",
|
||||
"button.attributes.add.another": "Přidat další pole",
|
||||
"button.component.add": "Přidat komponent",
|
||||
|
||||
@ -30,7 +30,7 @@
|
||||
"attribute.time": "Time",
|
||||
"attribute.timestamp": "Timestamp",
|
||||
"attribute.uid.description": "Unique identifier",
|
||||
"attribute.uid": "Uid",
|
||||
"attribute.uid": "UID",
|
||||
"button.attributes.add.another": "Add another field",
|
||||
"button.component.add": "Add a component",
|
||||
"button.component.create": "Create new component",
|
||||
@ -100,6 +100,7 @@
|
||||
"form.button.add-first-field-to-created-component": "Add first field to the component",
|
||||
"form.button.add.field.to.component": "Add another field to this component",
|
||||
"form.button.add.field.to.collectionType": "Add another field to this collection type",
|
||||
"form.button.add.field.to.contentType ": "Add another field to this content type",
|
||||
"form.button.add.field.to.singleType": "Add another field to this single type",
|
||||
"form.button.cancel": "Cancel",
|
||||
"form.button.configure-component": "Configure the component",
|
||||
@ -113,7 +114,7 @@
|
||||
"form.button.single-type.description": "Best for single instance like about us, homepage, etc.",
|
||||
"from": "from",
|
||||
"injected-components.content-manager.edit-settings-view.link.components": "Edit the component",
|
||||
"injected-components.content-manager.edit-settings-view.link.content-types": "Edit the collection type",
|
||||
"injected-components.content-manager.edit-settings-view.link.content-types": "Edit the content type",
|
||||
"menu.section.components.name.plural": "Components",
|
||||
"menu.section.components.name.singular": "Component",
|
||||
"menu.section.models.name.plural": "Collection Types",
|
||||
@ -123,6 +124,7 @@
|
||||
"modalForm.attribute.target-field": "Attached field",
|
||||
"modalForm.attribute.form.base.name.description": "No space is allowed for the name of the attribute",
|
||||
"modalForm.attribute.form.base.name": "Name",
|
||||
"modalForm.attribute.form.base.name.placeholder": "e.g. Slug, SEO URL, Canonical URL",
|
||||
"modalForm.attribute.text.type-selection": "Type",
|
||||
"modalForm.attributes.select-component": "Select a component",
|
||||
"modalForm.attributes.select-components": "Select the components",
|
||||
|
||||
@ -36,6 +36,7 @@
|
||||
"form.attribute.settings.default": "Valeur par défault",
|
||||
"form.button.add.field.to.component": "Ajouter un nouveau champ à ce composant",
|
||||
"form.button.add.field.to.collectionType": "Ajouter un nouveau champ à cette collection",
|
||||
"form.button.add.field.to.contentType ": "Ajouter un nouveau champ à cette content type",
|
||||
"form.button.add.field.to.singleType": "Ajouter un nouveau champ à ce single type",
|
||||
"form.button.cancel": "Annuler",
|
||||
"form.button.configure-view": "Configurer la vue",
|
||||
@ -44,6 +45,8 @@
|
||||
"form.button.finish": "Terminer",
|
||||
"form.button.delete": "Supprimer",
|
||||
"from": "de",
|
||||
"injected-components.content-manager.edit-settings-view.link.content-types": "Modifier le content type",
|
||||
"injected-components.content-manager.edit-settings-view.link.components": "Modifier le composant",
|
||||
"menu.section.components.name.plural": "Composants",
|
||||
"menu.section.components.name.singular": "Composant",
|
||||
"menu.section.models.name.plural": "Collections",
|
||||
@ -52,6 +55,7 @@
|
||||
"menu.section.single-types.name.singular": "Single Type",
|
||||
"modalForm.attribute.target-field": "Champ associé",
|
||||
"modalForm.attribute.target-field.none": "Aucun",
|
||||
"modalForm.attribute.form.base.name.placeholder": "ex : Slug, URL SEO, URL Canonique",
|
||||
"modalForm.singleType.header-create": "Créer un single type",
|
||||
"none": "Aucun",
|
||||
"button.single-types.create": "Créer un single type",
|
||||
|
||||
@ -68,7 +68,7 @@
|
||||
"attribute.richtext.description": "Edytor tekstu z możliwością formatowania",
|
||||
"attribute.text.description": "Krótki lub długi tekst jak tytuł lub opis",
|
||||
"attribute.time": "Czas",
|
||||
"attribute.uid": "Uid",
|
||||
"attribute.uid": "UID",
|
||||
"attribute.uid.description": "Unikalny identyfikator",
|
||||
"button.attributes.add.another": "Dodaj kolejne pole",
|
||||
"button.component.add": "Dodaj komponent",
|
||||
|
||||
@ -28,7 +28,7 @@
|
||||
"attribute.text": "Text",
|
||||
"attribute.text.description": "Простой текст для заголовка или описания",
|
||||
"attribute.time": "Time",
|
||||
"attribute.uid": "Uid",
|
||||
"attribute.uid": "UID",
|
||||
"attribute.uid.description": "Уникальный идентификатор",
|
||||
"button.attributes.add.another": "Ещё поле",
|
||||
"button.component.add": "Добавить компонент",
|
||||
|
||||
@ -28,7 +28,7 @@
|
||||
"attribute.text": "Text",
|
||||
"attribute.text.description": "Krátky alebo dlhší text",
|
||||
"attribute.time": "Čas",
|
||||
"attribute.uid": "Uid",
|
||||
"attribute.uid": "UID",
|
||||
"attribute.uid.description": "Unikátny identifikátor",
|
||||
"button.attributes.add.another": "Pridať ďalšie políčko",
|
||||
"button.component.add": "Pridať komponent",
|
||||
|
||||
@ -28,7 +28,7 @@
|
||||
"attribute.text": "文本",
|
||||
"attribute.text.description": "较短或较长的文字,例如标题或说明",
|
||||
"attribute.time": "时间",
|
||||
"attribute.uid": "Uid",
|
||||
"attribute.uid": "UID",
|
||||
"attribute.uid.description": "唯一标识符",
|
||||
"button.attributes.add.another": "添加一个新字段",
|
||||
"button.component.add": "添加组件",
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user