From ece15fe3b368e44951aad2c0081ca887bc3e4fee Mon Sep 17 00:00:00 2001 From: Chun-MingChen Date: Sat, 4 Nov 2017 16:59:34 +0800 Subject: [PATCH 01/15] fix missing defaultSorted props for default sort sample --- .../examples/sort/default-sort-table.js | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/packages/react-bootstrap-table2-example/examples/sort/default-sort-table.js b/packages/react-bootstrap-table2-example/examples/sort/default-sort-table.js index 0f238a849..9cda0a41e 100644 --- a/packages/react-bootstrap-table2-example/examples/sort/default-sort-table.js +++ b/packages/react-bootstrap-table2-example/examples/sort/default-sort-table.js @@ -41,7 +41,17 @@ const columns = [{ sort: true }]; - +const defaultSorted = [{ + dataField: 'name', + order: 'desc' +}]; + + `; From 8a932d74aa83b50aceb1c01380d95248aa2bf4dc Mon Sep 17 00:00:00 2001 From: Chun-MingChen Date: Sat, 4 Nov 2017 18:16:48 +0800 Subject: [PATCH 02/15] implement customized classes for sorted header --- .../examples/sort/sorted-header-classes.js | 53 +++++++++++++++++++ .../stories/index.js | 4 +- .../stories/stylesheet/sort/_index.scss | 3 ++ .../stories/stylesheet/storybook.scss | 3 +- .../src/bootstrap-table.js | 9 +++- .../react-bootstrap-table2/src/header-cell.js | 33 +++++++++--- packages/react-bootstrap-table2/src/header.js | 3 ++ 7 files changed, 97 insertions(+), 11 deletions(-) create mode 100644 packages/react-bootstrap-table2-example/examples/sort/sorted-header-classes.js create mode 100644 packages/react-bootstrap-table2-example/stories/stylesheet/sort/_index.scss diff --git a/packages/react-bootstrap-table2-example/examples/sort/sorted-header-classes.js b/packages/react-bootstrap-table2-example/examples/sort/sorted-header-classes.js new file mode 100644 index 000000000..2bd3f4f63 --- /dev/null +++ b/packages/react-bootstrap-table2-example/examples/sort/sorted-header-classes.js @@ -0,0 +1,53 @@ +/* eslint no-unused-vars: 0 */ +import React from 'react'; + +import BootstrapTable from 'react-bootstrap-table2'; +import Code from 'components/common/code-block'; +import { productsGenerator } from 'utils/common'; + +const products = productsGenerator(); + +const columns = [{ + dataField: 'id', + text: 'Product ID', + sort: true +}, { + dataField: 'name', + text: 'Product Name', + sort: true +}, { + dataField: 'price', + text: 'Product Price' +}]; + +const sortedHeader = { + classes: (column, colIndex) => 'demo-sorted' +}; + +const sourceCode = `\ +const columns = [{ + dataField: 'id', + text: 'Product ID', + sort: true +}, { + dataField: 'name', + text: 'Product Name', + sort: true +}, { + dataField: 'price', + text: 'Product Price' +}]; + +const sortedHeader = { + classes: (column, colIndex) => 'demo-sorted' +}; + + +`; + +export default () => ( +
+ + { sourceCode } +
+); diff --git a/packages/react-bootstrap-table2-example/stories/index.js b/packages/react-bootstrap-table2-example/stories/index.js index c97b373a4..d16d99a37 100644 --- a/packages/react-bootstrap-table2-example/stories/index.js +++ b/packages/react-bootstrap-table2-example/stories/index.js @@ -41,6 +41,7 @@ import RowEventTable from 'examples/rows/row-event'; import EnableSortTable from 'examples/sort/enable-sort-table'; import DefaultSortTable from 'examples/sort/default-sort-table'; import CustomSortTable from 'examples/sort/custom-sort-table'; +import SortedHeaderClassesTable from 'examples/sort/sorted-header-classes'; // cell editing import ClickToEditTable from 'examples/cell-edit/click-to-edit-table'; @@ -116,7 +117,8 @@ storiesOf('Work on Rows', module) storiesOf('Sort Table', module) .add('Enable Sort', () => ) .add('Default Sort Table', () => ) - .add('Custom Sort Fuction', () => ); + .add('Custom Sort Fuction', () => ) + .add('Sorted header classes', () => ); storiesOf('Cell Editing', module) .add('Click to Edit', () => ) diff --git a/packages/react-bootstrap-table2-example/stories/stylesheet/sort/_index.scss b/packages/react-bootstrap-table2-example/stories/stylesheet/sort/_index.scss new file mode 100644 index 000000000..d30bad46e --- /dev/null +++ b/packages/react-bootstrap-table2-example/stories/stylesheet/sort/_index.scss @@ -0,0 +1,3 @@ +.demo-sorted { + background-color: $green-lighten-2; +} diff --git a/packages/react-bootstrap-table2-example/stories/stylesheet/storybook.scss b/packages/react-bootstrap-table2-example/stories/stylesheet/storybook.scss index 3bbec85d6..baa1d1608 100644 --- a/packages/react-bootstrap-table2-example/stories/stylesheet/storybook.scss +++ b/packages/react-bootstrap-table2-example/stories/stylesheet/storybook.scss @@ -7,4 +7,5 @@ @import "columns/index"; @import "cell-edit/index"; @import "row-selection/index"; -@import "rows/index"; \ No newline at end of file +@import "rows/index"; +@import "sort/index"; diff --git a/packages/react-bootstrap-table2/src/bootstrap-table.js b/packages/react-bootstrap-table2/src/bootstrap-table.js index d77d47ff9..b38120163 100644 --- a/packages/react-bootstrap-table2/src/bootstrap-table.js +++ b/packages/react-bootstrap-table2/src/bootstrap-table.js @@ -38,7 +38,8 @@ class BootstrapTable extends PropsBaseResolver(Component) { caption, rowStyle, rowClasses, - rowEvents + rowEvents, + sortedHeader } = this.props; const tableClass = cs('table', { @@ -75,6 +76,7 @@ class BootstrapTable extends PropsBaseResolver(Component) { sortOrder={ store.sortOrder } onSort={ this.props.onSort } selectRow={ headerCellSelectionInfo } + sortedHeader={ sortedHeader } /> { index, onSort, sorting, - sortOrder + sortOrder, + sortedHeader } = props; + const { text, sort, @@ -30,15 +32,17 @@ const HeaderCell = (props) => { headerAttrs } = column; + const { classes: sortedHeaderClasses } = sortedHeader; + const cellAttrs = { ..._.isFunction(headerAttrs) ? headerAttrs(column, index) : headerAttrs, ...headerEvents }; const children = headerFormatter ? headerFormatter(column, index) : text; - const cellClasses = _.isFunction(headerClasses) ? headerClasses(column, index) : headerClasses; let cellStyle = {}; let sortSymbol; + let cellClasses = _.isFunction(headerClasses) ? headerClasses(column, index) : headerClasses; if (headerStyle) { cellStyle = _.isFunction(headerStyle) ? headerStyle(column, index) : headerStyle; @@ -56,10 +60,6 @@ const HeaderCell = (props) => { cellStyle.display = 'none'; } - if (cellClasses) cellAttrs.className = cellClasses; - - if (!_.isEmptyObject(cellStyle)) cellAttrs.style = cellStyle; - if (sort) { const customClick = cellAttrs.onClick; cellAttrs.onClick = (e) => { @@ -70,11 +70,23 @@ const HeaderCell = (props) => { if (sorting) { sortSymbol = ; + + // appending customized sorted classes + cellClasses = cs( + cellClasses, + _.isFunction(sortedHeaderClasses) + ? sortedHeaderClasses(column, index) + : sortedHeaderClasses + ); } else { sortSymbol = ; } } + if (cellClasses) cellAttrs.className = cs(cellAttrs.className, cellClasses); + + if (!_.isEmptyObject(cellStyle)) cellAttrs.style = cellStyle; + return ( { children }{ sortSymbol } @@ -112,7 +124,14 @@ HeaderCell.propTypes = { index: PropTypes.number.isRequired, onSort: PropTypes.func, sorting: PropTypes.bool, - sortOrder: PropTypes.oneOf([Const.SORT_ASC, Const.SORT_DESC]) + sortOrder: PropTypes.oneOf([Const.SORT_ASC, Const.SORT_DESC]), + sortedHeader: PropTypes.shape({ + classes: PropTypes.oneOfType([PropTypes.func, PropTypes.string]) + }) +}; + +HeaderCell.defaultProps = { + sortedHeader: {} }; export default HeaderCell; diff --git a/packages/react-bootstrap-table2/src/header.js b/packages/react-bootstrap-table2/src/header.js index e301eb032..0c86e3bc5 100644 --- a/packages/react-bootstrap-table2/src/header.js +++ b/packages/react-bootstrap-table2/src/header.js @@ -1,3 +1,4 @@ +/* eslint react/prop-types: 0 */ /* eslint react/require-default-props: 0 */ import React from 'react'; import PropTypes from 'prop-types'; @@ -14,6 +15,7 @@ const Header = (props) => { onSort, sortField, sortOrder, + sortedHeader, selectRow } = props; @@ -35,6 +37,7 @@ const Header = (props) => { onSort={ onSort } sorting={ currSort } sortOrder={ sortOrder } + sortedHeader={ sortedHeader } />); }) } From fa439977dfcd7dcd5d9f6ecc93d48d44e4f83f0c Mon Sep 17 00:00:00 2001 From: Chun-MingChen Date: Sat, 4 Nov 2017 22:46:28 +0800 Subject: [PATCH 03/15] [test] test for sorted header classes --- .../test/header-cell.test.js | 80 +++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/packages/react-bootstrap-table2/test/header-cell.test.js b/packages/react-bootstrap-table2/test/header-cell.test.js index 4e2dda5ca..b1fba342f 100644 --- a/packages/react-bootstrap-table2/test/header-cell.test.js +++ b/packages/react-bootstrap-table2/test/header-cell.test.js @@ -436,6 +436,86 @@ describe('HeaderCell', () => { }); }); }); + + describe('when sortedHeader.classes was defined ', () => { + let sortedHeader; + + describe('if sortedHeader.classes is a string', () => { + beforeEach(() => { + sortedHeader = { classes: 'foo' }; + wrapper = shallow( + ); + }); + + it('should append classes correcly', () => { + expect(wrapper.length).toBe(1); + expect(wrapper.hasClass(sortedHeader.classes)).toBe(true); + }); + + it('should have sortable class on header cell', () => { + expect(wrapper.hasClass('sortable')).toBe(true); + }); + }); + + describe('if sortedHeader.classes is a function', () => { + let classesCallBack; + const classes = 'foo'; + + beforeEach(() => { + classesCallBack = sinon.stub() + .withArgs(column, index) + .returns(classes); + + sortedHeader = { classes: classesCallBack }; + wrapper = shallow( + ); + }); + + it('should append classes correcly', () => { + expect(wrapper.length).toBe(1); + expect(wrapper.hasClass(classes)).toBe(true); + }); + + it('should call custom classes function correctly', () => { + expect(classesCallBack.callCount).toBe(1); + expect(classesCallBack.calledWith(column, index)).toBe(true); + }); + + it('should have sortable class on header cell', () => { + expect(wrapper.hasClass('sortable')).toBe(true); + }); + }); + }); + + describe('when sortedHeader.classes was not defined', () => { + it('should do nothing and keep the same on classes of header cell', () => { + column.headerClasses = 'td-test-class'; + + wrapper = shallow( + + ); + expect(wrapper.length).toBe(1); + expect(wrapper.hasClass('sortable')).toBe(true); + expect(wrapper.hasClass(column.headerClasses)).toBe(true); + }); + }); }); describe('when column.headerEvents prop is defined and have custom onClick', () => { From 97a62ed7efaae4d756ff284af6c395e9e2e14afc Mon Sep 17 00:00:00 2001 From: Chun-MingChen Date: Sat, 4 Nov 2017 23:06:17 +0800 Subject: [PATCH 04/15] implement customized style for sorted header --- .../examples/sort/sorted-header-style.js | 53 +++++++++++++++++++ .../stories/index.js | 4 +- .../src/bootstrap-table.js | 3 +- .../react-bootstrap-table2/src/header-cell.js | 17 ++++-- 4 files changed, 72 insertions(+), 5 deletions(-) create mode 100644 packages/react-bootstrap-table2-example/examples/sort/sorted-header-style.js diff --git a/packages/react-bootstrap-table2-example/examples/sort/sorted-header-style.js b/packages/react-bootstrap-table2-example/examples/sort/sorted-header-style.js new file mode 100644 index 000000000..a269934a4 --- /dev/null +++ b/packages/react-bootstrap-table2-example/examples/sort/sorted-header-style.js @@ -0,0 +1,53 @@ +/* eslint no-unused-vars: 0 */ +import React from 'react'; + +import BootstrapTable from 'react-bootstrap-table2'; +import Code from 'components/common/code-block'; +import { productsGenerator } from 'utils/common'; + +const products = productsGenerator(); + +const columns = [{ + dataField: 'id', + text: 'Product ID', + sort: true +}, { + dataField: 'name', + text: 'Product Name', + sort: true +}, { + dataField: 'price', + text: 'Product Price' +}]; + +const sortedHeader = { + style: { backgroundColor: '#c8e6c9' } +}; + +const sourceCode = `\ +const columns = [{ + dataField: 'id', + text: 'Product ID', + sort: true +}, { + dataField: 'name', + text: 'Product Name', + sort: true +}, { + dataField: 'price', + text: 'Product Price' +}]; + +const sortedHeader = { + style: { backgroundColor: '#c8e6c9' } +}; + + +`; + +export default () => ( +
+ + { sourceCode } +
+); diff --git a/packages/react-bootstrap-table2-example/stories/index.js b/packages/react-bootstrap-table2-example/stories/index.js index d16d99a37..5779fd7d9 100644 --- a/packages/react-bootstrap-table2-example/stories/index.js +++ b/packages/react-bootstrap-table2-example/stories/index.js @@ -42,6 +42,7 @@ import EnableSortTable from 'examples/sort/enable-sort-table'; import DefaultSortTable from 'examples/sort/default-sort-table'; import CustomSortTable from 'examples/sort/custom-sort-table'; import SortedHeaderClassesTable from 'examples/sort/sorted-header-classes'; +import SortedHeaderStyleTable from 'examples/sort/sorted-header-style'; // cell editing import ClickToEditTable from 'examples/cell-edit/click-to-edit-table'; @@ -118,7 +119,8 @@ storiesOf('Sort Table', module) .add('Enable Sort', () => ) .add('Default Sort Table', () => ) .add('Custom Sort Fuction', () => ) - .add('Sorted header classes', () => ); + .add('Sorted header classes', () => ) + .add('Sorted header style', () => ); storiesOf('Cell Editing', module) .add('Click to Edit', () => ) diff --git a/packages/react-bootstrap-table2/src/bootstrap-table.js b/packages/react-bootstrap-table2/src/bootstrap-table.js index b38120163..32d1def84 100644 --- a/packages/react-bootstrap-table2/src/bootstrap-table.js +++ b/packages/react-bootstrap-table2/src/bootstrap-table.js @@ -156,7 +156,8 @@ BootstrapTable.propTypes = { order: PropTypes.oneOf([Const.SORT_DESC, Const.SORT_ASC]).isRequired })), sortedHeader: PropTypes.shape({ - classes: PropTypes.oneOfType([PropTypes.func, PropTypes.string]) + classes: PropTypes.oneOfType([PropTypes.func, PropTypes.string]), + style: PropTypes.oneOfType([PropTypes.func, PropTypes.object]) }) }; diff --git a/packages/react-bootstrap-table2/src/header-cell.js b/packages/react-bootstrap-table2/src/header-cell.js index bfccf9be7..9c7f0cca2 100644 --- a/packages/react-bootstrap-table2/src/header-cell.js +++ b/packages/react-bootstrap-table2/src/header-cell.js @@ -32,7 +32,10 @@ const HeaderCell = (props) => { headerAttrs } = column; - const { classes: sortedHeaderClasses } = sortedHeader; + const { + classes: sortedHeaderClasses, + style: sortedHeaderStyle + } = sortedHeader; const cellAttrs = { ..._.isFunction(headerAttrs) ? headerAttrs(column, index) : headerAttrs, @@ -71,13 +74,20 @@ const HeaderCell = (props) => { if (sorting) { sortSymbol = ; - // appending customized sorted classes + // append customized classes or style if table was sorting based on the current column. cellClasses = cs( cellClasses, _.isFunction(sortedHeaderClasses) ? sortedHeaderClasses(column, index) : sortedHeaderClasses ); + + cellStyle = { + ...cellStyle, + ..._.isFunction(sortedHeaderStyle) + ? sortedHeaderStyle(column, index) + : sortedHeaderStyle + }; } else { sortSymbol = ; } @@ -126,7 +136,8 @@ HeaderCell.propTypes = { sorting: PropTypes.bool, sortOrder: PropTypes.oneOf([Const.SORT_ASC, Const.SORT_DESC]), sortedHeader: PropTypes.shape({ - classes: PropTypes.oneOfType([PropTypes.func, PropTypes.string]) + classes: PropTypes.oneOfType([PropTypes.func, PropTypes.string]), + style: PropTypes.oneOfType([PropTypes.func, PropTypes.object]) }) }; From 5de10c5a2356bec6b5583222c424dfc2ea3bfc6d Mon Sep 17 00:00:00 2001 From: Chun-MingChen Date: Sat, 4 Nov 2017 23:21:46 +0800 Subject: [PATCH 05/15] [test] test for sorted header style --- .../test/header-cell.test.js | 77 +++++++++++++++++++ 1 file changed, 77 insertions(+) diff --git a/packages/react-bootstrap-table2/test/header-cell.test.js b/packages/react-bootstrap-table2/test/header-cell.test.js index b1fba342f..5b553fdd1 100644 --- a/packages/react-bootstrap-table2/test/header-cell.test.js +++ b/packages/react-bootstrap-table2/test/header-cell.test.js @@ -516,6 +516,83 @@ describe('HeaderCell', () => { expect(wrapper.hasClass(column.headerClasses)).toBe(true); }); }); + + describe('when sortedHeader.style was defined', () => { + let sortedHeader; + + describe('if sortedHeader.style is an object', () => { + beforeEach(() => { + sortedHeader = { + style: { backgroundColor: 'red' } + }; + + wrapper = shallow( + ); + }); + + it('should append style correcly', () => { + expect(wrapper.length).toBe(1); + expect(wrapper.find('th').prop('style')).toEqual(sortedHeader.style); + }); + }); + + describe('if sortedHeader.style is a function', () => { + const style = { backgroundColor: 'red' }; + let styleCallBack; + + beforeEach(() => { + styleCallBack = sinon.stub() + .withArgs(column, index) + .returns(style); + + sortedHeader = { + style: styleCallBack + }; + + wrapper = shallow( + ); + }); + + it('should append style correcly', () => { + expect(wrapper.length).toBe(1); + expect(wrapper.find('th').prop('style')).toEqual(style); + }); + + it('should call custom style function correctly', () => { + expect(styleCallBack.callCount).toBe(1); + expect(styleCallBack.calledWith(column, index)).toBe(true); + }); + }); + }); + + describe('when sortedHeader.style was not defined', () => { + it('should do nothing and keep the same on style of header cell', () => { + column.headerStyle = { backgroundColor: 'red' }; + + wrapper = shallow( + + ); + expect(wrapper.length).toBe(1); + expect(wrapper.find('th').prop('style')).toEqual(column.headerStyle); + }); + }); }); describe('when column.headerEvents prop is defined and have custom onClick', () => { From 6770b4fc610199522fdb511700e0ded221b3cf33 Mon Sep 17 00:00:00 2001 From: Chun-MingChen Date: Sat, 4 Nov 2017 23:54:59 +0800 Subject: [PATCH 06/15] update document --- docs/README.md | 41 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/docs/README.md b/docs/README.md index fb53620f0..143f0c3cc 100644 --- a/docs/README.md +++ b/docs/README.md @@ -19,6 +19,7 @@ * [rowClasses](#rowClasses) * [rowEvents](#rowEvents) * [defaultSorted](#defaultSorted) +* [sortedHeader](#sortedHeader) ### keyField(**required**) - [String] Tells `react-bootstrap-table2` which column is unique. @@ -101,4 +102,42 @@ const defaultSorted = [{ dataField: 'name', // if dataField is not match to any column you defined, it will be ignored. order: 'desc' // desc or asc }]; -``` \ No newline at end of file +``` + +### sortedHeader - [Object] + +`sortedHeader` allows you to customize `class` or `style` for `header cell` which is currently sorting. `sortedHeader` accepts two `attributes`, `classes` and `style`. + +* classes +* style + +**sortedHeader.classes - [String | Function]** + +Append customized classes for `header cell` which the table was sorting based on. + +```js +sortedHeader = { + classes: 'demo-sorted' +}; +``` + +Furthermore, it also accepts a callback function which takes `2` arguments and `String` is expected to return: + +```js +sortedHeader = { + classes: function callback(column, colIndex) { ... } +} +``` + +* column: The value of current column. +* colIndex: The index of the current column being processed in BootstrapTable. + +**sortedHeader.style - [Object | Function]** + +It's similiar to `sortedHeader.classes`. It allow to customize style of `header cell` which is sorting based on. `Object` and `callback` function are acceptable. `callback` takes `2` arguments and an `Object` is expected to return: + +```js +sortedHeader = { + style: { backgroundColor: 'red' } +}; +``` From 241914625d64f6dde72de9e533a8001b2c64b726 Mon Sep 17 00:00:00 2001 From: Chun-MingChen Date: Sun, 5 Nov 2017 00:07:28 +0800 Subject: [PATCH 07/15] add missing props check and fix typo --- docs/README.md | 8 ++++---- packages/react-bootstrap-table2/src/header.js | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/README.md b/docs/README.md index 143f0c3cc..1ad8f71b9 100644 --- a/docs/README.md +++ b/docs/README.md @@ -116,7 +116,7 @@ const defaultSorted = [{ Append customized classes for `header cell` which the table was sorting based on. ```js -sortedHeader = { +const sortedHeader = { classes: 'demo-sorted' }; ``` @@ -124,7 +124,7 @@ sortedHeader = { Furthermore, it also accepts a callback function which takes `2` arguments and `String` is expected to return: ```js -sortedHeader = { +const sortedHeader = { classes: function callback(column, colIndex) { ... } } ``` @@ -134,10 +134,10 @@ sortedHeader = { **sortedHeader.style - [Object | Function]** -It's similiar to `sortedHeader.classes`. It allow to customize style of `header cell` which is sorting based on. `Object` and `callback` function are acceptable. `callback` takes `2` arguments and an `Object` is expected to return: +It's similiar to `sortedHeader.classes`. It allows to customize style of `header cell` which is sorting based on. `Object` and `callback` function are acceptable. `callback` takes `2` arguments and an `Object` is expected to return: ```js -sortedHeader = { +const sortedHeader = { style: { backgroundColor: 'red' } }; ``` diff --git a/packages/react-bootstrap-table2/src/header.js b/packages/react-bootstrap-table2/src/header.js index 0c86e3bc5..f86051234 100644 --- a/packages/react-bootstrap-table2/src/header.js +++ b/packages/react-bootstrap-table2/src/header.js @@ -1,4 +1,3 @@ -/* eslint react/prop-types: 0 */ /* eslint react/require-default-props: 0 */ import React from 'react'; import PropTypes from 'prop-types'; @@ -51,7 +50,8 @@ Header.propTypes = { onSort: PropTypes.func, sortField: PropTypes.string, sortOrder: PropTypes.string, - selectRow: PropTypes.object + selectRow: PropTypes.object, + sortedHeader: PropTypes.object }; export default Header; From 115ca19262adc10a225addfcf3a55e90e7e9270f Mon Sep 17 00:00:00 2001 From: Chun-MingChen Date: Sun, 5 Nov 2017 17:15:44 +0800 Subject: [PATCH 08/15] seperate sorting style and header into two props --- docs/README.md | 32 +++++--------- ...r-classes.js => sorting-header-classes.js} | 12 ++--- ...eader-style.js => sorting-header-style.js} | 12 ++--- .../stories/index.js | 8 ++-- .../stories/stylesheet/sort/_index.scss | 2 +- .../src/bootstrap-table.js | 12 ++--- .../react-bootstrap-table2/src/header-cell.js | 30 +++++-------- packages/react-bootstrap-table2/src/header.js | 9 ++-- .../test/header-cell.test.js | 44 +++++++------------ 9 files changed, 62 insertions(+), 99 deletions(-) rename packages/react-bootstrap-table2-example/examples/sort/{sorted-header-classes.js => sorting-header-classes.js} (78%) rename packages/react-bootstrap-table2-example/examples/sort/{sorted-header-style.js => sorting-header-style.js} (79%) diff --git a/docs/README.md b/docs/README.md index 1ad8f71b9..1c6c1251f 100644 --- a/docs/README.md +++ b/docs/README.md @@ -19,7 +19,8 @@ * [rowClasses](#rowClasses) * [rowEvents](#rowEvents) * [defaultSorted](#defaultSorted) -* [sortedHeader](#sortedHeader) +* [sortingHeaderClasses](#sortingHeaderClasses) +* [sortingHeaderStyle](#sortingHeaderStyle) ### keyField(**required**) - [String] Tells `react-bootstrap-table2` which column is unique. @@ -104,40 +105,29 @@ const defaultSorted = [{ }]; ``` -### sortedHeader - [Object] +### sortingHeaderClasses - [String | Function] -`sortedHeader` allows you to customize `class` or `style` for `header cell` which is currently sorting. `sortedHeader` accepts two `attributes`, `classes` and `style`. - -* classes -* style - -**sortedHeader.classes - [String | Function]** - -Append customized classes for `header cell` which the table was sorting based on. +`sortingHeaderClasses` allows you to customize `class` for `header cell` which the table was sorting based on. ```js -const sortedHeader = { - classes: 'demo-sorted' -}; +const sortingHeaderClasses = 'demo-sorting'; ``` Furthermore, it also accepts a callback function which takes `2` arguments and `String` is expected to return: ```js -const sortedHeader = { - classes: function callback(column, colIndex) { ... } -} +const sortingHeaderClasses = function callback(column, colIndex) { ... } ``` * column: The value of current column. * colIndex: The index of the current column being processed in BootstrapTable. -**sortedHeader.style - [Object | Function]** +### sortingHeaderStyle - [Object | Function] -It's similiar to `sortedHeader.classes`. It allows to customize style of `header cell` which is sorting based on. `Object` and `callback` function are acceptable. `callback` takes `2` arguments and an `Object` is expected to return: +It's similiar to `sortingHeaderClasses`. It allows to customize style of `header cell` which is sorting based on. `Object` and `callback` function are acceptable. `callback` takes `2` arguments and an `Object` is expected to return: ```js -const sortedHeader = { - style: { backgroundColor: 'red' } +const sortingHeaderStyle = { + backgroundColor: 'red' }; -``` +``` \ No newline at end of file diff --git a/packages/react-bootstrap-table2-example/examples/sort/sorted-header-classes.js b/packages/react-bootstrap-table2-example/examples/sort/sorting-header-classes.js similarity index 78% rename from packages/react-bootstrap-table2-example/examples/sort/sorted-header-classes.js rename to packages/react-bootstrap-table2-example/examples/sort/sorting-header-classes.js index 2bd3f4f63..640d58d0c 100644 --- a/packages/react-bootstrap-table2-example/examples/sort/sorted-header-classes.js +++ b/packages/react-bootstrap-table2-example/examples/sort/sorting-header-classes.js @@ -20,9 +20,7 @@ const columns = [{ text: 'Product Price' }]; -const sortedHeader = { - classes: (column, colIndex) => 'demo-sorted' -}; +const sortingHeaderClasses = (column, colIndex) => 'demo-sorting'; const sourceCode = `\ const columns = [{ @@ -38,16 +36,14 @@ const columns = [{ text: 'Product Price' }]; -const sortedHeader = { - classes: (column, colIndex) => 'demo-sorted' -}; +const sortingHeaderClasses = (column, colIndex) => 'demo-sorting'; - + `; export default () => (
- + { sourceCode }
); diff --git a/packages/react-bootstrap-table2-example/examples/sort/sorted-header-style.js b/packages/react-bootstrap-table2-example/examples/sort/sorting-header-style.js similarity index 79% rename from packages/react-bootstrap-table2-example/examples/sort/sorted-header-style.js rename to packages/react-bootstrap-table2-example/examples/sort/sorting-header-style.js index a269934a4..bbeb2dc6a 100644 --- a/packages/react-bootstrap-table2-example/examples/sort/sorted-header-style.js +++ b/packages/react-bootstrap-table2-example/examples/sort/sorting-header-style.js @@ -20,9 +20,7 @@ const columns = [{ text: 'Product Price' }]; -const sortedHeader = { - style: { backgroundColor: '#c8e6c9' } -}; +const sortingHeaderStyle = { backgroundColor: '#c8e6c9' }; const sourceCode = `\ const columns = [{ @@ -38,16 +36,14 @@ const columns = [{ text: 'Product Price' }]; -const sortedHeader = { - style: { backgroundColor: '#c8e6c9' } -}; +const sortingHeaderStyle = { backgroundColor: '#c8e6c9' }; - + `; export default () => (
- + { sourceCode }
); diff --git a/packages/react-bootstrap-table2-example/stories/index.js b/packages/react-bootstrap-table2-example/stories/index.js index 5779fd7d9..8d2381a43 100644 --- a/packages/react-bootstrap-table2-example/stories/index.js +++ b/packages/react-bootstrap-table2-example/stories/index.js @@ -41,8 +41,8 @@ import RowEventTable from 'examples/rows/row-event'; import EnableSortTable from 'examples/sort/enable-sort-table'; import DefaultSortTable from 'examples/sort/default-sort-table'; import CustomSortTable from 'examples/sort/custom-sort-table'; -import SortedHeaderClassesTable from 'examples/sort/sorted-header-classes'; -import SortedHeaderStyleTable from 'examples/sort/sorted-header-style'; +import SortingHeaderClassesTable from 'examples/sort/sorting-header-classes'; +import SortingHeaderStyleTable from 'examples/sort/sorting-header-style'; // cell editing import ClickToEditTable from 'examples/cell-edit/click-to-edit-table'; @@ -119,8 +119,8 @@ storiesOf('Sort Table', module) .add('Enable Sort', () => ) .add('Default Sort Table', () => ) .add('Custom Sort Fuction', () => ) - .add('Sorted header classes', () => ) - .add('Sorted header style', () => ); + .add('Sorting header classes', () => ) + .add('Sorting header style', () => ); storiesOf('Cell Editing', module) .add('Click to Edit', () => ) diff --git a/packages/react-bootstrap-table2-example/stories/stylesheet/sort/_index.scss b/packages/react-bootstrap-table2-example/stories/stylesheet/sort/_index.scss index d30bad46e..d954b94e2 100644 --- a/packages/react-bootstrap-table2-example/stories/stylesheet/sort/_index.scss +++ b/packages/react-bootstrap-table2-example/stories/stylesheet/sort/_index.scss @@ -1,3 +1,3 @@ -.demo-sorted { +.demo-sorting { background-color: $green-lighten-2; } diff --git a/packages/react-bootstrap-table2/src/bootstrap-table.js b/packages/react-bootstrap-table2/src/bootstrap-table.js index 32d1def84..875b5a9aa 100644 --- a/packages/react-bootstrap-table2/src/bootstrap-table.js +++ b/packages/react-bootstrap-table2/src/bootstrap-table.js @@ -39,7 +39,8 @@ class BootstrapTable extends PropsBaseResolver(Component) { rowStyle, rowClasses, rowEvents, - sortedHeader + sortingHeaderClasses, + sortingHeaderStyle } = this.props; const tableClass = cs('table', { @@ -76,7 +77,8 @@ class BootstrapTable extends PropsBaseResolver(Component) { sortOrder={ store.sortOrder } onSort={ this.props.onSort } selectRow={ headerCellSelectionInfo } - sortedHeader={ sortedHeader } + sortingHeaderClasses={ sortingHeaderClasses } + sortingHeaderStyle={ sortingHeaderStyle } /> { onSort, sorting, sortOrder, - sortedHeader + sortingHeaderClasses, + sortingHeaderStyle } = props; const { @@ -32,11 +33,6 @@ const HeaderCell = (props) => { headerAttrs } = column; - const { - classes: sortedHeaderClasses, - style: sortedHeaderStyle - } = sortedHeader; - const cellAttrs = { ..._.isFunction(headerAttrs) ? headerAttrs(column, index) : headerAttrs, ...headerEvents @@ -77,16 +73,16 @@ const HeaderCell = (props) => { // append customized classes or style if table was sorting based on the current column. cellClasses = cs( cellClasses, - _.isFunction(sortedHeaderClasses) - ? sortedHeaderClasses(column, index) - : sortedHeaderClasses + _.isFunction(sortingHeaderClasses) + ? sortingHeaderClasses(column, index) + : sortingHeaderClasses ); cellStyle = { ...cellStyle, - ..._.isFunction(sortedHeaderStyle) - ? sortedHeaderStyle(column, index) - : sortedHeaderStyle + ..._.isFunction(sortingHeaderStyle) + ? sortingHeaderStyle(column, index) + : sortingHeaderStyle }; } else { sortSymbol = ; @@ -135,14 +131,8 @@ HeaderCell.propTypes = { onSort: PropTypes.func, sorting: PropTypes.bool, sortOrder: PropTypes.oneOf([Const.SORT_ASC, Const.SORT_DESC]), - sortedHeader: PropTypes.shape({ - classes: PropTypes.oneOfType([PropTypes.func, PropTypes.string]), - style: PropTypes.oneOfType([PropTypes.func, PropTypes.object]) - }) -}; - -HeaderCell.defaultProps = { - sortedHeader: {} + sortingHeaderClasses: PropTypes.oneOfType([PropTypes.func, PropTypes.string]), + sortingHeaderStyle: PropTypes.oneOfType([PropTypes.func, PropTypes.object]) }; export default HeaderCell; diff --git a/packages/react-bootstrap-table2/src/header.js b/packages/react-bootstrap-table2/src/header.js index f86051234..ce20b4add 100644 --- a/packages/react-bootstrap-table2/src/header.js +++ b/packages/react-bootstrap-table2/src/header.js @@ -14,7 +14,8 @@ const Header = (props) => { onSort, sortField, sortOrder, - sortedHeader, + sortingHeaderClasses, + sortingHeaderStyle, selectRow } = props; @@ -36,7 +37,8 @@ const Header = (props) => { onSort={ onSort } sorting={ currSort } sortOrder={ sortOrder } - sortedHeader={ sortedHeader } + sortingHeaderClasses={ sortingHeaderClasses } + sortingHeaderStyle={ sortingHeaderStyle } />); }) } @@ -51,7 +53,8 @@ Header.propTypes = { sortField: PropTypes.string, sortOrder: PropTypes.string, selectRow: PropTypes.object, - sortedHeader: PropTypes.object + sortingHeaderClasses: PropTypes.oneOfType([PropTypes.func, PropTypes.string]), + sortingHeaderStyle: PropTypes.oneOfType([PropTypes.func, PropTypes.object]) }; export default Header; diff --git a/packages/react-bootstrap-table2/test/header-cell.test.js b/packages/react-bootstrap-table2/test/header-cell.test.js index 5b553fdd1..c249ce544 100644 --- a/packages/react-bootstrap-table2/test/header-cell.test.js +++ b/packages/react-bootstrap-table2/test/header-cell.test.js @@ -437,25 +437,24 @@ describe('HeaderCell', () => { }); }); - describe('when sortedHeader.classes was defined ', () => { - let sortedHeader; + describe('when sortingHeaderClasses was defined ', () => { + const classes = 'foo'; - describe('if sortedHeader.classes is a string', () => { + describe('if sortingHeaderClasses is a string', () => { beforeEach(() => { - sortedHeader = { classes: 'foo' }; wrapper = shallow( ); }); it('should append classes correcly', () => { expect(wrapper.length).toBe(1); - expect(wrapper.hasClass(sortedHeader.classes)).toBe(true); + expect(wrapper.hasClass(classes)).toBe(true); }); it('should have sortable class on header cell', () => { @@ -463,23 +462,21 @@ describe('HeaderCell', () => { }); }); - describe('if sortedHeader.classes is a function', () => { + describe('if sortingHeaderClasses is a function', () => { let classesCallBack; - const classes = 'foo'; beforeEach(() => { classesCallBack = sinon.stub() .withArgs(column, index) .returns(classes); - sortedHeader = { classes: classesCallBack }; wrapper = shallow( ); }); @@ -499,7 +496,7 @@ describe('HeaderCell', () => { }); }); - describe('when sortedHeader.classes was not defined', () => { + describe('when sortingHeaderClasses was not defined', () => { it('should do nothing and keep the same on classes of header cell', () => { column.headerClasses = 'td-test-class'; @@ -517,33 +514,28 @@ describe('HeaderCell', () => { }); }); - describe('when sortedHeader.style was defined', () => { - let sortedHeader; + describe('when sortingHeaderStyle was defined', () => { + const style = { backgroundColor: 'red' }; - describe('if sortedHeader.style is an object', () => { + describe('if sortingHeaderStyle is an object', () => { beforeEach(() => { - sortedHeader = { - style: { backgroundColor: 'red' } - }; - wrapper = shallow( ); }); it('should append style correcly', () => { expect(wrapper.length).toBe(1); - expect(wrapper.find('th').prop('style')).toEqual(sortedHeader.style); + expect(wrapper.find('th').prop('style')).toEqual(style); }); }); - describe('if sortedHeader.style is a function', () => { - const style = { backgroundColor: 'red' }; + describe('if sortingHeaderStyle is a function', () => { let styleCallBack; beforeEach(() => { @@ -551,17 +543,13 @@ describe('HeaderCell', () => { .withArgs(column, index) .returns(style); - sortedHeader = { - style: styleCallBack - }; - wrapper = shallow( ); }); @@ -577,7 +565,7 @@ describe('HeaderCell', () => { }); }); - describe('when sortedHeader.style was not defined', () => { + describe('when sortingHeaderStyle was not defined', () => { it('should do nothing and keep the same on style of header cell', () => { column.headerStyle = { backgroundColor: 'red' }; From e06bfbbf64f92863aac1d4a2f13b66677625820c Mon Sep 17 00:00:00 2001 From: Chun-MingChen Date: Sun, 5 Nov 2017 18:13:10 +0800 Subject: [PATCH 09/15] [test] add test case if column.headerStyle and column.headerClasses were defined --- .../test/header-cell.test.js | 89 ++++++++++++------- 1 file changed, 58 insertions(+), 31 deletions(-) diff --git a/packages/react-bootstrap-table2/test/header-cell.test.js b/packages/react-bootstrap-table2/test/header-cell.test.js index c249ce544..9b6bd1ba8 100644 --- a/packages/react-bootstrap-table2/test/header-cell.test.js +++ b/packages/react-bootstrap-table2/test/header-cell.test.js @@ -494,23 +494,25 @@ describe('HeaderCell', () => { expect(wrapper.hasClass('sortable')).toBe(true); }); }); - }); - describe('when sortingHeaderClasses was not defined', () => { - it('should do nothing and keep the same on classes of header cell', () => { - column.headerClasses = 'td-test-class'; - - wrapper = shallow( - - ); - expect(wrapper.length).toBe(1); - expect(wrapper.hasClass('sortable')).toBe(true); - expect(wrapper.hasClass(column.headerClasses)).toBe(true); + describe('if column.headerClasses was defined as well', () => { + it('should keep both classes', () => { + column.headerClasses = 'td-test-class'; + wrapper = shallow( + + ); + + expect(wrapper.length).toBe(1); + expect(wrapper.hasClass('sortable')).toBe(true); + expect(wrapper.hasClass(classes)).toBe(true); + expect(wrapper.hasClass(column.headerClasses)).toBe(true); + }); }); }); @@ -563,22 +565,47 @@ describe('HeaderCell', () => { expect(styleCallBack.calledWith(column, index)).toBe(true); }); }); - }); - describe('when sortingHeaderStyle was not defined', () => { - it('should do nothing and keep the same on style of header cell', () => { - column.headerStyle = { backgroundColor: 'red' }; - - wrapper = shallow( - - ); - expect(wrapper.length).toBe(1); - expect(wrapper.find('th').prop('style')).toEqual(column.headerStyle); + describe('if column.headerStyle was defined as well', () => { + it('should keep both styles', () => { + column.headerStyle = { opacity: '1' }; + + wrapper = shallow( + + ); + expect(wrapper.length).toBe(1); + expect(wrapper.find('th').prop('style')).toEqual(expect.objectContaining({ + ...style, + ...column.headerStyle + })); + }); + + it('sortingHeaderStyle should have higher priority', () => { + column.headerStyle = { backgroundColor: 'green' }; + + wrapper = shallow( + + ); + expect(wrapper.length).toBe(1); + expect(wrapper.find('th').prop('style')).toEqual(expect.objectContaining({ + ...style + })); + expect(wrapper.find('th').prop('style')).not.toEqual(expect.objectContaining({ + ...column.headerStyle + })); + }); }); }); }); From c75f239b37d9a21fc3634b6f422c2b287a6ea92e Mon Sep 17 00:00:00 2001 From: Chun-MingChen Date: Mon, 20 Nov 2017 00:28:40 +0800 Subject: [PATCH 10/15] implement customized header style and classes in column level --- .../examples/sort/sorting-header-classes.js | 36 +++++++++++++------ .../examples/sort/sorting-header-style.js | 23 +++++++----- .../stories/stylesheet/base/_base.scss | 1 + .../stories/stylesheet/sort/_index.scss | 7 +++- .../src/bootstrap-table.js | 10 ++---- .../react-bootstrap-table2/src/header-cell.js | 22 ++++++------ packages/react-bootstrap-table2/src/header.js | 11 +++--- 7 files changed, 64 insertions(+), 46 deletions(-) diff --git a/packages/react-bootstrap-table2-example/examples/sort/sorting-header-classes.js b/packages/react-bootstrap-table2-example/examples/sort/sorting-header-classes.js index 640d58d0c..260affacc 100644 --- a/packages/react-bootstrap-table2-example/examples/sort/sorting-header-classes.js +++ b/packages/react-bootstrap-table2-example/examples/sort/sorting-header-classes.js @@ -1,4 +1,8 @@ -/* eslint no-unused-vars: 0 */ +/* eslint + no-unused-vars: 0 + arrow-body-style: 0 +*/ + import React from 'react'; import BootstrapTable from 'react-bootstrap-table2'; @@ -7,43 +11,55 @@ import { productsGenerator } from 'utils/common'; const products = productsGenerator(); +const headerSortingClasses = (column, sortOrder, isLastSorting, colIndex) => ( + sortOrder === 'asc' ? 'demo-sorting-asc' : 'demo-sorting-desc' +); + const columns = [{ dataField: 'id', text: 'Product ID', - sort: true + sort: true, + headerSortingClasses }, { dataField: 'name', text: 'Product Name', - sort: true + sort: true, + headerSortingClasses }, { dataField: 'price', text: 'Product Price' }]; -const sortingHeaderClasses = (column, colIndex) => 'demo-sorting'; - const sourceCode = `\ +const headerSortingClasses = (column, sortOrder, isLastSorting, colIndex) => ( + sortOrder === 'asc' ? 'demo-sorting-asc' : 'demo-sorting-desc' +); + const columns = [{ dataField: 'id', text: 'Product ID', - sort: true + sort: true, + headerSortingClasses }, { dataField: 'name', text: 'Product Name', - sort: true + sort: true, + headerSortingClasses }, { dataField: 'price', text: 'Product Price' }]; -const sortingHeaderClasses = (column, colIndex) => 'demo-sorting'; +const headerSortingClasses = (column, sortOrder, isLastSorting, colIndex) => ( + sortOrder === 'asc' ? 'demo-sorting-asc' : 'demo-sorting-desc' +); - + `; export default () => (
- + { sourceCode }
); diff --git a/packages/react-bootstrap-table2-example/examples/sort/sorting-header-style.js b/packages/react-bootstrap-table2-example/examples/sort/sorting-header-style.js index bbeb2dc6a..c39096542 100644 --- a/packages/react-bootstrap-table2-example/examples/sort/sorting-header-style.js +++ b/packages/react-bootstrap-table2-example/examples/sort/sorting-header-style.js @@ -7,43 +7,48 @@ import { productsGenerator } from 'utils/common'; const products = productsGenerator(); +const headerSortingStyle = { backgroundColor: '#c8e6c9' }; + const columns = [{ dataField: 'id', text: 'Product ID', - sort: true + sort: true, + headerSortingStyle }, { dataField: 'name', text: 'Product Name', - sort: true + sort: true, + headerSortingStyle }, { dataField: 'price', text: 'Product Price' }]; -const sortingHeaderStyle = { backgroundColor: '#c8e6c9' }; const sourceCode = `\ +const headerSortingStyle = { backgroundColor: '#c8e6c9' }; + const columns = [{ dataField: 'id', text: 'Product ID', - sort: true + sort: true, + headerSortingStyle }, { dataField: 'name', text: 'Product Name', - sort: true + sort: true, + headerSortingStyle }, { dataField: 'price', text: 'Product Price' }]; -const sortingHeaderStyle = { backgroundColor: '#c8e6c9' }; - - + `; export default () => (
- + { sourceCode }
); diff --git a/packages/react-bootstrap-table2-example/stories/stylesheet/base/_base.scss b/packages/react-bootstrap-table2-example/stories/stylesheet/base/_base.scss index 5097d01d6..5ee5a54bb 100644 --- a/packages/react-bootstrap-table2-example/stories/stylesheet/base/_base.scss +++ b/packages/react-bootstrap-table2-example/stories/stylesheet/base/_base.scss @@ -10,4 +10,5 @@ $grey-900: #212121; $pink-500: #E91E63; $green-lighten-2: #81c784; $green-lighten-4: #c8e6c9; +$light-blue: #00BFFF; $markdown-color: #f6f8fa; diff --git a/packages/react-bootstrap-table2-example/stories/stylesheet/sort/_index.scss b/packages/react-bootstrap-table2-example/stories/stylesheet/sort/_index.scss index d954b94e2..bb8b1e889 100644 --- a/packages/react-bootstrap-table2-example/stories/stylesheet/sort/_index.scss +++ b/packages/react-bootstrap-table2-example/stories/stylesheet/sort/_index.scss @@ -1,3 +1,8 @@ -.demo-sorting { +.demo-sorting, +.demo-sorting-asc { background-color: $green-lighten-2; } + +.demo-sorting-desc { + background-color: $light-blue; +} diff --git a/packages/react-bootstrap-table2/src/bootstrap-table.js b/packages/react-bootstrap-table2/src/bootstrap-table.js index 875b5a9aa..d77d47ff9 100644 --- a/packages/react-bootstrap-table2/src/bootstrap-table.js +++ b/packages/react-bootstrap-table2/src/bootstrap-table.js @@ -38,9 +38,7 @@ class BootstrapTable extends PropsBaseResolver(Component) { caption, rowStyle, rowClasses, - rowEvents, - sortingHeaderClasses, - sortingHeaderStyle + rowEvents } = this.props; const tableClass = cs('table', { @@ -77,8 +75,6 @@ class BootstrapTable extends PropsBaseResolver(Component) { sortOrder={ store.sortOrder } onSort={ this.props.onSort } selectRow={ headerCellSelectionInfo } - sortingHeaderClasses={ sortingHeaderClasses } - sortingHeaderStyle={ sortingHeaderStyle } /> { onSort, sorting, sortOrder, - sortingHeaderClasses, - sortingHeaderStyle + isLastSorting } = props; const { @@ -30,7 +29,9 @@ const HeaderCell = (props) => { headerEvents, headerClasses, headerStyle, - headerAttrs + headerAttrs, + headerSortingClasses, + headerSortingStyle } = column; const cellAttrs = { @@ -73,16 +74,16 @@ const HeaderCell = (props) => { // append customized classes or style if table was sorting based on the current column. cellClasses = cs( cellClasses, - _.isFunction(sortingHeaderClasses) - ? sortingHeaderClasses(column, index) - : sortingHeaderClasses + _.isFunction(headerSortingClasses) + ? headerSortingClasses(column, sortOrder, isLastSorting, index) + : headerSortingClasses ); cellStyle = { ...cellStyle, - ..._.isFunction(sortingHeaderStyle) - ? sortingHeaderStyle(column, index) - : sortingHeaderStyle + ..._.isFunction(headerSortingStyle) + ? headerSortingStyle(column, sortOrder, isLastSorting, index) + : headerSortingStyle }; } else { sortSymbol = ; @@ -131,8 +132,7 @@ HeaderCell.propTypes = { onSort: PropTypes.func, sorting: PropTypes.bool, sortOrder: PropTypes.oneOf([Const.SORT_ASC, Const.SORT_DESC]), - sortingHeaderClasses: PropTypes.oneOfType([PropTypes.func, PropTypes.string]), - sortingHeaderStyle: PropTypes.oneOfType([PropTypes.func, PropTypes.object]) + isLastSorting: PropTypes.bool }; export default HeaderCell; diff --git a/packages/react-bootstrap-table2/src/header.js b/packages/react-bootstrap-table2/src/header.js index ce20b4add..da77cb9c7 100644 --- a/packages/react-bootstrap-table2/src/header.js +++ b/packages/react-bootstrap-table2/src/header.js @@ -14,8 +14,6 @@ const Header = (props) => { onSort, sortField, sortOrder, - sortingHeaderClasses, - sortingHeaderStyle, selectRow } = props; @@ -29,6 +27,8 @@ const Header = (props) => { { columns.map((column, i) => { const currSort = column.dataField === sortField; + const isLastSorting = column.dataField === sortField; + return ( { onSort={ onSort } sorting={ currSort } sortOrder={ sortOrder } - sortingHeaderClasses={ sortingHeaderClasses } - sortingHeaderStyle={ sortingHeaderStyle } + isLastSorting={ isLastSorting } />); }) } @@ -52,9 +51,7 @@ Header.propTypes = { onSort: PropTypes.func, sortField: PropTypes.string, sortOrder: PropTypes.string, - selectRow: PropTypes.object, - sortingHeaderClasses: PropTypes.oneOfType([PropTypes.func, PropTypes.string]), - sortingHeaderStyle: PropTypes.oneOfType([PropTypes.func, PropTypes.object]) + selectRow: PropTypes.object }; export default Header; From eab1a63118fec952928b18c4d79b58b427e65e1a Mon Sep 17 00:00:00 2001 From: Chun-MingChen Date: Mon, 20 Nov 2017 01:11:54 +0800 Subject: [PATCH 11/15] [test] test for customized header style and classes in column level --- .../test/header-cell.test.js | 121 +++++++++++++----- 1 file changed, 88 insertions(+), 33 deletions(-) diff --git a/packages/react-bootstrap-table2/test/header-cell.test.js b/packages/react-bootstrap-table2/test/header-cell.test.js index 9b6bd1ba8..4f9999748 100644 --- a/packages/react-bootstrap-table2/test/header-cell.test.js +++ b/packages/react-bootstrap-table2/test/header-cell.test.js @@ -437,18 +437,19 @@ describe('HeaderCell', () => { }); }); - describe('when sortingHeaderClasses was defined ', () => { + describe('when headerSortingClasses was defined ', () => { const classes = 'foo'; + const order = Const.SORT_DESC; - describe('if sortingHeaderClasses is a string', () => { + describe('if headerSortingClasses is a string', () => { beforeEach(() => { + column = { ...column, headerSortingClasses: classes }; wrapper = shallow( ); }); @@ -462,21 +463,22 @@ describe('HeaderCell', () => { }); }); - describe('if sortingHeaderClasses is a function', () => { + describe('if headerSortingClasses is a function', () => { let classesCallBack; + let isLastSorting; beforeEach(() => { classesCallBack = sinon.stub() - .withArgs(column, index) + .withArgs(column, order, isLastSorting, index) .returns(classes); + column = { ...column, headerSortingClasses: classesCallBack }; wrapper = shallow( ); }); @@ -485,26 +487,49 @@ describe('HeaderCell', () => { expect(wrapper.hasClass(classes)).toBe(true); }); - it('should call custom classes function correctly', () => { + it('should have sortable class on header cell', () => { + expect(wrapper.hasClass('sortable')).toBe(true); + }); + + it('should call custom class function with correct params', () => { expect(classesCallBack.callCount).toBe(1); - expect(classesCallBack.calledWith(column, index)).toBe(true); + expect(classesCallBack.calledWith(column, order, isLastSorting, index)).toBe(true); }); - it('should have sortable class on header cell', () => { - expect(wrapper.hasClass('sortable')).toBe(true); + describe('when the field is last sorting', () => { + it('should call custom classes function with isLastSorting being true', () => { + isLastSorting = true; + classesCallBack.reset(); + + wrapper = shallow( + ); + + expect(classesCallBack.callCount).toBe(1); + expect(classesCallBack.calledWith(column, order, isLastSorting, index)).toBe(true); + }); }); }); describe('if column.headerClasses was defined as well', () => { it('should keep both classes', () => { - column.headerClasses = 'td-test-class'; + column = { + ...column, + headerClasses: 'td-test-class', + headerSortingClasses: classes + }; + wrapper = shallow( ); @@ -516,19 +541,22 @@ describe('HeaderCell', () => { }); }); - describe('when sortingHeaderStyle was defined', () => { + describe('when headerSortingStyle was defined', () => { const style = { backgroundColor: 'red' }; + const order = Const.SORT_DESC; - describe('if sortingHeaderStyle is an object', () => { + describe('if headerSortingStyle is an object', () => { beforeEach(() => { + column = { ...column, headerSortingStyle: style }; + wrapper = shallow( ); + sortOrder={ order } + /> + ); }); it('should append style correcly', () => { @@ -537,21 +565,23 @@ describe('HeaderCell', () => { }); }); - describe('if sortingHeaderStyle is a function', () => { + describe('if headerSortingStyle is a function', () => { let styleCallBack; + let isLastSorting; beforeEach(() => { styleCallBack = sinon.stub() - .withArgs(column, index) + .withArgs(column, order, isLastSorting, index) .returns(style); + column = { ...column, headerSortingStyle: styleCallBack }; + wrapper = shallow( ); }); @@ -560,23 +590,45 @@ describe('HeaderCell', () => { expect(wrapper.find('th').prop('style')).toEqual(style); }); - it('should call custom style function correctly', () => { + it('should call custom style function with correct params', () => { expect(styleCallBack.callCount).toBe(1); - expect(styleCallBack.calledWith(column, index)).toBe(true); + expect(styleCallBack.calledWith(column, order, isLastSorting, index)).toBe(true); + }); + + describe('when the field is last sorting', () => { + it('should call custom classes function with isLastSorting being true', () => { + isLastSorting = true; + styleCallBack.reset(); + + wrapper = shallow( + ); + + expect(styleCallBack.callCount).toBe(1); + expect(styleCallBack.calledWith(column, order, isLastSorting, index)).toBe(true); + }); }); }); describe('if column.headerStyle was defined as well', () => { it('should keep both styles', () => { - column.headerStyle = { opacity: '1' }; + column = { + ...column, + headerStyle: { opacity: '1' }, + headerSortingStyle: style + }; wrapper = shallow( ); expect(wrapper.length).toBe(1); @@ -586,16 +638,19 @@ describe('HeaderCell', () => { })); }); - it('sortingHeaderStyle should have higher priority', () => { - column.headerStyle = { backgroundColor: 'green' }; + it('headerSortingStyle should have higher priority', () => { + column = { + ...column, + headerStyle: { backgroundColor: 'green' }, + headerSortingStyle: style + }; wrapper = shallow( ); expect(wrapper.length).toBe(1); From 61ca2e3ec868fe9afcea467fea0c36ca8c6f0f1c Mon Sep 17 00:00:00 2001 From: Chun-MingChen Date: Sat, 25 Nov 2017 18:23:56 +0800 Subject: [PATCH 12/15] [DOC] document for customized classes and styles --- docs/README.md | 29 ----------------------------- docs/columns.md | 31 +++++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 29 deletions(-) diff --git a/docs/README.md b/docs/README.md index 1c6c1251f..dff143d13 100644 --- a/docs/README.md +++ b/docs/README.md @@ -19,8 +19,6 @@ * [rowClasses](#rowClasses) * [rowEvents](#rowEvents) * [defaultSorted](#defaultSorted) -* [sortingHeaderClasses](#sortingHeaderClasses) -* [sortingHeaderStyle](#sortingHeaderStyle) ### keyField(**required**) - [String] Tells `react-bootstrap-table2` which column is unique. @@ -104,30 +102,3 @@ const defaultSorted = [{ order: 'desc' // desc or asc }]; ``` - -### sortingHeaderClasses - [String | Function] - -`sortingHeaderClasses` allows you to customize `class` for `header cell` which the table was sorting based on. - -```js -const sortingHeaderClasses = 'demo-sorting'; -``` - -Furthermore, it also accepts a callback function which takes `2` arguments and `String` is expected to return: - -```js -const sortingHeaderClasses = function callback(column, colIndex) { ... } -``` - -* column: The value of current column. -* colIndex: The index of the current column being processed in BootstrapTable. - -### sortingHeaderStyle - [Object | Function] - -It's similiar to `sortingHeaderClasses`. It allows to customize style of `header cell` which is sorting based on. `Object` and `callback` function are acceptable. `callback` takes `2` arguments and an `Object` is expected to return: - -```js -const sortingHeaderStyle = { - backgroundColor: 'red' -}; -``` \ No newline at end of file diff --git a/docs/columns.md b/docs/columns.md index 9fe7745a3..d0462b918 100644 --- a/docs/columns.md +++ b/docs/columns.md @@ -25,6 +25,8 @@ Available properties in a column object: * [headerEvents](#headerEvents) * [headerAlign](#headerAlign) * [headerAttrs](#headerAttrs) +* [headerSortingClasses](#headerSortingClasses) +* [headerSortingStyle](#headerSortingStyle) * [editable](#editable) * [validator](#validator) * [editCellStyle](#editCellStyle) @@ -419,6 +421,35 @@ A new `Object` will be the result of element headerAttrs. > Same as [column.attrs](#attrs), it has lower priority and will be > overwrited when other props related to HTML attributes were given. +### headerSortingClasses - [String | Function] + +`headerSortingClasses` allows to customize `class` for header cell which the table was sorting based on. + +```js +const headerSortingClasses = 'demo-sorting'; +``` + +Furthermore, it also accepts a callback which takes **4** arguments and `String` is expected to return: + +```js +const headerSortingClasses = (column, sortOrder, isLastSorting, colIndex) => { ... } +``` + +* column: The value of current column. +* sortOrder: The order of current sorting +* isLastSorting: Is the last one of sorting. +* colIndex: The index of the current column being processed in BootstrapTable. + +### headerSortingStyle - [Object | Function] + +It's similiar to [headerSortingClasses](#headerSortingClasses). It allows to customize style of `header cell` which is sorting based on. `Object` or `callback` are acceptable. `callback` takes **4** arguments and an `Object` is expected to return: + +```js +const sortingHeaderStyle = { + backgroundColor: 'red' +}; +``` + ## column.editable - [Bool | Function] `column.editable` default is true, means every column is editable if you configure [`cellEdit`](./README.md#cellEdit). But you can disable some columns editable via setting `false`. From af095c0549ebc0032795ca7c6350d1b338c10946 Mon Sep 17 00:00:00 2001 From: Chun-MingChen Date: Sat, 25 Nov 2017 18:36:51 +0800 Subject: [PATCH 13/15] sample for customized classes and styles --- ...orting-header-classes.js => header-sorting-classes.js} | 4 ---- .../{sorting-header-style.js => header-sorting-style.js} | 0 packages/react-bootstrap-table2-example/stories/index.js | 8 ++++---- 3 files changed, 4 insertions(+), 8 deletions(-) rename packages/react-bootstrap-table2-example/examples/sort/{sorting-header-classes.js => header-sorting-classes.js} (89%) rename packages/react-bootstrap-table2-example/examples/sort/{sorting-header-style.js => header-sorting-style.js} (100%) diff --git a/packages/react-bootstrap-table2-example/examples/sort/sorting-header-classes.js b/packages/react-bootstrap-table2-example/examples/sort/header-sorting-classes.js similarity index 89% rename from packages/react-bootstrap-table2-example/examples/sort/sorting-header-classes.js rename to packages/react-bootstrap-table2-example/examples/sort/header-sorting-classes.js index 260affacc..d70bdd752 100644 --- a/packages/react-bootstrap-table2-example/examples/sort/sorting-header-classes.js +++ b/packages/react-bootstrap-table2-example/examples/sort/header-sorting-classes.js @@ -50,10 +50,6 @@ const columns = [{ text: 'Product Price' }]; -const headerSortingClasses = (column, sortOrder, isLastSorting, colIndex) => ( - sortOrder === 'asc' ? 'demo-sorting-asc' : 'demo-sorting-desc' -); - `; diff --git a/packages/react-bootstrap-table2-example/examples/sort/sorting-header-style.js b/packages/react-bootstrap-table2-example/examples/sort/header-sorting-style.js similarity index 100% rename from packages/react-bootstrap-table2-example/examples/sort/sorting-header-style.js rename to packages/react-bootstrap-table2-example/examples/sort/header-sorting-style.js diff --git a/packages/react-bootstrap-table2-example/stories/index.js b/packages/react-bootstrap-table2-example/stories/index.js index 8d2381a43..060ebed15 100644 --- a/packages/react-bootstrap-table2-example/stories/index.js +++ b/packages/react-bootstrap-table2-example/stories/index.js @@ -41,8 +41,8 @@ import RowEventTable from 'examples/rows/row-event'; import EnableSortTable from 'examples/sort/enable-sort-table'; import DefaultSortTable from 'examples/sort/default-sort-table'; import CustomSortTable from 'examples/sort/custom-sort-table'; -import SortingHeaderClassesTable from 'examples/sort/sorting-header-classes'; -import SortingHeaderStyleTable from 'examples/sort/sorting-header-style'; +import HeaderSortingClassesTable from 'examples/sort/header-sorting-classes'; +import HeaderSortingStyleTable from 'examples/sort/header-sorting-style'; // cell editing import ClickToEditTable from 'examples/cell-edit/click-to-edit-table'; @@ -119,8 +119,8 @@ storiesOf('Sort Table', module) .add('Enable Sort', () => ) .add('Default Sort Table', () => ) .add('Custom Sort Fuction', () => ) - .add('Sorting header classes', () => ) - .add('Sorting header style', () => ); + .add('Header sorting classes', () => ) + .add('Header sorting style', () => ); storiesOf('Cell Editing', module) .add('Click to Edit', () => ) From 1014de25b9c7355062a758f829a3448fb1743f8d Mon Sep 17 00:00:00 2001 From: Chun-MingChen Date: Sat, 25 Nov 2017 18:42:21 +0800 Subject: [PATCH 14/15] typo fix for document --- docs/columns.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/columns.md b/docs/columns.md index d0462b918..567f8e867 100644 --- a/docs/columns.md +++ b/docs/columns.md @@ -435,14 +435,14 @@ Furthermore, it also accepts a callback which takes **4** arguments and `String` const headerSortingClasses = (column, sortOrder, isLastSorting, colIndex) => { ... } ``` -* column: The value of current column. -* sortOrder: The order of current sorting -* isLastSorting: Is the last one of sorting. -* colIndex: The index of the current column being processed in BootstrapTable. +* `column`: The value of current column. +* `sortOrder`: The order of current sorting +* `isLastSorting`: Is the last one of sorting. +* `colIndex`: The index of the current column being processed in BootstrapTable. ### headerSortingStyle - [Object | Function] -It's similiar to [headerSortingClasses](#headerSortingClasses). It allows to customize style of `header cell` which is sorting based on. `Object` or `callback` are acceptable. `callback` takes **4** arguments and an `Object` is expected to return: +It's similiar to [headerSortingClasses](#headerSortingClasses). It allows to customize the style of header cell which the table was sorting based on. A style `Object` and `callback` are acceptable. `callback` takes **4** arguments and an `Object` is expected to return: ```js const sortingHeaderStyle = { From 90cada4bac65275f16a52a64eafaaeb50908a37e Mon Sep 17 00:00:00 2001 From: Chun-MingChen Date: Sat, 9 Dec 2017 17:59:33 +0800 Subject: [PATCH 15/15] tuning the wording for test and documents --- docs/columns.md | 6 +++--- .../stories/index.js | 4 ++-- .../test/header-cell.test.js | 14 +++++++------- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/docs/columns.md b/docs/columns.md index 567f8e867..52aaa1749 100644 --- a/docs/columns.md +++ b/docs/columns.md @@ -423,7 +423,7 @@ A new `Object` will be the result of element headerAttrs. ### headerSortingClasses - [String | Function] -`headerSortingClasses` allows to customize `class` for header cell which the table was sorting based on. +`headerSortingClasses` allows to customize `class` for header cell when this column is sorting. ```js const headerSortingClasses = 'demo-sorting'; @@ -437,12 +437,12 @@ const headerSortingClasses = (column, sortOrder, isLastSorting, colIndex) => { . * `column`: The value of current column. * `sortOrder`: The order of current sorting -* `isLastSorting`: Is the last one of sorting. +* `isLastSorting`: Is the last one of sorted columns. * `colIndex`: The index of the current column being processed in BootstrapTable. ### headerSortingStyle - [Object | Function] -It's similiar to [headerSortingClasses](#headerSortingClasses). It allows to customize the style of header cell which the table was sorting based on. A style `Object` and `callback` are acceptable. `callback` takes **4** arguments and an `Object` is expected to return: +It's similiar to [headerSortingClasses](#headerSortingClasses). It allows to customize the style of header cell when this column is sorting. A style `Object` and `callback` are acceptable. `callback` takes **4** arguments and an `Object` is expected to return: ```js const sortingHeaderStyle = { diff --git a/packages/react-bootstrap-table2-example/stories/index.js b/packages/react-bootstrap-table2-example/stories/index.js index 90cc6062c..738cfc63a 100644 --- a/packages/react-bootstrap-table2-example/stories/index.js +++ b/packages/react-bootstrap-table2-example/stories/index.js @@ -130,8 +130,8 @@ storiesOf('Sort Table', module) .add('Enable Sort', () => ) .add('Default Sort Table', () => ) .add('Custom Sort Fuction', () => ) - .add('Header sorting classes', () => ) - .add('Header sorting style', () => ); + .add('Custom Classes on Sorting Header Column', () => ) + .add('Custom Style on Sorting Header Column', () => ); storiesOf('Cell Editing', module) .add('Click to Edit', () => ) diff --git a/packages/react-bootstrap-table2/test/header-cell.test.js b/packages/react-bootstrap-table2/test/header-cell.test.js index 4f9999748..43ef4da01 100644 --- a/packages/react-bootstrap-table2/test/header-cell.test.js +++ b/packages/react-bootstrap-table2/test/header-cell.test.js @@ -437,7 +437,7 @@ describe('HeaderCell', () => { }); }); - describe('when headerSortingClasses was defined ', () => { + describe('when headerSortingClasses is defined ', () => { const classes = 'foo'; const order = Const.SORT_DESC; @@ -453,7 +453,7 @@ describe('HeaderCell', () => { />); }); - it('should append classes correcly', () => { + it('should append classes correctly', () => { expect(wrapper.length).toBe(1); expect(wrapper.hasClass(classes)).toBe(true); }); @@ -482,7 +482,7 @@ describe('HeaderCell', () => { />); }); - it('should append classes correcly', () => { + it('should append classes correctly', () => { expect(wrapper.length).toBe(1); expect(wrapper.hasClass(classes)).toBe(true); }); @@ -516,7 +516,7 @@ describe('HeaderCell', () => { }); }); - describe('if column.headerClasses was defined as well', () => { + describe('if column.headerClasses is defined as well', () => { it('should keep both classes', () => { column = { ...column, @@ -541,7 +541,7 @@ describe('HeaderCell', () => { }); }); - describe('when headerSortingStyle was defined', () => { + describe('when headerSortingStyle is defined', () => { const style = { backgroundColor: 'red' }; const order = Const.SORT_DESC; @@ -559,7 +559,7 @@ describe('HeaderCell', () => { ); }); - it('should append style correcly', () => { + it('should append style correctly', () => { expect(wrapper.length).toBe(1); expect(wrapper.find('th').prop('style')).toEqual(style); }); @@ -585,7 +585,7 @@ describe('HeaderCell', () => { />); }); - it('should append style correcly', () => { + it('should append style correctly', () => { expect(wrapper.length).toBe(1); expect(wrapper.find('th').prop('style')).toEqual(style); });