diff --git a/front-packages/akeneo-design-system/src/__image_snapshots__/all-visual-tsx-visual-tests-renders-components-table-warning-and-locked-rows-correctly-1-snap.png b/front-packages/akeneo-design-system/src/__image_snapshots__/all-visual-tsx-visual-tests-renders-components-table-warning-and-locked-rows-correctly-1-snap.png new file mode 100644 index 000000000000..fe11826d7698 Binary files /dev/null and b/front-packages/akeneo-design-system/src/__image_snapshots__/all-visual-tsx-visual-tests-renders-components-table-warning-and-locked-rows-correctly-1-snap.png differ diff --git a/front-packages/akeneo-design-system/src/components/ProgressBar/ProgressBar.tsx b/front-packages/akeneo-design-system/src/components/ProgressBar/ProgressBar.tsx index f48a912c34a9..aed1a6c703a6 100644 --- a/front-packages/akeneo-design-system/src/components/ProgressBar/ProgressBar.tsx +++ b/front-packages/akeneo-design-system/src/components/ProgressBar/ProgressBar.tsx @@ -161,11 +161,9 @@ const ProgressBar = forwardRef( {(title || progressLabel) && (
- {title && ( - - {title} - - )} + + {title} + {progressLabel && {progressLabel}}
)} diff --git a/front-packages/akeneo-design-system/src/components/SwitcherButton/SwitcherButton.tsx b/front-packages/akeneo-design-system/src/components/SwitcherButton/SwitcherButton.tsx index 5a4a08105641..69ec26b3ce24 100644 --- a/front-packages/akeneo-design-system/src/components/SwitcherButton/SwitcherButton.tsx +++ b/front-packages/akeneo-design-system/src/components/SwitcherButton/SwitcherButton.tsx @@ -112,7 +112,7 @@ const SwitcherButton = forwardRef( return ( - + diff --git a/front-packages/akeneo-design-system/src/components/Table/Table.stories.mdx b/front-packages/akeneo-design-system/src/components/Table/Table.stories.mdx index 26bba1b2f0df..0f8a1a806ce9 100644 --- a/front-packages/akeneo-design-system/src/components/Table/Table.stories.mdx +++ b/front-packages/akeneo-design-system/src/components/Table/Table.stories.mdx @@ -487,14 +487,14 @@ If you want your `Table.Header` to stay on top when scrolling in the Table, just -## Table with warning rows +## Table with warning and locked rows - + {args => { return ( - +
Name Family @@ -504,6 +504,20 @@ If you want your `Table.Header` to stay on top when scrolling in the Table, just Actions + + Giant panda + Ursidae + Carnivora + Ursus + + vu + + + + + Giant panda Ursidae diff --git a/front-packages/akeneo-design-system/src/components/Table/Table.tsx b/front-packages/akeneo-design-system/src/components/Table/Table.tsx index 114bb9ccb37a..d5af6571925f 100644 --- a/front-packages/akeneo-design-system/src/components/Table/Table.tsx +++ b/front-packages/akeneo-design-system/src/components/Table/Table.tsx @@ -27,6 +27,11 @@ type TableProps = Override< */ hasWarningRows?: boolean; + /** + * Define if the table has some locked rows. + */ + hasLockedRows?: boolean; + /** * Define if the checkbox should be always displayed or displayed on hover. * This props should be true when one element is checked. @@ -66,6 +71,7 @@ type TableProps = Override< const Table = ({ isSelectable = false, hasWarningRows = false, + hasLockedRows = false, displayCheckbox = false, isDragAndDroppable = false, onReorder = undefined, @@ -73,8 +79,8 @@ const Table = ({ ...rest }: TableProps) => { const providerValue = useMemo( - () => ({isSelectable, hasWarningRows, displayCheckbox, isDragAndDroppable, onReorder}), - [isSelectable, hasWarningRows, displayCheckbox, isDragAndDroppable, onReorder] + () => ({isSelectable, hasWarningRows, hasLockedRows, displayCheckbox, isDragAndDroppable, onReorder}), + [isSelectable, hasWarningRows, hasLockedRows, displayCheckbox, isDragAndDroppable, onReorder] ); return ( diff --git a/front-packages/akeneo-design-system/src/components/Table/TableContext.ts b/front-packages/akeneo-design-system/src/components/Table/TableContext.ts index b1d44ecb93d1..fd317c66cc93 100644 --- a/front-packages/akeneo-design-system/src/components/Table/TableContext.ts +++ b/front-packages/akeneo-design-system/src/components/Table/TableContext.ts @@ -3,6 +3,7 @@ import {createContext} from 'react'; type TableContextType = { isSelectable: boolean; hasWarningRows: boolean; + hasLockedRows: boolean; displayCheckbox: boolean; isDragAndDroppable: boolean; onReorder: ((reorderedIndices: number[]) => void) | undefined; @@ -11,6 +12,7 @@ type TableContextType = { const TableContext = createContext({ isSelectable: false, hasWarningRows: false, + hasLockedRows: false, displayCheckbox: false, isDragAndDroppable: false, onReorder: undefined, diff --git a/front-packages/akeneo-design-system/src/components/Table/TableHeader/TableHeader.tsx b/front-packages/akeneo-design-system/src/components/Table/TableHeader/TableHeader.tsx index 170d960e1ba6..04c9e165ae37 100644 --- a/front-packages/akeneo-design-system/src/components/Table/TableHeader/TableHeader.tsx +++ b/front-packages/akeneo-design-system/src/components/Table/TableHeader/TableHeader.tsx @@ -23,6 +23,10 @@ const HasWarningColumn = styled.th` width: 20px; background: linear-gradient(to top, ${getColor('grey', 120)} 1px, ${getColor('white')} 0px); `; +const HasLockedColumn = styled.th` + width: 20px; + background: linear-gradient(to top, ${getColor('grey', 120)} 1px, ${getColor('white')} 0px); +`; const OrderColumn = styled.th` width: 40px; background: linear-gradient(to top, ${getColor('grey', 120)} 1px, ${getColor('white')} 0px); @@ -42,7 +46,7 @@ type TableHeaderProps = { const TableHeader = React.forwardRef( ({children, sticky, ...rest}: TableHeaderProps, forwardedRef: Ref) => { - const {isSelectable, isDragAndDroppable, hasWarningRows} = React.useContext(TableContext); + const {isSelectable, isDragAndDroppable, hasWarningRows, hasLockedRows} = React.useContext(TableContext); return ( @@ -52,6 +56,7 @@ const TableHeader = React.forwardRef( {hasWarningRows && } {isDragAndDroppable && } {children} + {hasLockedRows && } ); diff --git a/front-packages/akeneo-design-system/src/components/Table/TableRow/TableRow.tsx b/front-packages/akeneo-design-system/src/components/Table/TableRow/TableRow.tsx index 90df869dcfcf..34a0e631408e 100644 --- a/front-packages/akeneo-design-system/src/components/Table/TableRow/TableRow.tsx +++ b/front-packages/akeneo-design-system/src/components/Table/TableRow/TableRow.tsx @@ -14,10 +14,10 @@ import {Checkbox} from '../../../components'; import {Override} from '../../../shared'; import {TableContext} from '../TableContext'; import {TableCell} from '../TableCell/TableCell'; -import {RowIcon, DangerIcon} from '../../../icons'; +import {RowIcon, DangerIcon, LockIcon} from '../../../icons'; import {PlaceholderPosition, usePlaceholderPosition} from '../../../hooks/usePlaceholderPosition'; -type Level = 'warning'; +type Level = 'warning' | 'tertiary'; const RowContainer = styled.tr< { @@ -78,15 +78,22 @@ const RowContainer = styled.tr< } ${({level}) => - level === 'warning' && - css` - > td { - :first-child { - padding: 0 0 0 5px; - } - background-color: ${getColor('yellow', 10)}; - } - `}; + level === 'warning' + ? css` + > td { + :first-child { + padding: 0 0 0 5px; + } + background-color: ${getColor('yellow', 10)}; + } + ` + : level === 'tertiary' && + css` + > td { + background-color: ${getColor('grey', 20)}; + color: ${getColor('grey', 120)}; + } + `}; `; const CheckboxContainer = styled.td<{isVisible: boolean}>` @@ -112,6 +119,15 @@ const HandleCell = styled(TableCell)` } `; +const getIcon = (level: Level) => { + switch (level) { + case 'warning': + return ; + case 'tertiary': + return ; + } +}; + const WarningIcon = styled(DangerIcon)` color: ${getColor('yellow', 120)}; `; @@ -180,7 +196,7 @@ const TableRow = forwardRef( const [placeholderPosition, placeholderDragEnter, placeholderDragLeave, placeholderDragEnd] = usePlaceholderPosition(rowIndex); - const {isSelectable, displayCheckbox, isDragAndDroppable, hasWarningRows} = useContext(TableContext); + const {isSelectable, displayCheckbox, isDragAndDroppable, hasWarningRows, hasLockedRows} = useContext(TableContext); if (isSelectable && (undefined === isSelected || undefined === onSelectToggle)) { throw Error('A row in a selectable table should have the prop "isSelected" and "onSelectToggle"'); } @@ -240,8 +256,17 @@ const TableRow = forwardRef( )} - {hasWarningRows && {level === 'warning' && }} + {hasWarningRows && ( + + {level === 'warning' && React.cloneElement(getIcon(level), {size: 16, 'data-testid': 'warning-icon'})} + + )} {children} + {hasLockedRows && ( + + {level === 'tertiary' && React.cloneElement(getIcon(level), {size: 16, 'data-testid': 'lock-icon'})} + + )} ); } diff --git a/front-packages/akeneo-design-system/src/components/Table/TableRow/TableRow.unit.tsx b/front-packages/akeneo-design-system/src/components/Table/TableRow/TableRow.unit.tsx index 8b97579f6853..a06f2f310fbb 100644 --- a/front-packages/akeneo-design-system/src/components/Table/TableRow/TableRow.unit.tsx +++ b/front-packages/akeneo-design-system/src/components/Table/TableRow/TableRow.unit.tsx @@ -101,3 +101,33 @@ test('Table.Row supports ...rest props', () => { expect(screen.getByTestId('my_value')).toBeInTheDocument(); }); + +test('it renders warning icon when row has a warning', () => { + render( +
+ + + A value + Another value + + +
+ ); + + expect(screen.getByTestId('warning-icon')).toBeInTheDocument(); +}); + +test('it renders lock icon when row is locked', () => { + render( + + + + A value + Another value + + +
+ ); + + expect(screen.getByTestId('lock-icon')).toBeInTheDocument(); +}); diff --git a/front-packages/akeneo-design-system/src/icons/ChecklistIcon.tsx b/front-packages/akeneo-design-system/src/icons/ChecklistIcon.tsx new file mode 100644 index 000000000000..5409278345cd --- /dev/null +++ b/front-packages/akeneo-design-system/src/icons/ChecklistIcon.tsx @@ -0,0 +1,16 @@ +import React from 'react'; +import {IconProps} from './IconProps'; + +const ChecklistIcon = ({title, size = 24, color = 'currentColor', ...props}: IconProps) => ( + + {title && {title}} + + + + +); + +export {ChecklistIcon}; diff --git a/front-packages/akeneo-design-system/src/icons/WorkflowIcon.tsx b/front-packages/akeneo-design-system/src/icons/WorkflowIcon.tsx new file mode 100644 index 000000000000..eab2008d0879 --- /dev/null +++ b/front-packages/akeneo-design-system/src/icons/WorkflowIcon.tsx @@ -0,0 +1,39 @@ +import React from 'react'; +import {IconProps} from './IconProps'; + +const WorkflowIcon = ({title, size = 24, color = 'currentColor', ...props}: IconProps) => ( + + + + + + + +); + +export {WorkflowIcon}; diff --git a/front-packages/akeneo-design-system/src/icons/index.ts b/front-packages/akeneo-design-system/src/icons/index.ts index 7d97c26dcc49..42cf56b334f5 100644 --- a/front-packages/akeneo-design-system/src/icons/index.ts +++ b/front-packages/akeneo-design-system/src/icons/index.ts @@ -51,6 +51,7 @@ export * from './DownloadIcon'; export * from './DragDropIcon'; export * from './EditIcon'; export * from './EntityIcon'; +export * from './ChecklistIcon'; export * from './EntityMultiIcon'; export * from './EraseIcon'; export * from './ExpandIcon'; @@ -119,3 +120,4 @@ export * from './UserIcon'; export * from './ValueIcon'; export * from './ViewIcon'; export * from './WaveIcon'; +export * from './WorkflowIcon';