Skip to content

Commit

Permalink
feat(react-grid): add tableRowTemplate to the TableView plugin (#317)
Browse files Browse the repository at this point in the history
  • Loading branch information
SergeyAlexeev authored Sep 7, 2017
1 parent a93a030 commit 24d9446
Show file tree
Hide file tree
Showing 17 changed files with 307 additions and 35 deletions.
10 changes: 9 additions & 1 deletion packages/dx-react-grid-bootstrap3/src/plugins/table-view.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,25 @@ import { combineTemplates } from '@devexpress/dx-react-core';
import { TableView as TableViewBase } from '@devexpress/dx-react-grid';
import { Table } from '../templates/table';
import { TableCell } from '../templates/table-cell';
import { TableRow } from '../templates/table-row';
import { TableStubCell } from '../templates/table-stub-cell';
import { TableStubHeaderCell } from '../templates/table-stub-header-cell';
import { TableNoDataCell } from '../templates/table-no-data-cell';

const tableLayoutTemplate = props => <Table {...props} />;
const defaultRowTemplate = props => <TableRow {...props} />;
const defaultCellTemplate = props => <TableCell {...props} />;
const stubCellTemplate = props => <TableStubCell {...props} />;
const stubHeaderCellTemplate = props => <TableStubHeaderCell {...props} />;
const noDataCellTemplate = props => <TableNoDataCell {...props} />;

export const TableView = ({ tableCellTemplate, ...props }) => (
export const TableView = ({ tableCellTemplate, tableRowTemplate, ...props }) => (
<TableViewBase
tableLayoutTemplate={tableLayoutTemplate}
tableRowTemplate={combineTemplates(
tableRowTemplate,
defaultRowTemplate,
)}
tableCellTemplate={combineTemplates(
tableCellTemplate,
defaultCellTemplate,
Expand All @@ -30,8 +36,10 @@ export const TableView = ({ tableCellTemplate, ...props }) => (

TableView.propTypes = {
tableCellTemplate: PropTypes.func,
tableRowTemplate: PropTypes.func,
};

TableView.defaultProps = {
tableCellTemplate: undefined,
tableRowTemplate: undefined,
};
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,25 @@ import { combineTemplates } from '@devexpress/dx-react-core';
import { TableView as TableViewBase } from '@devexpress/dx-react-grid';
import { VirtualTable } from '../templates/virtual-table';
import { TableCell } from '../templates/table-cell';
import { TableRow } from '../templates/table-row';
import { TableNoDataCell } from '../templates/table-no-data-cell';
import { TableStubCell } from '../templates/table-stub-cell';
import { TableStubHeaderCell } from '../templates/table-stub-header-cell';

const tableLayoutTemplate = props => <VirtualTable {...props} />;
const defaultRowTemplate = props => <TableRow {...props} />;
const defaultCellTemplate = props => <TableCell {...props} />;
const noDataCellTemplate = props => <TableNoDataCell {...props} />;
const stubCellTemplate = props => <TableStubCell {...props} />;
const stubHeaderCellTemplate = props => <TableStubHeaderCell {...props} />;

export const VirtualTableView = ({ tableCellTemplate, ...props }) => (
export const VirtualTableView = ({ tableCellTemplate, tableRowTemplate, ...props }) => (
<TableViewBase
tableLayoutTemplate={tableLayoutTemplate}
tableRowTemplate={combineTemplates(
tableRowTemplate,
defaultRowTemplate,
)}
tableCellTemplate={combineTemplates(
tableCellTemplate,
defaultCellTemplate,
Expand All @@ -29,7 +35,9 @@ export const VirtualTableView = ({ tableCellTemplate, ...props }) => (
);
VirtualTableView.propTypes = {
tableCellTemplate: PropTypes.func,
tableRowTemplate: PropTypes.func,
};
VirtualTableView.defaultProps = {
tableCellTemplate: undefined,
tableRowTemplate: undefined,
};
20 changes: 20 additions & 0 deletions packages/dx-react-grid-bootstrap3/src/templates/table-row.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import React from 'react';
import PropTypes from 'prop-types';

export const TableRow = ({ children, tableRow, ...restProps }) => (
<tr
className={tableRow.selected ? 'active' : ''}
{...restProps}
>
{children}
</tr>
);

TableRow.propTypes = {
tableRow: PropTypes.object.isRequired,
children: PropTypes.node,
};

TableRow.defaultProps = {
children: null,
};
31 changes: 31 additions & 0 deletions packages/dx-react-grid-bootstrap3/src/templates/table-row.test.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import React from 'react';
import { mount } from 'enzyme';
import { setupConsole } from '@devexpress/dx-testing';
import { TableRow } from './table-row';

describe('TableRow', () => {
const mountTableRow = ({ tableRow }) => (
mount(
<TableRow
tableRow={tableRow}
/>,
)
);

let resetConsole;
beforeAll(() => {
resetConsole = setupConsole({ ignore: ['validateDOMNesting'] });
});

afterAll(() => {
resetConsole();
});

it('should have correct className', () => {
let tree = mountTableRow({ tableRow: {} });
expect(tree.find('tr').hasClass('active')).toBeFalsy();

tree = mountTableRow({ tableRow: { selected: true } });
expect(tree.find('tr').hasClass('active')).toBeTruthy();
});
});
11 changes: 2 additions & 9 deletions packages/dx-react-grid-bootstrap3/src/templates/table.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,20 +22,12 @@ const headTemplate = ({ children, ...restProps }) => (
const bodyTemplate = ({ children, ...restProps }) => (
<tbody {...restProps}>{children}</tbody>
);
const rowTemplate = ({ children, row, ...restProps }) => (
<tr
className={row.selected ? 'active' : ''}
{...restProps}
>
{children}
</tr>
);
/* eslint-enable react/prop-types */

export const Table = ({
headerRows, bodyRows, getRowId,
columns,
cellTemplate,
rowTemplate,
onClick,
allowColumnReordering, setColumnOrder,
}) => (
Expand All @@ -62,6 +54,7 @@ Table.propTypes = {
bodyRows: PropTypes.array.isRequired,
columns: PropTypes.array.isRequired,
cellTemplate: PropTypes.func.isRequired,
rowTemplate: PropTypes.func.isRequired,
getRowId: PropTypes.func.isRequired,
onClick: PropTypes.func,
allowColumnReordering: PropTypes.bool.isRequired,
Expand Down
51 changes: 51 additions & 0 deletions packages/dx-react-grid-bootstrap3/src/templates/table.test.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import React from 'react';
import { mount } from 'enzyme';
import { setupConsole } from '@devexpress/dx-testing';
import { TableLayout } from '@devexpress/dx-react-grid';
import { Table } from './table';

jest.mock('@devexpress/dx-react-grid', () => ({
TableLayout: jest.fn(),
}));

describe('Table', () => {
let resetConsole;
beforeAll(() => {
resetConsole = setupConsole({ ignore: ['validateDOMNesting'] });
});
afterAll(() => {
resetConsole();
});

afterEach(() => {
jest.resetAllMocks();
});

it('should pass rowTemplate to TableLayout', () => {
const rowTemplateMock = jest.fn();
const rowTemplateArgs = {
row: 'row',
children: null,
};
TableLayout.mockImplementation(({ rowTemplate }) => (
<table>
{rowTemplate(rowTemplateArgs)}
</table>
));

mount(
<Table
rowTemplate={rowTemplateMock}
headerRows={[]}
bodyRows={[]}
columns={[]}
cellTemplate={() => {}}
getRowId={() => {}}
allowColumnReordering={false}
setColumnOrder={() => {}}
/>,
);

expect(rowTemplateMock).toBeCalledWith(rowTemplateArgs);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ export class VirtualTable extends React.Component {
};
}
render() {
const { headerRows, bodyRows, columns, cellTemplate } = this.props;
const { headerRows, bodyRows, columns, cellTemplate, rowTemplate } = this.props;

const columnWidths = calculateColumnWidths(columns, this.state.viewportWidth);
const scrollWidth = columnWidths.reduce((accum, width) => accum + width, 0);
Expand All @@ -54,7 +54,7 @@ export class VirtualTable extends React.Component {
return (
<VirtualBox
rootTag="tr"

rootTagTemplate={params => (rowTemplate({ tableRow: row, ...params }))}
position={position}
crossSize={this.rowHeight(row)}
direction="horizontal"
Expand Down Expand Up @@ -159,4 +159,5 @@ VirtualTable.propTypes = {
bodyRows: PropTypes.array.isRequired,
columns: PropTypes.array.isRequired,
cellTemplate: PropTypes.func.isRequired,
rowTemplate: PropTypes.func.isRequired,
};
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ export class VirtualBox extends React.Component {
};
}
render() {
const { direction, position, stick, iref } = this.props;
const { direction, position, stick, iref, rootTagTemplate } = this.props;
const viewport = this.context.virtualHost.viewport;

const positionProp = direction === 'horizontal' ? 'left' : 'top';
Expand Down Expand Up @@ -166,17 +166,31 @@ export class VirtualBox extends React.Component {
});

const RootTag = this.props.rootTag;
const rootTagProps = {
style: {
position: 'relative',
...this.props.style,
[sizeProp]: `${fullSize}px`,
display: 'block',
},
className: this.props.className,
};

if (rootTagTemplate) {
return rootTagTemplate({
...rootTagProps,
children: visibleItems,
});
}

return (
<RootTag
className={this.props.className}
style={{
position: 'relative',
...this.props.style,
[sizeProp]: `${fullSize}px`,
display: 'block',
}}
{...(iref ? { ref: iref } : {})}
{
...{
...(iref ? { ref: iref } : {}),
...rootTagProps,
}
}
>
{visibleItems}
</RootTag>
Expand All @@ -185,6 +199,7 @@ export class VirtualBox extends React.Component {
}
VirtualBox.defaultProps = {
rootTag: 'div',
rootTagTemplate: undefined,
className: '',
style: {},
position: 0,
Expand All @@ -194,6 +209,7 @@ VirtualBox.defaultProps = {
};
VirtualBox.propTypes = {
rootTag: PropTypes.string,
rootTagTemplate: PropTypes.func,
className: PropTypes.string,
style: PropTypes.object,
position: PropTypes.number,
Expand Down
10 changes: 9 additions & 1 deletion packages/dx-react-grid-material-ui/src/plugins/table-view.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,23 @@ import { combineTemplates } from '@devexpress/dx-react-core';
import { TableView as TableViewBase } from '@devexpress/dx-react-grid';
import { Table } from '../templates/table';
import { TableCell } from '../templates/table-cell';
import { TableRow } from '../templates/table-row';
import { TableStubCell } from '../templates/table-stub-cell';
import { TableNoDataCell } from '../templates/table-no-data-cell';

const tableLayoutTemplate = props => <Table {...props} />;
const defaultRowTemplate = props => <TableRow {...props} />;
const defaultCellTemplate = props => <TableCell {...props} />;
const stubCellTemplate = props => <TableStubCell {...props} />;
const noDataCellTemplate = props => <TableNoDataCell {...props} />;

export const TableView = ({ tableCellTemplate, ...props }) => (
export const TableView = ({ tableCellTemplate, tableRowTemplate, ...props }) => (
<TableViewBase
tableLayoutTemplate={tableLayoutTemplate}
tableRowTemplate={combineTemplates(
tableRowTemplate,
defaultRowTemplate,
)}
tableCellTemplate={combineTemplates(
tableCellTemplate,
defaultCellTemplate,
Expand All @@ -27,7 +33,9 @@ export const TableView = ({ tableCellTemplate, ...props }) => (
);
TableView.propTypes = {
tableCellTemplate: PropTypes.func,
tableRowTemplate: PropTypes.func,
};
TableView.defaultProps = {
tableCellTemplate: undefined,
tableRowTemplate: undefined,
};
27 changes: 27 additions & 0 deletions packages/dx-react-grid-material-ui/src/templates/table-row.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import React from 'react';
import PropTypes from 'prop-types';

import {
TableRow as TableRowMUI,
} from 'material-ui';
import { withStyles } from 'material-ui/styles';

const TableRowBase = ({ children, tableRow, ...restProps }) => (
<TableRowMUI
selected={tableRow.selected}
{...restProps}
>
{children}
</TableRowMUI>
);

TableRowBase.propTypes = {
tableRow: PropTypes.object.isRequired,
children: PropTypes.node,
};

TableRowBase.defaultProps = {
children: null,
};

export const TableRow = withStyles({}, { name: 'TableRow' })(TableRowBase);
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import React from 'react';
import { TableRow as TableRowMUI } from 'material-ui';
import { createMount } from 'material-ui/test-utils';
import { setupConsole } from '@devexpress/dx-testing';
import { TableRow } from './table-row';

describe('TableRow', () => {
let resetConsole;
let mount;

const mountTableCell = ({ tableRow }) => (
mount(
<TableRow
tableRow={tableRow}
/>,
)
);
beforeAll(() => {
resetConsole = setupConsole({ ignore: ['validateDOMNesting'] });
mount = createMount();
});
afterAll(() => {
resetConsole();
mount.cleanUp();
});

it('should have correct selected prop', () => {
let tree = mountTableCell({ tableRow: { } });
expect(tree.find(TableRowMUI).prop('selected')).toBeFalsy();

tree = mountTableCell({ tableRow: { selected: true } });
expect(tree.find(TableRowMUI).prop('selected')).toBeTruthy();
});
});
Loading

0 comments on commit 24d9446

Please sign in to comment.