mirror of
https://github.com/strapi/strapi.git
synced 2025-09-22 06:50:51 +00:00
Merge branch 'v4/ds-migration' of github.com:strapi/strapi into v4/ds-migration
This commit is contained in:
commit
e0184b62b1
@ -304,6 +304,14 @@ const EditViewDataManagerProvider = ({
|
||||
console.error(err);
|
||||
|
||||
errors = getYupInnerErrors(err);
|
||||
|
||||
toggleNotification({
|
||||
type: 'warning',
|
||||
message: {
|
||||
id: getTrad('containers.EditView.notification.errors'),
|
||||
defaultMessage: 'The form contains some errors',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
dispatch({
|
||||
@ -311,7 +319,16 @@ const EditViewDataManagerProvider = ({
|
||||
errors,
|
||||
});
|
||||
},
|
||||
[createFormData, isCreatingEntry, modifiedData, onPost, onPut, trackerProperty, yupSchema]
|
||||
[
|
||||
createFormData,
|
||||
isCreatingEntry,
|
||||
modifiedData,
|
||||
onPost,
|
||||
onPut,
|
||||
toggleNotification,
|
||||
trackerProperty,
|
||||
yupSchema,
|
||||
]
|
||||
);
|
||||
|
||||
const handlePublish = useCallback(async () => {
|
||||
|
@ -295,6 +295,14 @@ const createYupSchemaAttribute = (type, validations, options) => {
|
||||
return value !== null;
|
||||
}
|
||||
|
||||
if (type === 'date' || type === 'datetime') {
|
||||
if (typeof value === 'string') {
|
||||
return !isEmpty(value);
|
||||
}
|
||||
|
||||
return !isEmpty(value.toString());
|
||||
}
|
||||
|
||||
return !isEmpty(value);
|
||||
});
|
||||
}
|
||||
|
@ -17,13 +17,15 @@ const Label = ({ intlLabel, id, labelAction, name, numberOfEntries, showNumberOf
|
||||
const label = intlLabel?.id ? formatMessage(intlLabel) : '';
|
||||
|
||||
return (
|
||||
<Row>
|
||||
<Text textColor="neutral800" htmlFor={id || name} small bold as="label">
|
||||
{label}
|
||||
{showNumberOfEntries && <> ({numberOfEntries})</>}
|
||||
</Text>
|
||||
{labelAction && <LabelAction paddingLeft={1}>{labelAction}</LabelAction>}
|
||||
</Row>
|
||||
<Box paddingBottom={1}>
|
||||
<Row>
|
||||
<Text textColor="neutral800" htmlFor={id || name} small bold as="label">
|
||||
{label}
|
||||
{showNumberOfEntries && <> ({numberOfEntries})</>}
|
||||
</Text>
|
||||
{labelAction && <LabelAction paddingLeft={1}>{labelAction}</LabelAction>}
|
||||
</Row>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -59,31 +59,32 @@ const FieldComponent = ({
|
||||
|
||||
return (
|
||||
<Box>
|
||||
<Stack size={1}>
|
||||
<Row justifyContent="space-between">
|
||||
{intlLabel && (
|
||||
<Label
|
||||
intlLabel={intlLabel}
|
||||
labelAction={labelAction}
|
||||
name={name}
|
||||
numberOfEntries={componentValueLength}
|
||||
showNumberOfEntries={isRepeatable}
|
||||
/>
|
||||
)}
|
||||
<Row justifyContent="space-between">
|
||||
{intlLabel && (
|
||||
<Label
|
||||
intlLabel={intlLabel}
|
||||
labelAction={labelAction}
|
||||
name={name}
|
||||
numberOfEntries={componentValueLength}
|
||||
showNumberOfEntries={isRepeatable}
|
||||
/>
|
||||
)}
|
||||
|
||||
{showResetComponent && (
|
||||
<IconButton
|
||||
label={formatMessage({
|
||||
id: getTrad('components.reset-entry'),
|
||||
defaultMessage: 'Reset Entry',
|
||||
})}
|
||||
icon={<DeleteIcon />}
|
||||
onClick={() => {
|
||||
removeComponentFromField(name, componentUid);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</Row>
|
||||
{showResetComponent && (
|
||||
<IconButton
|
||||
label={formatMessage({
|
||||
id: getTrad('components.reset-entry'),
|
||||
defaultMessage: 'Reset Entry',
|
||||
})}
|
||||
icon={<DeleteIcon />}
|
||||
noBorder
|
||||
onClick={() => {
|
||||
removeComponentFromField(name, componentUid);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</Row>
|
||||
<Stack size={1}>
|
||||
{!isRepeatable && !isInitialized && (
|
||||
<ComponentInitializer
|
||||
isReadOnly={isReadOnly}
|
||||
@ -94,6 +95,7 @@ const FieldComponent = ({
|
||||
<NonRepeatableComponent
|
||||
componentUid={componentUid}
|
||||
isFromDynamicZone={isFromDynamicZone}
|
||||
isNested={isNested}
|
||||
name={name}
|
||||
/>
|
||||
)}
|
||||
|
@ -18,7 +18,7 @@ const CominSoonInput = ({ description, intlLabel, labelAction, error, name }) =>
|
||||
)
|
||||
: name;
|
||||
|
||||
const hint = description
|
||||
const hint = description?.id
|
||||
? formatMessage(
|
||||
{ id: description.id, defaultMessage: description.defaultMessage },
|
||||
{ ...description.values }
|
||||
|
@ -10,7 +10,7 @@ import { useContentTypeLayout } from '../../hooks';
|
||||
import FieldComponent from '../FieldComponent';
|
||||
import Inputs from '../Inputs';
|
||||
|
||||
const NonRepeatableComponent = ({ componentUid, name }) => {
|
||||
const NonRepeatableComponent = ({ componentUid, isFromDynamicZone, isNested, name }) => {
|
||||
const { getComponentLayout } = useContentTypeLayout();
|
||||
const componentLayoutData = useMemo(() => getComponentLayout(componentUid), [
|
||||
componentUid,
|
||||
@ -19,7 +19,15 @@ const NonRepeatableComponent = ({ componentUid, name }) => {
|
||||
const fields = componentLayoutData.layouts.edit;
|
||||
|
||||
return (
|
||||
<Box background="neutral100" paddingLeft={6} paddingRight={6} paddingTop={6} paddingBottom={6}>
|
||||
<Box
|
||||
background={isFromDynamicZone ? 'neutral0' : 'neutral100'}
|
||||
paddingLeft={6}
|
||||
paddingRight={6}
|
||||
paddingTop={6}
|
||||
paddingBottom={6}
|
||||
hasRadius={isNested}
|
||||
borderColor={isNested ? 'neutral200' : ''}
|
||||
>
|
||||
<Stack size={6}>
|
||||
{fields.map((fieldRow, key) => {
|
||||
return (
|
||||
@ -39,6 +47,7 @@ const NonRepeatableComponent = ({ componentUid, name }) => {
|
||||
id: metadatas.label,
|
||||
defaultMessage: metadatas.label,
|
||||
}}
|
||||
isNested
|
||||
isRepeatable={fieldSchema.repeatable}
|
||||
max={fieldSchema.max}
|
||||
min={fieldSchema.min}
|
||||
@ -67,8 +76,15 @@ const NonRepeatableComponent = ({ componentUid, name }) => {
|
||||
);
|
||||
};
|
||||
|
||||
NonRepeatableComponent.defaultProps = {
|
||||
isFromDynamicZone: false,
|
||||
isNested: false,
|
||||
};
|
||||
|
||||
NonRepeatableComponent.propTypes = {
|
||||
componentUid: PropTypes.string.isRequired,
|
||||
isFromDynamicZone: PropTypes.bool,
|
||||
isNested: PropTypes.bool,
|
||||
name: PropTypes.string.isRequired,
|
||||
};
|
||||
|
||||
|
@ -1,27 +1,37 @@
|
||||
import React, { useCallback, useState, useEffect, useMemo, memo } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { FormattedMessage, useIntl } from 'react-intl';
|
||||
import { Link, useLocation } from 'react-router-dom';
|
||||
import { findIndex, get, isArray, isEmpty, set } from 'lodash';
|
||||
import {
|
||||
DropdownIndicator,
|
||||
LabelIconWrapper,
|
||||
// FormattedMessage,
|
||||
useIntl,
|
||||
} from 'react-intl';
|
||||
// import { Link, useLocation } from 'react-router-dom';
|
||||
// import { findIndex, get, isArray, isEmpty, set } from 'lodash';
|
||||
import get from 'lodash/get';
|
||||
import isArray from 'lodash/isArray';
|
||||
import {
|
||||
// DropdownIndicator,
|
||||
|
||||
NotAllowedInput,
|
||||
useCMEditViewDataManager,
|
||||
useQueryParams,
|
||||
// useQueryParams,
|
||||
} from '@strapi/helper-plugin';
|
||||
import { Flex, Text, Padded } from '@buffetjs/core';
|
||||
import { stringify } from 'qs';
|
||||
// import { Flex, Text, Padded } from '@buffetjs/core';
|
||||
// import { stringify } from 'qs';
|
||||
import axios from 'axios';
|
||||
import { axiosInstance } from '../../../core/utils';
|
||||
import { getTrad } from '../../utils';
|
||||
import SelectOne from '../SelectOne';
|
||||
import SelectMany from '../SelectMany';
|
||||
import ClearIndicator from './ClearIndicator';
|
||||
import IndicatorSeparator from './IndicatorSeparator';
|
||||
import Option from './Option';
|
||||
import { A, BaselineAlignment } from './components';
|
||||
import { connect, select, styles } from './utils';
|
||||
// import { getTrad } from '../../utils';
|
||||
import ComingSoonInput from '../Inputs/ComingSoonInput';
|
||||
// import SelectOne from '../SelectOne';
|
||||
// import SelectMany from '../SelectMany';
|
||||
// import ClearIndicator from './ClearIndicator';
|
||||
// import IndicatorSeparator from './IndicatorSeparator';
|
||||
// import Option from './Option';
|
||||
// import { A, BaselineAlignment } from './components';
|
||||
import {
|
||||
connect,
|
||||
select,
|
||||
// styles
|
||||
} from './utils';
|
||||
|
||||
const initialPaginationState = {
|
||||
_contains: '',
|
||||
@ -29,77 +39,89 @@ const initialPaginationState = {
|
||||
_start: 0,
|
||||
};
|
||||
|
||||
const buildParams = (query, paramsToKeep) => {
|
||||
if (!paramsToKeep) {
|
||||
return {};
|
||||
}
|
||||
// const buildParams = (query, paramsToKeep) => {
|
||||
// if (!paramsToKeep) {
|
||||
// return {};
|
||||
// }
|
||||
|
||||
return paramsToKeep.reduce((acc, current) => {
|
||||
const value = get(query, current, null);
|
||||
// return paramsToKeep.reduce((acc, current) => {
|
||||
// const value = get(query, current, null);
|
||||
|
||||
if (value) {
|
||||
set(acc, current, value);
|
||||
}
|
||||
// if (value) {
|
||||
// set(acc, current, value);
|
||||
// }
|
||||
|
||||
return acc;
|
||||
}, {});
|
||||
};
|
||||
// return acc;
|
||||
// }, {});
|
||||
// };
|
||||
function SelectWrapper({
|
||||
description,
|
||||
editable,
|
||||
label,
|
||||
labelIcon,
|
||||
// editable,
|
||||
labelAction,
|
||||
intlLabel,
|
||||
isCreatingEntry,
|
||||
isFieldAllowed,
|
||||
isFieldReadable,
|
||||
mainField,
|
||||
name,
|
||||
relationType,
|
||||
targetModel,
|
||||
placeholder,
|
||||
// targetModel,
|
||||
// placeholder,
|
||||
queryInfos,
|
||||
}) {
|
||||
const { formatMessage } = useIntl();
|
||||
const [{ query }] = useQueryParams();
|
||||
// const [{ query }] = useQueryParams();
|
||||
// Disable the input in case of a polymorphic relation
|
||||
const isMorph = useMemo(() => relationType.toLowerCase().includes('morph'), [relationType]);
|
||||
const {
|
||||
addRelation,
|
||||
// addRelation,
|
||||
modifiedData,
|
||||
moveRelation,
|
||||
onChange,
|
||||
onRemoveRelation,
|
||||
// moveRelation,
|
||||
// onChange,
|
||||
// onRemoveRelation,
|
||||
} = useCMEditViewDataManager();
|
||||
const { pathname } = useLocation();
|
||||
// const { pathname } = useLocation();
|
||||
|
||||
const value = get(modifiedData, name, null);
|
||||
const [state, setState] = useState(initialPaginationState);
|
||||
const [options, setOptions] = useState([]);
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const [
|
||||
state,
|
||||
// setState
|
||||
] = useState(initialPaginationState);
|
||||
const [
|
||||
// options,
|
||||
setOptions,
|
||||
] = useState([]);
|
||||
const [
|
||||
// isLoading,
|
||||
setIsLoading,
|
||||
] = useState(false);
|
||||
const [
|
||||
isOpen,
|
||||
// setIsOpen
|
||||
] = useState(false);
|
||||
|
||||
const filteredOptions = useMemo(() => {
|
||||
return options.filter(option => {
|
||||
if (!isEmpty(value)) {
|
||||
// SelectMany
|
||||
if (Array.isArray(value)) {
|
||||
return findIndex(value, o => o.id === option.value.id) === -1;
|
||||
}
|
||||
// const filteredOptions = useMemo(() => {
|
||||
// return options.filter(option => {
|
||||
// if (!isEmpty(value)) {
|
||||
// // SelectMany
|
||||
// if (Array.isArray(value)) {
|
||||
// return findIndex(value, o => o.id === option.value.id) === -1;
|
||||
// }
|
||||
|
||||
// SelectOne
|
||||
return get(value, 'id', '') !== option.value.id;
|
||||
}
|
||||
// // SelectOne
|
||||
// return get(value, 'id', '') !== option.value.id;
|
||||
// }
|
||||
|
||||
return true;
|
||||
});
|
||||
}, [options, value]);
|
||||
// return true;
|
||||
// });
|
||||
// }, [options, value]);
|
||||
|
||||
const {
|
||||
endPoint,
|
||||
containsKey,
|
||||
defaultParams,
|
||||
shouldDisplayRelationLink,
|
||||
paramsToKeep,
|
||||
// shouldDisplayRelationLink,
|
||||
// paramsToKeep,
|
||||
} = queryInfos;
|
||||
|
||||
const isSingle = ['oneWay', 'oneToOne', 'manyToOne', 'oneToManyMorph', 'oneToOneMorph'].includes(
|
||||
@ -170,15 +192,17 @@ function SelectWrapper({
|
||||
}
|
||||
},
|
||||
[
|
||||
isMorph,
|
||||
isFieldAllowed,
|
||||
state._limit,
|
||||
state._contains,
|
||||
defaultParams,
|
||||
containsKey,
|
||||
defaultParams,
|
||||
endPoint,
|
||||
idsToOmit,
|
||||
isFieldAllowed,
|
||||
isMorph,
|
||||
mainField.name,
|
||||
setIsLoading,
|
||||
setOptions,
|
||||
state._contains,
|
||||
state._limit,
|
||||
]
|
||||
);
|
||||
|
||||
@ -193,180 +217,198 @@ function SelectWrapper({
|
||||
return () => source.cancel('Operation canceled by the user.');
|
||||
}, [getData, isOpen]);
|
||||
|
||||
const handleInputChange = (inputValue, { action }) => {
|
||||
if (action === 'input-change') {
|
||||
setState(prevState => {
|
||||
if (prevState._contains === inputValue) {
|
||||
return prevState;
|
||||
}
|
||||
// const handleInputChange = (inputValue, { action }) => {
|
||||
// if (action === 'input-change') {
|
||||
// setState(prevState => {
|
||||
// if (prevState._contains === inputValue) {
|
||||
// return prevState;
|
||||
// }
|
||||
|
||||
return { ...prevState, _contains: inputValue, _start: 0 };
|
||||
});
|
||||
}
|
||||
// return { ...prevState, _contains: inputValue, _start: 0 };
|
||||
// });
|
||||
// }
|
||||
|
||||
return inputValue;
|
||||
};
|
||||
// return inputValue;
|
||||
// };
|
||||
|
||||
const handleMenuScrollToBottom = () => {
|
||||
setState(prevState => ({ ...prevState, _limit: prevState._limit + 20 }));
|
||||
};
|
||||
// const handleMenuScrollToBottom = () => {
|
||||
// setState(prevState => ({ ...prevState, _limit: prevState._limit + 20 }));
|
||||
// };
|
||||
|
||||
const handleMenuClose = () => {
|
||||
setState(initialPaginationState);
|
||||
setIsOpen(false);
|
||||
};
|
||||
// const handleMenuClose = () => {
|
||||
// setState(initialPaginationState);
|
||||
// setIsOpen(false);
|
||||
// };
|
||||
|
||||
const handleChange = value => {
|
||||
onChange({ target: { name, value: value ? value.value : value } });
|
||||
};
|
||||
// const handleChange = value => {
|
||||
// onChange({ target: { name, value: value ? value.value : value } });
|
||||
// };
|
||||
|
||||
const handleAddRelation = value => {
|
||||
if (!isEmpty(value)) {
|
||||
addRelation({ target: { name, value } });
|
||||
}
|
||||
};
|
||||
// const handleAddRelation = value => {
|
||||
// if (!isEmpty(value)) {
|
||||
// addRelation({ target: { name, value } });
|
||||
// }
|
||||
// };
|
||||
|
||||
const handleMenuOpen = () => {
|
||||
setIsOpen(true);
|
||||
};
|
||||
// const handleMenuOpen = () => {
|
||||
// setIsOpen(true);
|
||||
// };
|
||||
|
||||
const to = `/content-manager/collectionType/${targetModel}/${value ? value.id : null}`;
|
||||
// const to = `/content-manager/collectionType/${targetModel}/${value ? value.id : null}`;
|
||||
|
||||
const searchToPersist = stringify(buildParams(query, paramsToKeep), { encode: false });
|
||||
// const searchToPersist = stringify(buildParams(query, paramsToKeep), { encode: false });
|
||||
|
||||
const link = useMemo(() => {
|
||||
if (!value) {
|
||||
return null;
|
||||
}
|
||||
// const link = useMemo(() => {
|
||||
// if (!value) {
|
||||
// return null;
|
||||
// }
|
||||
|
||||
if (!shouldDisplayRelationLink) {
|
||||
return null;
|
||||
}
|
||||
// if (!shouldDisplayRelationLink) {
|
||||
// return null;
|
||||
// }
|
||||
|
||||
return (
|
||||
<Link to={{ pathname: to, state: { from: pathname }, search: searchToPersist }}>
|
||||
<FormattedMessage id="content-manager.containers.Edit.seeDetails">
|
||||
{msg => <A color="mediumBlue">{msg}</A>}
|
||||
</FormattedMessage>
|
||||
</Link>
|
||||
);
|
||||
}, [shouldDisplayRelationLink, pathname, to, value, searchToPersist]);
|
||||
// return (
|
||||
// <Link to={{ pathname: to, state: { from: pathname }, search: searchToPersist }}>
|
||||
// <FormattedMessage id="content-manager.containers.Edit.seeDetails">
|
||||
// {msg => <A color="mediumBlue">{msg}</A>}
|
||||
// </FormattedMessage>
|
||||
// </Link>
|
||||
// );
|
||||
// }, [shouldDisplayRelationLink, pathname, to, value, searchToPersist]);
|
||||
|
||||
const Component = isSingle ? SelectOne : SelectMany;
|
||||
// const Component = isSingle ? SelectOne : SelectMany;
|
||||
const associationsLength = isArray(value) ? value.length : 0;
|
||||
|
||||
const isDisabled = useMemo(() => {
|
||||
if (isMorph) {
|
||||
return true;
|
||||
}
|
||||
// const isDisabled = useMemo(() => {
|
||||
// if (isMorph) {
|
||||
// return true;
|
||||
// }
|
||||
|
||||
if (!isCreatingEntry) {
|
||||
return (!isFieldAllowed && isFieldReadable) || !editable;
|
||||
}
|
||||
// if (!isCreatingEntry) {
|
||||
// return (!isFieldAllowed && isFieldReadable) || !editable;
|
||||
// }
|
||||
|
||||
return !editable;
|
||||
}, [isMorph, isCreatingEntry, editable, isFieldAllowed, isFieldReadable]);
|
||||
// return !editable;
|
||||
// }, [isMorph, isCreatingEntry, editable, isFieldAllowed, isFieldReadable]);
|
||||
|
||||
const labelIconformatted = labelIcon
|
||||
? { icon: labelIcon.icon, title: formatMessage(labelIcon.title) }
|
||||
: labelIcon;
|
||||
const multipleLabel = intlLabel.id
|
||||
? formatMessage({ id: intlLabel.id, defaultMessage: intlLabel.defaultMessage })
|
||||
: name;
|
||||
const formattedLabel = isSingle
|
||||
? intlLabel
|
||||
: {
|
||||
// Custom trad id in order to add the label count
|
||||
id: 'relations-label',
|
||||
defaultMessage: '{label} ({count})',
|
||||
values: { label: multipleLabel, count: associationsLength },
|
||||
};
|
||||
|
||||
if (!isFieldAllowed && isCreatingEntry) {
|
||||
return <NotAllowedInput label={label} labelIcon={labelIconformatted} />;
|
||||
return <NotAllowedInput intlLabel={intlLabel} labelAction={labelAction} />;
|
||||
}
|
||||
|
||||
if (!isCreatingEntry && !isFieldAllowed && !isFieldReadable) {
|
||||
return <NotAllowedInput label={label} labelIcon={labelIconformatted} />;
|
||||
return <NotAllowedInput intlLabel={intlLabel} labelAction={labelAction} />;
|
||||
}
|
||||
|
||||
return (
|
||||
<Padded>
|
||||
<BaselineAlignment />
|
||||
<Flex justifyContent="space-between">
|
||||
<Flex>
|
||||
<Text fontWeight="semiBold">
|
||||
<span>
|
||||
{label}
|
||||
{!isSingle && ` (${associationsLength})`}
|
||||
</span>
|
||||
</Text>
|
||||
{labelIconformatted && (
|
||||
<div style={{ lineHeight: '13px' }}>
|
||||
<LabelIconWrapper title={labelIconformatted.title}>
|
||||
{labelIconformatted.icon}
|
||||
</LabelIconWrapper>
|
||||
</div>
|
||||
)}
|
||||
</Flex>
|
||||
{isSingle && link}
|
||||
</Flex>
|
||||
{!isEmpty(description) && (
|
||||
<Padded top size="xs">
|
||||
<BaselineAlignment />
|
||||
<Text fontSize="sm" color="grey" lineHeight="12px" ellipsis>
|
||||
{description}
|
||||
</Text>
|
||||
</Padded>
|
||||
)}
|
||||
<Padded top size="sm">
|
||||
<BaselineAlignment />
|
||||
|
||||
<Component
|
||||
addRelation={handleAddRelation}
|
||||
components={{ ClearIndicator, DropdownIndicator, IndicatorSeparator, Option }}
|
||||
displayNavigationLink={shouldDisplayRelationLink}
|
||||
id={name}
|
||||
isDisabled={isDisabled}
|
||||
isLoading={isLoading}
|
||||
isClearable
|
||||
mainField={mainField}
|
||||
move={moveRelation}
|
||||
name={name}
|
||||
options={filteredOptions}
|
||||
onChange={handleChange}
|
||||
onInputChange={handleInputChange}
|
||||
onMenuClose={handleMenuClose}
|
||||
onMenuOpen={handleMenuOpen}
|
||||
onMenuScrollToBottom={handleMenuScrollToBottom}
|
||||
onRemove={onRemoveRelation}
|
||||
placeholder={
|
||||
isEmpty(placeholder) ? (
|
||||
<FormattedMessage id={getTrad('containers.Edit.addAnItem')} />
|
||||
) : (
|
||||
placeholder
|
||||
)
|
||||
}
|
||||
searchToPersist={searchToPersist}
|
||||
styles={styles}
|
||||
targetModel={targetModel}
|
||||
value={value}
|
||||
/>
|
||||
</Padded>
|
||||
<div style={{ marginBottom: 28 }} />
|
||||
</Padded>
|
||||
<ComingSoonInput
|
||||
intlLabel={formattedLabel}
|
||||
labelAction={labelAction}
|
||||
description={description}
|
||||
name={name}
|
||||
/>
|
||||
);
|
||||
|
||||
// return (
|
||||
// <Padded>
|
||||
// <BaselineAlignment />
|
||||
// <Flex justifyContent="space-between">
|
||||
// <Flex>
|
||||
// <Text fontWeight="semiBold">
|
||||
// <span>
|
||||
// {label}
|
||||
// {!isSingle && ` (${associationsLength})`}
|
||||
// </span>
|
||||
// </Text>
|
||||
// {labelIconformatted && (
|
||||
// <div style={{ lineHeight: '13px' }}>
|
||||
// <LabelIconWrapper title={labelIconformatted.title}>
|
||||
// {labelIconformatted.icon}
|
||||
// </LabelIconWrapper>
|
||||
// </div>
|
||||
// )}
|
||||
// </Flex>
|
||||
// {isSingle && link}
|
||||
// </Flex>
|
||||
// {!isEmpty(description) && (
|
||||
// <Padded top size="xs">
|
||||
// <BaselineAlignment />
|
||||
// <Text fontSize="sm" color="grey" lineHeight="12px" ellipsis>
|
||||
// {description}
|
||||
// </Text>
|
||||
// </Padded>
|
||||
// )}
|
||||
// <Padded top size="sm">
|
||||
// <BaselineAlignment />
|
||||
|
||||
// <Component
|
||||
// addRelation={handleAddRelation}
|
||||
// components={{ ClearIndicator, DropdownIndicator, IndicatorSeparator, Option }}
|
||||
// displayNavigationLink={shouldDisplayRelationLink}
|
||||
// id={name}
|
||||
// isDisabled={isDisabled}
|
||||
// isLoading={isLoading}
|
||||
// isClearable
|
||||
// mainField={mainField}
|
||||
// move={moveRelation}
|
||||
// name={name}
|
||||
// options={filteredOptions}
|
||||
// onChange={handleChange}
|
||||
// onInputChange={handleInputChange}
|
||||
// onMenuClose={handleMenuClose}
|
||||
// onMenuOpen={handleMenuOpen}
|
||||
// onMenuScrollToBottom={handleMenuScrollToBottom}
|
||||
// onRemove={onRemoveRelation}
|
||||
// placeholder={
|
||||
// isEmpty(placeholder) ? (
|
||||
// <FormattedMessage id={getTrad('containers.Edit.addAnItem')} />
|
||||
// ) : (
|
||||
// placeholder
|
||||
// )
|
||||
// }
|
||||
// searchToPersist={searchToPersist}
|
||||
// styles={styles}
|
||||
// targetModel={targetModel}
|
||||
// value={value}
|
||||
// />
|
||||
// </Padded>
|
||||
// <div style={{ marginBottom: 28 }} />
|
||||
// </Padded>
|
||||
// );
|
||||
}
|
||||
|
||||
SelectWrapper.defaultProps = {
|
||||
editable: true,
|
||||
// editable: true,
|
||||
description: '',
|
||||
label: '',
|
||||
labelIcon: null,
|
||||
labelAction: null,
|
||||
isFieldAllowed: true,
|
||||
placeholder: '',
|
||||
// placeholder: null,
|
||||
};
|
||||
|
||||
SelectWrapper.propTypes = {
|
||||
editable: PropTypes.bool,
|
||||
description: PropTypes.string,
|
||||
label: PropTypes.string,
|
||||
labelIcon: PropTypes.shape({
|
||||
icon: PropTypes.node.isRequired,
|
||||
title: PropTypes.shape({
|
||||
id: PropTypes.string.isRequired,
|
||||
defaultMessage: PropTypes.string,
|
||||
}),
|
||||
// editable: PropTypes.bool,
|
||||
description: PropTypes.shape({
|
||||
id: PropTypes.string.isRequired,
|
||||
defaultMessage: PropTypes.string.isRequired,
|
||||
values: PropTypes.object,
|
||||
}),
|
||||
intlLabel: PropTypes.shape({
|
||||
id: PropTypes.string.isRequired,
|
||||
defaultMessage: PropTypes.string.isRequired,
|
||||
values: PropTypes.object,
|
||||
}).isRequired,
|
||||
labelAction: PropTypes.element,
|
||||
isCreatingEntry: PropTypes.bool.isRequired,
|
||||
isFieldAllowed: PropTypes.bool,
|
||||
isFieldReadable: PropTypes.bool.isRequired,
|
||||
@ -377,9 +419,13 @@ SelectWrapper.propTypes = {
|
||||
}).isRequired,
|
||||
}).isRequired,
|
||||
name: PropTypes.string.isRequired,
|
||||
placeholder: PropTypes.string,
|
||||
// placeholder: PropTypes.shape({
|
||||
// id: PropTypes.string.isRequired,
|
||||
// defaultMessage: PropTypes.string.isRequired,
|
||||
// values: PropTypes.object,
|
||||
// }),
|
||||
relationType: PropTypes.string.isRequired,
|
||||
targetModel: PropTypes.string.isRequired,
|
||||
// targetModel: PropTypes.string.isRequired,
|
||||
queryInfos: PropTypes.shape({
|
||||
containsKey: PropTypes.string.isRequired,
|
||||
defaultParams: PropTypes.object,
|
||||
|
@ -5,10 +5,12 @@ import { CheckPermissions, useTracking } from '@strapi/helper-plugin';
|
||||
import { useIntl } from 'react-intl';
|
||||
import { ContentLayout } from '@strapi/parts/Layout';
|
||||
import { Box } from '@strapi/parts/Box';
|
||||
import { Divider } from '@strapi/parts/Divider';
|
||||
import { Grid, GridItem } from '@strapi/parts/Grid';
|
||||
import { LinkButton } from '@strapi/parts/LinkButton';
|
||||
import { Main } from '@strapi/parts/Main';
|
||||
import { Stack } from '@strapi/parts/Stack';
|
||||
import { TableLabel } from '@strapi/parts/Text';
|
||||
import ConfigureIcon from '@strapi/icons/ConfigureIcon';
|
||||
import EditIcon from '@strapi/icons/EditIcon';
|
||||
import { InjectionZone } from '../../../shared/components';
|
||||
@ -18,7 +20,7 @@ import DynamicZone from '../../components/DynamicZone';
|
||||
// import FormWrapper from '../../components/FormWrapper';
|
||||
import FieldComponent from '../../components/FieldComponent';
|
||||
import Inputs from '../../components/Inputs';
|
||||
// import SelectWrapper from '../../components/SelectWrapper';
|
||||
import SelectWrapper from '../../components/SelectWrapper';
|
||||
import CollectionTypeFormWrapper from '../../components/CollectionTypeFormWrapper';
|
||||
import EditViewDataManagerProvider from '../../components/EditViewDataManagerProvider';
|
||||
import SingleTypeFormWrapper from '../../components/SingleTypeFormWrapper';
|
||||
@ -88,6 +90,9 @@ const EditView = ({
|
||||
);
|
||||
}, [currentContentTypeLayoutData]);
|
||||
|
||||
const relationsLayout = currentContentTypeLayoutData.layouts.editRelations;
|
||||
const displayedRelationsLength = relationsLayout.length;
|
||||
|
||||
return (
|
||||
<DataManagementWrapper allLayoutData={layout} slug={slug} id={id} origin={origin}>
|
||||
{({
|
||||
@ -241,6 +246,66 @@ const EditView = ({
|
||||
<Informations />
|
||||
<InjectionZone area="contentManager.editView.informations" />
|
||||
</Box>
|
||||
{displayedRelationsLength > 0 && (
|
||||
<Box
|
||||
as="aside"
|
||||
aria-labelledby="additional-informations"
|
||||
background="neutral0"
|
||||
borderColor="neutral150"
|
||||
hasRadius
|
||||
paddingBottom={4}
|
||||
paddingLeft={4}
|
||||
paddingRight={4}
|
||||
paddingTop={6}
|
||||
>
|
||||
<TableLabel textColor="neutral600">
|
||||
{formatMessage(
|
||||
{
|
||||
id: getTrad('containers.Edit.relations'),
|
||||
defaultMessage:
|
||||
'{number, plural, =0 {relations} one {relation} other {relations}}',
|
||||
},
|
||||
{ number: displayedRelationsLength }
|
||||
)}
|
||||
</TableLabel>
|
||||
<Box paddingTop={2} paddingBottom={6}>
|
||||
<Divider />
|
||||
</Box>
|
||||
<Stack size={4}>
|
||||
{relationsLayout.map(
|
||||
({ name, fieldSchema, labelAction, metadatas, queryInfos }) => {
|
||||
return (
|
||||
<SelectWrapper
|
||||
{...fieldSchema}
|
||||
{...metadatas}
|
||||
key={name}
|
||||
description={{
|
||||
id: metadatas.description,
|
||||
defaultMessage: metadatas.description,
|
||||
}}
|
||||
intlLabel={{
|
||||
id: metadatas.label,
|
||||
defaultMessage: metadatas.label,
|
||||
}}
|
||||
labelAction={labelAction}
|
||||
name={name}
|
||||
relationsType={fieldSchema.relationType}
|
||||
queryInfos={queryInfos}
|
||||
placeholder={
|
||||
metadatas.placeholder
|
||||
? {
|
||||
id: metadatas.placeholder,
|
||||
defaultMessage: metadatas.placeholder,
|
||||
}
|
||||
: null
|
||||
}
|
||||
/>
|
||||
);
|
||||
}
|
||||
)}
|
||||
</Stack>
|
||||
</Box>
|
||||
)}
|
||||
<Box as="aside" aria-labelledby="links">
|
||||
<Stack size={2}>
|
||||
{slug !== 'strapi::administrator' && (
|
||||
@ -423,13 +488,13 @@ const EditView = ({
|
||||
// ({ name, fieldSchema, labelIcon, metadatas, queryInfos }) => {
|
||||
// return (
|
||||
// <SelectWrapper
|
||||
// {...fieldSchema}
|
||||
// {...metadatas}
|
||||
// key={name}
|
||||
// labelIcon={labelIcon}
|
||||
// name={name}
|
||||
// relationsType={fieldSchema.relationType}
|
||||
// queryInfos={queryInfos}
|
||||
// {...fieldSchema}
|
||||
// {...metadatas}
|
||||
// key={name}
|
||||
// labelIcon={labelIcon}
|
||||
// name={name}
|
||||
// relationsType={fieldSchema.relationType}
|
||||
// queryInfos={queryInfos}
|
||||
// />
|
||||
// );
|
||||
// }
|
||||
|
@ -110,7 +110,6 @@ const CMEditViewLocalePicker = ({
|
||||
<Option
|
||||
value={value.value}
|
||||
disabled
|
||||
hidden
|
||||
startIcon={hasDraftAndPublishEnabled ? <Bullet status={currentLocaleStatus} /> : null}
|
||||
>
|
||||
{value.label}
|
||||
|
@ -1,8 +1,7 @@
|
||||
import React from 'react';
|
||||
import get from 'lodash/get';
|
||||
import I18N from '@strapi/icons/I18N';
|
||||
// FIXME
|
||||
import HelpIcon from '@strapi/icons/HelpIcon';
|
||||
import StrikedWorld from '@strapi/icons/StrikedWorld';
|
||||
import LabelAction from '../components/LabelAction';
|
||||
import { getTrad } from '../utils';
|
||||
|
||||
@ -45,7 +44,7 @@ const enhanceEditLayout = layout =>
|
||||
? 'This value is unique for the selected locale'
|
||||
: 'This value is common to all locales',
|
||||
},
|
||||
icon: hasI18nEnabled ? <I18N aria-hidden /> : <HelpIcon aria-hidden />,
|
||||
icon: hasI18nEnabled ? <I18N aria-hidden /> : <StrikedWorld aria-hidden />,
|
||||
};
|
||||
|
||||
acc.push({ ...field, labelAction: <LabelAction {...labelActionProps} /> });
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React from 'react';
|
||||
import I18N from '@strapi/icons/I18N';
|
||||
// FIXME
|
||||
import HelpIcon from '@strapi/icons/HelpIcon';
|
||||
|
||||
import StrikedWorld from '@strapi/icons/StrikedWorld';
|
||||
import LabelAction from '../../components/LabelAction';
|
||||
import { getTrad } from '../../utils';
|
||||
import mutateEditViewLayout, {
|
||||
@ -450,7 +450,7 @@ describe('i18n | contentManagerHooks | mutateEditViewLayout', () => {
|
||||
labelAction: (
|
||||
<LabelAction
|
||||
title={{ id: notLocalizedTrad, defaultMessage: notLocalizedTradDefaultMessage }}
|
||||
icon={<HelpIcon aria-hidden />}
|
||||
icon={<StrikedWorld aria-hidden />}
|
||||
/>
|
||||
),
|
||||
},
|
||||
|
Loading…
x
Reference in New Issue
Block a user