mirror of
https://github.com/strapi/strapi.git
synced 2025-09-11 01:26:42 +00:00
WIP Desgin rows
This commit is contained in:
parent
fab2a6f46b
commit
fbd22b8c33
@ -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,
|
||||||
|
Bool,
|
||||||
|
DynamicZone,
|
||||||
|
Email,
|
||||||
|
Enumeration,
|
||||||
|
Json,
|
||||||
|
LongDescription,
|
||||||
|
Media,
|
||||||
|
Numbers,
|
||||||
|
Password,
|
||||||
|
Relation,
|
||||||
|
St,
|
||||||
|
Text,
|
||||||
|
Uid,
|
||||||
|
} from '@strapi/icons';
|
||||||
|
import { pxToRem } from '@strapi/helper-plugin';
|
||||||
|
|
||||||
|
const types = {
|
||||||
|
biginteger: Numbers,
|
||||||
|
boolean: Bool,
|
||||||
|
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 StyledCompo = styled(Box)`
|
||||||
|
width: ${pxToRem(32)};
|
||||||
|
height: ${pxToRem(24)};
|
||||||
|
box-sizing: content-box;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const AttributeIcon = ({ type, ...rest }) => {
|
||||||
|
const Compo = types[type];
|
||||||
|
|
||||||
|
if (!types[type]) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return <StyledCompo as={Compo} {...rest} />;
|
||||||
|
};
|
||||||
|
|
||||||
|
AttributeIcon.propTypes = {
|
||||||
|
type: PropTypes.string.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default AttributeIcon;
|
@ -0,0 +1,48 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
* 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 {
|
||||||
|
border-bottom: 1px solid ${({ theme }) => theme.colors.neutral150};
|
||||||
|
|
||||||
|
& 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;
|
|
@ -9,6 +9,7 @@ import React from 'react';
|
|||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { get } from 'lodash';
|
import { get } from 'lodash';
|
||||||
import { ListButton, useTracking } from '@strapi/helper-plugin';
|
import { ListButton, useTracking } from '@strapi/helper-plugin';
|
||||||
|
import { TableLabel } from '@strapi/parts';
|
||||||
import { Button } from '@buffetjs/core';
|
import { Button } from '@buffetjs/core';
|
||||||
import { Plus } from '@buffetjs/icons';
|
import { Plus } from '@buffetjs/icons';
|
||||||
import { useIntl } from 'react-intl';
|
import { useIntl } from 'react-intl';
|
||||||
@ -17,13 +18,12 @@ import useListView from '../../hooks/useListView';
|
|||||||
import useDataManager from '../../hooks/useDataManager';
|
import useDataManager from '../../hooks/useDataManager';
|
||||||
import DynamicZoneList from '../DynamicZoneList';
|
import DynamicZoneList from '../DynamicZoneList';
|
||||||
import ComponentList from '../ComponentList';
|
import ComponentList from '../ComponentList';
|
||||||
import Wrapper from './List';
|
import BoxWrapper from './BoxWrapper';
|
||||||
|
|
||||||
/* eslint-disable jsx-a11y/click-events-have-key-events */
|
/* eslint-disable jsx-a11y/click-events-have-key-events */
|
||||||
/* eslint-disable jsx-a11y/no-static-element-interactions */
|
/* eslint-disable jsx-a11y/no-static-element-interactions */
|
||||||
|
|
||||||
function List({
|
function List({
|
||||||
className,
|
|
||||||
customRowComponent,
|
customRowComponent,
|
||||||
items,
|
items,
|
||||||
addComponentToDZ,
|
addComponentToDZ,
|
||||||
@ -186,8 +186,25 @@ function List({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Wrapper className={className} isFromDynamicZone={isFromDynamicZone}>
|
<BoxWrapper
|
||||||
|
isFromDynamicZone={isFromDynamicZone}
|
||||||
|
background="neutral0"
|
||||||
|
shadow="filterShadow"
|
||||||
|
hasRadius
|
||||||
|
paddingLeft={6}
|
||||||
|
paddingRight={6}
|
||||||
|
>
|
||||||
<table>
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th colSpan="2">
|
||||||
|
<TableLabel textColor="neutral600">Name</TableLabel>
|
||||||
|
</th>
|
||||||
|
<th colSpan="2">
|
||||||
|
<TableLabel textColor="neutral600">Type</TableLabel>
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{items.map(item => {
|
{items.map(item => {
|
||||||
const { type } = item;
|
const { type } = item;
|
||||||
@ -247,7 +264,7 @@ function List({
|
|||||||
<Button {...addButtonProps} />
|
<Button {...addButtonProps} />
|
||||||
</ListButton>
|
</ListButton>
|
||||||
)}
|
)}
|
||||||
</Wrapper>
|
</BoxWrapper>
|
||||||
{isSub && (
|
{isSub && (
|
||||||
<div className="plus-icon" onClick={onClickAddField}>
|
<div className="plus-icon" onClick={onClickAddField}>
|
||||||
{isInDevelopmentMode && <Plus fill={isFromDynamicZone ? '#007EFF' : '#b4b6ba'} />}
|
{isInDevelopmentMode && <Plus fill={isFromDynamicZone ? '#007EFF' : '#b4b6ba'} />}
|
||||||
@ -259,7 +276,6 @@ function List({
|
|||||||
|
|
||||||
List.defaultProps = {
|
List.defaultProps = {
|
||||||
addComponentToDZ: () => {},
|
addComponentToDZ: () => {},
|
||||||
className: null,
|
|
||||||
customRowComponent: null,
|
customRowComponent: null,
|
||||||
dzName: null,
|
dzName: null,
|
||||||
firstLoopComponentName: null,
|
firstLoopComponentName: null,
|
||||||
@ -276,7 +292,6 @@ List.defaultProps = {
|
|||||||
|
|
||||||
List.propTypes = {
|
List.propTypes = {
|
||||||
addComponentToDZ: PropTypes.func,
|
addComponentToDZ: PropTypes.func,
|
||||||
className: PropTypes.string,
|
|
||||||
customRowComponent: PropTypes.func,
|
customRowComponent: PropTypes.func,
|
||||||
dzName: PropTypes.string,
|
dzName: PropTypes.string,
|
||||||
editTarget: PropTypes.string.isRequired,
|
editTarget: PropTypes.string.isRequired,
|
||||||
|
@ -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;
|
|
@ -2,15 +2,16 @@ import React, { memo } from 'react';
|
|||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { get } from 'lodash';
|
import { get } from 'lodash';
|
||||||
import { FormattedMessage } from 'react-intl';
|
import { FormattedMessage } from 'react-intl';
|
||||||
import { AttributeIcon, IconLinks } from '@buffetjs/core';
|
import { IconLinks } from '@buffetjs/core';
|
||||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||||
import pluginId from '../../pluginId';
|
import pluginId from '../../pluginId';
|
||||||
import useDataManager from '../../hooks/useDataManager';
|
import useDataManager from '../../hooks/useDataManager';
|
||||||
import getAttributeDisplayedType from '../../utils/getAttributeDisplayedType';
|
import getAttributeDisplayedType from '../../utils/getAttributeDisplayedType';
|
||||||
import getTrad from '../../utils/getTrad';
|
import getTrad from '../../utils/getTrad';
|
||||||
import Curve from '../../icons/Curve';
|
// import Curve from '../../icons/Curve';
|
||||||
import UpperFist from '../UpperFirst';
|
import UpperFist from '../UpperFirst';
|
||||||
import Wrapper from './Wrapper';
|
import BoxWrapper from './BoxWrapper';
|
||||||
|
import AttributeIcon from '../AttributeIcon';
|
||||||
|
|
||||||
function ListRow({
|
function ListRow({
|
||||||
configurable,
|
configurable,
|
||||||
@ -198,14 +199,15 @@ function ListRow({
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Wrapper
|
<BoxWrapper
|
||||||
|
as="tr"
|
||||||
onClick={handleClick}
|
onClick={handleClick}
|
||||||
className={[target ? 'relation-row' : '', configurable ? 'clickable' : '']}
|
className={[target ? 'relation-row' : '', configurable ? 'clickable' : '']}
|
||||||
loopNumber={loopNumber}
|
loopNumber={loopNumber}
|
||||||
>
|
>
|
||||||
<td>
|
<td>
|
||||||
<AttributeIcon key={src} type={src} />
|
<AttributeIcon paddingLeft={2} key={src} type={src} />
|
||||||
<Curve fill={isFromDynamicZone ? '#AED4FB' : '#f3f4f4'} />
|
{/* <Curve fill={isFromDynamicZone ? '#AED4FB' : '#f3f4f4'} /> */}
|
||||||
</td>
|
</td>
|
||||||
<td style={{ fontWeight: 600 }}>
|
<td style={{ fontWeight: 600 }}>
|
||||||
<p>{name}</p>
|
<p>{name}</p>
|
||||||
@ -288,7 +290,7 @@ function ListRow({
|
|||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</td>
|
</td>
|
||||||
</Wrapper>
|
</BoxWrapper>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
import React, { useEffect, useState } from 'react';
|
|
||||||
import { useTracking } from '@strapi/helper-plugin';
|
import { useTracking } from '@strapi/helper-plugin';
|
||||||
import { AddIcon, BackIcon, CheckIcon, EditIcon } from '@strapi/icons';
|
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 { get, has, isEqual, upperFirst } from 'lodash';
|
||||||
import PropTypes from 'prop-types';
|
import React, { useEffect, useState } from 'react';
|
||||||
import { useIntl } from 'react-intl';
|
import { useIntl } from 'react-intl';
|
||||||
import { Prompt, useHistory, useLocation } from 'react-router-dom';
|
import { Prompt, useHistory, useLocation } from 'react-router-dom';
|
||||||
import List from '../../components/List';
|
import List from '../../components/List';
|
||||||
@ -202,20 +201,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 (
|
return (
|
||||||
<ListViewContext.Provider value={{ openModalAddField: handleClickAddField }}>
|
<ListViewContext.Provider value={{ openModalAddField: handleClickAddField }}>
|
||||||
<>
|
<>
|
||||||
@ -302,19 +287,17 @@ const ListView = () => {
|
|||||||
</Button>
|
</Button>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Row>
|
</Row>
|
||||||
<Box background="neutral0" padding={6} shadow="filterShadow" hasRadius>
|
<List
|
||||||
<List
|
items={attributes}
|
||||||
items={attributes}
|
customRowComponent={props => <ListRow {...props} onClick={handleClickEditField} />}
|
||||||
customRowComponent={props => <CustomRow {...props} />}
|
addComponentToDZ={handleClickAddComponentToDZ}
|
||||||
addComponentToDZ={handleClickAddComponentToDZ}
|
targetUid={targetUid}
|
||||||
targetUid={targetUid}
|
dataType={forTarget}
|
||||||
dataType={forTarget}
|
dataTypeName={currentDataName}
|
||||||
dataTypeName={currentDataName}
|
mainTypeName={currentDataName}
|
||||||
mainTypeName={currentDataName}
|
editTarget={forTarget}
|
||||||
editTarget={forTarget}
|
isMain
|
||||||
isMain
|
/>
|
||||||
/>
|
|
||||||
</Box>
|
|
||||||
</Stack>
|
</Stack>
|
||||||
</ContentLayout>
|
</ContentLayout>
|
||||||
</>
|
</>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user