mirror of
https://github.com/strapi/strapi.git
synced 2025-12-27 15:13:21 +00:00
SubAction row migrated to DS
This commit is contained in:
parent
3c9e92a2c4
commit
863540ee79
@ -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('..')}
|
||||
|
||||
@ -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;
|
||||
@ -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 }) => {
|
||||
|
||||
@ -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>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@ -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 };
|
||||
@ -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 };
|
||||
@ -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};
|
||||
}
|
||||
`;
|
||||
|
||||
|
||||
@ -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}
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -13,6 +13,7 @@ const CenteredStack = styled(Stack)`
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: ${cellWidth};
|
||||
flex-shrink: 0;
|
||||
`;
|
||||
|
||||
const GlobalActions = ({ actions, isFormDisabled, kind }) => {
|
||||
|
||||
@ -1,2 +1,3 @@
|
||||
export const cellWidth = `${120 / 16}rem`;
|
||||
export const firstRowWidth = `${200 / 16}rem`;
|
||||
export const rowHeight = `${53 / 16}rem`;
|
||||
|
||||
@ -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>;
|
||||
|
||||
@ -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}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user