Skip to content

Commit

Permalink
feat: implement enumerate rows to table component (#1582)
Browse files Browse the repository at this point in the history
* feat: implement enumerate rows to table component

* fix: improved extra columns append to columnsData

* fix: improved getColumns setup

* fix: updated to align with spec results

* fix: counter updates and markup fix

* css counter used for enumerable
* markup aligned with standards

* feat: specs added for enumerable column integration for Table component

* fix: counter

* fix: firt data column

Co-authored-by: LeandroTorresSicilia <jtorressicilia@gmail.com>
  • Loading branch information
José Faro and LeandroTorresSicilia committed Jun 1, 2020
1 parent 7ee18cf commit 189bc64
Show file tree
Hide file tree
Showing 17 changed files with 571 additions and 39 deletions.
299 changes: 295 additions & 4 deletions src/components/Table/__test__/table.spec.js

Large diffs are not rendered by default.

8 changes: 8 additions & 0 deletions src/components/Table/body/__test__/cell.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ describe('<Cell /> when isFirst is not passed', () => {
const component = mount(<Cell value="cell-1" columnType="SELECTABLE_CHECKBOX" />);
expect(component.find('SelectableCell').exists()).toBe(true);
});
it('should render the EnumerableCell component when columnType is "WITH_ENUMERABLE"', () => {
const component = mount(<Cell value="cell-1" columnType="WITH_ENUMERABLE" />);
expect(component.find('EnumerableCell').exists()).toBe(true);
});
it('should render the ActionsCell component when columnType is "action"', () => {
const component = mount(<Cell value="cell-1" columnType="action" />);
expect(component.find('ActionsCell').exists()).toBe(true);
Expand Down Expand Up @@ -106,4 +110,8 @@ describe('<Cell /> when isFirst is passed', () => {
const component = mount(<Cell value="cell-1" isFirst columnType="SELECTABLE_CHECKBOX" />);
expect(component.find('SelectableCell').exists()).toBe(true);
});
it('should render the EnumerableCell component when columnType is "WITH_ENUMERABLE"', () => {
const component = mount(<Cell value="cell-1" isFirst columnType="WITH_ENUMERABLE" />);
expect(component.find('EnumerableCell').exists()).toBe(true);
});
});
4 changes: 4 additions & 0 deletions src/components/Table/body/__test__/row.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,12 @@ const columns = [
{
component: undefined,
field: 'name',
isFirstDataColumn: true,
},
{
component: undefined,
field: 'number',
isFirstDataColumn: false,
},
];

Expand Down Expand Up @@ -122,9 +124,11 @@ describe('<Row />', () => {
{
component: undefined,
field: 'number',
isFirstDataColumn: true,
},
{
field: 'name',
isFirstDataColumn: false,
},
];
const component = mount(<Row rowData={data} columns={columnsWithSelectable} />);
Expand Down
7 changes: 6 additions & 1 deletion src/components/Table/body/cell.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React from 'react';
import PropTypes from 'prop-types';
import { SELECTABLE_CHECKBOX } from '../helpers/columns';
import { SELECTABLE_CHECKBOX, WITH_ENUMERABLE } from '../helpers/columns';
import EnumerableCell from './enumerableCell';
import SelectableCell from './selectableCell';
import ActionsCell from './actionsCell';
import StyledCell from './styled/cell';
Expand Down Expand Up @@ -55,6 +56,10 @@ export default function Cell(props) {
return undefined;
};

if (columnType === WITH_ENUMERABLE) {
return <EnumerableCell />;
}

if (columnType === 'action') {
return (
<ActionsCell
Expand Down
14 changes: 14 additions & 0 deletions src/components/Table/body/enumerableCell.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import React from 'react';
import StyledCellContainer from './styled/cellContainer';
import StyledCellContent from './styled/cellContent';
import StyledEnumerable from './styled/enumerable';

export default function EnumerableCell() {
return (
<StyledCellContainer role="gridcell" tabIndex={-1}>
<StyledCellContent>
<StyledEnumerable />
</StyledCellContent>
</StyledCellContainer>
);
}
14 changes: 2 additions & 12 deletions src/components/Table/body/row.js
Original file line number Diff line number Diff line change
@@ -1,22 +1,13 @@
import React from 'react';
import PropTypes from 'prop-types';
import { SELECTABLE_CHECKBOX } from '../helpers/columns';
import { getFieldValue } from '../helpers/rows';
import Cell from './cell';
import LoadingCells from './loadingCells';
import StyledRow from './styled/row';

function isFirstAndNoSelectable(index, type) {
if (index === 0 && type !== SELECTABLE_CHECKBOX) {
return true;
}
return false;
}

export default function Row(props) {
const { rowData, columns, isSelected, ...rest } = props;

let isFirstColumn;
const cells = columns.map((column, index) => {
const {
header,
Expand All @@ -28,13 +19,12 @@ export default function Row(props) {
computedWidth,
isResized,
type: columnType,
isFirstDataColumn,
children,
...restColumnProps
} = column;
const key = `cell-${index}`;
const value = getFieldValue(rowData, field);
isFirstColumn =
!isFirstColumn && (isFirstAndNoSelectable(index, columnType) || index === 1);

return (
<Cell
Expand All @@ -46,7 +36,7 @@ export default function Row(props) {
component={component}
value={value}
columnType={columnType}
isFirst={isFirstColumn}
isFirst={isFirstDataColumn}
isSelected={isSelected}
columnChildren={children}
/>
Expand Down
14 changes: 14 additions & 0 deletions src/components/Table/body/styled/enumerable.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import styled from 'styled-components';
import attachThemeAttrs from '../../../../styles/helpers/attachThemeAttrs';

const StyledEnumerable = attachThemeAttrs(styled.span)`
display: block;
text-align: center;
color: ${props => props.palette.text.header};
&::after {
content: counter(rowCounter);
}
`;

export default StyledEnumerable;
1 change: 1 addition & 0 deletions src/components/Table/body/styled/row.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ const StyledRow = attachThemeAttrs(styled.tr)`
box-shadow: ${props => props.shadows.shadow_8};
transition: all 250ms cubic-bezier(0.4, 0, 0.2, 1) 0ms;
box-sizing: border-box;
counter-increment: rowCounter;
&:hover {
background-color: ${props => replaceAlpha(props.palette.action.hover, 0.4)};
Expand Down
80 changes: 71 additions & 9 deletions src/components/Table/helpers/columns/__test__/getColumns.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,37 +2,44 @@ import React from 'react';
import Column from '../../../../Column';
import getColumns from '../getColumns';

jest.mock('../../../helpers/columns/getEnumerableWidth', () => jest.fn(() => 50));

describe('getColumns', () => {
it('should return null when children is null and showCheckboxColumn is false', () => {
it('should return null when children is null, showCheckboxColumn is false and showRowNumberColumn is false', () => {
const children = null;
const showCheckboxColumn = false;
expect(getColumns({ children, showCheckboxColumn })).toBeNull();
const showRowNumberColumn = false;
expect(getColumns({ children, showCheckboxColumn, showRowNumberColumn })).toBeNull();
});
it('should return an empty array when children is not passed', () => {
it('should return an empty array when children is not passed, showCheckboxColumn is false and showRowNumberColumn is false', () => {
const children = undefined;
const showCheckboxColumn = false;
expect(getColumns({ children, showCheckboxColumn })).toEqual([]);
const showRowNumberColumn = false;
expect(getColumns({ children, showCheckboxColumn, showRowNumberColumn })).toEqual([]);
});
it('should return an empty array when children is an array with falsy values and showCheckboxColumn is false', () => {
it('should return an empty array when children is an array with falsy values, showCheckboxColumn is false and showRowNumberColumn is false', () => {
const children = [null, undefined];
const showCheckboxColumn = false;
expect(getColumns({ children, showCheckboxColumn })).toEqual([]);
const showRowNumberColumn = false;
expect(getColumns({ children, showCheckboxColumn, showRowNumberColumn })).toEqual([]);
});
it('should return an array with the columns props when showCheckboxColumn is false', () => {
it('should return an array with the columns props when showCheckboxColumn is false and showRowNumberColumn is false', () => {
const children = [<Column field="a" header="header" component={<span />} />];
const showCheckboxColumn = false;
expect(getColumns({ children, showCheckboxColumn })).toEqual([
const showRowNumberColumn = false;
expect(getColumns({ children, showCheckboxColumn, showRowNumberColumn })).toEqual([
{
field: 'a',
header: 'header',
component: <span />,
sortable: false,
type: 'text',
isFirstDataColumn: true,
width: undefined,
},
]);
});
it('should return an array with the columns props plus the selectable column when showCheckboxColumn is true', () => {
it('should return an array with the columns props, plus the selectable column when showCheckboxColumn is true', () => {
const children = [<Column field="a" header="header" component={<span />} />];
const showCheckboxColumn = true;
expect(getColumns({ children, showCheckboxColumn })).toEqual([
Expand All @@ -46,6 +53,56 @@ describe('getColumns', () => {
component: <span />,
sortable: false,
type: 'text',
isFirstDataColumn: true,
width: undefined,
},
]);
});
it('should return an array with the columns props, plus the enumerable column data including enumerable offset value when showRowNumberColumn is true and rowNumberOffset is set', () => {
const children = [<Column field="a" header="header" component={<span />} />];
const showRowNumberColumn = true;
const rowNumberOffset = 333;
expect(getColumns({ children, showRowNumberColumn, rowNumberOffset })).toEqual([
{
type: 'WITH_ENUMERABLE',
rowNumberOffset: 333,
width: 50,
},
{
field: 'a',
header: 'header',
component: <span />,
sortable: false,
type: 'text',
isFirstDataColumn: true,
width: undefined,
},
]);
});
it('should return an array with the columns props, plus the enumerable and the selectable columns when showCheckboxColumn and showRowNumberColumn are true', () => {
const children = [<Column field="a" header="header" component={<span />} />];
const showCheckboxColumn = true;
const showRowNumberColumn = true;
const rowNumberOffset = 0;
expect(
getColumns({ children, showCheckboxColumn, showRowNumberColumn, rowNumberOffset }),
).toEqual([
{
type: 'WITH_ENUMERABLE',
rowNumberOffset: 0,
width: 50,
},
{
type: 'SELECTABLE_CHECKBOX',
width: 52,
},
{
field: 'a',
header: 'header',
component: <span />,
sortable: false,
type: 'text',
isFirstDataColumn: true,
width: undefined,
},
]);
Expand All @@ -63,6 +120,7 @@ describe('getColumns', () => {
component: <span />,
sortable: false,
type: 'text',
isFirstDataColumn: true,
width: undefined,
},
{
Expand Down Expand Up @@ -92,6 +150,7 @@ describe('getColumns', () => {
component: <span />,
sortable: false,
type: 'text',
isFirstDataColumn: true,
defaultWidth: 160,
width: 30,
},
Expand All @@ -100,6 +159,7 @@ describe('getColumns', () => {
header: 'header b',
sortable: false,
type: 'text',
isFirstDataColumn: false,
defaultWidth: 150,
},
]);
Expand All @@ -126,13 +186,15 @@ describe('getColumns', () => {
component: <span />,
sortable: false,
type: 'text',
isFirstDataColumn: true,
defaultWidth: 150,
},
{
field: 'b',
header: 'header b',
sortable: false,
type: 'text',
isFirstDataColumn: false,
defaultWidth: 50,
},
]);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import getEnumerableWidth from '../getEnumerableWidth';

describe('getEnumerableWidth', () => {
it('should return the default width when value is not sent', () => {
expect(getEnumerableWidth()).toBe(48);
});
it('should return the default calculated width when value is default', () => {
expect(getEnumerableWidth(0)).toBe(48);
});
it('should return the right width when value length is 3 (999)', () => {
expect(getEnumerableWidth(999)).toBe(72);
});
});
42 changes: 31 additions & 11 deletions src/components/Table/helpers/columns/getColumns.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react';
import { SELECTABLE_CHECKBOX } from './';
import { getEnumerableWidth, SELECTABLE_CHECKBOX, WITH_ENUMERABLE } from './';

function getDefaultWidth(defaultWidth, minColumnWidth, maxColumnWidth) {
const minColWidth = Number(minColumnWidth);
Expand All @@ -16,11 +16,35 @@ function getDefaultWidth(defaultWidth, minColumnWidth, maxColumnWidth) {
}

export default function getColumns(params) {
const { children = [], showCheckboxColumn, minColumnWidth, maxColumnWidth } = params;
const {
children = [],
showCheckboxColumn,
showRowNumberColumn,
rowNumberOffset,
minColumnWidth,
maxColumnWidth,
} = params;

const configColumns = [];

if (showRowNumberColumn) {
configColumns.push({
type: WITH_ENUMERABLE,
rowNumberOffset,
width: getEnumerableWidth(rowNumberOffset),
});
}

if (showCheckboxColumn) {
configColumns.push({
type: SELECTABLE_CHECKBOX,
width: 52,
});
}

const columnsData = React.Children.map(
children,
column => {
(column, index) => {
if (column && column.props) {
const { type, width, defaultWidth } = column.props;
const widthNumber = Number(width);
Expand All @@ -34,21 +58,17 @@ export default function getColumns(params) {
...column.props,
width: widthNumber || undefined,
defaultWidth: getDefaultWidth(defaultWidth, minColumnWidth, maxColumnWidth),
isFirstDataColumn: index === 0,
};
}
return null;
},
null,
);

if (showCheckboxColumn) {
return [
{
type: SELECTABLE_CHECKBOX,
width: 52,
},
...columnsData,
];
if (configColumns.length) {
return configColumns.concat(columnsData);
}

return columnsData;
}
11 changes: 11 additions & 0 deletions src/components/Table/helpers/columns/getEnumerableWidth.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
const enumerableColumnOffset = 40;
const singleNumberWidth = 8;

export default function getEnumerableWidth(numberValue) {
if (numberValue) {
const valuePlusOne = Number(numberValue) + 1;
const enumerableStringWidth = singleNumberWidth * valuePlusOne.toString().length;
return enumerableStringWidth + enumerableColumnOffset;
}
return 48;
}
Loading

0 comments on commit 189bc64

Please sign in to comment.