SubAction row migrated to DS

This commit is contained in:
bulby97 2021-08-25 16:25:17 +02:00
parent 3c9e92a2c4
commit 863540ee79
13 changed files with 193 additions and 161 deletions

View File

@ -1,5 +1,4 @@
import { Down, Up } from '@strapi/icons';
import { Box, Checkbox, Row } from '@strapi/parts';
import { Checkbox, Row } from '@strapi/parts';
import IS_DISABLED from 'ee_else_ce/components/Roles/ContentTypeCollapse/CollapsePropertyMatrix/ActionRow/utils/constants';
import { get } from 'lodash';
import PropTypes from 'prop-types';
@ -12,41 +11,25 @@ import RequiredSign from '../../../RequiredSign';
import RowLabelWithCheckbox from '../../../RowLabelWithCheckbox';
import { getCheckboxState } from '../../../utils';
import { activeStyle } from '../../utils';
import CarretIcon from '../CarretIcon';
import SubActionRow from '../SubActionRow';
import getRowLabelCheckboxeState from './utils/getRowLabelCheckboxeState';
const Cell = styled(Box)`
const Cell = styled(Row)`
width: ${cellWidth};
display: flex;
align-items: center;
justify-content: center;
position: relative;
`;
// ! Something needs to be done in the DS parts to avoid doing this
const Chevron = styled(Box)`
display: none;
svg {
width: ${11 / 16}rem;
}
* {
fill: ${({ theme }) => theme.colors.primary600};
}
`;
const Wrapper = styled(Row)`
height: 52px;
height: ${52 / 16}rem;
flex: 1;
background: ${({ theme, isOdd }) => theme.colors[isOdd ? 'neutral100' : 'neutral0']};
${Chevron} {
width: ${13 / 16}rem;
}
${({ isCollapsable, theme }) =>
isCollapsable &&
`
${Chevron} {
${CarretIcon} {
display: block;
color: ${theme.main.colors.grey};
color: ${theme.colors.neutral100};
}
&:hover {
${activeStyle(theme)}
@ -108,7 +91,12 @@ const ActionRow = ({
return (
<>
<Wrapper alignItems="center" isCollapsable={isCollapsable} isActive={isActive} isOdd={isOdd}>
<Wrapper
alignItems="center"
isCollapsable={isCollapsable}
isActive={isActive}
background={isOdd ? 'neutral100' : 'neutral0'}
>
<Row>
<RowLabelWithCheckbox
onChange={handleChangeLeftRowCheckbox}
@ -121,7 +109,7 @@ const ActionRow = ({
isActive={isActive}
>
{required && <RequiredSign />}
<Chevron paddingLeft={2}>{isActive ? <Up /> : <Down />}</Chevron>
<CarretIcon $isActive={isActive} />
</RowLabelWithCheckbox>
<Row>
{propertyActions.map(({ label, isActionRelatedToCurrentProperty, actionId }) => {
@ -141,7 +129,7 @@ const ActionRow = ({
const checkboxValue = get(modifiedData, checkboxName, false);
return (
<Cell key={actionId}>
<Cell key={actionId} justifyContent="center" alignItems="center">
<Checkbox
disabled={isFormDisabled || IS_DISABLED}
name={checkboxName.join('..')}
@ -165,7 +153,7 @@ const ActionRow = ({
const { hasAllActionsSelected, hasSomeActionsSelected } = getCheckboxState(data);
return (
<Cell key={label}>
<Cell key={label} justifyContent="center" alignItems="center">
<Checkbox
disabled={isFormDisabled || IS_DISABLED}
name={checkboxName.join('..')}

View File

@ -0,0 +1,14 @@
import { Carret } from '@strapi/icons';
import styled from 'styled-components';
const CarretIcon = styled(Carret)`
display: none;
width: ${10 / 16}rem;
transform: rotate(${({ $isActive }) => ($isActive ? '180' : '0')}deg);
margin-left: ${({ theme }) => theme.spaces[2]};
* {
fill: ${({ theme }) => theme.colors.primary600};
}
`;
export default CarretIcon;

View File

@ -7,10 +7,12 @@ import { cellWidth, firstRowWidth } from '../../../Permissions/utils/constants';
const HeaderLabel = styled(Row)`
width: ${cellWidth};
flex-shrink: 0;
`;
const PropertyLabelWrapper = styled(Row)`
width: ${firstRowWidth};
height: ${52 / 16}rem;
flex-shrink: 0;
`;
const Header = ({ headers, label }) => {

View File

@ -1,23 +1,69 @@
import React, { memo, useMemo, useState } from 'react';
import PropTypes from 'prop-types';
import { get } from 'lodash';
import { Flex, Text } from '@buffetjs/core';
import { Box } from '@strapi/parts';
import { get, upperFirst } from 'lodash';
import styled from 'styled-components';
import { Box, Row, Text, Checkbox } from '@strapi/parts';
import IS_DISABLED from 'ee_else_ce/components/Roles/ContentTypeCollapse/CollapsePropertyMatrix/SubActionRow/utils/constants';
import { usePermissionsDataManager } from '../../../../../hooks';
import { getCheckboxState } from '../../../utils';
import CheckboxWithCondition from '../../../CheckboxWithCondition';
import Chevron from '../../../Chevron';
import CollapseLabel from '../../../CollapseLabel';
import Curve from '../../../Curve';
import HiddenAction from '../../../HiddenAction';
import RequiredSign from '../../../RequiredSign';
import { RowStyle, RowWrapper } from './row';
import { LeftBorderTimeline, TopTimeline } from './timeline';
import { cellWidth, rowHeight } from '../../../Permissions/utils/constants';
import CarretIcon from '../CarretIcon';
import { activeStyle } from '../../utils';
const SubLevelWrapper = styled.div`
padding-bottom: 8px;
const Cell = styled(Row)`
width: ${cellWidth};
position: relative;
`;
const RowWrapper = styled(Row)`
height: ${rowHeight};
`;
const Wrapper = styled(Box)`
padding-left: ${31 / 16}rem;
`;
const LeftBorderTimeline = styled(Box)`
border-left: ${({ isVisible, theme }) =>
isVisible ? `4px solid ${theme.colors.primary200}` : '4px solid transparent'};
`;
const RowStyle = styled(Row)`
padding-left: ${({ theme }) => theme.spaces[4]};
width: ${({ level }) => 145 - level * 36}px;
${({ isCollapsable, theme }) =>
isCollapsable &&
`
${CarretIcon} {
display: block;
color: ${theme.colors.neutral100};
}
&:hover {
${activeStyle(theme)}
}
`}
${({ isActive, theme }) => isActive && activeStyle(theme)};
`;
const TopTimeline = styled.div`
padding-top: 8px;
margin-top: 8px;
width: 4px;
background-color: ${({ theme }) => theme.colors.primary200};
border-top-left-radius: 2px;
border-top-right-radius: 2px;
`;
// ! REMOVE THIS WHEN DS IS UPDATED WITH ELLIPSIS PROP
const StyledText = styled(Text)`
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
`;
const SubActionRow = ({
@ -55,45 +101,38 @@ const SubActionRow = ({
}, [rowToOpen, childrenForm]);
return (
<Box>
<Wrapper>
<TopTimeline />
{childrenForm.map(({ label, value, required, children: subChildrenForm }, index) => {
const isVisible = index + 1 < childrenForm.length;
const isArrayType = Array.isArray(subChildrenForm);
const isSmall = isArrayType || index + 1 === childrenForm.length;
const isActive = rowToOpen === value;
return (
<LeftBorderTimeline key={value} isVisible={isVisible}>
<RowWrapper isSmall={isSmall}>
<Curve fill="#a5d5ff" />
<Flex style={{ flex: 1 }}>
<RowWrapper>
<Curve color="primary200" />
<Row style={{ flex: 1 }}>
<RowStyle level={recursiveLevel} isActive={isActive} isCollapsable={isArrayType}>
<CollapseLabel
alignItems="center"
isCollapsable={isArrayType}
onClick={() => {
if (isArrayType) {
handleClickToggleSubLevel(value);
}
}}
{...(isArrayType && {
onClick: () => handleClickToggleSubLevel(value),
'aria-expanded': isActive,
onKeyDown: ({ key }) =>
(key === 'Enter' || key === ' ') && handleClickToggleSubLevel(value),
tabIndex: 0,
role: 'button',
})}
title={label}
>
<Text
color={isActive ? 'mediumBlue' : 'grey'}
ellipsis
fontSize="xs"
fontWeight="bold"
lineHeight="20px"
textTransform="uppercase"
>
{label}
</Text>
<StyledText>{upperFirst(label)}</StyledText>
{required && <RequiredSign />}
<Chevron icon={isActive ? 'caret-up' : 'caret-down'} />
<CarretIcon $isActive={isActive} />
</CollapseLabel>
</RowStyle>
<Flex style={{ flex: 1 }}>
<Row style={{ flex: 1 }}>
{propertyActions.map(({ actionId, label, isActionRelatedToCurrentProperty }) => {
if (!isActionRelatedToCurrentProperty) {
return <HiddenAction key={actionId} />;
@ -115,13 +154,22 @@ const SubActionRow = ({
if (!subChildrenForm) {
return (
<CheckboxWithCondition
key={label}
disabled={isFormDisabled || IS_DISABLED}
name={checkboxName.join('..')}
onChange={onChangeSimpleCheckbox}
value={checkboxValue}
/>
<Cell key={label} justifyContent="center" alignItems="center">
<Checkbox
disabled={isFormDisabled || IS_DISABLED}
name={checkboxName.join('..')}
aria-label={checkboxName.join('..')}
// Keep same signature as packages/core/admin/admin/src/components/Roles/Permissions/index.js l.91
onValueChange={value =>
onChangeSimpleCheckbox({
target: {
name: checkboxName.join('..'),
value,
},
})}
value={checkboxValue}
/>
</Cell>
);
}
@ -130,21 +178,31 @@ const SubActionRow = ({
);
return (
<CheckboxWithCondition
key={label}
disabled={isFormDisabled || IS_DISABLED}
name={checkboxName.join('..')}
onChange={onChangeParentCheckbox}
value={hasAllActionsSelected}
someChecked={hasSomeActionsSelected}
/>
<Cell key={label} justifyContent="center" alignItems="center">
<Checkbox
key={label}
disabled={isFormDisabled || IS_DISABLED}
name={checkboxName.join('..')}
aria-label={checkboxName.join('..')}
// Keep same signature as packages/core/admin/admin/src/components/Roles/Permissions/index.js l.91
onValueChange={value =>
onChangeParentCheckbox({
target: {
name: checkboxName.join('..'),
value,
},
})}
value={hasAllActionsSelected}
indeterminate={hasSomeActionsSelected}
/>
</Cell>
);
})}
</Flex>
</Flex>
</Row>
</Row>
</RowWrapper>
{displayedRecursiveChildren && isActive && (
<SubLevelWrapper>
<Box paddingBottom={2}>
<SubActionRow
isFormDisabled={isFormDisabled}
parentName={`${parentName}..${value}`}
@ -154,12 +212,12 @@ const SubActionRow = ({
recursiveLevel={recursiveLevel + 1}
childrenForm={displayedRecursiveChildren.children}
/>
</SubLevelWrapper>
</Box>
)}
</LeftBorderTimeline>
);
})}
</Box>
</Wrapper>
);
};

View File

@ -1,37 +0,0 @@
import styled from 'styled-components';
import { Flex } from '@buffetjs/core';
import PropTypes from 'prop-types';
import Chevron from '../../../Chevron';
import { activeStyle } from '../../utils';
const RowStyle = styled.div`
padding-left: ${({ theme }) => theme.main.sizes.paddings.xs};
width: ${({ level }) => 128 - level * 18}px;
${Chevron} {
width: 13px;
}
${({ isCollapsable, theme }) =>
isCollapsable &&
`
${Chevron} {
display: block;
color: ${theme.main.colors.grey};
}
&:hover {
${activeStyle(theme)}
}
`}
${({ isActive, theme }) => isActive && activeStyle(theme)}
`;
RowStyle.propTypes = {
isActive: PropTypes.bool.isRequired,
isCollapsable: PropTypes.bool.isRequired,
level: PropTypes.number.isRequired,
};
const RowWrapper = styled(Flex)`
height: ${({ isSmall }) => (isSmall ? '28px' : '36px')};
`;
export { RowStyle, RowWrapper };

View File

@ -1,15 +0,0 @@
import styled from 'styled-components';
const LeftBorderTimeline = styled.div`
border-left: ${({ isVisible }) => (isVisible ? '3px solid #a5d5ff' : '3px solid transparent')};
`;
const TopTimeline = styled.div`
padding-top: 8px;
width: 3px;
background-color: #a5d5ff;
border-top-left-radius: 2px;
border-top-right-radius: 2px;
`;
export { LeftBorderTimeline, TopTimeline };

View File

@ -1,14 +1,14 @@
import { Text } from '@buffetjs/core';
import Chevron from '../../Chevron';
import { Text } from '@strapi/parts';
import CarretIcon from '../CollapsePropertyMatrix/CarretIcon';
const activeStyle = theme => `
color: ${theme.main.colors.mediumBlue};
${Text} {
color: ${theme.main.colors.mediumBlue};
color: ${theme.colors.primary600};
font-weight: bold;
}
${Chevron} {
${CarretIcon} {
display: block;
color: ${theme.main.colors.mediumBlue};
color: ${theme.colors.primary600};
}
`;

View File

@ -6,7 +6,7 @@ import GlobalActions from '../GlobalActions';
const ContentTypes = ({ isFormDisabled, kind, layout: { actions, subjects } }) => {
return (
<Box background="neutral0">
<Box background="neutral0" style={{ overflowX: 'auto' }}>
<GlobalActions actions={actions} kind={kind} isFormDisabled={isFormDisabled} />
<ContentTypeCollapses
actions={actions}

View File

@ -1,32 +1,52 @@
import React, { memo } from 'react';
import PropTypes from 'prop-types';
import styled from 'styled-components';
import { Box } from '@strapi/parts';
const StyledBox = styled(Box)`
transform: translate(-4px, -12px);
&:before {
content: '';
width: ${4 / 16}rem;
height: ${12 / 16}rem;
background: ${({ theme }) => theme.colors.primary200};
display: block;
}
`;
const Svg = styled.svg`
position: relative;
flex-shrink: 0;
transform: translate(-0.5px, -1px);
* {
fill: ${({ theme, color }) => theme.colors[color]};
}
`;
const Curve = props => (
<svg
style={{
height: '14px',
transform: 'translate(-3.2px, -1px)',
position: 'relative',
}}
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 21.08 21"
{...props}
>
<g>
<StyledBox>
<Svg
width="20"
height="23"
viewBox="0 0 20 23"
fill="none"
xmlns="http://www.w3.org/2000/svg"
{...props}
>
<path
d="M2.58 2.5q-1.2 16 16 16"
fill="none"
stroke={props.fill}
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="5"
fillRule="evenodd"
clipRule="evenodd"
d="M7.02477 14.7513C8.65865 17.0594 11.6046 18.6059 17.5596 18.8856C18.6836 18.9384 19.5976 19.8435 19.5976 20.9688V20.9688C19.5976 22.0941 18.6841 23.0125 17.5599 22.9643C10.9409 22.6805 6.454 20.9387 3.75496 17.1258C0.937988 13.1464 0.486328 7.39309 0.486328 0.593262H4.50974C4.50974 7.54693 5.06394 11.9813 7.02477 14.7513Z"
fill="#D9D8FF"
/>
</g>
</svg>
</Svg>
</StyledBox>
);
Curve.defaultProps = {
fill: '#f3f4f4',
fill: 'primary200',
};
Curve.propTypes = {
fill: PropTypes.string,

View File

@ -13,6 +13,7 @@ const CenteredStack = styled(Stack)`
align-items: center;
justify-content: center;
width: ${cellWidth};
flex-shrink: 0;
`;
const GlobalActions = ({ actions, isFormDisabled, kind }) => {

View File

@ -1,2 +1,3 @@
export const cellWidth = `${120 / 16}rem`;
export const firstRowWidth = `${200 / 16}rem`;
export const rowHeight = `${53 / 16}rem`;

View File

@ -2,8 +2,8 @@ import React from 'react';
import styled from 'styled-components';
const Required = styled.span`
color: ${({ theme }) => theme.main.colors.red};
padding-left: 2px;
color: ${({ theme }) => theme.colors.danger700};
padding-left: ${({ theme }) => theme.spaces[1]}px;
`;
const RequiredSign = () => <Required>*</Required>;

View File

@ -26,7 +26,7 @@ const RowLabelWithCheckbox = ({
value,
}) => {
return (
<Row alignItems="center" paddingLeft={6} style={{ width: firstRowWidth }}>
<Row alignItems="center" paddingLeft={6} style={{ width: firstRowWidth, flexShrink: 0 }}>
<Checkbox
name={checkboxName}
aria-label={checkboxName}