Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@
"jsdom": "11.2.0",
"jsdom-global": "3.0.2",
"lerna": "2.8.0",
"node-sass": "4.5.3",
"node-sass": "4.12.0",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

any reason why upgrade node-sass?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I forget exactly, but I think I couldn't get the dev environment to build on Ubuntu 18.04

"react-test-renderer": "16.0.0",
"sass-loader": "6.0.6",
"sinon": "3.2.1",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/* eslint react/prop-types: 0 */
import React from 'react';

import BootstrapTable from 'react-bootstrap-table-next';
import ToolkitProvider, { ColumnToggle } from 'react-bootstrap-table2-toolkit';
import Code from 'components/common/code-block';
import { productsGenerator } from 'utils/common';

const { ToggleList } = ColumnToggle;
const products = productsGenerator().map(row => ({ ...row, name: (row.id > 2 ? 'Item name >2' : 'Item name <=2') }));

const columns = [{
dataField: 'id',
text: 'Product ID'
}, {
dataField: 'name',
text: 'Product Name'
}, {
dataField: 'price',
text: 'Product Price',
reduce: (total, num) => total + num
}];

const sourceCode = `\
import BootstrapTable from 'react-bootstrap-table-next';
import filterFactory from 'react-bootstrap-table2-filter';
import ToolkitProvider, { ColumnToggle } from 'react-bootstrap-table2-toolkit';

const { ToggleList } = ColumnToggle;
const columns = [{
dataField: 'id',
text: 'Product ID'
}, {
dataField: 'name',
text: 'Product Name'
}, {
dataField: 'price',
text: 'Product Price',
reduce: (total, num) => total + num
}];

<ToolkitProvider
keyField="id"
data={ products }
columns={ columns }
columnToggle
>
{
props => (
<div>
<ToggleList { ...props.columnToggleProps } />
<hr />
<BootstrapTable
{ ...props.baseProps }
/>
</div>
)
}
</ToolkitProvider>
`;

export default () => (
<div>
<h3>Table will pivot when column toggle</h3>
<ToolkitProvider
keyField="id"
data={ products }
columns={ columns }
columnToggle
>
{
props => (
<div>
<ToggleList { ...props.columnToggleProps } />
<hr />
<BootstrapTable
{ ...props.baseProps }
/>
</div>
)
}
</ToolkitProvider>
<Code>{ sourceCode }</Code>
</div>
);
4 changes: 3 additions & 1 deletion packages/react-bootstrap-table2-example/stories/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,7 @@ import DefaultVisibility from 'examples/column-toggle/default-visibility';
import StylingColumnToggle from 'examples/column-toggle/styling-toggle-list';
import CustomToggleList from 'examples/column-toggle/custom-toggle-list';
import ColumnToggleWithFilter from 'examples/column-toggle/column-toggle-with-filter';
import ColumnToggleWithPivot from 'examples/column-toggle/column-toggle-with-pivot';

// loading overlay
import EmptyTableOverlay from 'examples/loading-overlay/empty-table-overlay';
Expand Down Expand Up @@ -478,7 +479,8 @@ storiesOf('Column Toggle', module)
.add('Default Visibility', () => <DefaultVisibility />)
.add('Styling Column Toggle', () => <StylingColumnToggle />)
.add('Custom Column Toggle', () => <CustomToggleList />)
.add('Column Toggle with Filter', () => <ColumnToggleWithFilter />);
.add('Column Toggle with Filter', () => <ColumnToggleWithFilter />)
.add('Column Toggle with Pivot', () => <ColumnToggleWithPivot />);

storiesOf('Export CSV', module)
.addDecorator(bootstrapStyle())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const ToggleList = ({
<div className={ `btn-group btn-group-toggle ${className}` } data-toggle="buttons">
{
columns
.filter(column => !Object.prototype.hasOwnProperty.call(column, 'reduce'))
.map(column => ({
...column,
toggle: toggles[column.dataField]
Expand Down
61 changes: 61 additions & 0 deletions packages/react-bootstrap-table2-toolkit/test/toggle-list.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import React from 'react';
import { shallow } from 'enzyme';

import ToggleList from '../src/column-toggle/toggle-list';

describe('ToggleList', () => {
const columns = [{
dataField: 'id',
text: 'ID'
}, {
dataField: 'name',
text: 'Name'
}];
const pivotColumns = [{
dataField: 'id',
text: 'ID'
}, {
dataField: 'name',
text: 'Name',
reduce: (T, t) => T + t
}];

let wrapper;
describe('simple toggle list', () => {
beforeEach(() => {
wrapper = shallow(
<ToggleList
columns={ columns }
onColumnToggle={ () => {} }
toggles={ { id: true, name: true } }
contextual={ 'btn-warning' }
className={ 'test' }
btnClassName={ 'test' }
/>
);
});

it('should render successfully', () => {
expect(wrapper.children().length).toBe(2);
});
});

describe('pivot toggle list', () => {
beforeEach(() => {
wrapper = shallow(
<ToggleList
columns={ pivotColumns }
onColumnToggle={ () => {} }
toggles={ { id: true, name: true } }
contextual={ 'btn-warning' }
className={ 'test' }
btnClassName={ 'test' }
/>
);
});

it('should render successfully', () => {
expect(wrapper.children().length).toBe(1);
});
});
});
47 changes: 41 additions & 6 deletions packages/react-bootstrap-table2/src/props-resolver/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,46 @@ export default ExtendBase =>
}

visibleRows() {
const { data, hiddenRows, keyField } = this.props;
if (!hiddenRows || hiddenRows.length === 0) return data;
return data.filter((row) => {
const key = _.get(row, keyField);
return !_.contains(hiddenRows, key);
});
const { data, hiddenRows, keyField, columns } = this.props;
const isPivotTable = this.props.columns.some(column => Object.prototype.hasOwnProperty.call(column, 'reduce'));

const filtered = (
!hiddenRows || hiddenRows.length === 0
? data
: data.filter((row) => {
const key = _.get(row, keyField);
return !_.contains(hiddenRows, key);
}));

if (isPivotTable) {
const groupByCols = columns.filter(
c => (this.props.columnToggle ? this.props.columnToggle.toggles[c.dataField] : true)
).filter(
c => !Object.prototype.hasOwnProperty.call(c, 'reduce')
).map(c => c.dataField);

const reduceCols = columns.filter(
c => Object.prototype.hasOwnProperty.call(c, 'reduce')
);

const aggregated = filtered.reduce((grouped, row) => {
const equals = grouped.map(g => groupByCols.every(k => g[0][k] === row[k]));
if (equals.some(b => b)) {
return grouped.map((g, i) => (equals[i] ? g.concat([row]) : g));
}
return grouped.concat([[row]]);
}, []).map(
group => Object.fromEntries(groupByCols.map(
name => [name, group[0][name]]
).concat(
reduceCols.map(
r => [r.dataField, group.map(g => g[r.dataField]).reduce(r.reduce)]
)
))
);

return aggregated;
}
return filtered;
}
};
47 changes: 47 additions & 0 deletions packages/react-bootstrap-table2/test/props-resolver/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,21 @@ describe('TableResolver', () => {
id: 2,
name: 'B'
}];
const pivotColumns = [{
dataField: keyField,
text: 'ID'
}, {
dataField: 'name',
text: 'Name',
reduce: (T, t) => T + t
}];
const pivotData = [{
id: 1,
name: 'A'
}, {
id: 1,
name: 'B'
}];

const ExtendBase = baseResolver(Component);
const BootstrapTableMock = extendTo(ExtendBase);
Expand Down Expand Up @@ -52,6 +67,38 @@ describe('TableResolver', () => {
});
});

describe('if pivot table is not collapsed', () => {
beforeEach(() => {
const mockElement = React.createElement(BootstrapTableMock, {
data, columns: pivotColumns, keyField
}, null);
wrapper = shallow(mockElement);
});

it('should return correct data', () => {
expect(pivotColumns.some(
column => Object.prototype.hasOwnProperty.call(column, 'reduce')
)).toBeTruthy();
expect(wrapper.instance().visibleRows()).toEqual(data);
});
});

describe('if pivot table is collapsed', () => {
beforeEach(() => {
const mockElement = React.createElement(BootstrapTableMock, {
data: pivotData, columns: pivotColumns, keyField
}, null);
wrapper = shallow(mockElement);
});

it('should return correct data', () => {
expect(pivotColumns.some(
column => Object.prototype.hasOwnProperty.call(column, 'reduce')
)).toBeTruthy();
expect(wrapper.instance().visibleRows()).toEqual([{ id: 1, name: 'AB' }]);
});
});

describe('if hiddenRows prop is not an empty array', () => {
const hiddenRows = [1];

Expand Down