mirror of
https://github.com/strapi/strapi.git
synced 2025-12-24 13:43:41 +00:00
Merge branch 'v4/ds-migration' of github.com:strapi/strapi into migration/cm-table
This commit is contained in:
commit
2a5d4938c5
@ -88,6 +88,8 @@ const SocialLinks = () => {
|
||||
|
||||
return (
|
||||
<Box
|
||||
as="aside"
|
||||
aria-labelledby="join-the-community"
|
||||
background="neutral0"
|
||||
hasRadius
|
||||
paddingRight={5}
|
||||
@ -99,7 +101,7 @@ const SocialLinks = () => {
|
||||
<Box paddingBottom={7}>
|
||||
<Stack size={5}>
|
||||
<Stack size={3}>
|
||||
<H3>
|
||||
<H3 as="h2" id="join-the-community">
|
||||
{formatMessage({
|
||||
id: 'app.components.HomePage.community',
|
||||
defaultMessage: 'Join the community',
|
||||
|
||||
@ -60,7 +60,7 @@ const HomePage = () => {
|
||||
</FormattedMessage>
|
||||
<Main labelledBy="homepage">
|
||||
<LogoContainer>
|
||||
<img alt="Strapi logo" src={Logo} />
|
||||
<img alt="" aria-hidden src={Logo} />
|
||||
</LogoContainer>
|
||||
<Box padding={10}>
|
||||
<Grid>
|
||||
|
||||
@ -917,7 +917,8 @@ describe('Homepage', () => {
|
||||
<div
|
||||
class=""
|
||||
>
|
||||
<div
|
||||
<aside
|
||||
aria-labelledby="join-the-community"
|
||||
class="c34"
|
||||
>
|
||||
<div
|
||||
@ -929,11 +930,12 @@ describe('Homepage', () => {
|
||||
<div
|
||||
class="c36"
|
||||
>
|
||||
<h3
|
||||
<h2
|
||||
class="c37"
|
||||
id="join-the-community"
|
||||
>
|
||||
Join the community
|
||||
</h3>
|
||||
</h2>
|
||||
<span
|
||||
class="c12 c38"
|
||||
>
|
||||
@ -1288,7 +1290,7 @@ describe('Homepage', () => {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -0,0 +1,76 @@
|
||||
import React from 'react';
|
||||
import styled from 'styled-components';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Box } from '@strapi/parts';
|
||||
import {
|
||||
Component,
|
||||
CT,
|
||||
Date,
|
||||
Boolean,
|
||||
DynamicZone,
|
||||
Email,
|
||||
Enumeration,
|
||||
Json,
|
||||
LongDescription,
|
||||
Media,
|
||||
Numbers,
|
||||
Password,
|
||||
Relation,
|
||||
St,
|
||||
Text,
|
||||
Uid,
|
||||
} from '@strapi/icons';
|
||||
import { pxToRem } from '@strapi/helper-plugin';
|
||||
|
||||
const iconByTypes = {
|
||||
biginteger: Numbers,
|
||||
boolean: Boolean,
|
||||
component: Component,
|
||||
contentType: CT,
|
||||
date: Date,
|
||||
datetime: Date,
|
||||
decimal: Numbers,
|
||||
dynamiczone: DynamicZone,
|
||||
email: Email,
|
||||
enum: Enumeration,
|
||||
enumeration: Enumeration,
|
||||
file: Media,
|
||||
files: Media,
|
||||
float: Numbers,
|
||||
integer: Numbers,
|
||||
json: Json,
|
||||
JSON: Json,
|
||||
media: Media,
|
||||
number: Numbers,
|
||||
password: Password,
|
||||
relation: Relation,
|
||||
richtext: LongDescription,
|
||||
singleType: St,
|
||||
string: Text,
|
||||
text: Text,
|
||||
time: Date,
|
||||
timestamp: Date,
|
||||
uid: Uid,
|
||||
};
|
||||
|
||||
const IconBox = styled(Box)`
|
||||
width: ${pxToRem(32)};
|
||||
height: ${pxToRem(24)};
|
||||
box-sizing: content-box;
|
||||
`;
|
||||
|
||||
const AttributeIcon = ({ type, ...rest }) => {
|
||||
const Compo = iconByTypes[type];
|
||||
|
||||
if (!iconByTypes[type]) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return <IconBox as={Compo} {...rest} />;
|
||||
};
|
||||
|
||||
AttributeIcon.propTypes = {
|
||||
type: PropTypes.string.isRequired,
|
||||
};
|
||||
|
||||
export default AttributeIcon;
|
||||
@ -6,6 +6,7 @@
|
||||
/* eslint-disable import/no-cycle */
|
||||
import React from 'react';
|
||||
import { get } from 'lodash';
|
||||
import { Box } from '@strapi/parts';
|
||||
import PropTypes from 'prop-types';
|
||||
import List from '../List';
|
||||
import useDataManager from '../../hooks/useDataManager';
|
||||
@ -28,6 +29,19 @@ function ComponentList({
|
||||
schema: { attributes: [] },
|
||||
});
|
||||
|
||||
// ! TEMPORARY DISABLE NESTED COMPONENT
|
||||
const bool = true; // prevent eslint from crying
|
||||
|
||||
if (bool) {
|
||||
return (
|
||||
<tr>
|
||||
<td colSpan={12} style={{ padding: 10 }}>
|
||||
<Box background="neutral100" style={{ height: 40 }} />
|
||||
</td>
|
||||
</tr>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<tr className="component-row">
|
||||
<Td colSpan={12} isChildOfDynamicZone={isFromDynamicZone}>
|
||||
|
||||
@ -0,0 +1,50 @@
|
||||
/**
|
||||
*
|
||||
* Wrapper
|
||||
*
|
||||
*/
|
||||
import { Box } from '@strapi/parts';
|
||||
import styled from 'styled-components';
|
||||
|
||||
const BoxWrapper = styled(Box)`
|
||||
overflow-x: auto;
|
||||
|
||||
table {
|
||||
width: 100%;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
thead {
|
||||
border-bottom: 1px solid ${({ theme }) => theme.colors.neutral150};
|
||||
}
|
||||
|
||||
tr:not(:last-child) {
|
||||
border-bottom: 1px solid ${({ theme }) => theme.colors.neutral150};
|
||||
}
|
||||
|
||||
tr {
|
||||
& td,
|
||||
& th {
|
||||
padding: ${({ theme }) => theme.spaces[4]};
|
||||
}
|
||||
|
||||
& td:first-of-type,
|
||||
& th:first-of-type {
|
||||
padding: 0 ${({ theme }) => theme.spaces[1]};
|
||||
}
|
||||
}
|
||||
|
||||
th,
|
||||
td {
|
||||
vertical-align: middle;
|
||||
text-align: left;
|
||||
color: ${({ theme }) => theme.colors.neutral600};
|
||||
outline-offset: -4px;
|
||||
}
|
||||
`;
|
||||
|
||||
BoxWrapper.defaultProps = {
|
||||
isFromDynamicZone: false,
|
||||
};
|
||||
|
||||
export default BoxWrapper;
|
||||
@ -1,131 +0,0 @@
|
||||
/**
|
||||
*
|
||||
* Wrapper
|
||||
*
|
||||
*/
|
||||
|
||||
import styled from 'styled-components';
|
||||
import { List } from '@buffetjs/styles';
|
||||
|
||||
const Wrapper = styled(List)`
|
||||
table-layout: fixed;
|
||||
|
||||
tbody {
|
||||
td:first-of-type:not(:last-of-type) {
|
||||
width: 73px;
|
||||
padding-left: 30px;
|
||||
> svg {
|
||||
width: auto;
|
||||
height: 16px;
|
||||
position: absolute;
|
||||
left: -4px;
|
||||
top: 16px;
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
td[colspan='12'] {
|
||||
position: relative;
|
||||
padding: 0 0 0 50px;
|
||||
> div {
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
tr.component-row {
|
||||
&:not(:first-of-type) {
|
||||
&::before {
|
||||
background-color: transparent;
|
||||
}
|
||||
}
|
||||
table tr td:first-of-type:not(:last-of-type) {
|
||||
width: 79px;
|
||||
padding-left: 36px;
|
||||
svg {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
table + div button {
|
||||
position: relative;
|
||||
background-color: transparent;
|
||||
text-transform: initial;
|
||||
color: #9ea7b8;
|
||||
text-align: left;
|
||||
padding-left: 35px;
|
||||
border-color: transparent;
|
||||
svg {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
}
|
||||
tr.dynamiczone-row {
|
||||
&:not(:first-of-type) {
|
||||
&::before {
|
||||
background-color: transparent;
|
||||
}
|
||||
}
|
||||
> td[colspan='12'] {
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
}
|
||||
|
||||
.tabs-wrapper {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 2;
|
||||
padding-top: 18px;
|
||||
padding-left: 86px;
|
||||
padding-right: 30px;
|
||||
.nav-tabs {
|
||||
border-bottom: 0;
|
||||
}
|
||||
ul.nav {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
overflow-x: auto;
|
||||
overflow-y: hidden;
|
||||
li {
|
||||
margin-right: 9px;
|
||||
}
|
||||
}
|
||||
& + .tab-content {
|
||||
padding-top: 126px;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
& + .plus-icon {
|
||||
width: 27px;
|
||||
height: 27px;
|
||||
border-radius: 18px;
|
||||
position: absolute;
|
||||
bottom: 14px;
|
||||
left: 34px;
|
||||
background-color: ${({ isFromDynamicZone }) => (isFromDynamicZone ? '#AED4FB' : '#f3f4f4')};
|
||||
|
||||
color: transparent;
|
||||
text-align: center;
|
||||
line-height: 27px;
|
||||
display: flex;
|
||||
cursor: pointer;
|
||||
svg {
|
||||
margin: auto;
|
||||
width: 11px;
|
||||
height: 11px;
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
Wrapper.defaultProps = {
|
||||
isFromDynamicZone: false,
|
||||
};
|
||||
|
||||
export default Wrapper;
|
||||
@ -8,22 +8,21 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { get } from 'lodash';
|
||||
import { ListButton, useTracking } from '@strapi/helper-plugin';
|
||||
import { Button } from '@buffetjs/core';
|
||||
import { Plus } from '@buffetjs/icons';
|
||||
import { useTracking } from '@strapi/helper-plugin';
|
||||
import { TableLabel, TFooter, Box, TextButton } from '@strapi/parts';
|
||||
import { AddIcon } from '@strapi/icons';
|
||||
import { useIntl } from 'react-intl';
|
||||
import pluginId from '../../pluginId';
|
||||
import useListView from '../../hooks/useListView';
|
||||
import useDataManager from '../../hooks/useDataManager';
|
||||
import DynamicZoneList from '../DynamicZoneList';
|
||||
import ComponentList from '../ComponentList';
|
||||
import Wrapper from './List';
|
||||
import BoxWrapper from './BoxWrapper';
|
||||
import getTrad from '../../utils/getTrad';
|
||||
|
||||
/* eslint-disable jsx-a11y/click-events-have-key-events */
|
||||
/* eslint-disable jsx-a11y/no-static-element-interactions */
|
||||
|
||||
function List({
|
||||
className,
|
||||
customRowComponent,
|
||||
items,
|
||||
addComponentToDZ,
|
||||
@ -160,106 +159,114 @@ function List({
|
||||
);
|
||||
};
|
||||
|
||||
/* eslint-disable indent */
|
||||
const addButtonProps = {
|
||||
icon: !isSub ? <Plus fill="#007eff" width="11px" height="11px" /> : false,
|
||||
color: 'primary',
|
||||
label: isInDevelopmentMode
|
||||
? formatMessage({
|
||||
id: !isSub
|
||||
? `${pluginId}.form.button.add.field.to.${
|
||||
modifiedData.contentType
|
||||
? modifiedData.contentType.schema.kind
|
||||
: editTarget || 'collectionType'
|
||||
}`
|
||||
: `${pluginId}.form.button.add.field.to.component`,
|
||||
defaultMessage: 'Add another field',
|
||||
})
|
||||
: null,
|
||||
onClick: onClickAddField,
|
||||
};
|
||||
/* eslint-enable indent */
|
||||
|
||||
if (!targetUid) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Wrapper className={className} isFromDynamicZone={isFromDynamicZone}>
|
||||
<table>
|
||||
<tbody>
|
||||
{items.map(item => {
|
||||
const { type } = item;
|
||||
const CustomRow = customRowComponent;
|
||||
<BoxWrapper
|
||||
isFromDynamicZone={isFromDynamicZone}
|
||||
background="neutral0"
|
||||
shadow="filterShadow"
|
||||
hasRadius
|
||||
>
|
||||
<Box paddingLeft={6} paddingRight={6}>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>
|
||||
<TableLabel textColor="neutral600">
|
||||
{formatMessage({ id: 'table.headers.name', defaultMessage: 'Name' })}
|
||||
</TableLabel>
|
||||
</th>
|
||||
<th colSpan="2">
|
||||
<TableLabel textColor="neutral600">
|
||||
{formatMessage({ id: 'table.headers.type', defaultMessage: 'Type' })}
|
||||
</TableLabel>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{items.map(item => {
|
||||
const { type } = item;
|
||||
const CustomRow = customRowComponent;
|
||||
|
||||
return (
|
||||
<React.Fragment key={item.name}>
|
||||
<CustomRow
|
||||
{...item}
|
||||
dzName={dzName}
|
||||
isNestedInDZComponent={isNestedInDZComponent}
|
||||
targetUid={targetUid}
|
||||
mainTypeName={mainTypeName}
|
||||
editTarget={editTarget}
|
||||
firstLoopComponentName={firstLoopComponentName}
|
||||
firstLoopComponentUid={firstLoopComponentUid}
|
||||
isFromDynamicZone={isFromDynamicZone}
|
||||
secondLoopComponentName={secondLoopComponentName}
|
||||
secondLoopComponentUid={secondLoopComponentUid}
|
||||
/>
|
||||
|
||||
{type === 'component' && (
|
||||
<ComponentList
|
||||
return (
|
||||
<React.Fragment key={item.name}>
|
||||
<CustomRow
|
||||
{...item}
|
||||
customRowComponent={customRowComponent}
|
||||
targetUid={targetUid}
|
||||
dzName={dzName}
|
||||
isNestedInDZComponent={isFromDynamicZone}
|
||||
isNestedInDZComponent={isNestedInDZComponent}
|
||||
targetUid={targetUid}
|
||||
mainTypeName={mainTypeName}
|
||||
editTarget={editTarget}
|
||||
firstLoopComponentName={firstLoopComponentName}
|
||||
firstLoopComponentUid={firstLoopComponentUid}
|
||||
isFromDynamicZone={isFromDynamicZone}
|
||||
secondLoopComponentName={secondLoopComponentName}
|
||||
secondLoopComponentUid={secondLoopComponentUid}
|
||||
/>
|
||||
)}
|
||||
|
||||
{type === 'dynamiczone' && (
|
||||
<DynamicZoneList
|
||||
{...item}
|
||||
customRowComponent={customRowComponent}
|
||||
addComponent={addComponentToDZ}
|
||||
targetUid={targetUid}
|
||||
mainTypeName={mainTypeName}
|
||||
/>
|
||||
)}
|
||||
</React.Fragment>
|
||||
);
|
||||
})}
|
||||
</tbody>
|
||||
</table>
|
||||
{type === 'component' && (
|
||||
<ComponentList
|
||||
{...item}
|
||||
customRowComponent={customRowComponent}
|
||||
targetUid={targetUid}
|
||||
dzName={dzName}
|
||||
isNestedInDZComponent={isFromDynamicZone}
|
||||
mainTypeName={mainTypeName}
|
||||
editTarget={editTarget}
|
||||
firstLoopComponentName={firstLoopComponentName}
|
||||
firstLoopComponentUid={firstLoopComponentUid}
|
||||
/>
|
||||
)}
|
||||
|
||||
{type === 'dynamiczone' && (
|
||||
<DynamicZoneList
|
||||
{...item}
|
||||
customRowComponent={customRowComponent}
|
||||
addComponent={addComponentToDZ}
|
||||
targetUid={targetUid}
|
||||
mainTypeName={mainTypeName}
|
||||
/>
|
||||
)}
|
||||
</React.Fragment>
|
||||
);
|
||||
})}
|
||||
</tbody>
|
||||
</table>
|
||||
</Box>
|
||||
|
||||
{isMain && isInDevelopmentMode && (
|
||||
<ListButton>
|
||||
<Button {...addButtonProps} />
|
||||
</ListButton>
|
||||
<TFooter icon={<AddIcon />} onClick={onClickAddField}>
|
||||
{formatMessage({
|
||||
id: getTrad(
|
||||
`form.button.add.field.to.${
|
||||
modifiedData.contentType
|
||||
? modifiedData.contentType.schema.kind
|
||||
: editTarget || 'collectionType'
|
||||
}`
|
||||
),
|
||||
defaultMessage: 'Add another field',
|
||||
})}
|
||||
</TFooter>
|
||||
)}
|
||||
{!isMain && (
|
||||
<ListButton>
|
||||
<Button {...addButtonProps} />
|
||||
</ListButton>
|
||||
{isSub && isInDevelopmentMode && (
|
||||
<TextButton startIcon={<AddIcon />} onClick={onClickAddField}>
|
||||
{formatMessage({
|
||||
id: getTrad(`form.button.add.field.to.component`),
|
||||
defaultMessage: 'Add another field',
|
||||
})}
|
||||
</TextButton>
|
||||
)}
|
||||
</Wrapper>
|
||||
{isSub && (
|
||||
<div className="plus-icon" onClick={onClickAddField}>
|
||||
{isInDevelopmentMode && <Plus fill={isFromDynamicZone ? '#007EFF' : '#b4b6ba'} />}
|
||||
</div>
|
||||
)}
|
||||
</BoxWrapper>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
List.defaultProps = {
|
||||
addComponentToDZ: () => {},
|
||||
className: null,
|
||||
customRowComponent: null,
|
||||
dzName: null,
|
||||
firstLoopComponentName: null,
|
||||
@ -276,7 +283,6 @@ List.defaultProps = {
|
||||
|
||||
List.propTypes = {
|
||||
addComponentToDZ: PropTypes.func,
|
||||
className: PropTypes.string,
|
||||
customRowComponent: PropTypes.func,
|
||||
dzName: PropTypes.string,
|
||||
editTarget: PropTypes.string.isRequired,
|
||||
|
||||
@ -1,9 +0,0 @@
|
||||
import styled from 'styled-components';
|
||||
import { Button } from '@buffetjs/core';
|
||||
|
||||
const ListHeaderButton = styled(Button)`
|
||||
padding-left: 15px;
|
||||
padding-right: 15px;
|
||||
`;
|
||||
|
||||
export default ListHeaderButton;
|
||||
@ -0,0 +1,12 @@
|
||||
/**
|
||||
*
|
||||
* Wrapper
|
||||
*
|
||||
*/
|
||||
|
||||
import styled from 'styled-components';
|
||||
import { Box } from '@strapi/parts';
|
||||
|
||||
const BoxWrapper = styled(Box)``;
|
||||
|
||||
export default BoxWrapper;
|
||||
@ -1,76 +0,0 @@
|
||||
/**
|
||||
*
|
||||
* Wrapper
|
||||
*
|
||||
*/
|
||||
|
||||
import styled from 'styled-components';
|
||||
import { colors } from '@strapi/helper-plugin';
|
||||
|
||||
/* eslint-disable indent */
|
||||
|
||||
const Wrapper = styled.tr`
|
||||
background-color: transparent;
|
||||
p {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
img {
|
||||
width: 35px;
|
||||
}
|
||||
button {
|
||||
cursor: pointer;
|
||||
}
|
||||
td:first-of-type {
|
||||
padding-left: 3rem;
|
||||
position: relative;
|
||||
img {
|
||||
width: 35px;
|
||||
height: 20px;
|
||||
position: absolute;
|
||||
top: calc(50% - 10px);
|
||||
left: 3rem;
|
||||
}
|
||||
img + p {
|
||||
width: 237px;
|
||||
padding-left: calc(3rem + 35px);
|
||||
}
|
||||
}
|
||||
td:nth-child(2) {
|
||||
${({ loopNumber }) => {
|
||||
return `
|
||||
width: calc(25rem - ${5 * loopNumber}rem);
|
||||
`;
|
||||
}}
|
||||
p {
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
td:last-child {
|
||||
text-align: right;
|
||||
&:not(:first-of-type) {
|
||||
font-size: 10px;
|
||||
}
|
||||
}
|
||||
&.relation-row {
|
||||
background: linear-gradient(135deg, rgba(28, 93, 231, 0.05), rgba(239, 243, 253, 0));
|
||||
}
|
||||
&.clickable {
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
background-color: ${colors.grey};
|
||||
& + tr {
|
||||
&::before {
|
||||
background-color: transparent;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.button-container {
|
||||
svg {
|
||||
color: #333740;
|
||||
vertical-align: middle;
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export default Wrapper;
|
||||
@ -1,16 +1,18 @@
|
||||
import React, { memo } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { get } from 'lodash';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
import { AttributeIcon, IconLinks } from '@buffetjs/core';
|
||||
import upperFirst from 'lodash/upperFirst';
|
||||
import { useIntl } from 'react-intl';
|
||||
import { IconButton, Stack, Text, Row } from '@strapi/parts';
|
||||
import { EditIcon, DeleteIcon } from '@strapi/icons';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import pluginId from '../../pluginId';
|
||||
import useDataManager from '../../hooks/useDataManager';
|
||||
import getAttributeDisplayedType from '../../utils/getAttributeDisplayedType';
|
||||
import getTrad from '../../utils/getTrad';
|
||||
import Curve from '../../icons/Curve';
|
||||
// import Curve from '../../icons/Curve';
|
||||
import UpperFist from '../UpperFirst';
|
||||
import Wrapper from './Wrapper';
|
||||
import BoxWrapper from './BoxWrapper';
|
||||
import AttributeIcon from '../AttributeIcon';
|
||||
|
||||
function ListRow({
|
||||
configurable,
|
||||
@ -33,6 +35,7 @@ function ListRow({
|
||||
relation,
|
||||
}) {
|
||||
const { contentTypes, isInDevelopmentMode, modifiedData, removeAttribute } = useDataManager();
|
||||
const { formatMessage } = useIntl();
|
||||
|
||||
const isMorph = type === 'relation' && relation.includes('morph');
|
||||
const ico = ['integer', 'biginteger', 'float', 'decimal'].includes(type) ? 'number' : type;
|
||||
@ -198,97 +201,90 @@ function ListRow({
|
||||
}
|
||||
|
||||
return (
|
||||
<Wrapper
|
||||
<BoxWrapper
|
||||
as="tr"
|
||||
onClick={handleClick}
|
||||
className={[target ? 'relation-row' : '', configurable ? 'clickable' : '']}
|
||||
// PaddingLeft handled here in nested component
|
||||
loopNumber={loopNumber}
|
||||
>
|
||||
<td>
|
||||
<AttributeIcon key={src} type={src} />
|
||||
<Curve fill={isFromDynamicZone ? '#AED4FB' : '#f3f4f4'} />
|
||||
</td>
|
||||
<td style={{ fontWeight: 600 }}>
|
||||
<p>{name}</p>
|
||||
<Stack paddingLeft={2} size={4} horizontal>
|
||||
<AttributeIcon key={src} type={src} />
|
||||
<Text bold>{upperFirst(name)}</Text>
|
||||
{/* <Curve fill={isFromDynamicZone ? '#AED4FB' : '#f3f4f4'} /> */}
|
||||
</Stack>
|
||||
</td>
|
||||
<td>
|
||||
{target ? (
|
||||
<div>
|
||||
<FormattedMessage
|
||||
id={`${pluginId}.modelPage.attribute.${
|
||||
isMorph ? 'relation-polymorphic' : 'relationWith'
|
||||
}`}
|
||||
/>
|
||||
<Text>
|
||||
{formatMessage({
|
||||
id: getTrad(
|
||||
`modelPage.attribute.${isMorph ? 'relation-polymorphic' : 'relationWith'}`
|
||||
),
|
||||
defaultMessage: 'Relation with',
|
||||
})}
|
||||
|
||||
<FormattedMessage id={`${pluginId}.from`}>
|
||||
{msg => (
|
||||
<span style={{ fontStyle: 'italic' }}>
|
||||
<UpperFist content={contentTypeFriendlyName} />
|
||||
|
||||
{plugin && `(${msg}: ${plugin})`}
|
||||
</span>
|
||||
)}
|
||||
</FormattedMessage>
|
||||
</div>
|
||||
<span style={{ fontStyle: 'italic' }}>
|
||||
<UpperFist content={contentTypeFriendlyName} />
|
||||
|
||||
{plugin &&
|
||||
`(${formatMessage({
|
||||
id: getTrad(`from`),
|
||||
defaultMessage: 'from',
|
||||
})}: ${plugin})`}
|
||||
</span>
|
||||
</Text>
|
||||
) : (
|
||||
<>
|
||||
<FormattedMessage id={`${pluginId}.attribute.${readableType}`} defaultMessage={type} />
|
||||
<Text>
|
||||
{formatMessage({
|
||||
id: getTrad(`attribute.${readableType}`),
|
||||
defaultMessage: type,
|
||||
})}
|
||||
|
||||
{repeatable && <FormattedMessage id={getTrad('component.repeatable')} />}
|
||||
</>
|
||||
{repeatable &&
|
||||
formatMessage({
|
||||
id: getTrad('component.repeatable'),
|
||||
defaultMessage: '(repeatable)',
|
||||
})}
|
||||
</Text>
|
||||
)}
|
||||
</td>
|
||||
<td className="button-container">
|
||||
<td>
|
||||
{isInDevelopmentMode && (
|
||||
<>
|
||||
<Row justifyContent="flex-end">
|
||||
{configurable ? (
|
||||
<>
|
||||
{!isMorph ? (
|
||||
<IconLinks
|
||||
links={[
|
||||
{
|
||||
icon: <FontAwesomeIcon icon="pencil-alt" />,
|
||||
onClick: () => handleClick(),
|
||||
},
|
||||
{
|
||||
icon: <FontAwesomeIcon icon="trash-alt" />,
|
||||
onClick: e => {
|
||||
e.stopPropagation();
|
||||
removeAttribute(
|
||||
editTarget,
|
||||
name,
|
||||
secondLoopComponentUid || firstLoopComponentUid || ''
|
||||
);
|
||||
},
|
||||
},
|
||||
]}
|
||||
/>
|
||||
) : (
|
||||
<IconLinks
|
||||
links={[
|
||||
{
|
||||
icon: <FontAwesomeIcon icon="trash-alt" />,
|
||||
onClick: e => {
|
||||
e.stopPropagation();
|
||||
removeAttribute(
|
||||
editTarget,
|
||||
name,
|
||||
secondLoopComponentUid || firstLoopComponentUid || ''
|
||||
);
|
||||
},
|
||||
},
|
||||
]}
|
||||
<Stack horizontal size={1}>
|
||||
{!isMorph && (
|
||||
<IconButton
|
||||
onClick={handleClick}
|
||||
label={formatMessage({ id: 'app.utils.edit', formatMessage: 'Edit' })}
|
||||
noBorder
|
||||
icon={<EditIcon />}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
<IconButton
|
||||
onClick={e => {
|
||||
e.stopPropagation();
|
||||
removeAttribute(
|
||||
editTarget,
|
||||
name,
|
||||
secondLoopComponentUid || firstLoopComponentUid || ''
|
||||
);
|
||||
}}
|
||||
label={formatMessage({ id: 'app.utils.delete', defaultMessage: 'Delete' })}
|
||||
noBorder
|
||||
icon={<DeleteIcon />}
|
||||
/>
|
||||
</Stack>
|
||||
) : (
|
||||
<button type="button">
|
||||
<FontAwesomeIcon icon="lock" />
|
||||
</button>
|
||||
// ! TODO ASK DESIGN TO PUT LOCK ICON INSIDE DS
|
||||
<FontAwesomeIcon icon="lock" />
|
||||
)}
|
||||
</>
|
||||
</Row>
|
||||
)}
|
||||
</td>
|
||||
</Wrapper>
|
||||
</BoxWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -1,16 +1,14 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { useTracking } from '@strapi/helper-plugin';
|
||||
import { AddIcon, BackIcon, CheckIcon, EditIcon } from '@strapi/icons';
|
||||
import { Box, Button, ContentLayout, HeaderLayout, Link, Row, Stack } from '@strapi/parts';
|
||||
import { Button, ContentLayout, HeaderLayout, Link, Row, Stack } from '@strapi/parts';
|
||||
import { get, has, isEqual, upperFirst } from 'lodash';
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { useIntl } from 'react-intl';
|
||||
import { Prompt, useHistory, useLocation } from 'react-router-dom';
|
||||
import List from '../../components/List';
|
||||
import ListRow from '../../components/ListRow';
|
||||
import ListViewContext from '../../contexts/ListViewContext';
|
||||
import useDataManager from '../../hooks/useDataManager';
|
||||
import pluginId from '../../pluginId';
|
||||
import getAttributeDisplayedType from '../../utils/getAttributeDisplayedType';
|
||||
import getTrad from '../../utils/getTrad';
|
||||
import makeSearch from '../../utils/makeSearch';
|
||||
@ -152,7 +150,7 @@ const ListView = () => {
|
||||
return (
|
||||
description ||
|
||||
formatMessage({
|
||||
id: `${pluginId}.modelPage.contentHeader.emptyDescription.description`,
|
||||
id: getTrad('modelPage.contentHeader.emptyDescription.description'),
|
||||
})
|
||||
);
|
||||
};
|
||||
@ -202,20 +200,6 @@ const ListView = () => {
|
||||
});
|
||||
};
|
||||
|
||||
const CustomRow = props => {
|
||||
const { name } = props;
|
||||
|
||||
return <ListRow {...props} attributeName={name} name={name} onClick={handleClickEditField} />;
|
||||
};
|
||||
|
||||
CustomRow.defaultProps = {
|
||||
name: null,
|
||||
};
|
||||
|
||||
CustomRow.propTypes = {
|
||||
name: PropTypes.string,
|
||||
};
|
||||
|
||||
return (
|
||||
<ListViewContext.Provider value={{ openModalAddField: handleClickAddField }}>
|
||||
<>
|
||||
@ -298,23 +282,21 @@ const ListView = () => {
|
||||
handleClickAddField(forTarget, targetUid, headerDisplayObject);
|
||||
}}
|
||||
>
|
||||
{formatMessage({ id: `${pluginId}.button.attributes.add.another` })}
|
||||
{formatMessage({ id: getTrad('button.attributes.add.another') })}
|
||||
</Button>
|
||||
</Stack>
|
||||
</Row>
|
||||
<Box background="neutral0" padding={6} shadow="filterShadow" hasRadius>
|
||||
<List
|
||||
items={attributes}
|
||||
customRowComponent={props => <CustomRow {...props} />}
|
||||
addComponentToDZ={handleClickAddComponentToDZ}
|
||||
targetUid={targetUid}
|
||||
dataType={forTarget}
|
||||
dataTypeName={currentDataName}
|
||||
mainTypeName={currentDataName}
|
||||
editTarget={forTarget}
|
||||
isMain
|
||||
/>
|
||||
</Box>
|
||||
<List
|
||||
items={attributes}
|
||||
customRowComponent={props => <ListRow {...props} onClick={handleClickEditField} />}
|
||||
addComponentToDZ={handleClickAddComponentToDZ}
|
||||
targetUid={targetUid}
|
||||
dataType={forTarget}
|
||||
dataTypeName={currentDataName}
|
||||
mainTypeName={currentDataName}
|
||||
editTarget={forTarget}
|
||||
isMain
|
||||
/>
|
||||
</Stack>
|
||||
</ContentLayout>
|
||||
</>
|
||||
|
||||
@ -182,5 +182,7 @@
|
||||
"relation.oneToOne": "has and belongs to one",
|
||||
"relation.oneWay": "has one",
|
||||
"table.attributes.title.plural": "{number} fields",
|
||||
"table.attributes.title.singular": "{number} field"
|
||||
"table.attributes.title.singular": "{number} field",
|
||||
"table.headers.name": "Name",
|
||||
"table.headers.type": "Type"
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user