From a8083ac17d4a19e9feb25e32ceb33177998d270f Mon Sep 17 00:00:00 2001 From: Parth Prajapati Date: Sat, 24 Feb 2018 20:23:52 +0530 Subject: [PATCH 001/549] Fixes #186 (#219) * Fixes #186 * Solved lint error --- packages/react-bootstrap-table2/src/bootstrap-table.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/react-bootstrap-table2/src/bootstrap-table.js b/packages/react-bootstrap-table2/src/bootstrap-table.js index 4834ec01d..dae389335 100644 --- a/packages/react-bootstrap-table2/src/bootstrap-table.js +++ b/packages/react-bootstrap-table2/src/bootstrap-table.js @@ -70,10 +70,12 @@ class BootstrapTable extends PropsBaseResolver(Component) { allRowsSelected: isSelectedAll(store) }); + const tableCaption = (caption && { caption }); + return (
- + { tableCaption }
Date: Sat, 24 Feb 2018 23:03:09 +0800 Subject: [PATCH 002/549] fix #221 --- packages/react-bootstrap-table2-editor/src/text-editor.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/react-bootstrap-table2-editor/src/text-editor.js b/packages/react-bootstrap-table2-editor/src/text-editor.js index 52233e7f4..7937282b6 100644 --- a/packages/react-bootstrap-table2-editor/src/text-editor.js +++ b/packages/react-bootstrap-table2-editor/src/text-editor.js @@ -32,9 +32,10 @@ TextEditor.propTypes = { defaultValue: PropTypes.oneOfType([ PropTypes.string, PropTypes.number - ]).isRequired + ]) }; TextEditor.defaultProps = { - className: null + className: null, + defaultValue: '' }; export default TextEditor; From 931cf8045045c3fdb7ce8e3945ebac76f9730965 Mon Sep 17 00:00:00 2001 From: Parth Prajapati Date: Sat, 24 Feb 2018 20:23:52 +0530 Subject: [PATCH 003/549] Fixes #186 (#219) * Fixes #186 * Solved lint error --- packages/react-bootstrap-table2/src/bootstrap-table.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/react-bootstrap-table2/src/bootstrap-table.js b/packages/react-bootstrap-table2/src/bootstrap-table.js index 4834ec01d..dae389335 100644 --- a/packages/react-bootstrap-table2/src/bootstrap-table.js +++ b/packages/react-bootstrap-table2/src/bootstrap-table.js @@ -70,10 +70,12 @@ class BootstrapTable extends PropsBaseResolver(Component) { allRowsSelected: isSelectedAll(store) }); + const tableCaption = (caption &&
); + return (
{ caption }{ caption }
- + { tableCaption }
Date: Sat, 24 Feb 2018 23:03:09 +0800 Subject: [PATCH 004/549] fix #221 --- packages/react-bootstrap-table2-editor/src/text-editor.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/react-bootstrap-table2-editor/src/text-editor.js b/packages/react-bootstrap-table2-editor/src/text-editor.js index 52233e7f4..7937282b6 100644 --- a/packages/react-bootstrap-table2-editor/src/text-editor.js +++ b/packages/react-bootstrap-table2-editor/src/text-editor.js @@ -32,9 +32,10 @@ TextEditor.propTypes = { defaultValue: PropTypes.oneOfType([ PropTypes.string, PropTypes.number - ]).isRequired + ]) }; TextEditor.defaultProps = { - className: null + className: null, + defaultValue: '' }; export default TextEditor; From a11913c49a10b80a31c35a2c2b02e075b8ed3e61 Mon Sep 17 00:00:00 2001 From: Allen Date: Sun, 4 Mar 2018 16:21:10 +0800 Subject: [PATCH 005/549] fix #210 (#232) --- .../examples/sort/enable-sort-table.js | 31 +++++++++++++++---- .../src/sort/wrapper.js | 10 +++--- .../test/sort/wrapper.test.js | 26 +++------------- 3 files changed, 33 insertions(+), 34 deletions(-) diff --git a/packages/react-bootstrap-table2-example/examples/sort/enable-sort-table.js b/packages/react-bootstrap-table2-example/examples/sort/enable-sort-table.js index 16e628f97..7d0d406c4 100644 --- a/packages/react-bootstrap-table2-example/examples/sort/enable-sort-table.js +++ b/packages/react-bootstrap-table2-example/examples/sort/enable-sort-table.js @@ -38,9 +38,28 @@ const columns = [{ `; -export default () => ( -
- - { sourceCode } -
-); +export default class Test extends React.Component { + constructor(props) { + super(props); + this.state = { data: products }; + } + + handleClick = () => { + this.setState(() => { + const newProducts = productsGenerator(21); + return { + data: newProducts + }; + }); + } + + render() { + return ( +
+ + + { sourceCode } +
+ ); + } +} diff --git a/packages/react-bootstrap-table2/src/sort/wrapper.js b/packages/react-bootstrap-table2/src/sort/wrapper.js index 90a9bb92b..71c50511c 100644 --- a/packages/react-bootstrap-table2/src/sort/wrapper.js +++ b/packages/react-bootstrap-table2/src/sort/wrapper.js @@ -39,12 +39,10 @@ export default Base => } componentWillReceiveProps(nextProps) { - if (nextProps.isDataChanged) { - const sortedColumn = nextProps.columns.find( - column => column.dataField === nextProps.store.sortField); - if (sortedColumn) { - nextProps.store.sortBy(sortedColumn); - } + const sortedColumn = nextProps.columns.find( + column => column.dataField === nextProps.store.sortField); + if (sortedColumn && sortedColumn.sort) { + nextProps.store.sortBy(sortedColumn); } } diff --git a/packages/react-bootstrap-table2/test/sort/wrapper.test.js b/packages/react-bootstrap-table2/test/sort/wrapper.test.js index 1c28b8ca1..2575e8676 100644 --- a/packages/react-bootstrap-table2/test/sort/wrapper.test.js +++ b/packages/react-bootstrap-table2/test/sort/wrapper.test.js @@ -219,30 +219,12 @@ describe('SortWrapper', () => { nextProps = { columns, store }; store.sortField = columns[1].dataField; store.sortOrder = Const.SORT_DESC; + store.sortBy = sinon.stub(); }); - describe('if nextProps.isDataChanged is true', () => { - beforeEach(() => { - nextProps.isDataChanged = true; - store.sortBy = sinon.stub(); - }); - - it('should sorting again', () => { - wrapper.instance().componentWillReceiveProps(nextProps); - expect(store.sortBy.calledOnce).toBeTruthy(); - }); - }); - - describe('if nextProps.isDataChanged is false', () => { - beforeEach(() => { - nextProps.isDataChanged = false; - store.sortBy = sinon.stub(); - }); - - it('should not sorting', () => { - wrapper.instance().componentWillReceiveProps(nextProps); - expect(store.sortBy.calledOnce).toBeFalsy(); - }); + it('should sorting again', () => { + wrapper.instance().componentWillReceiveProps(nextProps); + expect(store.sortBy.calledOnce).toBeTruthy(); }); }); }); From 9382ed587b3bf30623a03c6a0b11f05d7013b065 Mon Sep 17 00:00:00 2001 From: Allen Date: Sun, 4 Mar 2018 17:22:52 +0800 Subject: [PATCH 006/549] implement row event delegater (#233) --- .../src/row-event-delegater.js | 84 +++++++++++++++++++ packages/react-bootstrap-table2/src/row.js | 72 +--------------- .../react-bootstrap-table2/test/row.test.js | 6 +- 3 files changed, 92 insertions(+), 70 deletions(-) create mode 100644 packages/react-bootstrap-table2/src/row-event-delegater.js diff --git a/packages/react-bootstrap-table2/src/row-event-delegater.js b/packages/react-bootstrap-table2/src/row-event-delegater.js new file mode 100644 index 000000000..a35de461e --- /dev/null +++ b/packages/react-bootstrap-table2/src/row-event-delegater.js @@ -0,0 +1,84 @@ +import _ from './utils'; + +const events = [ + 'onClick', + 'onMouseEnter', + 'onMouseLeave' +]; + +export default ExtendBase => + class RowEventDelegater extends ExtendBase { + constructor(props) { + super(props); + this.clickNum = 0; + this.createDefaultEventHandler = this.createDefaultEventHandler.bind(this); + this.createClickEventHandler = this.createClickEventHandler.bind(this); + } + + createDefaultEventHandler(cb) { + return (e) => { + const { row, rowIndex } = this.props; + cb(e, row, rowIndex); + }; + } + + createClickEventHandler(cb) { + return (e) => { + const { + row, + selected, + keyField, + selectable, + rowIndex, + selectRow: { + onRowSelect, + clickToEdit + }, + cellEdit: { + mode, + DBCLICK_TO_CELL_EDIT, + DELAY_FOR_DBCLICK + } + } = this.props; + + const clickFn = () => { + if (cb) { + cb(e, row, rowIndex); + } + if (selectable) { + const key = _.get(row, keyField); + onRowSelect(key, !selected, rowIndex); + } + }; + + if (mode === DBCLICK_TO_CELL_EDIT && clickToEdit) { + this.clickNum += 1; + _.debounce(() => { + if (this.clickNum === 1) { + clickFn(); + } + this.clickNum = 0; + }, DELAY_FOR_DBCLICK)(); + } else { + clickFn(); + } + }; + } + + delegate(attrs = {}) { + const newAttrs = {}; + if (this.props.selectRow && this.props.selectRow.clickToSelect) { + newAttrs.onClick = this.createClickEventHandler(attrs.onClick); + } + Object.keys(attrs).forEach((attr) => { + if (!newAttrs[attr]) { + if (events.includes(attr)) { + newAttrs[attr] = this.createDefaultEventHandler(attrs[attr]); + } else { + newAttrs[attr] = attrs[attr]; + } + } + }); + return newAttrs; + } + }; diff --git a/packages/react-bootstrap-table2/src/row.js b/packages/react-bootstrap-table2/src/row.js index 1b5562864..7b1df3750 100644 --- a/packages/react-bootstrap-table2/src/row.js +++ b/packages/react-bootstrap-table2/src/row.js @@ -6,68 +6,10 @@ import PropTypes from 'prop-types'; import _ from './utils'; import Cell from './cell'; import SelectionCell from './row-selection/selection-cell'; +import eventDelegater from './row-event-delegater'; import Const from './const'; -class Row extends Component { - constructor(props) { - super(props); - this.clickNum = 0; - this.handleRowClick = this.handleRowClick.bind(this); - this.handleSimpleRowClick = this.handleSimpleRowClick.bind(this); - } - - handleRowClick(e) { - const { - row, - selected, - keyField, - selectable, - rowIndex, - selectRow: { - onRowSelect, - clickToEdit - }, - cellEdit: { - mode, - DBCLICK_TO_CELL_EDIT, - DELAY_FOR_DBCLICK - }, - attrs - } = this.props; - - const clickFn = () => { - if (attrs.onClick) { - attrs.onClick(e, row, rowIndex); - } - if (selectable) { - const key = _.get(row, keyField); - onRowSelect(key, !selected, rowIndex); - } - }; - - if (mode === DBCLICK_TO_CELL_EDIT && clickToEdit) { - this.clickNum += 1; - _.debounce(() => { - if (this.clickNum === 1) { - clickFn(); - } - this.clickNum = 0; - }, DELAY_FOR_DBCLICK)(); - } else { - clickFn(); - } - } - - handleSimpleRowClick(e) { - const { - row, - rowIndex, - attrs - } = this.props; - - attrs.onClick(e, row, rowIndex); - } - +class Row extends eventDelegater(Component) { render() { const { row, @@ -96,14 +38,8 @@ class Row extends Component { } = cellEdit; const key = _.get(row, keyField); - const { clickToSelect, hideSelectColumn } = selectRow; - - const trAttrs = { ...attrs }; - if (clickToSelect) { - trAttrs.onClick = this.handleRowClick; - } else if (attrs.onClick) { - trAttrs.onClick = this.handleSimpleRowClick; - } + const { hideSelectColumn } = selectRow; + const trAttrs = this.delegate(attrs); return (
diff --git a/packages/react-bootstrap-table2/test/row.test.js b/packages/react-bootstrap-table2/test/row.test.js index 955a42151..02cc06837 100644 --- a/packages/react-bootstrap-table2/test/row.test.js +++ b/packages/react-bootstrap-table2/test/row.test.js @@ -799,8 +799,10 @@ describe('Row', () => { selected selectable />); - wrapper.instance().handleRowClick(); - wrapper.instance().handleRowClick(); + // console.log(wrapper.instance()); + const rowClick = wrapper.instance().createClickEventHandler(); + rowClick(); + rowClick(); }); it('should increase clickNum as 2', () => { From a5cb806d9851c1f45c2cf770e4d4e036f8ea2a0d Mon Sep 17 00:00:00 2001 From: Allen Date: Mon, 5 Mar 2018 22:27:46 +0800 Subject: [PATCH 007/549] implement default selection (#234) --- docs/row-selection.md | 11 ++++ .../examples/row-selection/default-select.js | 59 +++++++++++++++++++ .../stories/index.js | 2 + .../src/row-selection/wrapper.js | 11 ++++ .../test/row-selection/wrapper.test.js | 36 +++++++++-- 5 files changed, 115 insertions(+), 4 deletions(-) create mode 100644 packages/react-bootstrap-table2-example/examples/row-selection/default-select.js diff --git a/docs/row-selection.md b/docs/row-selection.md index e50ef838c..c877e6b19 100644 --- a/docs/row-selection.md +++ b/docs/row-selection.md @@ -6,6 +6,7 @@ * [mode (**required**)](#mode) ## Optional +* [selected](#selected) * [style](#style) * [classes)](#classes) * [bgColor](#bgColor) @@ -52,6 +53,16 @@ const selectRow = { /> ``` +### selectRow.selected - [Array] +`selectRow.selected` allow you have default selections on table. + +```js +const selectRow = { + mode: 'checkbox', + selected: [1, 3] // should be a row keys array +}; +``` + ### selectRow.style - [Object | Function] `selectRow.style` allow you to have custom style on selected rows: diff --git a/packages/react-bootstrap-table2-example/examples/row-selection/default-select.js b/packages/react-bootstrap-table2-example/examples/row-selection/default-select.js new file mode 100644 index 000000000..d11a68831 --- /dev/null +++ b/packages/react-bootstrap-table2-example/examples/row-selection/default-select.js @@ -0,0 +1,59 @@ +import React from 'react'; + +import BootstrapTable from 'react-bootstrap-table-next'; +import Code from 'components/common/code-block'; +import { productsGenerator } from 'utils/common'; + +const products = productsGenerator(); + +const columns = [{ + dataField: 'id', + text: 'Product ID' +}, { + dataField: 'name', + text: 'Product Name' +}, { + dataField: 'price', + text: 'Product Price' +}]; + +const selectRow = { + mode: 'checkbox', + clickToSelect: true, + selected: [1, 3] +}; + +const sourceCode = `\ +import BootstrapTable from 'react-bootstrap-table-next'; + +const columns = [{ + dataField: 'id', + text: 'Product ID' +}, { + dataField: 'name', + text: 'Product Name' +}, { + dataField: 'price', + text: 'Product Price' +}]; + +const selectRow = { + mode: 'checkbox', + clickToSelect: true, + selected: [1, 3] +}; + + +`; + +export default () => ( +
+ + { sourceCode } +
+); diff --git a/packages/react-bootstrap-table2-example/stories/index.js b/packages/react-bootstrap-table2-example/stories/index.js index 09bce470c..b7444a741 100644 --- a/packages/react-bootstrap-table2-example/stories/index.js +++ b/packages/react-bootstrap-table2-example/stories/index.js @@ -77,6 +77,7 @@ import CellEditClassTable from 'examples/cell-edit/cell-edit-class-table'; import SingleSelectionTable from 'examples/row-selection/single-selection'; import MultipleSelectionTable from 'examples/row-selection/multiple-selection'; import ClickToSelectTable from 'examples/row-selection/click-to-select'; +import DefaultSelectTable from 'examples/row-selection/default-select'; import ClickToSelectWithCellEditTable from 'examples/row-selection/click-to-select-with-cell-edit'; import SelectionStyleTable from 'examples/row-selection/selection-style'; import SelectionClassTable from 'examples/row-selection/selection-class'; @@ -189,6 +190,7 @@ storiesOf('Row Selection', module) .add('Single Selection', () => ) .add('Multiple Selection', () => ) .add('Click to Select', () => ) + .add('Default Select', () => ) .add('Click to Select and Edit Cell', () => ) .add('Selection Style', () => ) .add('Selection Class', () => ) diff --git a/packages/react-bootstrap-table2/src/row-selection/wrapper.js b/packages/react-bootstrap-table2/src/row-selection/wrapper.js index 442cb18cb..b8c79bd97 100644 --- a/packages/react-bootstrap-table2/src/row-selection/wrapper.js +++ b/packages/react-bootstrap-table2/src/row-selection/wrapper.js @@ -1,3 +1,4 @@ +/* eslint no-param-reassign: 0 */ import React, { Component } from 'react'; import PropTypes from 'prop-types'; @@ -21,11 +22,21 @@ export default Base => super(props); this.handleRowSelect = this.handleRowSelect.bind(this); this.handleAllRowsSelect = this.handleAllRowsSelect.bind(this); + props.store.selected = this.props.selectRow.selected || []; this.state = { selectedRowKeys: props.store.selected }; } + componentWillReceiveProps(nextProps) { + if (nextProps.selectRow) { + this.store.selected = nextProps.selectRow.selected || []; + this.setState(() => ({ + selectedRowKeys: this.store.selected + })); + } + } + /** * row selection handler * @param {String} rowKey - row key of what was selected. diff --git a/packages/react-bootstrap-table2/test/row-selection/wrapper.test.js b/packages/react-bootstrap-table2/test/row-selection/wrapper.test.js index fba2c676c..278a54e52 100644 --- a/packages/react-bootstrap-table2/test/row-selection/wrapper.test.js +++ b/packages/react-bootstrap-table2/test/row-selection/wrapper.test.js @@ -8,6 +8,7 @@ import wrapperFactory from '../../src/row-selection/wrapper'; describe('RowSelectionWrapper', () => { let wrapper; + let selectRow; const columns = [{ dataField: 'id', @@ -25,10 +26,6 @@ describe('RowSelectionWrapper', () => { name: 'B' }]; - const selectRow = { - mode: 'radio' - }; - const rowIndex = 1; const keyField = 'id'; @@ -38,6 +35,9 @@ describe('RowSelectionWrapper', () => { const RowSelectionWrapper = wrapperFactory(BootstrapTable); beforeEach(() => { + selectRow = { + mode: 'radio' + }; wrapper = shallow( { expect(wrapper.find(BootstrapTable)).toBeDefined(); }); + it('should have correct store.selected value', () => { + expect(store.selected).toEqual([]); + }); + it('should have correct state', () => { expect(wrapper.state().selectedRowKeys).toBeDefined(); expect(wrapper.state().selectedRowKeys.length).toEqual(0); @@ -64,6 +68,30 @@ describe('RowSelectionWrapper', () => { expect(wrapper.props().onAllRowsSelect).toBeDefined(); }); + describe('when selectRow.selected is defiend', () => { + beforeEach(() => { + selectRow.mode = 'checkbox'; + selectRow.selected = [1, 3]; + wrapper = shallow( + + ); + }); + + it('should have correct store.selected value', () => { + expect(store.selected).toEqual(selectRow.selected); + }); + + it('should have correct state', () => { + expect(wrapper.state().selectedRowKeys).toEqual(selectRow.selected); + }); + }); + describe('when selectRow.mode is \'radio\'', () => { const firstSelectedRow = data[0][keyField]; const secondSelectedRow = data[1][keyField]; From 4011cae18e8e8bf632671647ad950e8b3209e2c1 Mon Sep 17 00:00:00 2001 From: AllenFang Date: Tue, 6 Mar 2018 23:59:04 +0800 Subject: [PATCH 008/549] Publish --- packages/react-bootstrap-table2-editor/package.json | 2 +- packages/react-bootstrap-table2-example/package.json | 2 +- packages/react-bootstrap-table2/package.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/react-bootstrap-table2-editor/package.json b/packages/react-bootstrap-table2-editor/package.json index 726e4345f..ded23c816 100644 --- a/packages/react-bootstrap-table2-editor/package.json +++ b/packages/react-bootstrap-table2-editor/package.json @@ -1,6 +1,6 @@ { "name": "react-bootstrap-table2-editor", - "version": "0.1.1", + "version": "0.1.2", "description": "it's the editor addon for react-bootstrap-table2", "main": "./lib/index.js", "scripts": { diff --git a/packages/react-bootstrap-table2-example/package.json b/packages/react-bootstrap-table2-example/package.json index 684997e44..b7e59dd28 100644 --- a/packages/react-bootstrap-table2-example/package.json +++ b/packages/react-bootstrap-table2-example/package.json @@ -1,6 +1,6 @@ { "name": "react-bootstrap-table2-example", - "version": "0.1.2", + "version": "0.1.3", "description": "", "main": "index.js", "private": true, diff --git a/packages/react-bootstrap-table2/package.json b/packages/react-bootstrap-table2/package.json index e7a5a1910..983bd57f3 100644 --- a/packages/react-bootstrap-table2/package.json +++ b/packages/react-bootstrap-table2/package.json @@ -1,6 +1,6 @@ { "name": "react-bootstrap-table-next", - "version": "0.1.3", + "version": "0.1.4", "description": "Next generation of react-bootstrap-table", "main": "./lib/index.js", "repository": { From 9f9203bffabab94e8e7fc65eae0141eb9be21196 Mon Sep 17 00:00:00 2001 From: Chun-MingChen Date: Sat, 10 Mar 2018 18:54:26 +0800 Subject: [PATCH 009/549] implement customized classes and id on the table --- packages/react-bootstrap-table2/src/bootstrap-table.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/react-bootstrap-table2/src/bootstrap-table.js b/packages/react-bootstrap-table2/src/bootstrap-table.js index dae389335..743eb3b00 100644 --- a/packages/react-bootstrap-table2/src/bootstrap-table.js +++ b/packages/react-bootstrap-table2/src/bootstrap-table.js @@ -42,6 +42,8 @@ class BootstrapTable extends PropsBaseResolver(Component) { store, columns, keyField, + id, + classes, striped, hover, bordered, @@ -58,7 +60,7 @@ class BootstrapTable extends PropsBaseResolver(Component) { 'table-hover': hover, 'table-bordered': bordered, 'table-condensed': condensed - }); + }, classes); const cellSelectionInfo = this.resolveSelectRowProps({ onRowSelect: this.props.onRowSelect @@ -74,7 +76,7 @@ class BootstrapTable extends PropsBaseResolver(Component) { return (
-
{ caption }
+
{ tableCaption }
Date: Sat, 10 Mar 2018 18:54:41 +0800 Subject: [PATCH 010/549] [test] test for customized classes and id --- .../test/bootstrap-table.test.js | 46 ++++++++++++++++++- 1 file changed, 44 insertions(+), 2 deletions(-) diff --git a/packages/react-bootstrap-table2/test/bootstrap-table.test.js b/packages/react-bootstrap-table2/test/bootstrap-table.test.js index 3e5e0e1fa..682dc735e 100644 --- a/packages/react-bootstrap-table2/test/bootstrap-table.test.js +++ b/packages/react-bootstrap-table2/test/bootstrap-table.test.js @@ -46,8 +46,50 @@ describe('BootstrapTable', () => { expect(wrapper.state().data).toEqual(store.data); }); - it('should have table-bordered class as default', () => { - expect(wrapper.find('table.table-bordered').length).toBe(1); + it("should only have classes 'table' and 'table-bordered' as default", () => { + expect(wrapper.find('table').prop('className')).toBe('table table-bordered'); + }); + + it('should not have customized id as default', () => { + expect(wrapper.find('table').prop('id')).toBeUndefined(); + }); + }); + + describe('when props.classes was defined', () => { + const classes = 'foo'; + + beforeEach(() => { + wrapper = shallow( + ); + }); + + it('should display customized classes correctly', () => { + expect(wrapper.find(`table.${classes}`).length).toBe(1); + }); + }); + + describe('when props.id was defined', () => { + const id = 'foo'; + + beforeEach(() => { + wrapper = shallow( + ); + }); + + it('should display customized id correctly', () => { + expect(wrapper.find(`table#${id}`).length).toBe(1); }); }); From 8a8c2d49643335baafaadb58ec0eb71745c8c249 Mon Sep 17 00:00:00 2001 From: Chun-MingChen Date: Sat, 10 Mar 2018 18:54:59 +0800 Subject: [PATCH 011/549] [example] add demo for customized classes and id table --- .../examples/basic/customized-id-classes.js | 48 +++++++++++++++++++ .../stories/index.js | 2 + .../stories/stylesheet/base-table/_index.scss | 7 +++ .../stories/stylesheet/storybook.scss | 1 + 4 files changed, 58 insertions(+) create mode 100644 packages/react-bootstrap-table2-example/examples/basic/customized-id-classes.js create mode 100644 packages/react-bootstrap-table2-example/stories/stylesheet/base-table/_index.scss diff --git a/packages/react-bootstrap-table2-example/examples/basic/customized-id-classes.js b/packages/react-bootstrap-table2-example/examples/basic/customized-id-classes.js new file mode 100644 index 000000000..d14c606a2 --- /dev/null +++ b/packages/react-bootstrap-table2-example/examples/basic/customized-id-classes.js @@ -0,0 +1,48 @@ +import React from 'react'; + +import BootstrapTable from 'react-bootstrap-table-next'; +import Code from 'components/common/code-block'; +import { productsGenerator } from 'utils/common'; + +const products = productsGenerator(); + +const columns = [{ + dataField: 'id', + text: 'Product ID' +}, { + dataField: 'name', + text: 'Product Name' +}, { + dataField: 'price', + text: 'Product Price' +}]; + +const sourceCode = `\ +import BootstrapTable from 'react-bootstrap-table-next'; + +const columns = [{ + dataField: 'id', + text: 'Product ID' +}, { + dataField: 'name', + text: 'Product Name' +}, { + dataField: 'price', + text: 'Product Price' +}]; + + + +`; + +export default () => ( +
+

Customized table ID

+ + +

Customized table className

+ + + { sourceCode } +
+); diff --git a/packages/react-bootstrap-table2-example/stories/index.js b/packages/react-bootstrap-table2-example/stories/index.js index b7444a741..c16dc5379 100644 --- a/packages/react-bootstrap-table2-example/stories/index.js +++ b/packages/react-bootstrap-table2-example/stories/index.js @@ -9,6 +9,7 @@ import BasicTable from 'examples/basic'; import BorderlessTable from 'examples/basic/borderless-table'; import StripHoverCondensedTable from 'examples/basic/striped-hover-condensed-table'; import NoDataTable from 'examples/basic/no-data-table'; +import CustomizedIdClassesTable from 'examples/basic/customized-id-classes'; import CaptionTable from 'examples/basic/caption-table'; // work on columns @@ -121,6 +122,7 @@ storiesOf('Basic Table', module) .add('striped, hover, condensed table', () => ) .add('borderless table', () => ) .add('Indication For Empty Table', () => ) + .add('Customized id and class table', () => ) .add('Table with caption', () => ); storiesOf('Work on Columns', module) diff --git a/packages/react-bootstrap-table2-example/stories/stylesheet/base-table/_index.scss b/packages/react-bootstrap-table2-example/stories/stylesheet/base-table/_index.scss new file mode 100644 index 000000000..34353eb98 --- /dev/null +++ b/packages/react-bootstrap-table2-example/stories/stylesheet/base-table/_index.scss @@ -0,0 +1,7 @@ +table.foo { + background-color: $grey-500; +} + +table#bar { + background-color: $light-blue; +} diff --git a/packages/react-bootstrap-table2-example/stories/stylesheet/storybook.scss b/packages/react-bootstrap-table2-example/stories/stylesheet/storybook.scss index cf0a024e4..c38e02cab 100644 --- a/packages/react-bootstrap-table2-example/stories/stylesheet/storybook.scss +++ b/packages/react-bootstrap-table2-example/stories/stylesheet/storybook.scss @@ -3,6 +3,7 @@ @import "http://github.com/base/github-corner"; @import "http://github.com/base/code-block"; +@import "http://github.com/base-table/index"; @import "http://github.com/welcome/index"; @import "http://github.com/columns/index"; @import "http://github.com/cell-edit/index"; From 3ed4d87b29049a2437e8f5a745d53202d2e37a28 Mon Sep 17 00:00:00 2001 From: Chun-MingChen Date: Sat, 17 Mar 2018 15:29:09 +0800 Subject: [PATCH 012/549] correct attribute key of columns.headerEvent in column-event-tables --- .../examples/header-columns/column-event-table.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/react-bootstrap-table2-example/examples/header-columns/column-event-table.js b/packages/react-bootstrap-table2-example/examples/header-columns/column-event-table.js index 7928a3799..d4394a7a0 100644 --- a/packages/react-bootstrap-table2-example/examples/header-columns/column-event-table.js +++ b/packages/react-bootstrap-table2-example/examples/header-columns/column-event-table.js @@ -28,7 +28,7 @@ import BootstrapTable from 'react-bootstrap-table-next'; const columns = [{ dataField: 'id', text: 'Product ID', - events: { + headerEvents: { onClick: () => alert('Click on Product ID header column') } }, { From 0eda54b772955c908c1ebea970f3c0236522e8ed Mon Sep 17 00:00:00 2001 From: Chun-MingChen Date: Sat, 17 Mar 2018 16:04:03 +0800 Subject: [PATCH 013/549] correct the typo of documents --- docs/README.md | 10 +++++----- docs/columns.md | 22 +++++++++++----------- docs/migration.md | 16 ++++++++-------- docs/row-selection.md | 2 +- 4 files changed, 25 insertions(+), 25 deletions(-) diff --git a/docs/README.md b/docs/README.md index 096ca24bb..7871d5f39 100644 --- a/docs/README.md +++ b/docs/README.md @@ -59,14 +59,14 @@ A special case for remote pagination: remote={ { pagination: true, filter: false, sort: false } } ``` -There is a apecial case for remote pagination, even you only specified the paignation need to handle as remote, `react-bootstrap-table2` will handle all the table changes(filter, sort etc) as remote mode, because `react-bootstrap-table2` only know the data of current page, but filtering, searching or sort need to work on overall datas. +There is a special case for remote pagination, even you only specified the pagination need to handle as remote, `react-bootstrap-table2` will handle all the table changes(filter, sort etc) as remote mode, because `react-bootstrap-table2` only know the data of current page, but filtering, searching or sort need to work on overall data. ### loading - [Bool] Telling if table is loading or not, for example: waiting data loading, filtering etc. It's **only** valid when [`remote`](#remote) is enabled. When `loading` is `true`, `react-bootstrap-table2` will attend to render a overlay on table via [`overlay`](#overlay) prop, if [`overlay`](#overlay) prop is not given, `react-bootstrap-table2` will ignore the overlay rendering. ### overlay - [Function] -`overlay` accept a factory funtion which should returning a higher order component. By default, `react-bootstrap-table2-overlay` can be a good option for you: +`overlay` accept a factory function which should returning a higher order component. By default, `react-bootstrap-table2-overlay` can be a good option for you: ```sh $ npm install react-bootstrap-table2-overlay @@ -163,7 +163,7 @@ const defaultSorted = [{ ``` ### pagination - [Object] -`pagination` allow user to render a pagination panel on the bottom of table. But pagination funcitonality is separated from core of `react-bootstrap-table2` so that you are suppose to install `react-bootstrap-table2-paginator` additionaly. +`pagination` allow user to render a pagination panel on the bottom of table. But pagination functionality is separated from core of `react-bootstrap-table2` so that you are suppose to install `react-bootstrap-table2-paginator` additionally. ```sh $ npm install react-bootstrap-table2-paginator --save @@ -205,7 +205,7 @@ paginator({ prePageTitle: 'Go to previous', // the title of previous page button firstPageTitle: 'Go to first', // the title of first page button lastPageTitle: 'Go to last', // the title of last page button - hideSizePerPage: true, // hide the size per page dorpdown + hideSizePerPage: true, // hide the size per page dropdown hidePageListOnlyOnePage: true, // hide pagination bar when only one page, default is false onPageChange: (page, sizePerPage) => {}, // callback function when page was changing onSizePerPageChange: (sizePerPage, page) => {}, // callback function when page size was changing @@ -213,7 +213,7 @@ paginator({ ``` ### filter - [Object] -`filter` allow user to filter data by column. However, filter funcitonality is separated from core of `react-bootstrap-table2` so that you are suppose to install `react-bootstrap-table2-filter` firstly. +`filter` allow user to filter data by column. However, filter functionality is separated from core of `react-bootstrap-table2` so that you are suppose to install `react-bootstrap-table2-filter` firstly. ```sh $ npm install react-bootstrap-table2-filter --save diff --git a/docs/columns.md b/docs/columns.md index b80c48a67..eeab42ba2 100644 --- a/docs/columns.md +++ b/docs/columns.md @@ -137,7 +137,7 @@ Enable the column sort via a `true` value given. ``` ## column.classes - [String | Function] -It's availabe to have custom class on table column: +It's available to have custom class on table column: ```js { @@ -165,7 +165,7 @@ In addition, `classes` also accept a callback function which have more power to A new `String` will be the result as element class. ## column.headerClasses - [String | Function] -It's similar to [`column.classes`](#classes), `headerClasses` is availabe to have customized class on table header column: +It's similar to [`column.classes`](#classes), `headerClasses` is available to have customized class on table header column: ```js { @@ -190,7 +190,7 @@ Furthermore, it also accept a callback function which takes 2 arguments and a `S A new `String` will be the result of element headerClasses. ## column.style - [Object | Function] -It's availabe to have custom style on table column: +It's available to have custom style on table column: ```js { @@ -220,7 +220,7 @@ A new `Object` will be the result of element style. ## column.headerStyle - [Object | Function] -It's availabe to have customized inline-style on table header column: +It's available to have customized inline-style on table header column: ```js { @@ -278,7 +278,7 @@ A new `String` will be the result of element title. } ``` -It's also availabe to custom via a callback function: +It's also available to custom via a callback function: ```js { headerTitle: function callback(column, colIndex) { ... } @@ -401,7 +401,7 @@ A new `Object` will be the result of element HTML attributes. > Caution: -> If `column.classes`, `column.style`, `column.title`, `column.hidden` or `column.align` was given at the same time, property `attrs` has lower priorty and it will be overwrited. +> If `column.classes`, `column.style`, `column.title`, `column.hidden` or `column.align` was given at the same time, property `attrs` has lower priority and it will be overwritten. ```js { @@ -412,7 +412,7 @@ A new `Object` will be the result of element HTML attributes. ``` ## column.headerAttrs - [Object | Function] -`headerAttrs` is similiar to [`column.attrs`](#attrs) but it works for header column. +`headerAttrs` is similar to [`column.attrs`](#attrs) but it works for header column. ```js { // omit... @@ -444,7 +444,7 @@ A new `Object` will be the result of element headerAttrs. > Caution: > Same as [column.attrs](#attrs), it has lower priority and will be -> overwrited when other props related to HTML attributes were given. +> overwritten when other props related to HTML attributes were given. ### headerSortingClasses - [String | Function] @@ -467,7 +467,7 @@ const headerSortingClasses = (column, sortOrder, isLastSorting, colIndex) => { . ### headerSortingStyle - [Object | Function] -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: +It's similar 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 = { @@ -502,7 +502,7 @@ If a callback function given, you can control the editable level as cell level: } ``` -The return value can be a bool or an object. If your valiation is pass, return `true` explicitly. If your valiation is invalid, return following object instead: +The return value can be a bool or an object. If your validation is pass, return `true` explicitly. If your validation is invalid, return following object instead: ```js { valid: false, @@ -574,7 +574,7 @@ import { textFilter } from 'react-bootstrap-table2-filter'; For some reason of simple customization, `react-bootstrap-table2` allow you to pass some props to filter factory function. Please check [here](https://github.com/react-bootstrap-table/react-bootstrap-table2/tree/master/packages/react-bootstrap-table2-filter/README.md) for more detail tutorial. ## column.filterValue - [Function] -Sometimes, if the cell/column value that you don't want to filter on them, you can define `filterValue` to return a actual value you wanna be filterd: +Sometimes, if the cell/column value that you don't want to filter on them, you can define `filterValue` to return a actual value you wanna be filtered: **Parameters** * `cell`: The value of current cell. diff --git a/docs/migration.md b/docs/migration.md index ae009e4f3..a9d2104fe 100644 --- a/docs/migration.md +++ b/docs/migration.md @@ -1,8 +1,8 @@ # Migration Guide * Please see the [CHANGELOG](https://react-bootstrap-table.github.io/react-bootstrap-table2/blog/2018/01/24/new-version-0.1.0.html) for `react-bootstrap-table2` first drop. -* Please see the [Roadmap](https://react-bootstrap-table.github.io/react-bootstrap-table2/blog/2018/01/24/release-plan.html) for `react-bootstrap-table2` in 2018/Q1. -* Feel free to see the [offical docs](https://react-bootstrap-table.github.io/react-bootstrap-table2/docs/about.html), we list all the basic usage here!! +* Please see the [Road Map](https://react-bootstrap-table.github.io/react-bootstrap-table2/blog/2018/01/24/release-plan.html) for `react-bootstrap-table2` in 2018/Q1. +* Feel free to see the [official docs](https://react-bootstrap-table.github.io/react-bootstrap-table2/docs/about.html), we list all the basic usage here!! ## Preface @@ -23,11 +23,11 @@ Currently, **I still can't implement all the mainly features in legacy `react-bo * [`react-bootstrap-table2-overlay`](https://www.npmjs.com/package/react-bootstrap-table2-overlay) * Overlay/Loading Addons -This can help your application with less bundled size and also help `react-bootstrap-table2` have clean design to avoid handling to much logic in kernal module(SRP). Hence, which means you probably need to install above addons when you need specific features. +This can help your application with less bundled size and also help `react-bootstrap-table2` have clean design to avoid handling to much logic in kernel module(SRP). Hence, which means you probably need to install above addons when you need specific features. ## Core Table Migration -There is a big chagne is that there's no `TableHeaderColumn` in the `react-bootstrap-table2`, instead you are supposed to be define the `columns` prop on `BootstrapTable`: +There is a big change is that there's no `TableHeaderColumn` in the `react-bootstrap-table2`, instead you are supposed to be define the `columns` prop on `BootstrapTable`: ```js import BootstrapTable from 'react-bootstrap-table-next'; @@ -48,8 +48,8 @@ const columns = [{ The `text` property is just same as the children for the `TableHeaderColumn`, if you want to custom the header, there's a new property is: [`headerFormatter`](https://react-bootstrap-table.github.io/react-bootstrap-table2/docs/column-props.html#columnheaderformatter-function). -* [`BootstrapTable` Definitation](https://react-bootstrap-table.github.io/react-bootstrap-table2/docs/table-props.html) -* [Column Definitation](https://react-bootstrap-table.github.io/react-bootstrap-table2/docs/column-props.html) +* [`BootstrapTable` Definition](https://react-bootstrap-table.github.io/react-bootstrap-table2/docs/table-props.html) +* [Column Definition](https://react-bootstrap-table.github.io/react-bootstrap-table2/docs/column-props.html) ## Table Sort @@ -65,7 +65,7 @@ Please see [Work with table sort](https://react-bootstrap-table.github.io/react- - [ ] Sort management - [ ] Multi sort -Due to no `TableHeaderColumn` so that no `dataSort` here, please add [`sort`](https://react-bootstrap-table.github.io/react-bootstrap-table2/docs/column-props.html#columnsort-bool) property on column definitation. +Due to no `TableHeaderColumn` so that no `dataSort` here, please add [`sort`](https://react-bootstrap-table.github.io/react-bootstrap-table2/docs/column-props.html#columnsort-bool) property on column definition. ## Row Selection @@ -93,7 +93,7 @@ Please see [available filter configuration](https://react-bootstrap-table.github Remember to install [`react-bootstrap-table2-filter`](https://www.npmjs.com/package/react-bootstrap-table2-filter) firstly. -Due to no `TableHeaderColumn` so that no `filter` here, please add [`filter`](https://react-bootstrap-table.github.io/react-bootstrap-table2/docs/column-props.html#columnfilter-object) property on column definitation and [`filter`](https://react-bootstrap-table.github.io/react-bootstrap-table2/docs/table-props.html#filter-object) prop on `BootstrapTable`. +Due to no `TableHeaderColumn` so that no `filter` here, please add [`filter`](https://react-bootstrap-table.github.io/react-bootstrap-table2/docs/column-props.html#columnfilter-object) property on column definition and [`filter`](https://react-bootstrap-table.github.io/react-bootstrap-table2/docs/table-props.html#filter-object) prop on `BootstrapTable`. ## Cell Edit diff --git a/docs/row-selection.md b/docs/row-selection.md index c877e6b19..b75aa1ff2 100644 --- a/docs/row-selection.md +++ b/docs/row-selection.md @@ -102,7 +102,7 @@ const selectRow = { ``` ### selectRow.bgColor - [String | Function] -The backgroud color when row is selected +The background color when row is selected ```js const selectRow = { From ceebdf5a139f1c3035e7910a0296bbaff835d84b Mon Sep 17 00:00:00 2001 From: Chun-MingChen Date: Sat, 17 Mar 2018 17:05:02 +0800 Subject: [PATCH 014/549] refine store to set selectRow when receiving props --- .../src/row-selection/wrapper.js | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/packages/react-bootstrap-table2/src/row-selection/wrapper.js b/packages/react-bootstrap-table2/src/row-selection/wrapper.js index b8c79bd97..1be101e10 100644 --- a/packages/react-bootstrap-table2/src/row-selection/wrapper.js +++ b/packages/react-bootstrap-table2/src/row-selection/wrapper.js @@ -22,19 +22,17 @@ export default Base => super(props); this.handleRowSelect = this.handleRowSelect.bind(this); this.handleAllRowsSelect = this.handleAllRowsSelect.bind(this); - props.store.selected = this.props.selectRow.selected || []; + + props.store.selected = props.selectRow.selected || []; this.state = { selectedRowKeys: props.store.selected }; } componentWillReceiveProps(nextProps) { - if (nextProps.selectRow) { - this.store.selected = nextProps.selectRow.selected || []; - this.setState(() => ({ - selectedRowKeys: this.store.selected - })); - } + this.setState(() => ({ + selectedRowKeys: nextProps.store.selected + })); } /** From d80ae13513a413f7d2a611612e8cb5a48d2134b7 Mon Sep 17 00:00:00 2001 From: Chun-MingChen Date: Sat, 17 Mar 2018 17:25:20 +0800 Subject: [PATCH 015/549] [test] test for RowSelectionWrapper#componentWillReceiveProps --- .../test/row-selection/wrapper.test.js | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/packages/react-bootstrap-table2/test/row-selection/wrapper.test.js b/packages/react-bootstrap-table2/test/row-selection/wrapper.test.js index 278a54e52..347b86713 100644 --- a/packages/react-bootstrap-table2/test/row-selection/wrapper.test.js +++ b/packages/react-bootstrap-table2/test/row-selection/wrapper.test.js @@ -68,7 +68,18 @@ describe('RowSelectionWrapper', () => { expect(wrapper.props().onAllRowsSelect).toBeDefined(); }); - describe('when selectRow.selected is defiend', () => { + describe('componentWillReceiveProps', () => { + const nextSelected = [0]; + const nextProps = { store: { selected: nextSelected } }; + + it('should update state.selectedRowKeys with next selected rows', () => { + wrapper.instance().componentWillReceiveProps(nextProps); + + expect(wrapper.state('selectedRowKeys')).toEqual(nextSelected); + }); + }); + + describe('when selectRow.selected is defined', () => { beforeEach(() => { selectRow.mode = 'checkbox'; selectRow.selected = [1, 3]; From 923439dc816bfeec9c15fe91af8e0f3edeebecff Mon Sep 17 00:00:00 2001 From: Chun-MingChen Date: Sat, 17 Mar 2018 17:29:30 +0800 Subject: [PATCH 016/549] correct typo --- .../test/row-selection/wrapper.test.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/react-bootstrap-table2/test/row-selection/wrapper.test.js b/packages/react-bootstrap-table2/test/row-selection/wrapper.test.js index 347b86713..749c0e428 100644 --- a/packages/react-bootstrap-table2/test/row-selection/wrapper.test.js +++ b/packages/react-bootstrap-table2/test/row-selection/wrapper.test.js @@ -107,7 +107,7 @@ describe('RowSelectionWrapper', () => { const firstSelectedRow = data[0][keyField]; const secondSelectedRow = data[1][keyField]; - it('call handleRowSelect function should seting correct state.selectedRowKeys', () => { + it('call handleRowSelect function should setting correct state.selectedRowKeys', () => { wrapper.instance().handleRowSelect(firstSelectedRow, rowIndex); expect(wrapper.state('selectedRowKeys')).toEqual([firstSelectedRow]); @@ -133,7 +133,7 @@ describe('RowSelectionWrapper', () => { ); }); - it('call handleRowSelect function should seting correct state.selectedRowKeys', () => { + it('call handleRowSelect function should setting correct state.selectedRowKeys', () => { wrapper.instance().handleRowSelect(firstSelectedRow, true, rowIndex); expect(wrapper.state('selectedRowKeys')).toEqual(expect.arrayContaining([firstSelectedRow])); @@ -147,7 +147,7 @@ describe('RowSelectionWrapper', () => { expect(wrapper.state('selectedRowKeys')).toEqual([]); }); - it('call handleAllRowsSelect function should seting correct state.selectedRowKeys', () => { + it('call handleAllRowsSelect function should setting correct state.selectedRowKeys', () => { wrapper.instance().handleAllRowsSelect(); expect(wrapper.state('selectedRowKeys')).toEqual(expect.arrayContaining([firstSelectedRow, secondSelectedRow])); @@ -155,7 +155,7 @@ describe('RowSelectionWrapper', () => { expect(wrapper.state('selectedRowKeys')).toEqual([]); }); - it('call handleAllRowsSelect function with a bool args should seting correct state.selectedRowKeys', () => { + it('call handleAllRowsSelect function with a bool args should setting correct state.selectedRowKeys', () => { wrapper.instance().handleAllRowsSelect(true); expect(wrapper.state('selectedRowKeys')).toEqual(expect.arrayContaining([firstSelectedRow, secondSelectedRow])); From 55336108a05dafc0740b56136857f12ddcdcb7a7 Mon Sep 17 00:00:00 2001 From: AllenFang Date: Sun, 18 Mar 2018 14:07:44 +0800 Subject: [PATCH 017/549] should recieve newest selectRow.selected --- .../src/row-selection/wrapper.js | 3 ++- .../test/row-selection/wrapper.test.js | 12 ++++++++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/packages/react-bootstrap-table2/src/row-selection/wrapper.js b/packages/react-bootstrap-table2/src/row-selection/wrapper.js index 1be101e10..1a944160b 100644 --- a/packages/react-bootstrap-table2/src/row-selection/wrapper.js +++ b/packages/react-bootstrap-table2/src/row-selection/wrapper.js @@ -30,8 +30,9 @@ export default Base => } componentWillReceiveProps(nextProps) { + nextProps.store.selected = nextProps.selectRow.selected || []; this.setState(() => ({ - selectedRowKeys: nextProps.store.selected + selectedRowKeys: nextProps.selectRow.selected })); } diff --git a/packages/react-bootstrap-table2/test/row-selection/wrapper.test.js b/packages/react-bootstrap-table2/test/row-selection/wrapper.test.js index 749c0e428..59dc19013 100644 --- a/packages/react-bootstrap-table2/test/row-selection/wrapper.test.js +++ b/packages/react-bootstrap-table2/test/row-selection/wrapper.test.js @@ -70,11 +70,19 @@ describe('RowSelectionWrapper', () => { describe('componentWillReceiveProps', () => { const nextSelected = [0]; - const nextProps = { store: { selected: nextSelected } }; + const nextProps = { + store: { + selected: nextSelected + }, + selectRow: { + mode: 'checkbox', + selected: nextSelected + } + }; it('should update state.selectedRowKeys with next selected rows', () => { wrapper.instance().componentWillReceiveProps(nextProps); - + expect(nextProps.store.selected).toEqual(nextSelected); expect(wrapper.state('selectedRowKeys')).toEqual(nextSelected); }); }); From c11539b9fb1c0ce87f653ea836b6cac375cd3723 Mon Sep 17 00:00:00 2001 From: AllenFang Date: Sun, 18 Mar 2018 14:33:11 +0800 Subject: [PATCH 018/549] [docs] patch id and classes for BootstrapTable --- docs/README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/README.md b/docs/README.md index 7871d5f39..34b38df98 100644 --- a/docs/README.md +++ b/docs/README.md @@ -15,6 +15,8 @@ * [bordered](#bordered) * [hover](#hover) * [condensed](#condensed) +* [id](#id) +* [classes](#classes) * [cellEdit](#cellEdit) * [selectRow](#selectRow) * [rowStyle](#rowStyle) @@ -100,6 +102,10 @@ Same as bootstrap `.table-hover` class for adding mouse hover effect (grey backg ### condensed - [Bool] Same as bootstrap `.table-condensed` class for making a table more compact by cutting cell padding in half. +### id - [String] +Customize id on `table` element. +### classes - [String] +Customize class on `table` element. ### cellEdit - [Object] Makes table cells editable, please see [cellEdit definition](./cell-edit.md) for more detail. From 6bc81dddd0fb436e4387695b718f1f033424d4fc Mon Sep 17 00:00:00 2001 From: Parth Prajapati Date: Sun, 18 Mar 2018 13:12:21 +0530 Subject: [PATCH 019/549] Fixed #237 (#261) * Fixed #237 * Solved lint errors * Removed test cases for display: none checks - added test cases for hidden columns check --- packages/react-bootstrap-table2/src/cell.js | 5 -- .../react-bootstrap-table2/src/header-cell.js | 5 -- packages/react-bootstrap-table2/src/header.js | 29 +++++---- packages/react-bootstrap-table2/src/row.js | 65 ++++++++++--------- .../react-bootstrap-table2/test/cell.test.js | 32 --------- .../test/header-cell.test.js | 18 ----- .../test/header.test.js | 23 +++++++ .../react-bootstrap-table2/test/row.test.js | 26 ++++++++ 8 files changed, 99 insertions(+), 104 deletions(-) diff --git a/packages/react-bootstrap-table2/src/cell.js b/packages/react-bootstrap-table2/src/cell.js index d50eeb44a..dc535a715 100644 --- a/packages/react-bootstrap-table2/src/cell.js +++ b/packages/react-bootstrap-table2/src/cell.js @@ -39,7 +39,6 @@ class Cell extends Component { } = this.props; const { dataField, - hidden, formatter, formatExtraData, style, @@ -80,10 +79,6 @@ class Cell extends Component { _.isFunction(align) ? align(content, row, rowIndex, columnIndex) : align; } - if (hidden) { - cellStyle.display = 'none'; - } - if (cellClasses) cellAttrs.className = cellClasses; if (!_.isEmptyObject(cellStyle)) cellAttrs.style = cellStyle; diff --git a/packages/react-bootstrap-table2/src/header-cell.js b/packages/react-bootstrap-table2/src/header-cell.js index b6af21eeb..bb012d182 100644 --- a/packages/react-bootstrap-table2/src/header-cell.js +++ b/packages/react-bootstrap-table2/src/header-cell.js @@ -24,7 +24,6 @@ const HeaderCell = (props) => { text, sort, filter, - hidden, headerTitle, headerAlign, headerFormatter, @@ -58,10 +57,6 @@ const HeaderCell = (props) => { cellStyle.textAlign = _.isFunction(headerAlign) ? headerAlign(column, index) : headerAlign; } - if (hidden) { - cellStyle.display = 'none'; - } - if (sort) { const customClick = cellAttrs.onClick; cellAttrs.onClick = (e) => { diff --git a/packages/react-bootstrap-table2/src/header.js b/packages/react-bootstrap-table2/src/header.js index ddbc7bfa4..38b8c3a02 100644 --- a/packages/react-bootstrap-table2/src/header.js +++ b/packages/react-bootstrap-table2/src/header.js @@ -27,20 +27,23 @@ const Header = (props) => { } { columns.map((column, i) => { - const currSort = column.dataField === sortField; - const isLastSorting = column.dataField === sortField; + if (!column.hidden) { + const currSort = column.dataField === sortField; + const isLastSorting = column.dataField === sortField; - return ( - ); + return ( + ); + } + return false; }) } diff --git a/packages/react-bootstrap-table2/src/row.js b/packages/react-bootstrap-table2/src/row.js index 7b1df3750..3efb0c529 100644 --- a/packages/react-bootstrap-table2/src/row.js +++ b/packages/react-bootstrap-table2/src/row.js @@ -58,46 +58,49 @@ class Row extends eventDelegater(Component) { } { columns.map((column, index) => { - const { dataField } = column; - const content = _.get(row, dataField); - let editable = _.isDefined(column.editable) ? column.editable : true; - if (dataField === keyField || !editableRow) editable = false; - if (_.isFunction(column.editable)) { - editable = column.editable(content, row, rowIndex, index); - } - if (rowIndex === editingRowIdx && index === editingColIdx) { - let editCellstyle = column.editCellStyle || {}; - let editCellclasses = column.editCellClasses; - if (_.isFunction(column.editCellStyle)) { - editCellstyle = column.editCellStyle(content, row, rowIndex, index); + if (!column.hidden) { + const { dataField } = column; + const content = _.get(row, dataField); + let editable = _.isDefined(column.editable) ? column.editable : true; + if (dataField === keyField || !editableRow) editable = false; + if (_.isFunction(column.editable)) { + editable = column.editable(content, row, rowIndex, index); } - if (_.isFunction(column.editCellClasses)) { - editCellclasses = column.editCellClasses(content, row, rowIndex, index); + if (rowIndex === editingRowIdx && index === editingColIdx) { + let editCellstyle = column.editCellStyle || {}; + let editCellclasses = column.editCellClasses; + if (_.isFunction(column.editCellStyle)) { + editCellstyle = column.editCellStyle(content, row, rowIndex, index); + } + if (_.isFunction(column.editCellClasses)) { + editCellclasses = column.editCellClasses(content, row, rowIndex, index); + } + return ( + + ); } return ( - ); } - return ( - - ); + return false; }) } diff --git a/packages/react-bootstrap-table2/test/cell.test.js b/packages/react-bootstrap-table2/test/cell.test.js index b83bcc9bd..439a638b2 100644 --- a/packages/react-bootstrap-table2/test/cell.test.js +++ b/packages/react-bootstrap-table2/test/cell.test.js @@ -27,24 +27,6 @@ describe('Cell', () => { }); }); - describe('when column.hidden prop is true', () => { - const column = { - dataField: 'id', - text: 'ID', - hidden: true - }; - - beforeEach(() => { - wrapper = shallow(); - }); - - it('should have \'none\' value for style.display', () => { - const style = wrapper.find('td').prop('style'); - expect(style).toBeDefined(); - expect(style.display).toEqual('none'); - }); - }); - describe('when column.formatter prop is defined', () => { const rowIndex = 1; const column = { @@ -390,20 +372,6 @@ describe('Cell', () => { }); }); - describe('when column.hidden prop is defined', () => { - it('attrs.style.hidden should be overwrited', () => { - column.hidden = true; - column.attrs = { style: { hidden: true } }; - - wrapper = shallow( - ); - - const style = wrapper.find('td').prop('style'); - expect(style).toBeDefined(); - expect(style.display).toEqual('none'); - }); - }); - describe('when column.align prop is defined', () => { it('attrs.style.textAlign should be overwrited', () => { column.align = 'center'; diff --git a/packages/react-bootstrap-table2/test/header-cell.test.js b/packages/react-bootstrap-table2/test/header-cell.test.js index 598396448..535d22227 100644 --- a/packages/react-bootstrap-table2/test/header-cell.test.js +++ b/packages/react-bootstrap-table2/test/header-cell.test.js @@ -33,24 +33,6 @@ describe('HeaderCell', () => { }); }); - describe('when column.hidden props is true', () => { - const column = { - dataField: 'id', - text: 'ID', - hidden: true - }; - - beforeEach(() => { - wrapper = shallow(); - }); - - it('should have \'none\' value for style.display', () => { - const style = wrapper.find('th').prop('style'); - expect(style).toBeDefined(); - expect(style.display).toEqual('none'); - }); - }); - describe('when column.headerTitle prop is defined', () => { let column; beforeEach(() => { diff --git a/packages/react-bootstrap-table2/test/header.test.js b/packages/react-bootstrap-table2/test/header.test.js index 8ae604b0b..c50260256 100644 --- a/packages/react-bootstrap-table2/test/header.test.js +++ b/packages/react-bootstrap-table2/test/header.test.js @@ -101,6 +101,29 @@ describe('Header', () => { }); }); + describe('when column.hidden is true', () => { + beforeEach(() => { + const newColumns = [{ + dataField: 'id', + text: 'ID', + hidden: true + }, { + dataField: 'name', + text: 'Name' + }]; + wrapper = shallow( +
+ ); + }); + + it('should not render column with hidden value true', () => { + expect(wrapper.find(HeaderCell).length).toBe(1); + }); + }); + describe('when selectRow.mode is checkbox (multiple selection)', () => { beforeEach(() => { const selectRow = { mode: 'checkbox' }; diff --git a/packages/react-bootstrap-table2/test/row.test.js b/packages/react-bootstrap-table2/test/row.test.js index 02cc06837..117a24f35 100644 --- a/packages/react-bootstrap-table2/test/row.test.js +++ b/packages/react-bootstrap-table2/test/row.test.js @@ -502,6 +502,32 @@ describe('Row', () => { }); }); + describe('when cloumn.hidden is true', () => { + beforeEach(() => { + const newColumns = [{ + dataField: 'id', + text: 'ID', + hidden: true + }, { + dataField: 'name', + text: 'Name' + }, { + dataField: 'price', + text: 'Price' + }]; + wrapper = shallow( + ); + }); + + it('should not render column with hidden value true', () => { + expect(wrapper.find(Cell).length).toBe(2); + }); + }); describe('selectRow', () => { let selectRow; From 6f9361934a0bb44e6eb75172fa954975193d890d Mon Sep 17 00:00:00 2001 From: Chun-MingChen Date: Sun, 18 Mar 2018 16:10:06 +0800 Subject: [PATCH 020/549] set state.selectedRowKeys based on store --- packages/react-bootstrap-table2/src/row-selection/wrapper.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/react-bootstrap-table2/src/row-selection/wrapper.js b/packages/react-bootstrap-table2/src/row-selection/wrapper.js index 1a944160b..c2880bf6c 100644 --- a/packages/react-bootstrap-table2/src/row-selection/wrapper.js +++ b/packages/react-bootstrap-table2/src/row-selection/wrapper.js @@ -32,7 +32,7 @@ export default Base => componentWillReceiveProps(nextProps) { nextProps.store.selected = nextProps.selectRow.selected || []; this.setState(() => ({ - selectedRowKeys: nextProps.selectRow.selected + selectedRowKeys: nextProps.store.selected })); } From d5ddd8c3af8947ba6dfd6f93a891e67bc9f25e5b Mon Sep 17 00:00:00 2001 From: AllenFang Date: Sun, 18 Mar 2018 16:44:39 +0800 Subject: [PATCH 021/549] add selection management example --- .../row-selection/selection-management.js | 144 ++++++++++++++++++ .../stories/index.js | 2 + 2 files changed, 146 insertions(+) create mode 100644 packages/react-bootstrap-table2-example/examples/row-selection/selection-management.js diff --git a/packages/react-bootstrap-table2-example/examples/row-selection/selection-management.js b/packages/react-bootstrap-table2-example/examples/row-selection/selection-management.js new file mode 100644 index 000000000..e0466a3b8 --- /dev/null +++ b/packages/react-bootstrap-table2-example/examples/row-selection/selection-management.js @@ -0,0 +1,144 @@ +import React from 'react'; + +import BootstrapTable from 'react-bootstrap-table-next'; +import Code from 'components/common/code-block'; +import { productsGenerator } from 'utils/common'; + +const products = productsGenerator(); + +const columns = [{ + dataField: 'id', + text: 'Product ID' +}, { + dataField: 'name', + text: 'Product Name' +}, { + dataField: 'price', + text: 'Product Price' +}]; + +const sourceCode = `\ +import BootstrapTable from 'react-bootstrap-table-next'; + +class SelectionManagment extends React.Component { + constructor(props) { + super(props); + this.state = { selected: [0, 1] }; + } + + handleBtnClick = () => { + if (!this.state.selected.includes(2)) { + this.setState(() => ({ + selected: [...this.state.selected, 2] + })); + } else { + this.setState(() => ({ + selected: this.state.selected.filter(x => x !== 2) + })); + } + } + + handleOnSelect = (row, isSelect) => { + if (isSelect) { + this.setState(() => ({ + selected: [...this.state.selected, row.id] + })); + } else { + this.setState(() => ({ + selected: this.state.selected.filter(x => x !== row.id) + })); + } + } + + handleOnSelectAll = (isSelect, rows) => { + const ids = rows.map(r => r.id); + if (isSelect) { + this.setState(() => ({ + selected: ids + })); + } else { + this.setState(() => ({ + selected: [] + })); + } + } + + render() { + const selectRow = { + mode: 'checkbox', + clickToSelect: true, + selected: this.state.selected, + onSelect: this.handleOnSelect, + onSelectAll: this.handleOnSelectAll + }; + return ( +
+ + + { sourceCode } +
+ ); + } +} +`; + +export default class SelectionManagment extends React.Component { + constructor(props) { + super(props); + this.state = { selected: [0, 1] }; + } + + handleBtnClick = () => { + if (!this.state.selected.includes(2)) { + this.setState(() => ({ + selected: [...this.state.selected, 2] + })); + } else { + this.setState(() => ({ + selected: this.state.selected.filter(x => x !== 2) + })); + } + } + + handleOnSelect = (row, isSelect) => { + if (isSelect) { + this.setState(() => ({ + selected: [...this.state.selected, row.id] + })); + } else { + this.setState(() => ({ + selected: this.state.selected.filter(x => x !== row.id) + })); + } + } + + handleOnSelectAll = (isSelect, rows) => { + const ids = rows.map(r => r.id); + if (isSelect) { + this.setState(() => ({ + selected: ids + })); + } else { + this.setState(() => ({ + selected: [] + })); + } + } + + render() { + const selectRow = { + mode: 'checkbox', + clickToSelect: true, + selected: this.state.selected, + onSelect: this.handleOnSelect, + onSelectAll: this.handleOnSelectAll + }; + return ( +
+ + + { sourceCode } +
+ ); + } +} diff --git a/packages/react-bootstrap-table2-example/stories/index.js b/packages/react-bootstrap-table2-example/stories/index.js index c16dc5379..3f116f508 100644 --- a/packages/react-bootstrap-table2-example/stories/index.js +++ b/packages/react-bootstrap-table2-example/stories/index.js @@ -79,6 +79,7 @@ import SingleSelectionTable from 'examples/row-selection/single-selection'; import MultipleSelectionTable from 'examples/row-selection/multiple-selection'; import ClickToSelectTable from 'examples/row-selection/click-to-select'; import DefaultSelectTable from 'examples/row-selection/default-select'; +import SelectionManagement from 'examples/row-selection/selection-management'; import ClickToSelectWithCellEditTable from 'examples/row-selection/click-to-select-with-cell-edit'; import SelectionStyleTable from 'examples/row-selection/selection-style'; import SelectionClassTable from 'examples/row-selection/selection-class'; @@ -193,6 +194,7 @@ storiesOf('Row Selection', module) .add('Multiple Selection', () => ) .add('Click to Select', () => ) .add('Default Select', () => ) + .add('Selection Management', () => ) .add('Click to Select and Edit Cell', () => ) .add('Selection Style', () => ) .add('Selection Class', () => ) From 33a8da701b508e898d33deda157d42ecb3b77cef Mon Sep 17 00:00:00 2001 From: Parth Prajapati Date: Sun, 18 Mar 2018 14:28:27 +0530 Subject: [PATCH 022/549] Add TravisCI badge --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 9c91f4b65..7d90d42f1 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ # react-bootstrap-table2 +[![Build Status](https://travis-ci.org/react-bootstrap-table/react-bootstrap-table2.svg?branch=master)](https://travis-ci.org/react-bootstrap-table/react-bootstrap-table2) Rebuilt [react-bootstrap-table](https://github.com/AllenFang/react-bootstrap-table) > `react-bootstrap-table2`'s npm module name is [**`react-bootstrap-table-next`**](https://www.npmjs.com/package/react-bootstrap-table-next) due to some guys already used it From 6de57737eafaf49156a2464725df9335e7f6ba65 Mon Sep 17 00:00:00 2001 From: Chun-MingChen Date: Sun, 18 Mar 2018 17:35:05 +0800 Subject: [PATCH 023/549] allow travis to run test for master branch --- .travis.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 02a549251..4120d0a8e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,8 +9,7 @@ cache: branches: only: - # skip master branch when it's under development phase - # - master + - master - develop before_install: From bd9150f88fe3b9459334bba433aa683d7c75cfb2 Mon Sep 17 00:00:00 2001 From: AllenFang Date: Sun, 18 Mar 2018 23:07:46 +0800 Subject: [PATCH 024/549] Publish - react-bootstrap-table2-editor@0.1.3 - react-bootstrap-table2-example@0.1.4 - react-bootstrap-table-next@0.1.5 --- packages/react-bootstrap-table2-editor/package.json | 2 +- packages/react-bootstrap-table2-example/package.json | 2 +- packages/react-bootstrap-table2/package.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/react-bootstrap-table2-editor/package.json b/packages/react-bootstrap-table2-editor/package.json index ded23c816..86bb4d9a4 100644 --- a/packages/react-bootstrap-table2-editor/package.json +++ b/packages/react-bootstrap-table2-editor/package.json @@ -1,6 +1,6 @@ { "name": "react-bootstrap-table2-editor", - "version": "0.1.2", + "version": "0.1.3", "description": "it's the editor addon for react-bootstrap-table2", "main": "./lib/index.js", "scripts": { diff --git a/packages/react-bootstrap-table2-example/package.json b/packages/react-bootstrap-table2-example/package.json index b7e59dd28..5a0ead8a7 100644 --- a/packages/react-bootstrap-table2-example/package.json +++ b/packages/react-bootstrap-table2-example/package.json @@ -1,6 +1,6 @@ { "name": "react-bootstrap-table2-example", - "version": "0.1.3", + "version": "0.1.4", "description": "", "main": "index.js", "private": true, diff --git a/packages/react-bootstrap-table2/package.json b/packages/react-bootstrap-table2/package.json index 983bd57f3..c9fc9b89a 100644 --- a/packages/react-bootstrap-table2/package.json +++ b/packages/react-bootstrap-table2/package.json @@ -1,6 +1,6 @@ { "name": "react-bootstrap-table-next", - "version": "0.1.4", + "version": "0.1.5", "description": "Next generation of react-bootstrap-table", "main": "./lib/index.js", "repository": { From 42dbd00fd9edbf44b66b2cb577304d36741c2276 Mon Sep 17 00:00:00 2001 From: Patrick O'Meara Date: Sun, 25 Mar 2018 19:36:58 +1100 Subject: [PATCH 025/549] fix#264: wrong col span when enable selection in a empty table (#265) * noDataIndication * use the correct amount of cells when the first row is select * storybook added for development, not necessary in docs fixes react-bootstrap-table/react-bootstrap-table2#264 * eslint complaints 4:11 error 'columnLen' is never reassigned. Use 'const' instead prefer-const 7:9 error Expected an assignment or function call and instead saw an expression no-unused-expressions * tests updated --- .../row-selection/selection-no-data.js | 62 +++++++++++++++++++ .../stories/index.js | 2 + .../src/props-resolver/column-resolver.js | 9 ++- .../src/props-resolver/index.js | 6 +- .../test/props-resolver/index.test.js | 4 +- 5 files changed, 76 insertions(+), 7 deletions(-) create mode 100644 packages/react-bootstrap-table2-example/examples/row-selection/selection-no-data.js diff --git a/packages/react-bootstrap-table2-example/examples/row-selection/selection-no-data.js b/packages/react-bootstrap-table2-example/examples/row-selection/selection-no-data.js new file mode 100644 index 000000000..4867ffd9c --- /dev/null +++ b/packages/react-bootstrap-table2-example/examples/row-selection/selection-no-data.js @@ -0,0 +1,62 @@ +/* eslint no-unused-vars: 0 */ +import React from 'react'; + +import BootstrapTable from 'react-bootstrap-table-next'; +import Code from 'components/common/code-block'; + +const columns = [{ + dataField: 'id', + text: 'Product ID' +}, { + dataField: 'name', + text: 'Product Name' +}, { + dataField: 'price', + text: 'Product Price' +}]; + +const selectRow1 = { + mode: 'checkbox', + clickToSelect: true +}; + +const sourceCode1 = `\ +import BootstrapTable from 'react-bootstrap-table-next'; + +const columns = [{ + dataField: 'id', + text: 'Product ID' +}, { + dataField: 'name', + text: 'Product Name' +}, { + dataField: 'price', + text: 'Product Price' +}]; + +const selectRow = { + mode: 'checkbox', + clickToSelect: true +}; + + +`; + +export default () => ( +
+ + { sourceCode1 } +
+); diff --git a/packages/react-bootstrap-table2-example/stories/index.js b/packages/react-bootstrap-table2-example/stories/index.js index 3f116f508..f95959bb8 100644 --- a/packages/react-bootstrap-table2-example/stories/index.js +++ b/packages/react-bootstrap-table2-example/stories/index.js @@ -81,6 +81,7 @@ import ClickToSelectTable from 'examples/row-selection/click-to-select'; import DefaultSelectTable from 'examples/row-selection/default-select'; import SelectionManagement from 'examples/row-selection/selection-management'; import ClickToSelectWithCellEditTable from 'examples/row-selection/click-to-select-with-cell-edit'; +import SelectionNoDataTable from 'examples/row-selection/selection-no-data'; import SelectionStyleTable from 'examples/row-selection/selection-style'; import SelectionClassTable from 'examples/row-selection/selection-class'; import NonSelectableRowsTable from 'examples/row-selection/non-selectable-rows'; @@ -196,6 +197,7 @@ storiesOf('Row Selection', module) .add('Default Select', () => ) .add('Selection Management', () => ) .add('Click to Select and Edit Cell', () => ) + .add('Selection without Data', () => ) .add('Selection Style', () => ) .add('Selection Class', () => ) .add('Selection Background Color', () => ) diff --git a/packages/react-bootstrap-table2/src/props-resolver/column-resolver.js b/packages/react-bootstrap-table2/src/props-resolver/column-resolver.js index 584649896..c330c7d5e 100644 --- a/packages/react-bootstrap-table2/src/props-resolver/column-resolver.js +++ b/packages/react-bootstrap-table2/src/props-resolver/column-resolver.js @@ -1,6 +1,11 @@ export default ExtendBase => class ColumnResolver extends ExtendBase { - visibleColumnSize() { - return this.props.columns.filter(c => !c.hidden).length; + visibleColumnSize(includeSelectColumn = true) { + const columnLen = this.props.columns.filter(c => !c.hidden).length; + if (!includeSelectColumn) return columnLen; + if (this.props.selectRow && !this.props.selectRow.hideSelectColumn) { + return columnLen + 1; + } + return columnLen; } }; diff --git a/packages/react-bootstrap-table2/src/props-resolver/index.js b/packages/react-bootstrap-table2/src/props-resolver/index.js index 4871e2d5e..4f40d97fc 100644 --- a/packages/react-bootstrap-table2/src/props-resolver/index.js +++ b/packages/react-bootstrap-table2/src/props-resolver/index.js @@ -5,12 +5,12 @@ import _ from '../utils'; export default ExtendBase => class TableResolver extends ColumnResolver(ExtendBase) { validateProps() { - const { columns, keyField } = this.props; + const { keyField } = this.props; if (!keyField) { throw new Error('Please specify a field as key via keyField'); } - if (this.visibleColumnSize(columns) <= 0) { - throw new Error('No any visible columns detect'); + if (this.visibleColumnSize(false) <= 0) { + throw new Error('No visible columns detected'); } } diff --git a/packages/react-bootstrap-table2/test/props-resolver/index.test.js b/packages/react-bootstrap-table2/test/props-resolver/index.test.js index 1b6bf8c9d..cb3a54b52 100644 --- a/packages/react-bootstrap-table2/test/props-resolver/index.test.js +++ b/packages/react-bootstrap-table2/test/props-resolver/index.test.js @@ -56,7 +56,7 @@ describe('TableResolver', () => { }); }); - describe('if columns is all unvisible', () => { + describe('if no columns are visible', () => { beforeEach(() => { const mockElement = React.createElement(BootstrapTableMock, { data, keyField, columns: [] @@ -67,7 +67,7 @@ describe('TableResolver', () => { it('should throw error', () => { expect(() => wrapper.instance().validateProps() - ).toThrow(new Error('No any visible columns detect')); + ).toThrow(new Error('No visible columns detected')); }); }); }); From 9ee9c7de434ba19d2558583d4ed4542a25d4d95c Mon Sep 17 00:00:00 2001 From: Allen Date: Sun, 25 Mar 2018 16:37:27 +0800 Subject: [PATCH 026/549] Revert "fix#264: wrong col span when enable selection in a empty table (#265)" This reverts commit 42dbd00fd9edbf44b66b2cb577304d36741c2276. --- .../row-selection/selection-no-data.js | 62 ------------------- .../stories/index.js | 2 - .../src/props-resolver/column-resolver.js | 9 +-- .../src/props-resolver/index.js | 6 +- .../test/props-resolver/index.test.js | 4 +- 5 files changed, 7 insertions(+), 76 deletions(-) delete mode 100644 packages/react-bootstrap-table2-example/examples/row-selection/selection-no-data.js diff --git a/packages/react-bootstrap-table2-example/examples/row-selection/selection-no-data.js b/packages/react-bootstrap-table2-example/examples/row-selection/selection-no-data.js deleted file mode 100644 index 4867ffd9c..000000000 --- a/packages/react-bootstrap-table2-example/examples/row-selection/selection-no-data.js +++ /dev/null @@ -1,62 +0,0 @@ -/* eslint no-unused-vars: 0 */ -import React from 'react'; - -import BootstrapTable from 'react-bootstrap-table-next'; -import Code from 'components/common/code-block'; - -const columns = [{ - dataField: 'id', - text: 'Product ID' -}, { - dataField: 'name', - text: 'Product Name' -}, { - dataField: 'price', - text: 'Product Price' -}]; - -const selectRow1 = { - mode: 'checkbox', - clickToSelect: true -}; - -const sourceCode1 = `\ -import BootstrapTable from 'react-bootstrap-table-next'; - -const columns = [{ - dataField: 'id', - text: 'Product ID' -}, { - dataField: 'name', - text: 'Product Name' -}, { - dataField: 'price', - text: 'Product Price' -}]; - -const selectRow = { - mode: 'checkbox', - clickToSelect: true -}; - - -`; - -export default () => ( -
- - { sourceCode1 } -
-); diff --git a/packages/react-bootstrap-table2-example/stories/index.js b/packages/react-bootstrap-table2-example/stories/index.js index f95959bb8..3f116f508 100644 --- a/packages/react-bootstrap-table2-example/stories/index.js +++ b/packages/react-bootstrap-table2-example/stories/index.js @@ -81,7 +81,6 @@ import ClickToSelectTable from 'examples/row-selection/click-to-select'; import DefaultSelectTable from 'examples/row-selection/default-select'; import SelectionManagement from 'examples/row-selection/selection-management'; import ClickToSelectWithCellEditTable from 'examples/row-selection/click-to-select-with-cell-edit'; -import SelectionNoDataTable from 'examples/row-selection/selection-no-data'; import SelectionStyleTable from 'examples/row-selection/selection-style'; import SelectionClassTable from 'examples/row-selection/selection-class'; import NonSelectableRowsTable from 'examples/row-selection/non-selectable-rows'; @@ -197,7 +196,6 @@ storiesOf('Row Selection', module) .add('Default Select', () => ) .add('Selection Management', () => ) .add('Click to Select and Edit Cell', () => ) - .add('Selection without Data', () => ) .add('Selection Style', () => ) .add('Selection Class', () => ) .add('Selection Background Color', () => ) diff --git a/packages/react-bootstrap-table2/src/props-resolver/column-resolver.js b/packages/react-bootstrap-table2/src/props-resolver/column-resolver.js index c330c7d5e..584649896 100644 --- a/packages/react-bootstrap-table2/src/props-resolver/column-resolver.js +++ b/packages/react-bootstrap-table2/src/props-resolver/column-resolver.js @@ -1,11 +1,6 @@ export default ExtendBase => class ColumnResolver extends ExtendBase { - visibleColumnSize(includeSelectColumn = true) { - const columnLen = this.props.columns.filter(c => !c.hidden).length; - if (!includeSelectColumn) return columnLen; - if (this.props.selectRow && !this.props.selectRow.hideSelectColumn) { - return columnLen + 1; - } - return columnLen; + visibleColumnSize() { + return this.props.columns.filter(c => !c.hidden).length; } }; diff --git a/packages/react-bootstrap-table2/src/props-resolver/index.js b/packages/react-bootstrap-table2/src/props-resolver/index.js index 4f40d97fc..4871e2d5e 100644 --- a/packages/react-bootstrap-table2/src/props-resolver/index.js +++ b/packages/react-bootstrap-table2/src/props-resolver/index.js @@ -5,12 +5,12 @@ import _ from '../utils'; export default ExtendBase => class TableResolver extends ColumnResolver(ExtendBase) { validateProps() { - const { keyField } = this.props; + const { columns, keyField } = this.props; if (!keyField) { throw new Error('Please specify a field as key via keyField'); } - if (this.visibleColumnSize(false) <= 0) { - throw new Error('No visible columns detected'); + if (this.visibleColumnSize(columns) <= 0) { + throw new Error('No any visible columns detect'); } } diff --git a/packages/react-bootstrap-table2/test/props-resolver/index.test.js b/packages/react-bootstrap-table2/test/props-resolver/index.test.js index cb3a54b52..1b6bf8c9d 100644 --- a/packages/react-bootstrap-table2/test/props-resolver/index.test.js +++ b/packages/react-bootstrap-table2/test/props-resolver/index.test.js @@ -56,7 +56,7 @@ describe('TableResolver', () => { }); }); - describe('if no columns are visible', () => { + describe('if columns is all unvisible', () => { beforeEach(() => { const mockElement = React.createElement(BootstrapTableMock, { data, keyField, columns: [] @@ -67,7 +67,7 @@ describe('TableResolver', () => { it('should throw error', () => { expect(() => wrapper.instance().validateProps() - ).toThrow(new Error('No visible columns detected')); + ).toThrow(new Error('No any visible columns detect')); }); }); }); From c91f5219138619656e3d26b4171b92187f56c914 Mon Sep 17 00:00:00 2001 From: Allen Date: Sun, 25 Mar 2018 16:44:27 +0800 Subject: [PATCH 027/549] fix #258 (#268) --- docs/columns.md | 8 + .../react-bootstrap-table2-editor/README.md | 6 +- .../src/editing-cell.js | 21 ++- .../test/editing-cell.test.js | 141 +++++++++++++++++- .../examples/cell-edit/editor-class-table.js | 61 ++++++++ .../examples/cell-edit/editor-style-table.js | 69 +++++++++ .../stories/index.js | 8 +- .../react-bootstrap-table2/src/header-cell.js | 2 + packages/react-bootstrap-table2/src/row.js | 2 + 9 files changed, 311 insertions(+), 7 deletions(-) create mode 100644 packages/react-bootstrap-table2-example/examples/cell-edit/editor-class-table.js create mode 100644 packages/react-bootstrap-table2-example/examples/cell-edit/editor-style-table.js diff --git a/docs/columns.md b/docs/columns.md index eeab42ba2..d7a7beaf7 100644 --- a/docs/columns.md +++ b/docs/columns.md @@ -32,6 +32,8 @@ Available properties in a column object: * [validator](#validator) * [editCellStyle](#editCellStyle) * [editCellClasses](#editCellClasses) +* [editorStyle](#editorStyle) +* [editorClasses](#editorClasses) * [filter](#filter) * [filterValue](#filterValue) @@ -552,6 +554,12 @@ Or take a callback function } ``` +## column.editorStyle - [Object | Function] +This is almost same as [`column.editCellStyle`](#editCellStyle), but `column.editorStyle` is custom the style on editor instead of cell(`td`). + +## column.editorClasses - [Object | Function] +This is almost same as [`column.editCellClasses`](#editCellClasses), but `column.editorClasses` is custom the class on editor instead of cell(`td`). + ## column.filter - [Object] Configure `column.filter` will able to setup a column level filter on the header column. Currently, `react-bootstrap-table2` support following filters: diff --git a/packages/react-bootstrap-table2-editor/README.md b/packages/react-bootstrap-table2-editor/README.md index 02e0e46af..5c9719e1b 100644 --- a/packages/react-bootstrap-table2-editor/README.md +++ b/packages/react-bootstrap-table2-editor/README.md @@ -49,13 +49,15 @@ How user save their new editings? We offer two ways: * Cell Level (Configure [column.editable](https://react-bootstrap-table.github.io/react-bootstrap-table2/docs/column-props.html#columneditable-bool-function) as a callback function) ## Customize Style/Class -Currently, we only support the editing cell style/class customization, in the future, we will offer more customizations. - ### Editing Cell * Customize the editing cell style via [column.editCellStyle](https://react-bootstrap-table.github.io/react-bootstrap-table2/docs/column-props.html#columneditcellstyle-object-function) * Customize the editing cell classname via [column.editCellClasses](https://react-bootstrap-table.github.io/react-bootstrap-table2/docs/column-props.html#columneditcellclasses-string-function) +### Editor +* Customize the editor style via [column.editorStyle](https://react-bootstrap-table.github.io/react-bootstrap-table2/docs/column-props.html#columneditorstyle-object-function) +* Customize the editor classname via [column.editoClasses](https://react-bootstrap-table.github.io/react-bootstrap-table2/docs/column-props.html#columneditorclasses-string-function) + ## Validation [`column.validator`](https://react-bootstrap-table.github.io/react-bootstrap-table2/docs/column-props.html#columnvalidator-function) will help you to work on it! \ No newline at end of file diff --git a/packages/react-bootstrap-table2-editor/src/editing-cell.js b/packages/react-bootstrap-table2-editor/src/editing-cell.js index 5e54984c6..2c732de0d 100644 --- a/packages/react-bootstrap-table2-editor/src/editing-cell.js +++ b/packages/react-bootstrap-table2-editor/src/editing-cell.js @@ -14,7 +14,9 @@ export default _ => class EditingCell extends Component { static propTypes = { row: PropTypes.object.isRequired, + rowIndex: PropTypes.number.isRequired, column: PropTypes.object.isRequired, + columnIndex: PropTypes.number.isRequired, onUpdate: PropTypes.func.isRequired, onEscape: PropTypes.func.isRequired, timeToCloseMessage: PropTypes.number, @@ -123,7 +125,7 @@ export default _ => render() { const { invalidMessage } = this.state; - const { row, column, className, style } = this.props; + const { row, column, className, style, rowIndex, columnIndex } = this.props; const { dataField } = column; const value = _.get(row, dataField); @@ -133,7 +135,21 @@ export default _ => }; const hasError = _.isDefined(invalidMessage); - const editorClass = hasError ? cs('animated', 'shake') : null; + let customEditorClass = column.editorClasses || ''; + if (_.isFunction(column.editorClasses)) { + customEditorClass = column.editorClasses(value, row, rowIndex, columnIndex); + } + + let editorStyle = column.editorStyle || {}; + if (_.isFunction(column.editorStyle)) { + editorStyle = column.editorStyle(value, row, rowIndex, columnIndex); + } + + const editorClass = cs({ + animated: hasError, + shake: hasError + }, customEditorClass); + return (
); } diff --git a/packages/react-bootstrap-table2-editor/src/text-editor.js b/packages/react-bootstrap-table2-editor/src/text-editor.js index 7937282b6..b44c2da30 100644 --- a/packages/react-bootstrap-table2-editor/src/text-editor.js +++ b/packages/react-bootstrap-table2-editor/src/text-editor.js @@ -10,6 +10,10 @@ class TextEditor extends Component { this.text.focus(); } + getValue() { + return this.text.value; + } + render() { const { defaultValue, className, ...rest } = this.props; const editorClass = cs('form-control editor edit-text', className); diff --git a/packages/react-bootstrap-table2-editor/src/textarea-editor.js b/packages/react-bootstrap-table2-editor/src/textarea-editor.js new file mode 100644 index 000000000..e65b27ecd --- /dev/null +++ b/packages/react-bootstrap-table2-editor/src/textarea-editor.js @@ -0,0 +1,60 @@ +/* eslint no-return-assign: 0 */ +import React, { Component } from 'react'; +import cs from 'classnames'; +import PropTypes from 'prop-types'; + +class TextAreaEditor extends Component { + constructor(props) { + super(props); + this.handleKeyDown = this.handleKeyDown.bind(this); + } + + componentDidMount() { + const { defaultValue } = this.props; + this.text.value = defaultValue; + this.text.focus(); + } + + getValue() { + return this.text.value; + } + + handleKeyDown(e) { + if (e.keyCode === 13 && !e.shiftKey) return; + if (this.props.onKeyDown) { + this.props.onKeyDown(e); + } + } + + render() { + const { defaultValue, className, ...rest } = this.props; + const editorClass = cs('form-control editor edit-textarea', className); + return ( +
this.editor = node } defaultValue={ value } + style={ editorStyle } className={ editorClass } { ...editorAttrs } /> diff --git a/packages/react-bootstrap-table2-editor/test/editing-cell.test.js b/packages/react-bootstrap-table2-editor/test/editing-cell.test.js index 9b34d9388..2741ee103 100644 --- a/packages/react-bootstrap-table2-editor/test/editing-cell.test.js +++ b/packages/react-bootstrap-table2-editor/test/editing-cell.test.js @@ -28,6 +28,9 @@ describe('EditingCell', () => { name: 'A' }; + const rowIndex = 1; + const columnIndex = 1; + let column = { dataField: 'id', text: 'ID' @@ -39,6 +42,8 @@ describe('EditingCell', () => { wrapper = shallow( { expect(textEditor.props().defaultValue).toEqual(row[column.dataField]); expect(textEditor.props().onKeyDown).toBeDefined(); expect(textEditor.props().onBlur).toBeDefined(); - expect(textEditor.props().className).toBeNull(); + expect(textEditor.props().className).toEqual(''); }); it('should not render EditorIndicator due to state.invalidMessage is null', () => { @@ -92,6 +97,8 @@ describe('EditingCell', () => { wrapper = shallow( { wrapper = shallow( { }); }); + describe('if column.editorClasses is defined', () => { + let columnWithEditorClasses; + const classes = 'test test1'; + + describe('and it is a function', () => { + beforeEach(() => { + columnWithEditorClasses = { + ...column, + editorClasses: jest.fn(() => classes) + }; + wrapper = shallow( + + ); + }); + + it('should render TextEditor with correct props', () => { + const textEditor = wrapper.find(TextEditor); + expect(textEditor.props().className).toEqual(classes); + }); + + it('should call column.editorClasses correctly', () => { + expect(columnWithEditorClasses.editorClasses).toHaveBeenCalledTimes(1); + expect(columnWithEditorClasses.editorClasses).toHaveBeenCalledWith( + _.get(row, column.dataField), + row, + rowIndex, + columnIndex + ); + }); + }); + + describe('and it is a string', () => { + beforeEach(() => { + columnWithEditorClasses = { + ...column, + editorClasses: classes + }; + wrapper = shallow( + + ); + }); + + it('should render TextEditor with correct props', () => { + const textEditor = wrapper.find(TextEditor); + expect(textEditor.props().className).toEqual(classes); + }); + }); + }); + + describe('if column.editorStyle is defined', () => { + let columnWithEditorStyle; + const style = { color: 'red' }; + + describe('and it is a function', () => { + beforeEach(() => { + columnWithEditorStyle = { + ...column, + editorStyle: jest.fn(() => style) + }; + wrapper = shallow( + + ); + }); + + it('should render TextEditor with correct props', () => { + const textEditor = wrapper.find(TextEditor); + expect(textEditor.props().style).toEqual(style); + }); + + it('should call column.editorStyle correctly', () => { + expect(columnWithEditorStyle.editorStyle).toHaveBeenCalledTimes(1); + expect(columnWithEditorStyle.editorStyle).toHaveBeenCalledWith( + _.get(row, column.dataField), + row, + rowIndex, + columnIndex + ); + }); + }); + + describe('and it is an object', () => { + beforeEach(() => { + columnWithEditorStyle = { + ...column, + editorStyle: style + }; + wrapper = shallow( + + ); + }); + + it('should render TextEditor with correct props', () => { + const textEditor = wrapper.find(TextEditor); + expect(textEditor.props().style).toEqual(style); + }); + }); + }); + describe('if blurToSave prop is true', () => { beforeEach(() => { wrapper = mount( { wrapper = mount( + (cell > 2101 ? 'editing-price-bigger-than-2101' : 'editing-price-small-than-2101') +}]; + +const sourceCode = `\ +import BootstrapTable from 'react-bootstrap-table-next'; +import cellEditFactory from 'react-bootstrap-table2-editor'; + +const columns = [{ + dataField: 'id', + text: 'Product ID' +}, { + dataField: 'name', + text: 'Product Name', + editorClasses: 'editing-name' +}, { + dataField: 'price', + text: 'Product Price', + editorClasses: (cell, row, rowIndex, colIndex) => + (cell > 2101 ? 'editing-price-bigger-than-2101' : 'editing-price-small-than-2101') +}]; + + +`; + +export default () => ( +
+ + { sourceCode } +
+); diff --git a/packages/react-bootstrap-table2-example/examples/cell-edit/editor-style-table.js b/packages/react-bootstrap-table2-example/examples/cell-edit/editor-style-table.js new file mode 100644 index 000000000..37bf5bf96 --- /dev/null +++ b/packages/react-bootstrap-table2-example/examples/cell-edit/editor-style-table.js @@ -0,0 +1,69 @@ +/* eslint no-unused-vars: 0 */ +import React from 'react'; + +import BootstrapTable from 'react-bootstrap-table-next'; +import cellEditFactory from 'react-bootstrap-table2-editor'; +import Code from 'components/common/code-block'; +import { productsGenerator } from 'utils/common'; + +const products = productsGenerator(); + +const columns = [{ + dataField: 'id', + text: 'Product ID' +}, { + dataField: 'name', + text: 'Product Name', + editorStyle: { + backgroundColor: '#20B2AA' + } +}, { + dataField: 'price', + text: 'Product Price', + editorStyle: (cell, row, rowIndex, colIndex) => { + const backgroundColor = cell > 2101 ? '#00BFFF' : '#00FFFF'; + return { backgroundColor }; + } +}]; + +const sourceCode = `\ +import BootstrapTable from 'react-bootstrap-table-next'; +import cellEditFactory from 'react-bootstrap-table2-editor'; + +const columns = [{ + dataField: 'id', + text: 'Product ID' +}, { + dataField: 'name', + text: 'Product Name', + editorStyle: { + backgroundColor: '#20B2AA' + } +}, { + dataField: 'price', + text: 'Product Price', + editorStyle: (cell, row, rowIndex, colIndex) => { + const backgroundColor = cell > 2101 ? '#00BFFF' : '#00FFFF'; + return { backgroundColor }; + } +}]; + + +`; + +export default () => ( +
+ + { sourceCode } +
+); diff --git a/packages/react-bootstrap-table2-example/stories/index.js b/packages/react-bootstrap-table2-example/stories/index.js index 3f116f508..ae50d60ed 100644 --- a/packages/react-bootstrap-table2-example/stories/index.js +++ b/packages/react-bootstrap-table2-example/stories/index.js @@ -73,6 +73,8 @@ import CellEditHooks from 'examples/cell-edit/cell-edit-hooks-table'; import CellEditValidator from 'examples/cell-edit/cell-edit-validator-table'; import CellEditStyleTable from 'examples/cell-edit/cell-edit-style-table'; import CellEditClassTable from 'examples/cell-edit/cell-edit-class-table'; +import EditorStyleTable from 'examples/cell-edit/editor-style-table'; +import EditorClassTable from 'examples/cell-edit/editor-class-table'; // work on row selection import SingleSelectionTable from 'examples/row-selection/single-selection'; @@ -186,8 +188,10 @@ storiesOf('Cell Editing', module) .add('Cell Level Editable', () => ) .add('Rich Hook Functions', () => ) .add('Validation', () => ) - .add('Custom Cell Style When Editing', () => ) - .add('Custom Cell Classes When Editing', () => ); + .add('Custom Cell Style', () => ) + .add('Custom Cell Classes', () => ) + .add('Custom Editor Classes', () => ) + .add('Custom Editor Style', () => ); storiesOf('Row Selection', module) .add('Single Selection', () => ) diff --git a/packages/react-bootstrap-table2/src/header-cell.js b/packages/react-bootstrap-table2/src/header-cell.js index bb012d182..69fdfed11 100644 --- a/packages/react-bootstrap-table2/src/header-cell.js +++ b/packages/react-bootstrap-table2/src/header-cell.js @@ -130,6 +130,8 @@ HeaderCell.propTypes = { editable: PropTypes.oneOfType([PropTypes.bool, PropTypes.func]), editCellStyle: PropTypes.oneOfType([PropTypes.object, PropTypes.func]), editCellClasses: PropTypes.oneOfType([PropTypes.string, PropTypes.func]), + editorStyle: PropTypes.oneOfType([PropTypes.object, PropTypes.func]), + editorClasses: PropTypes.oneOfType([PropTypes.string, PropTypes.func]), validator: PropTypes.func, filter: PropTypes.object, filterValue: PropTypes.func diff --git a/packages/react-bootstrap-table2/src/row.js b/packages/react-bootstrap-table2/src/row.js index 3efb0c529..b6222bb07 100644 --- a/packages/react-bootstrap-table2/src/row.js +++ b/packages/react-bootstrap-table2/src/row.js @@ -79,7 +79,9 @@ class Row extends eventDelegater(Component) { Date: Sat, 31 Mar 2018 22:30:59 -0700 Subject: [PATCH 028/549] Fix textFilter() for Internet Explorer (includes() and find() are not supported) (#274) * Fix textFilter() for Internet Explorer 11 - replace includes() with indexOf() !== -1 - replace find() with for loop * Requested changes; more readability with for loop - use .length of the columns instead of the Object.keys() --- packages/react-bootstrap-table2-filter/src/filter.js | 10 ++++++++-- packages/react-bootstrap-table2/src/sort/wrapper.js | 9 +++++++-- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/packages/react-bootstrap-table2-filter/src/filter.js b/packages/react-bootstrap-table2-filter/src/filter.js index f16674228..e0d7a452b 100644 --- a/packages/react-bootstrap-table2-filter/src/filter.js +++ b/packages/react-bootstrap-table2-filter/src/filter.js @@ -21,7 +21,7 @@ export const filterByText = _ => ( if (caseSensitive) { return cellStr.includes(filterVal); } - return cellStr.toLocaleUpperCase().includes(filterVal.toLocaleUpperCase()); + return cellStr.toLocaleUpperCase().indexOf(filterVal.toLocaleUpperCase()) !== -1; }); export const filterByNumber = _ => ( @@ -106,7 +106,13 @@ export const filters = (store, columns, _) => (currFilters) => { Object.keys(currFilters).forEach((dataField) => { const filterObj = currFilters[dataField]; filterFn = factory(filterObj.filterType); - const { filterValue } = columns.find(col => col.dataField === dataField); + let filterValue; + for (let i = 0; i < columns.length; i += 1) { + if (columns[i].dataField === dataField) { + filterValue = columns[i].filterValue; + break; + } + } result = filterFn(result, dataField, filterObj, filterValue); }); return result; diff --git a/packages/react-bootstrap-table2/src/sort/wrapper.js b/packages/react-bootstrap-table2/src/sort/wrapper.js index 71c50511c..8528e0f0b 100644 --- a/packages/react-bootstrap-table2/src/sort/wrapper.js +++ b/packages/react-bootstrap-table2/src/sort/wrapper.js @@ -39,8 +39,13 @@ export default Base => } componentWillReceiveProps(nextProps) { - const sortedColumn = nextProps.columns.find( - column => column.dataField === nextProps.store.sortField); + let sortedColumn; + for (let i = 0; i < nextProps.columns.length; i += 1) { + if (nextProps.columns[i].dataField === nextProps.store.sortField) { + sortedColumn = nextProps.columns[i]; + break; + } + } if (sortedColumn && sortedColumn.sort) { nextProps.store.sortBy(sortedColumn); } From 41dc3ef6191e9f6d7528fffdb1a125a202c64dc0 Mon Sep 17 00:00:00 2001 From: Patrick O'Meara Date: Sun, 1 Apr 2018 15:32:24 +1000 Subject: [PATCH 029/549] empty noDataIndication when empty (#275) * don't display unneeded empty row when noDataIndication isn't set --- packages/react-bootstrap-table2/src/body.js | 3 +++ packages/react-bootstrap-table2/test/body.test.js | 8 +++----- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/packages/react-bootstrap-table2/src/body.js b/packages/react-bootstrap-table2/src/body.js index 9ee9e898e..b4ca400c0 100644 --- a/packages/react-bootstrap-table2/src/body.js +++ b/packages/react-bootstrap-table2/src/body.js @@ -35,6 +35,9 @@ const Body = (props) => { if (isEmpty) { const indication = _.isFunction(noDataIndication) ? noDataIndication() : noDataIndication; + if (!indication) { + return null; + } content = ; } else { const nonEditableRows = cellEdit.nonEditableRows || []; diff --git a/packages/react-bootstrap-table2/test/body.test.js b/packages/react-bootstrap-table2/test/body.test.js index 5674b83fe..ea624e51f 100644 --- a/packages/react-bootstrap-table2/test/body.test.js +++ b/packages/react-bootstrap-table2/test/body.test.js @@ -53,12 +53,10 @@ describe('Body', () => { />); }); - it('should render successfully', () => { + it('should not render', () => { expect(wrapper.length).toBe(1); - expect(wrapper.find('tbody').length).toBe(1); - expect(wrapper.find(RowSection).length).toBe(1); - expect(wrapper.find(RowSection).prop('colSpan')).toBe(columns.length); - expect(wrapper.find(RowSection).prop('content')).toBe(null); + expect(wrapper.find('tbody').length).toBe(0); + expect(wrapper.find(RowSection).length).toBe(0); }); describe('when noDataIndication props is defined', () => { From 11d4f40089879e5e4f830c0e4f5c76c9a9c064a3 Mon Sep 17 00:00:00 2001 From: Patrick O'Meara Date: Sun, 1 Apr 2018 15:34:06 +1000 Subject: [PATCH 030/549] noDataIndication (#276) * use the correct amount of cells when the first row is select * storybook added for development, not necessary in docs fixes react-bootstrap-table/react-bootstrap-table2#264 --- .../row-selection/selection-no-data.js | 62 +++++++++++++++++++ .../stories/index.js | 2 + .../src/props-resolver/column-resolver.js | 9 ++- .../src/props-resolver/index.js | 6 +- .../test/props-resolver/index.test.js | 4 +- 5 files changed, 76 insertions(+), 7 deletions(-) create mode 100644 packages/react-bootstrap-table2-example/examples/row-selection/selection-no-data.js diff --git a/packages/react-bootstrap-table2-example/examples/row-selection/selection-no-data.js b/packages/react-bootstrap-table2-example/examples/row-selection/selection-no-data.js new file mode 100644 index 000000000..4867ffd9c --- /dev/null +++ b/packages/react-bootstrap-table2-example/examples/row-selection/selection-no-data.js @@ -0,0 +1,62 @@ +/* eslint no-unused-vars: 0 */ +import React from 'react'; + +import BootstrapTable from 'react-bootstrap-table-next'; +import Code from 'components/common/code-block'; + +const columns = [{ + dataField: 'id', + text: 'Product ID' +}, { + dataField: 'name', + text: 'Product Name' +}, { + dataField: 'price', + text: 'Product Price' +}]; + +const selectRow1 = { + mode: 'checkbox', + clickToSelect: true +}; + +const sourceCode1 = `\ +import BootstrapTable from 'react-bootstrap-table-next'; + +const columns = [{ + dataField: 'id', + text: 'Product ID' +}, { + dataField: 'name', + text: 'Product Name' +}, { + dataField: 'price', + text: 'Product Price' +}]; + +const selectRow = { + mode: 'checkbox', + clickToSelect: true +}; + + +`; + +export default () => ( +
+ + { sourceCode1 } +
+); diff --git a/packages/react-bootstrap-table2-example/stories/index.js b/packages/react-bootstrap-table2-example/stories/index.js index ae50d60ed..206f1eee0 100644 --- a/packages/react-bootstrap-table2-example/stories/index.js +++ b/packages/react-bootstrap-table2-example/stories/index.js @@ -83,6 +83,7 @@ import ClickToSelectTable from 'examples/row-selection/click-to-select'; import DefaultSelectTable from 'examples/row-selection/default-select'; import SelectionManagement from 'examples/row-selection/selection-management'; import ClickToSelectWithCellEditTable from 'examples/row-selection/click-to-select-with-cell-edit'; +import SelectionNoDataTable from 'examples/row-selection/selection-no-data'; import SelectionStyleTable from 'examples/row-selection/selection-style'; import SelectionClassTable from 'examples/row-selection/selection-class'; import NonSelectableRowsTable from 'examples/row-selection/non-selectable-rows'; @@ -200,6 +201,7 @@ storiesOf('Row Selection', module) .add('Default Select', () => ) .add('Selection Management', () => ) .add('Click to Select and Edit Cell', () => ) + .add('Selection without Data', () => ) .add('Selection Style', () => ) .add('Selection Class', () => ) .add('Selection Background Color', () => ) diff --git a/packages/react-bootstrap-table2/src/props-resolver/column-resolver.js b/packages/react-bootstrap-table2/src/props-resolver/column-resolver.js index 584649896..c330c7d5e 100644 --- a/packages/react-bootstrap-table2/src/props-resolver/column-resolver.js +++ b/packages/react-bootstrap-table2/src/props-resolver/column-resolver.js @@ -1,6 +1,11 @@ export default ExtendBase => class ColumnResolver extends ExtendBase { - visibleColumnSize() { - return this.props.columns.filter(c => !c.hidden).length; + visibleColumnSize(includeSelectColumn = true) { + const columnLen = this.props.columns.filter(c => !c.hidden).length; + if (!includeSelectColumn) return columnLen; + if (this.props.selectRow && !this.props.selectRow.hideSelectColumn) { + return columnLen + 1; + } + return columnLen; } }; diff --git a/packages/react-bootstrap-table2/src/props-resolver/index.js b/packages/react-bootstrap-table2/src/props-resolver/index.js index 4871e2d5e..4f40d97fc 100644 --- a/packages/react-bootstrap-table2/src/props-resolver/index.js +++ b/packages/react-bootstrap-table2/src/props-resolver/index.js @@ -5,12 +5,12 @@ import _ from '../utils'; export default ExtendBase => class TableResolver extends ColumnResolver(ExtendBase) { validateProps() { - const { columns, keyField } = this.props; + const { keyField } = this.props; if (!keyField) { throw new Error('Please specify a field as key via keyField'); } - if (this.visibleColumnSize(columns) <= 0) { - throw new Error('No any visible columns detect'); + if (this.visibleColumnSize(false) <= 0) { + throw new Error('No visible columns detected'); } } diff --git a/packages/react-bootstrap-table2/test/props-resolver/index.test.js b/packages/react-bootstrap-table2/test/props-resolver/index.test.js index 1b6bf8c9d..cb3a54b52 100644 --- a/packages/react-bootstrap-table2/test/props-resolver/index.test.js +++ b/packages/react-bootstrap-table2/test/props-resolver/index.test.js @@ -56,7 +56,7 @@ describe('TableResolver', () => { }); }); - describe('if columns is all unvisible', () => { + describe('if no columns are visible', () => { beforeEach(() => { const mockElement = React.createElement(BootstrapTableMock, { data, keyField, columns: [] @@ -67,7 +67,7 @@ describe('TableResolver', () => { it('should throw error', () => { expect(() => wrapper.instance().validateProps() - ).toThrow(new Error('No any visible columns detect')); + ).toThrow(new Error('No visible columns detected')); }); }); }); From 88e1a0774b91308bbb265209fe178ca082a8d5e3 Mon Sep 17 00:00:00 2001 From: Allen Date: Sun, 1 Apr 2018 14:14:32 +0800 Subject: [PATCH 031/549] fix #281 --- docs/README.md | 4 ++ .../examples/sort/default-sort-direction.js | 67 +++++++++++++++++++ .../stories/index.js | 2 + .../src/bootstrap-table.js | 1 + .../src/sort/wrapper.js | 6 +- .../react-bootstrap-table2/src/store/index.js | 4 +- .../react-bootstrap-table2/src/store/sort.js | 4 +- .../test/store/index.test.js | 7 +- .../test/store/sort.test.js | 4 ++ 9 files changed, 91 insertions(+), 8 deletions(-) create mode 100644 packages/react-bootstrap-table2-example/examples/sort/default-sort-direction.js diff --git a/docs/README.md b/docs/README.md index 34b38df98..181b4a809 100644 --- a/docs/README.md +++ b/docs/README.md @@ -23,6 +23,7 @@ * [rowClasses](#rowClasses) * [rowEvents](#rowEvents) * [defaultSorted](#defaultSorted) +* [defaultSortDirection](#defaultSortDirection) * [pagination](#pagination) * [filter](#filter) * [onTableChange](#onTableChange) @@ -168,6 +169,9 @@ const defaultSorted = [{ }]; ``` +### defaultSortDirection - [String] +Default sort direction when user click on header column at first time, available value is `asc` and `desc`. Default is `desc`. + ### pagination - [Object] `pagination` allow user to render a pagination panel on the bottom of table. But pagination functionality is separated from core of `react-bootstrap-table2` so that you are suppose to install `react-bootstrap-table2-paginator` additionally. diff --git a/packages/react-bootstrap-table2-example/examples/sort/default-sort-direction.js b/packages/react-bootstrap-table2-example/examples/sort/default-sort-direction.js new file mode 100644 index 000000000..f5c0aeafc --- /dev/null +++ b/packages/react-bootstrap-table2-example/examples/sort/default-sort-direction.js @@ -0,0 +1,67 @@ +/* eslint react/prefer-stateless-function: 0 */ +import React from 'react'; + +import BootstrapTable from 'react-bootstrap-table-next'; +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', + sort: true +}]; + + +const sourceCode = `\ +import BootstrapTable from 'react-bootstrap-table-next'; + +const columns = [{ + dataField: 'id', + text: 'Product ID', + sort: true +}, { + dataField: 'name', + text: 'Product Name', + sort: true +}, { + dataField: 'price', + text: 'Product Price', + sort: true +}]; + +const defaultSorted = [{ + dataField: 'name', + order: 'desc' +}]; + + +`; + + +class DefaultSortDirectionTable extends React.PureComponent { + render() { + return ( +
+ + { sourceCode } +
+ ); + } +} + +export default DefaultSortDirectionTable; diff --git a/packages/react-bootstrap-table2-example/stories/index.js b/packages/react-bootstrap-table2-example/stories/index.js index 206f1eee0..25d8538a3 100644 --- a/packages/react-bootstrap-table2-example/stories/index.js +++ b/packages/react-bootstrap-table2-example/stories/index.js @@ -57,6 +57,7 @@ import RowEventTable from 'examples/rows/row-event'; // table sort import EnableSortTable from 'examples/sort/enable-sort-table'; import DefaultSortTable from 'examples/sort/default-sort-table'; +import DefaultSortDirectionTable from 'examples/sort/default-sort-direction'; import SortEvents from 'examples/sort/sort-events'; import CustomSortTable from 'examples/sort/custom-sort-table'; import HeaderSortingClassesTable from 'examples/sort/header-sorting-classes'; @@ -175,6 +176,7 @@ storiesOf('Work on Rows', module) storiesOf('Sort Table', module) .add('Enable Sort', () => ) .add('Default Sort Table', () => ) + .add('Default Sort Direction Table', () => ) .add('Sort Events', () => ) .add('Custom Sort Fuction', () => ) .add('Custom Classes on Sorting Header Column', () => ) diff --git a/packages/react-bootstrap-table2/src/bootstrap-table.js b/packages/react-bootstrap-table2/src/bootstrap-table.js index 743eb3b00..0e801cb0e 100644 --- a/packages/react-bootstrap-table2/src/bootstrap-table.js +++ b/packages/react-bootstrap-table2/src/bootstrap-table.js @@ -149,6 +149,7 @@ BootstrapTable.propTypes = { dataField: PropTypes.string.isRequired, order: PropTypes.oneOf([Const.SORT_DESC, Const.SORT_ASC]).isRequired })), + defaultSortDirection: PropTypes.oneOf([Const.SORT_DESC, Const.SORT_ASC]), overlay: PropTypes.func, onTableChange: PropTypes.func, onSort: PropTypes.func, diff --git a/packages/react-bootstrap-table2/src/sort/wrapper.js b/packages/react-bootstrap-table2/src/sort/wrapper.js index 8528e0f0b..d20d207d6 100644 --- a/packages/react-bootstrap-table2/src/sort/wrapper.js +++ b/packages/react-bootstrap-table2/src/sort/wrapper.js @@ -15,7 +15,7 @@ export default Base => } componentWillMount() { - const { columns, defaultSorted, store } = this.props; + const { columns, defaultSorted, defaultSortDirection, store } = this.props; // defaultSorted is an array, it's ready to use as multi / single sort // when we start to support multi sort, please update following code to use array.forEach if (defaultSorted && defaultSorted.length > 0) { @@ -23,7 +23,7 @@ export default Base => const order = defaultSorted[0].order; const column = columns.filter(col => col.dataField === dataField); if (column.length > 0) { - store.setSort(column[0], order); + store.setSort(column[0], order, defaultSortDirection); if (column[0].onSort) { column[0].onSort(store.sortField, store.sortOrder); @@ -53,7 +53,7 @@ export default Base => handleSort(column) { const { store } = this.props; - store.setSort(column); + store.setSort(column, undefined, this.props.defaultSortDirection); if (column.onSort) { column.onSort(store.sortField, store.sortOrder); diff --git a/packages/react-bootstrap-table2/src/store/index.js b/packages/react-bootstrap-table2/src/store/index.js index 6711c99e7..f0d7933a4 100644 --- a/packages/react-bootstrap-table2/src/store/index.js +++ b/packages/react-bootstrap-table2/src/store/index.js @@ -21,8 +21,8 @@ export default class Store { if (row) _.set(row, dataField, newValue); } - setSort({ dataField }, order) { - this.sortOrder = nextOrder(this)(dataField, order); + setSort({ dataField }, order, defaultOrder) { + this.sortOrder = nextOrder(this)(dataField, order, defaultOrder); this.sortField = dataField; } diff --git a/packages/react-bootstrap-table2/src/store/sort.js b/packages/react-bootstrap-table2/src/store/sort.js index a2228bb1e..1987e0ef5 100644 --- a/packages/react-bootstrap-table2/src/store/sort.js +++ b/packages/react-bootstrap-table2/src/store/sort.js @@ -37,11 +37,11 @@ export const sort = ({ data, sortOrder, sortField }) => (sortFunc) => { return _data; }; -export const nextOrder = store => (field, order) => { +export const nextOrder = store => (field, order, defaultOrder = Const.SORT_DESC) => { if (order) return order; if (field !== store.sortField) { - return Const.SORT_DESC; + return defaultOrder; } return store.sortOrder === Const.SORT_DESC ? Const.SORT_ASC : Const.SORT_DESC; }; diff --git a/packages/react-bootstrap-table2/test/store/index.test.js b/packages/react-bootstrap-table2/test/store/index.test.js index dc8b28e42..a257272cf 100644 --- a/packages/react-bootstrap-table2/test/store/index.test.js +++ b/packages/react-bootstrap-table2/test/store/index.test.js @@ -56,10 +56,15 @@ describe('Store Base', () => { expect(store.sortOrder).toEqual(Const.SORT_DESC); }); - it('should force assign sortOrder correctly if second argument is passed', () => { + it('should force assign sortOrder correctly if second argument is given', () => { store.setSort({ dataField }, Const.SORT_DESC); expect(store.sortOrder).toEqual(Const.SORT_DESC); }); + + it('should force assign sortOrder correctly if third argument is given', () => { + store.setSort({ dataField }, undefined, Const.SORT_ASC); + expect(store.sortOrder).toEqual(Const.SORT_ASC); + }); }); describe('sortBy', () => { diff --git a/packages/react-bootstrap-table2/test/store/sort.test.js b/packages/react-bootstrap-table2/test/store/sort.test.js index 3279cd53d..33422b94c 100644 --- a/packages/react-bootstrap-table2/test/store/sort.test.js +++ b/packages/react-bootstrap-table2/test/store/sort.test.js @@ -63,6 +63,10 @@ describe('Sort Function', () => { expect(nextOrder(store)('name')).toBe(Const.SORT_DESC); }); + it('should return correcly order when store.sortField is not eq next sort field and default sort direction is given', () => { + expect(nextOrder(store)('name', undefined, Const.SORT_ASC)).toBe(Const.SORT_ASC); + }); + it('should return correcly order when store.sortField is eq next sort field', () => { store.sortField = 'name'; store.sortOrder = Const.SORT_DESC; From e8458b4b6331512719774d45ec8bf4e37614fb2f Mon Sep 17 00:00:00 2001 From: AllenFang Date: Sun, 1 Apr 2018 15:56:53 +0800 Subject: [PATCH 032/549] Publish - react-bootstrap-table2-editor@0.1.4 - react-bootstrap-table2-example@0.1.5 - react-bootstrap-table2-filter@0.1.4 - react-bootstrap-table-next@0.1.6 --- packages/react-bootstrap-table2-editor/package.json | 2 +- packages/react-bootstrap-table2-example/package.json | 2 +- packages/react-bootstrap-table2-filter/package.json | 2 +- packages/react-bootstrap-table2/package.json | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/react-bootstrap-table2-editor/package.json b/packages/react-bootstrap-table2-editor/package.json index 86bb4d9a4..595b63d6a 100644 --- a/packages/react-bootstrap-table2-editor/package.json +++ b/packages/react-bootstrap-table2-editor/package.json @@ -1,6 +1,6 @@ { "name": "react-bootstrap-table2-editor", - "version": "0.1.3", + "version": "0.1.4", "description": "it's the editor addon for react-bootstrap-table2", "main": "./lib/index.js", "scripts": { diff --git a/packages/react-bootstrap-table2-example/package.json b/packages/react-bootstrap-table2-example/package.json index 5a0ead8a7..3626c28c7 100644 --- a/packages/react-bootstrap-table2-example/package.json +++ b/packages/react-bootstrap-table2-example/package.json @@ -1,6 +1,6 @@ { "name": "react-bootstrap-table2-example", - "version": "0.1.4", + "version": "0.1.5", "description": "", "main": "index.js", "private": true, diff --git a/packages/react-bootstrap-table2-filter/package.json b/packages/react-bootstrap-table2-filter/package.json index 77dd46812..bd9c0120c 100644 --- a/packages/react-bootstrap-table2-filter/package.json +++ b/packages/react-bootstrap-table2-filter/package.json @@ -1,6 +1,6 @@ { "name": "react-bootstrap-table2-filter", - "version": "0.1.3", + "version": "0.1.4", "description": "it's a column filter addon for react-bootstrap-table2", "main": "./lib/index.js", "repository": { diff --git a/packages/react-bootstrap-table2/package.json b/packages/react-bootstrap-table2/package.json index c9fc9b89a..8dd50de7e 100644 --- a/packages/react-bootstrap-table2/package.json +++ b/packages/react-bootstrap-table2/package.json @@ -1,6 +1,6 @@ { "name": "react-bootstrap-table-next", - "version": "0.1.5", + "version": "0.1.6", "description": "Next generation of react-bootstrap-table", "main": "./lib/index.js", "repository": { From 3dc9cd39414be5468ac714bf8fa469be9d098b76 Mon Sep 17 00:00:00 2001 From: AllenFang Date: Mon, 2 Apr 2018 23:46:59 +0800 Subject: [PATCH 033/549] Publish - react-bootstrap-table2-editor@0.1.5 - react-bootstrap-table2-filter@0.1.5 - react-bootstrap-table-next@0.1.7 --- packages/react-bootstrap-table2-editor/package.json | 2 +- packages/react-bootstrap-table2-filter/package.json | 2 +- packages/react-bootstrap-table2/package.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/react-bootstrap-table2-editor/package.json b/packages/react-bootstrap-table2-editor/package.json index 595b63d6a..d6a5b1a81 100644 --- a/packages/react-bootstrap-table2-editor/package.json +++ b/packages/react-bootstrap-table2-editor/package.json @@ -1,6 +1,6 @@ { "name": "react-bootstrap-table2-editor", - "version": "0.1.4", + "version": "0.1.5", "description": "it's the editor addon for react-bootstrap-table2", "main": "./lib/index.js", "scripts": { diff --git a/packages/react-bootstrap-table2-filter/package.json b/packages/react-bootstrap-table2-filter/package.json index bd9c0120c..19c06b876 100644 --- a/packages/react-bootstrap-table2-filter/package.json +++ b/packages/react-bootstrap-table2-filter/package.json @@ -1,6 +1,6 @@ { "name": "react-bootstrap-table2-filter", - "version": "0.1.4", + "version": "0.1.5", "description": "it's a column filter addon for react-bootstrap-table2", "main": "./lib/index.js", "repository": { diff --git a/packages/react-bootstrap-table2/package.json b/packages/react-bootstrap-table2/package.json index 8dd50de7e..f880ab7ad 100644 --- a/packages/react-bootstrap-table2/package.json +++ b/packages/react-bootstrap-table2/package.json @@ -1,6 +1,6 @@ { "name": "react-bootstrap-table-next", - "version": "0.1.6", + "version": "0.1.7", "description": "Next generation of react-bootstrap-table", "main": "./lib/index.js", "repository": { From f34cb4bf6353b48240afa9f97d64fbf0a23fd2b0 Mon Sep 17 00:00:00 2001 From: Chun-MingChen Date: Mon, 26 Mar 2018 23:49:27 +0800 Subject: [PATCH 034/549] allow user to filter column without inputField * wrap onFilter to HOF to allow filter dynamically --- .../src/wrapper.js | 57 +++++++++++-------- 1 file changed, 33 insertions(+), 24 deletions(-) diff --git a/packages/react-bootstrap-table2-filter/src/wrapper.js b/packages/react-bootstrap-table2-filter/src/wrapper.js index f48e0316d..9a64eb1ed 100644 --- a/packages/react-bootstrap-table2-filter/src/wrapper.js +++ b/packages/react-bootstrap-table2-filter/src/wrapper.js @@ -40,33 +40,42 @@ export default (Base, { } } - onFilter(column, filterVal, filterType) { - const { store, columns } = this.props; - const currFilters = Object.assign({}, this.state.currFilters); - const { dataField, filter } = column; + /** + * filter the table like below: + * onFilter(column, filterType)(filterVal) + * @param {Object} column + * @param {String} filterType + * @param {String} filterVal - user input for filtering. + */ + onFilter(column, filterType) { + return (filterVal) => { + const { store, columns } = this.props; + const currFilters = Object.assign({}, this.state.currFilters); + const { dataField, filter } = column; - if (!_.isDefined(filterVal) || filterVal === '') { - delete currFilters[dataField]; - } else { - // select default comparator is EQ, others are LIKE - const { - comparator = (filterType === FILTER_TYPE.SELECT ? EQ : LIKE), - caseSensitive = false - } = filter.props; - currFilters[dataField] = { filterVal, filterType, comparator, caseSensitive }; - } - store.filters = currFilters; + if (!_.isDefined(filterVal) || filterVal === '') { + delete currFilters[dataField]; + } else { + // select default comparator is EQ, others are LIKE + const { + comparator = (filterType === FILTER_TYPE.SELECT ? EQ : LIKE), + caseSensitive = false + } = filter.props; + currFilters[dataField] = { filterVal, filterType, comparator, caseSensitive }; + } + store.filters = currFilters; - if (this.isRemoteFiltering() || this.isRemotePagination()) { - this.handleRemoteFilterChange(); - // when remote filtering is enable, dont set currFilters state - // in the componentWillReceiveProps, - // it's the key point that we can know the filter is changed - return; - } + if (this.isRemoteFiltering() || this.isRemotePagination()) { + this.handleRemoteFilterChange(); + // when remote filtering is enable, dont set currFilters state + // in the componentWillReceiveProps, + // it's the key point that we can know the filter is changed + return; + } - store.filteredData = filters(store, columns, _)(currFilters); - this.setState(() => ({ currFilters, isDataChanged: true })); + store.filteredData = filters(store, columns, _)(currFilters); + this.setState(() => ({ currFilters, isDataChanged: true })); + }; } render() { From a1477e2ad38b29f66e9652634caa2d59ee5a6c18 Mon Sep 17 00:00:00 2001 From: Chun-MingChen Date: Tue, 27 Mar 2018 00:16:33 +0800 Subject: [PATCH 035/549] filter column by new onFilter --- .../src/components/number.js | 12 ++++++------ .../src/components/select.js | 10 +++++----- .../src/components/text.js | 13 +++++++++---- 3 files changed, 20 insertions(+), 15 deletions(-) diff --git a/packages/react-bootstrap-table2-filter/src/components/number.js b/packages/react-bootstrap-table2-filter/src/components/number.js index 3c2b61286..5a996923d 100644 --- a/packages/react-bootstrap-table2-filter/src/components/number.js +++ b/packages/react-bootstrap-table2-filter/src/components/number.js @@ -34,7 +34,7 @@ class NumberFilter extends Component { const comparator = this.numberFilterComparator.value; const number = this.numberFilter.value; if (comparator && number) { - onFilter(column, { number, comparator }, FILTER_TYPE.NUMBER); + onFilter(column, FILTER_TYPE.NUMBER)({ number, comparator }); } } @@ -53,7 +53,7 @@ class NumberFilter extends Component { } const filterValue = e.target.value; this.timeout = setTimeout(() => { - onFilter(column, { number: filterValue, comparator }, FILTER_TYPE.NUMBER); + onFilter(column, FILTER_TYPE.NUMBER)({ number: filterValue, comparator }); }, delay); } @@ -65,7 +65,7 @@ class NumberFilter extends Component { // if (comparator === '') { // return; // } - onFilter(column, { number: value, comparator }, FILTER_TYPE.NUMBER); + onFilter(column, FILTER_TYPE.NUMBER)({ number: value, comparator }); } onChangeComparator(e) { @@ -75,7 +75,7 @@ class NumberFilter extends Component { // if (value === '') { // return; // } - onFilter(column, { number: value, comparator }, FILTER_TYPE.NUMBER); + onFilter(column, FILTER_TYPE.NUMBER)({ number: value, comparator }); } getComparatorOptions() { @@ -116,7 +116,7 @@ class NumberFilter extends Component { this.setState(() => ({ isSelected: (number !== '') })); this.numberFilterComparator.value = comparator; this.numberFilter.value = number; - onFilter(column, { number, comparator }, FILTER_TYPE.NUMBER); + onFilter(column, FILTER_TYPE.NUMBER)({ number, comparator }); } cleanFiltered() { @@ -126,7 +126,7 @@ class NumberFilter extends Component { this.setState(() => ({ isSelected: (value !== '') })); this.numberFilterComparator.value = comparator; this.numberFilter.value = value; - onFilter(column, { number: value, comparator }, FILTER_TYPE.NUMBER); + onFilter(column, FILTER_TYPE.NUMBER)({ number: value, comparator }); } render() { diff --git a/packages/react-bootstrap-table2-filter/src/components/select.js b/packages/react-bootstrap-table2-filter/src/components/select.js index 7e17afd7a..852938c89 100644 --- a/packages/react-bootstrap-table2-filter/src/components/select.js +++ b/packages/react-bootstrap-table2-filter/src/components/select.js @@ -27,7 +27,7 @@ class SelectFilter extends Component { componentDidMount() { const value = this.selectInput.value; if (value && value !== '') { - this.props.onFilter(this.props.column, value, FILTER_TYPE.SELECT); + this.props.onFilter(this.props.column, FILTER_TYPE.SELECT)(value); } } @@ -41,7 +41,7 @@ class SelectFilter extends Component { if (needFilter) { const value = this.selectInput.value; if (value) { - this.props.onFilter(this.props.column, value, FILTER_TYPE.SELECT); + this.props.onFilter(this.props.column, FILTER_TYPE.SELECT)(value); } } } @@ -64,19 +64,19 @@ class SelectFilter extends Component { const value = (this.props.defaultValue !== undefined) ? this.props.defaultValue : ''; this.setState(() => ({ isSelected: value !== '' })); this.selectInput.value = value; - this.props.onFilter(this.props.column, value, FILTER_TYPE.SELECT); + this.props.onFilter(this.props.column, FILTER_TYPE.SELECT)(value); } applyFilter(value) { this.selectInput.value = value; this.setState(() => ({ isSelected: value !== '' })); - this.props.onFilter(this.props.column, value, FILTER_TYPE.SELECT); + this.props.onFilter(this.props.column, FILTER_TYPE.SELECT)(value); } filter(e) { const { value } = e.target; this.setState(() => ({ isSelected: value !== '' })); - this.props.onFilter(this.props.column, value, FILTER_TYPE.SELECT); + this.props.onFilter(this.props.column, FILTER_TYPE.SELECT)(value); } render() { diff --git a/packages/react-bootstrap-table2-filter/src/components/text.js b/packages/react-bootstrap-table2-filter/src/components/text.js index ffbe70272..154f30811 100644 --- a/packages/react-bootstrap-table2-filter/src/components/text.js +++ b/packages/react-bootstrap-table2-filter/src/components/text.js @@ -17,10 +17,14 @@ class TextFilter extends Component { value: props.defaultValue }; } + componentDidMount() { + const { onFilter } = this.props; + const defaultValue = this.input.value; + if (defaultValue) { - this.props.onFilter(this.props.column, defaultValue, FILTER_TYPE.TEXT); + onFilter(this.props.column, FILTER_TYPE.TEXT)(defaultValue); } } @@ -40,7 +44,7 @@ class TextFilter extends Component { const filterValue = e.target.value; this.setState(() => ({ value: filterValue })); this.timeout = setTimeout(() => { - this.props.onFilter(this.props.column, filterValue, FILTER_TYPE.TEXT); + this.props.onFilter(this.props.column, FILTER_TYPE.TEXT)(filterValue); }, this.props.delay); } @@ -53,12 +57,12 @@ class TextFilter extends Component { cleanFiltered() { const value = this.props.defaultValue; this.setState(() => ({ value })); - this.props.onFilter(this.props.column, value, FILTER_TYPE.TEXT); + this.props.onFilter(this.props.column, value, FILTER_TYPE.TEXT)(); } applyFilter(filterText) { this.setState(() => ({ value: filterText })); - this.props.onFilter(this.props.column, filterText, FILTER_TYPE.TEXT); + this.props.onFilter(this.props.column, FILTER_TYPE.TEXT)(filterText); } handleClick(e) { @@ -79,6 +83,7 @@ class TextFilter extends Component { defaultValue, ...rest } = this.props; + // stopPropagation for onClick event is try to prevent sort was triggered. return ( Date: Sun, 1 Apr 2018 13:51:11 +0800 Subject: [PATCH 036/549] export onFilter function to allow user to access --- .../src/components/number.js | 17 +++++++++++++++-- .../src/components/select.js | 16 ++++++++++++++-- .../src/components/text.js | 15 ++++++++++++--- 3 files changed, 41 insertions(+), 7 deletions(-) diff --git a/packages/react-bootstrap-table2-filter/src/components/number.js b/packages/react-bootstrap-table2-filter/src/components/number.js index 5a996923d..3b946cf26 100644 --- a/packages/react-bootstrap-table2-filter/src/components/number.js +++ b/packages/react-bootstrap-table2-filter/src/components/number.js @@ -1,3 +1,4 @@ +/* eslint react/require-default-props: 0 */ /* eslint no-return-assign: 0 */ import React, { Component } from 'react'; @@ -30,12 +31,23 @@ class NumberFilter extends Component { } componentDidMount() { - const { column, onFilter } = this.props; + const { column, onFilter, getFilterBy } = this.props; const comparator = this.numberFilterComparator.value; const number = this.numberFilter.value; if (comparator && number) { onFilter(column, FILTER_TYPE.NUMBER)({ number, comparator }); } + + // export onFilter function to allow users to access + if (getFilterBy) { + getFilterBy((filterVal) => { + this.setState(() => ({ isSelected: (filterVal !== '') })); + onFilter(column, FILTER_TYPE.NUMBER)({ + number: filterVal.number, + comparator: filterVal.comparator + }); + }); + } } componentWillUnmount() { @@ -224,7 +236,8 @@ NumberFilter.propTypes = { comparatorStyle: PropTypes.object, comparatorClassName: PropTypes.string, numberStyle: PropTypes.object, - numberClassName: PropTypes.string + numberClassName: PropTypes.string, + getFilterBy: PropTypes.func }; NumberFilter.defaultProps = { diff --git a/packages/react-bootstrap-table2-filter/src/components/select.js b/packages/react-bootstrap-table2-filter/src/components/select.js index 852938c89..8ba74b217 100644 --- a/packages/react-bootstrap-table2-filter/src/components/select.js +++ b/packages/react-bootstrap-table2-filter/src/components/select.js @@ -25,9 +25,19 @@ class SelectFilter extends Component { } componentDidMount() { + const { column, onFilter, getFilterBy } = this.props; + const value = this.selectInput.value; if (value && value !== '') { - this.props.onFilter(this.props.column, FILTER_TYPE.SELECT)(value); + onFilter(column, FILTER_TYPE.SELECT)(value); + } + + // export onFilter function to allow users to access + if (getFilterBy) { + getFilterBy((filterVal) => { + this.setState(() => ({ isSelected: filterVal !== '' })); + onFilter(column, FILTER_TYPE.SELECT)(filterVal); + }); } } @@ -90,6 +100,7 @@ class SelectFilter extends Component { comparator, withoutEmptyOption, caseSensitive, + getFilterBy, ...rest } = this.props; @@ -121,7 +132,8 @@ SelectFilter.propTypes = { className: PropTypes.string, withoutEmptyOption: PropTypes.bool, defaultValue: PropTypes.any, - caseSensitive: PropTypes.bool + caseSensitive: PropTypes.bool, + getFilterBy: PropTypes.func }; SelectFilter.defaultProps = { diff --git a/packages/react-bootstrap-table2-filter/src/components/text.js b/packages/react-bootstrap-table2-filter/src/components/text.js index 154f30811..65b6c7d90 100644 --- a/packages/react-bootstrap-table2-filter/src/components/text.js +++ b/packages/react-bootstrap-table2-filter/src/components/text.js @@ -19,13 +19,20 @@ class TextFilter extends Component { } componentDidMount() { - const { onFilter } = this.props; - + const { onFilter, getFilterBy, column } = this.props; const defaultValue = this.input.value; if (defaultValue) { onFilter(this.props.column, FILTER_TYPE.TEXT)(defaultValue); } + + // export onFilter function to allow users to access + if (getFilterBy) { + getFilterBy((filterVal) => { + this.setState(() => ({ value: filterVal })); + onFilter(column, FILTER_TYPE.TEXT)(filterVal); + }); + } } componentWillReceiveProps(nextProps) { @@ -81,6 +88,7 @@ class TextFilter extends Component { onFilter, caseSensitive, defaultValue, + getFilterBy, ...rest } = this.props; @@ -110,7 +118,8 @@ TextFilter.propTypes = { placeholder: PropTypes.string, style: PropTypes.object, className: PropTypes.string, - caseSensitive: PropTypes.bool + caseSensitive: PropTypes.bool, + getFilterBy: PropTypes.func }; TextFilter.defaultProps = { From 09032349d0290365e307880b505350dc5467c616 Mon Sep 17 00:00:00 2001 From: Chun-MingChen Date: Sun, 1 Apr 2018 14:49:22 +0800 Subject: [PATCH 037/549] [example] example for programmatically filter by text, number and select --- .../programmatically-number-filter.js | 85 ++++++++++++++++ .../programmatically-select-filter.js | 96 +++++++++++++++++++ .../programmatically-text-filter.js | 80 ++++++++++++++++ .../stories/index.js | 8 +- 4 files changed, 268 insertions(+), 1 deletion(-) create mode 100644 packages/react-bootstrap-table2-example/examples/column-filter/programmatically-number-filter.js create mode 100644 packages/react-bootstrap-table2-example/examples/column-filter/programmatically-select-filter.js create mode 100644 packages/react-bootstrap-table2-example/examples/column-filter/programmatically-text-filter.js diff --git a/packages/react-bootstrap-table2-example/examples/column-filter/programmatically-number-filter.js b/packages/react-bootstrap-table2-example/examples/column-filter/programmatically-number-filter.js new file mode 100644 index 000000000..76a26b877 --- /dev/null +++ b/packages/react-bootstrap-table2-example/examples/column-filter/programmatically-number-filter.js @@ -0,0 +1,85 @@ +import React from 'react'; +import BootstrapTable from 'react-bootstrap-table-next'; +import filterFactory, { numberFilter, Comparator } from 'react-bootstrap-table2-filter'; +import Code from 'components/common/code-block'; +import { productsGenerator } from 'utils/common'; + +const products = productsGenerator(8); + +let filterBy; + +const columns = [{ + dataField: 'id', + text: 'Product ID' +}, { + dataField: 'name', + text: 'Product Name' +}, { + dataField: 'price', + text: 'Product Price', + filter: numberFilter({ + getFilterBy: (filterByFunc) => { + filterBy = filterByFunc; + } + }) +}]; + +const handleClick = () => { + filterBy({ + number: 2103, + comparator: Comparator.GT + }); +}; + +const sourceCode = `\ +import BootstrapTable from 'react-bootstrap-table-next'; +import filterFactory, { numberFilter } from 'react-bootstrap-table2-filter'; + +let filterBy; + +const columns = [{ + dataField: 'id', + text: 'Product ID' +}, { + dataField: 'name', + text: 'Product Name' +}, { + dataField: 'price', + text: 'Product Price', + filter: numberFilter({ + getFilterBy: (filterByFunc) => { + filterBy = filterByFunc; + } + }) +}]; + +const handleClick = () => { + filterBy({ + number: 2103, + comparator: Comparator.GT + }); +}; + + + +export default () => ( +
+ + + +
+); +`; + +export default () => ( +
+ + + { sourceCode } +
+); diff --git a/packages/react-bootstrap-table2-example/examples/column-filter/programmatically-select-filter.js b/packages/react-bootstrap-table2-example/examples/column-filter/programmatically-select-filter.js new file mode 100644 index 000000000..b084db29e --- /dev/null +++ b/packages/react-bootstrap-table2-example/examples/column-filter/programmatically-select-filter.js @@ -0,0 +1,96 @@ +import React from 'react'; +import BootstrapTable from 'react-bootstrap-table-next'; +import filterFactory, { selectFilter } from 'react-bootstrap-table2-filter'; +import Code from 'components/common/code-block'; +import { productsQualityGenerator } from 'utils/common'; + +const products = productsQualityGenerator(6); + +let filterBy; + +const selectOptions = { + 0: 'good', + 1: 'Bad', + 2: 'unknown' +}; + +const columns = [{ + dataField: 'id', + text: 'Product ID' +}, { + dataField: 'name', + text: 'Product Name' +}, { + dataField: 'quality', + text: 'Product Quailty', + formatter: cell => selectOptions[cell], + filter: selectFilter({ + options: selectOptions, + getFilterBy: (filterByFunc) => { + // filterBy was assigned to onFilter once the component has mount + filterBy = filterByFunc; + } + }) +}]; + +const handleClick = () => { + filterBy('0'); +}; + +const sourceCode = `\ +import BootstrapTable from 'react-bootstrap-table-next'; +import filterFactory, { selectFilter } from 'react-bootstrap-table2-filter'; + +let filterBy; + +const selectOptions = { + 0: 'good', + 1: 'Bad', + 2: 'unknown' +}; + +const columns = [{ + dataField: 'id', + text: 'Product ID' +}, { + dataField: 'name', + text: 'Product Name' +}, { + dataField: 'quality', + text: 'Product Quailty', + formatter: cell => selectOptions[cell], + filter: selectFilter({ + options: selectOptions, + getFilterBy: (filterByFunc) => { + // filterBy was assigned to onFilter once the component has mount + filterBy = filterByFunc; + } + }) +}]; + +const handleClick = () => { + filterBy('0'); +}; + +export default () => ( +
+ + + +
+); +`; + +export default () => ( +
+ + + + { sourceCode } +
+); diff --git a/packages/react-bootstrap-table2-example/examples/column-filter/programmatically-text-filter.js b/packages/react-bootstrap-table2-example/examples/column-filter/programmatically-text-filter.js new file mode 100644 index 000000000..2e7f01bfa --- /dev/null +++ b/packages/react-bootstrap-table2-example/examples/column-filter/programmatically-text-filter.js @@ -0,0 +1,80 @@ +import React from 'react'; +import BootstrapTable from 'react-bootstrap-table-next'; +import filterFactory, { textFilter } from 'react-bootstrap-table2-filter'; +import Code from 'components/common/code-block'; +import { productsGenerator } from 'utils/common'; + +const products = productsGenerator(8); + +let filterBy; + +const columns = [{ + dataField: 'id', + text: 'Product ID' +}, { + dataField: 'name', + text: 'Product Name', + filter: textFilter({ + getFilterBy: (filterByFunc) => { + filterBy = filterByFunc; + } + }) +}, { + dataField: 'price', + text: 'Product Price', + filter: textFilter() +}]; + +const handleClick = () => { + filterBy('0'); +}; + +const sourceCode = `\ +import BootstrapTable from 'react-bootstrap-table-next'; +import filterFactory, { textFilter } from 'react-bootstrap-table2-filter'; + +let filterBy; + +const columns = [{ + dataField: 'id', + text: 'Product ID' +}, { + dataField: 'name', + text: 'Product Name', + filter: textFilter({ + getFilterBy: (filterByFunc) => { + // filterBy was assigned to onFilter once the component has mount + filterBy = filterByFunc; + } + }) +}, { + dataField: 'price', + text: 'Product Price', + filter: textFilter() +}]; + +const handleClick = () => { + filterBy('0'); +}; + +export default () => ( +
+ + + +
+); +`; + +export default () => ( +
+ + + { sourceCode } +
+); diff --git a/packages/react-bootstrap-table2-example/stories/index.js b/packages/react-bootstrap-table2-example/stories/index.js index 25d8538a3..7e3ba5e8d 100644 --- a/packages/react-bootstrap-table2-example/stories/index.js +++ b/packages/react-bootstrap-table2-example/stories/index.js @@ -48,6 +48,9 @@ import CustomSelectFilter from 'examples/column-filter/custom-select-filter'; import NumberFilter from 'examples/column-filter/number-filter'; import NumberFilterWithDefaultValue from 'examples/column-filter/number-filter-default-value'; import CustomNumberFilter from 'examples/column-filter/custom-number-filter'; +import ProgrammaticallyTextFilter from 'examples/column-filter/programmatically-text-filter'; +import ProgrammaticallySelectFilter from 'examples/column-filter/programmatically-select-filter'; +import ProgrammaticallyNumberFilter from 'examples/column-filter/programmatically-number-filter'; // work on rows import RowStyleTable from 'examples/rows/row-style'; @@ -166,7 +169,10 @@ storiesOf('Column Filter', module) .add('Custom Text Filter', () => ) .add('Custom Select Filter', () => ) .add('Custom Number Filter', () => ) - .add('Custom Filter Value', () => ); + .add('Custom Filter Value', () => ) + .add('Programmatically Text Filter ', () => ) + .add('Programmatically Select Filter ', () => ) + .add('Programmatically Number Filter ', () => ); storiesOf('Work on Rows', module) .add('Customize Row Style', () => ) From 377534512a35e0f850f9b91052c66db9cd04e3e9 Mon Sep 17 00:00:00 2001 From: Chun-MingChen Date: Sun, 1 Apr 2018 15:59:26 +0800 Subject: [PATCH 038/549] rename props and variable in samples for better readability --- .../programmatically-number-filter.js | 22 +++++++++---------- .../programmatically-select-filter.js | 20 ++++++++--------- .../programmatically-text-filter.js | 19 ++++++++-------- .../src/components/number.js | 8 +++---- .../src/components/select.js | 10 ++++----- .../src/components/text.js | 10 ++++----- 6 files changed, 45 insertions(+), 44 deletions(-) diff --git a/packages/react-bootstrap-table2-example/examples/column-filter/programmatically-number-filter.js b/packages/react-bootstrap-table2-example/examples/column-filter/programmatically-number-filter.js index 76a26b877..12a5ebcb4 100644 --- a/packages/react-bootstrap-table2-example/examples/column-filter/programmatically-number-filter.js +++ b/packages/react-bootstrap-table2-example/examples/column-filter/programmatically-number-filter.js @@ -6,7 +6,7 @@ import { productsGenerator } from 'utils/common'; const products = productsGenerator(8); -let filterBy; +let priceFilter; const columns = [{ dataField: 'id', @@ -18,14 +18,15 @@ const columns = [{ dataField: 'price', text: 'Product Price', filter: numberFilter({ - getFilterBy: (filterByFunc) => { - filterBy = filterByFunc; + getFilter: (filter) => { + // pricerFilter was assigned once the component has been mounted. + priceFilter = filter; } }) }]; const handleClick = () => { - filterBy({ + priceFilter({ number: 2103, comparator: Comparator.GT }); @@ -35,7 +36,7 @@ const sourceCode = `\ import BootstrapTable from 'react-bootstrap-table-next'; import filterFactory, { numberFilter } from 'react-bootstrap-table2-filter'; -let filterBy; +let priceFilter; const columns = [{ dataField: 'id', @@ -47,24 +48,23 @@ const columns = [{ dataField: 'price', text: 'Product Price', filter: numberFilter({ - getFilterBy: (filterByFunc) => { - filterBy = filterByFunc; + getFilter: (filter) => { + // pricerFilter was assigned once the component has been mounted. + priceFilter = filter; } }) }]; const handleClick = () => { - filterBy({ + priceFilter({ number: 2103, comparator: Comparator.GT }); }; - - export default () => (
- +
diff --git a/packages/react-bootstrap-table2-example/examples/column-filter/programmatically-select-filter.js b/packages/react-bootstrap-table2-example/examples/column-filter/programmatically-select-filter.js index b084db29e..96f00de1d 100644 --- a/packages/react-bootstrap-table2-example/examples/column-filter/programmatically-select-filter.js +++ b/packages/react-bootstrap-table2-example/examples/column-filter/programmatically-select-filter.js @@ -6,7 +6,7 @@ import { productsQualityGenerator } from 'utils/common'; const products = productsQualityGenerator(6); -let filterBy; +let qualityFilter; const selectOptions = { 0: 'good', @@ -26,22 +26,22 @@ const columns = [{ formatter: cell => selectOptions[cell], filter: selectFilter({ options: selectOptions, - getFilterBy: (filterByFunc) => { - // filterBy was assigned to onFilter once the component has mount - filterBy = filterByFunc; + getFilter: (filter) => { + // qualityFilter was assigned once the component has been mounted. + qualityFilter = filter; } }) }]; const handleClick = () => { - filterBy('0'); + qualityFilter('0'); }; const sourceCode = `\ import BootstrapTable from 'react-bootstrap-table-next'; import filterFactory, { selectFilter } from 'react-bootstrap-table2-filter'; -let filterBy; +let qualityFilter; const selectOptions = { 0: 'good', @@ -61,15 +61,15 @@ const columns = [{ formatter: cell => selectOptions[cell], filter: selectFilter({ options: selectOptions, - getFilterBy: (filterByFunc) => { - // filterBy was assigned to onFilter once the component has mount - filterBy = filterByFunc; + getFilter: (filter) => { + // qualityFilter was assigned once the component has been mounted. + qualityFilter = filter; } }) }]; const handleClick = () => { - filterBy('0'); + qualityFilter('0'); }; export default () => ( diff --git a/packages/react-bootstrap-table2-example/examples/column-filter/programmatically-text-filter.js b/packages/react-bootstrap-table2-example/examples/column-filter/programmatically-text-filter.js index 2e7f01bfa..2db8698d9 100644 --- a/packages/react-bootstrap-table2-example/examples/column-filter/programmatically-text-filter.js +++ b/packages/react-bootstrap-table2-example/examples/column-filter/programmatically-text-filter.js @@ -6,7 +6,7 @@ import { productsGenerator } from 'utils/common'; const products = productsGenerator(8); -let filterBy; +let nameFilter; const columns = [{ dataField: 'id', @@ -15,8 +15,9 @@ const columns = [{ dataField: 'name', text: 'Product Name', filter: textFilter({ - getFilterBy: (filterByFunc) => { - filterBy = filterByFunc; + getFilter: (filter) => { + // nameFilter was assigned once the component has been mounted. + nameFilter = filter; } }) }, { @@ -26,14 +27,14 @@ const columns = [{ }]; const handleClick = () => { - filterBy('0'); + nameFilter('0'); }; const sourceCode = `\ import BootstrapTable from 'react-bootstrap-table-next'; import filterFactory, { textFilter } from 'react-bootstrap-table2-filter'; -let filterBy; +let nameFilter; const columns = [{ dataField: 'id', @@ -42,9 +43,9 @@ const columns = [{ dataField: 'name', text: 'Product Name', filter: textFilter({ - getFilterBy: (filterByFunc) => { - // filterBy was assigned to onFilter once the component has mount - filterBy = filterByFunc; + getFilter: (filter) => { + // nameFilter was assigned once the component has been mounted. + nameFilter = filter; } }) }, { @@ -54,7 +55,7 @@ const columns = [{ }]; const handleClick = () => { - filterBy('0'); + nameFilter('0'); }; export default () => ( diff --git a/packages/react-bootstrap-table2-filter/src/components/number.js b/packages/react-bootstrap-table2-filter/src/components/number.js index 3b946cf26..c2d07ce4b 100644 --- a/packages/react-bootstrap-table2-filter/src/components/number.js +++ b/packages/react-bootstrap-table2-filter/src/components/number.js @@ -31,7 +31,7 @@ class NumberFilter extends Component { } componentDidMount() { - const { column, onFilter, getFilterBy } = this.props; + const { column, onFilter, getFilter } = this.props; const comparator = this.numberFilterComparator.value; const number = this.numberFilter.value; if (comparator && number) { @@ -39,8 +39,8 @@ class NumberFilter extends Component { } // export onFilter function to allow users to access - if (getFilterBy) { - getFilterBy((filterVal) => { + if (getFilter) { + getFilter((filterVal) => { this.setState(() => ({ isSelected: (filterVal !== '') })); onFilter(column, FILTER_TYPE.NUMBER)({ number: filterVal.number, @@ -237,7 +237,7 @@ NumberFilter.propTypes = { comparatorClassName: PropTypes.string, numberStyle: PropTypes.object, numberClassName: PropTypes.string, - getFilterBy: PropTypes.func + getFilter: PropTypes.func }; NumberFilter.defaultProps = { diff --git a/packages/react-bootstrap-table2-filter/src/components/select.js b/packages/react-bootstrap-table2-filter/src/components/select.js index 8ba74b217..91ab9346c 100644 --- a/packages/react-bootstrap-table2-filter/src/components/select.js +++ b/packages/react-bootstrap-table2-filter/src/components/select.js @@ -25,7 +25,7 @@ class SelectFilter extends Component { } componentDidMount() { - const { column, onFilter, getFilterBy } = this.props; + const { column, onFilter, getFilter } = this.props; const value = this.selectInput.value; if (value && value !== '') { @@ -33,8 +33,8 @@ class SelectFilter extends Component { } // export onFilter function to allow users to access - if (getFilterBy) { - getFilterBy((filterVal) => { + if (getFilter) { + getFilter((filterVal) => { this.setState(() => ({ isSelected: filterVal !== '' })); onFilter(column, FILTER_TYPE.SELECT)(filterVal); }); @@ -100,7 +100,7 @@ class SelectFilter extends Component { comparator, withoutEmptyOption, caseSensitive, - getFilterBy, + getFilter, ...rest } = this.props; @@ -133,7 +133,7 @@ SelectFilter.propTypes = { withoutEmptyOption: PropTypes.bool, defaultValue: PropTypes.any, caseSensitive: PropTypes.bool, - getFilterBy: PropTypes.func + getFilter: PropTypes.func }; SelectFilter.defaultProps = { diff --git a/packages/react-bootstrap-table2-filter/src/components/text.js b/packages/react-bootstrap-table2-filter/src/components/text.js index 65b6c7d90..746804440 100644 --- a/packages/react-bootstrap-table2-filter/src/components/text.js +++ b/packages/react-bootstrap-table2-filter/src/components/text.js @@ -19,7 +19,7 @@ class TextFilter extends Component { } componentDidMount() { - const { onFilter, getFilterBy, column } = this.props; + const { onFilter, getFilter, column } = this.props; const defaultValue = this.input.value; if (defaultValue) { @@ -27,8 +27,8 @@ class TextFilter extends Component { } // export onFilter function to allow users to access - if (getFilterBy) { - getFilterBy((filterVal) => { + if (getFilter) { + getFilter((filterVal) => { this.setState(() => ({ value: filterVal })); onFilter(column, FILTER_TYPE.TEXT)(filterVal); }); @@ -88,7 +88,7 @@ class TextFilter extends Component { onFilter, caseSensitive, defaultValue, - getFilterBy, + getFilter, ...rest } = this.props; @@ -119,7 +119,7 @@ TextFilter.propTypes = { style: PropTypes.object, className: PropTypes.string, caseSensitive: PropTypes.bool, - getFilterBy: PropTypes.func + getFilter: PropTypes.func }; TextFilter.defaultProps = { From f54c1f77b41720953afbb0476ea1a52700f8f95e Mon Sep 17 00:00:00 2001 From: Chun-MingChen Date: Wed, 4 Apr 2018 15:39:23 +0800 Subject: [PATCH 039/549] display filter condition correctly and make sure text filter to be String --- .../programmatically-select-filter.js | 8 ++-- .../programmatically-text-filter.js | 4 +- .../src/components/number.js | 3 ++ .../src/components/select.js | 2 + .../src/filter.js | 44 +++++++++++-------- .../src/wrapper.js | 1 + 6 files changed, 38 insertions(+), 24 deletions(-) diff --git a/packages/react-bootstrap-table2-example/examples/column-filter/programmatically-select-filter.js b/packages/react-bootstrap-table2-example/examples/column-filter/programmatically-select-filter.js index 96f00de1d..d368af5a6 100644 --- a/packages/react-bootstrap-table2-example/examples/column-filter/programmatically-select-filter.js +++ b/packages/react-bootstrap-table2-example/examples/column-filter/programmatically-select-filter.js @@ -22,7 +22,7 @@ const columns = [{ text: 'Product Name' }, { dataField: 'quality', - text: 'Product Quailty', + text: 'Product Quality', formatter: cell => selectOptions[cell], filter: selectFilter({ options: selectOptions, @@ -34,7 +34,7 @@ const columns = [{ }]; const handleClick = () => { - qualityFilter('0'); + qualityFilter(0); }; const sourceCode = `\ @@ -57,7 +57,7 @@ const columns = [{ text: 'Product Name' }, { dataField: 'quality', - text: 'Product Quailty', + text: 'Product Quality', formatter: cell => selectOptions[cell], filter: selectFilter({ options: selectOptions, @@ -69,7 +69,7 @@ const columns = [{ }]; const handleClick = () => { - qualityFilter('0'); + qualityFilter(0); }; export default () => ( diff --git a/packages/react-bootstrap-table2-example/examples/column-filter/programmatically-text-filter.js b/packages/react-bootstrap-table2-example/examples/column-filter/programmatically-text-filter.js index 2db8698d9..f1080c000 100644 --- a/packages/react-bootstrap-table2-example/examples/column-filter/programmatically-text-filter.js +++ b/packages/react-bootstrap-table2-example/examples/column-filter/programmatically-text-filter.js @@ -27,7 +27,7 @@ const columns = [{ }]; const handleClick = () => { - nameFilter('0'); + nameFilter(0); }; const sourceCode = `\ @@ -55,7 +55,7 @@ const columns = [{ }]; const handleClick = () => { - nameFilter('0'); + nameFilter(0); }; export default () => ( diff --git a/packages/react-bootstrap-table2-filter/src/components/number.js b/packages/react-bootstrap-table2-filter/src/components/number.js index c2d07ce4b..ebf55e81b 100644 --- a/packages/react-bootstrap-table2-filter/src/components/number.js +++ b/packages/react-bootstrap-table2-filter/src/components/number.js @@ -42,6 +42,9 @@ class NumberFilter extends Component { if (getFilter) { getFilter((filterVal) => { this.setState(() => ({ isSelected: (filterVal !== '') })); + this.numberFilterComparator.value = filterVal.comparator; + this.numberFilter.value = filterVal.number; + onFilter(column, FILTER_TYPE.NUMBER)({ number: filterVal.number, comparator: filterVal.comparator diff --git a/packages/react-bootstrap-table2-filter/src/components/select.js b/packages/react-bootstrap-table2-filter/src/components/select.js index 91ab9346c..ba2d3060b 100644 --- a/packages/react-bootstrap-table2-filter/src/components/select.js +++ b/packages/react-bootstrap-table2-filter/src/components/select.js @@ -36,6 +36,8 @@ class SelectFilter extends Component { if (getFilter) { getFilter((filterVal) => { this.setState(() => ({ isSelected: filterVal !== '' })); + this.selectInput.value = filterVal; + onFilter(column, FILTER_TYPE.SELECT)(filterVal); }); } diff --git a/packages/react-bootstrap-table2-filter/src/filter.js b/packages/react-bootstrap-table2-filter/src/filter.js index e0d7a452b..9f7812ceb 100644 --- a/packages/react-bootstrap-table2-filter/src/filter.js +++ b/packages/react-bootstrap-table2-filter/src/filter.js @@ -6,30 +6,37 @@ import { LIKE, EQ, NE, GT, GE, LT, LE } from './comparison'; export const filterByText = _ => ( data, dataField, - { filterVal = '', comparator = LIKE, caseSensitive }, + { filterVal: userInput = '', comparator = LIKE, caseSensitive }, customFilterValue -) => - data.filter((row) => { - let cell = _.get(row, dataField); - if (customFilterValue) { - cell = customFilterValue(cell, row); - } - const cellStr = _.isDefined(cell) ? cell.toString() : ''; - if (comparator === EQ) { - return cellStr === filterVal; - } - if (caseSensitive) { - return cellStr.includes(filterVal); - } - return cellStr.toLocaleUpperCase().indexOf(filterVal.toLocaleUpperCase()) !== -1; - }); +) => { + // make sure filter value to be a string + const filterVal = userInput.toString(); + + return ( + data.filter((row) => { + let cell = _.get(row, dataField); + if (customFilterValue) { + cell = customFilterValue(cell, row); + } + const cellStr = _.isDefined(cell) ? cell.toString() : ''; + if (comparator === EQ) { + return cellStr === filterVal; + } + if (caseSensitive) { + return cellStr.includes(filterVal); + } + + return cellStr.toLocaleUpperCase().indexOf(filterVal.toLocaleUpperCase()) !== -1; + }) + ); +}; export const filterByNumber = _ => ( data, dataField, { filterVal: { comparator, number } }, customFilterValue -) => +) => ( data.filter((row) => { if (number === '' || !comparator) return true; let valid = true; @@ -81,7 +88,8 @@ export const filterByNumber = _ => ( } } return valid; - }); + }) +); export const filterFactory = _ => (filterType) => { let filterFn; diff --git a/packages/react-bootstrap-table2-filter/src/wrapper.js b/packages/react-bootstrap-table2-filter/src/wrapper.js index 9a64eb1ed..f13e6151f 100644 --- a/packages/react-bootstrap-table2-filter/src/wrapper.js +++ b/packages/react-bootstrap-table2-filter/src/wrapper.js @@ -63,6 +63,7 @@ export default (Base, { } = filter.props; currFilters[dataField] = { filterVal, filterType, comparator, caseSensitive }; } + store.filters = currFilters; if (this.isRemoteFiltering() || this.isRemotePagination()) { From a35701fabfc84675656a1f81fed1ba7c1c59116d Mon Sep 17 00:00:00 2001 From: Chun-MingChen Date: Wed, 4 Apr 2018 16:23:59 +0800 Subject: [PATCH 040/549] [test] correct test for filter wrapper --- .../test/filter.test.js | 13 ++++++++++++ .../test/wrapper.test.js | 20 +++++++++---------- 2 files changed, 23 insertions(+), 10 deletions(-) diff --git a/packages/react-bootstrap-table2-filter/test/filter.test.js b/packages/react-bootstrap-table2-filter/test/filter.test.js index ae66a38c9..2ffd36de4 100644 --- a/packages/react-bootstrap-table2-filter/test/filter.test.js +++ b/packages/react-bootstrap-table2-filter/test/filter.test.js @@ -42,6 +42,19 @@ describe('filter', () => { filterFn = filters(store, columns, _); }); + describe('when filter value is not a String', () => { + it('should transform to string and do the filter', () => { + currFilters.name = { + filterVal: 3, + filterType: FILTER_TYPE.TEXT + }; + + const result = filterFn(currFilters); + expect(result).toBeDefined(); + expect(result).toHaveLength(2); + }); + }); + describe(`when default comparator is ${LIKE}`, () => { it('should returning correct result', () => { currFilters.name = { diff --git a/packages/react-bootstrap-table2-filter/test/wrapper.test.js b/packages/react-bootstrap-table2-filter/test/wrapper.test.js index 3d862858d..144265845 100644 --- a/packages/react-bootstrap-table2-filter/test/wrapper.test.js +++ b/packages/react-bootstrap-table2-filter/test/wrapper.test.js @@ -167,14 +167,14 @@ describe('Wrapper', () => { it('should setting store object correctly', () => { filterVals.forEach((filterVal) => { - instance.onFilter(props.columns[1], filterVal, FILTER_TYPE.TEXT); + instance.onFilter(props.columns[1], FILTER_TYPE.TEXT)(filterVal); expect(props.store.filtering).toBeFalsy(); }); }); it('should setting state correctly', () => { filterVals.forEach((filterVal) => { - instance.onFilter(props.columns[1], filterVal, FILTER_TYPE.TEXT); + instance.onFilter(props.columns[1], FILTER_TYPE.TEXT)(filterVal); expect(instance.state.isDataChanged).toBeTruthy(); expect(Object.keys(instance.state.currFilters)).toHaveLength(0); }); @@ -185,12 +185,12 @@ describe('Wrapper', () => { const filterVal = '3'; it('should setting store object correctly', () => { - instance.onFilter(props.columns[1], filterVal, FILTER_TYPE.TEXT); + instance.onFilter(props.columns[1], FILTER_TYPE.TEXT)(filterVal); expect(props.store.filters).toEqual(instance.state.currFilters); }); it('should setting state correctly', () => { - instance.onFilter(props.columns[1], filterVal, FILTER_TYPE.TEXT); + instance.onFilter(props.columns[1], FILTER_TYPE.TEXT)(filterVal); expect(instance.state.isDataChanged).toBeTruthy(); expect(Object.keys(instance.state.currFilters)).toHaveLength(1); }); @@ -203,7 +203,7 @@ describe('Wrapper', () => { props = createTableProps(); props.remote = { filter: true }; createFilterWrapper(props); - instance.onFilter(props.columns[1], filterVal, FILTER_TYPE.TEXT); + instance.onFilter(props.columns[1], FILTER_TYPE.TEXT)(filterVal); }); it('should not setting store object correctly', () => { @@ -222,27 +222,27 @@ describe('Wrapper', () => { describe('combination', () => { it('should setting store object correctly', () => { - instance.onFilter(props.columns[1], '3', FILTER_TYPE.TEXT); + instance.onFilter(props.columns[1], FILTER_TYPE.TEXT)('3'); expect(props.store.filters).toEqual(instance.state.currFilters); expect(instance.state.isDataChanged).toBeTruthy(); expect(Object.keys(instance.state.currFilters)).toHaveLength(1); - instance.onFilter(props.columns[1], '2', FILTER_TYPE.TEXT); + instance.onFilter(props.columns[1], FILTER_TYPE.TEXT)('2'); expect(props.store.filters).toEqual(instance.state.currFilters); expect(instance.state.isDataChanged).toBeTruthy(); expect(Object.keys(instance.state.currFilters)).toHaveLength(1); - instance.onFilter(props.columns[2], '2', FILTER_TYPE.TEXT); + instance.onFilter(props.columns[2], FILTER_TYPE.TEXT)('2'); expect(props.store.filters).toEqual(instance.state.currFilters); expect(instance.state.isDataChanged).toBeTruthy(); expect(Object.keys(instance.state.currFilters)).toHaveLength(2); - instance.onFilter(props.columns[2], '', FILTER_TYPE.TEXT); + instance.onFilter(props.columns[2], FILTER_TYPE.TEXT)(''); expect(props.store.filters).toEqual(instance.state.currFilters); expect(instance.state.isDataChanged).toBeTruthy(); expect(Object.keys(instance.state.currFilters)).toHaveLength(1); - instance.onFilter(props.columns[1], '', FILTER_TYPE.TEXT); + instance.onFilter(props.columns[1], FILTER_TYPE.TEXT)(''); expect(props.store.filters).toEqual(instance.state.currFilters); expect(instance.state.isDataChanged).toBeTruthy(); expect(Object.keys(instance.state.currFilters)).toHaveLength(0); From c64951fd6fb8d710c6018431420a4620943bc2ea Mon Sep 17 00:00:00 2001 From: Chun-MingChen Date: Wed, 4 Apr 2018 16:51:54 +0800 Subject: [PATCH 041/549] [test] correct tests for filter components * , this.checkbox = node } + type="checkbox" + className={ editorClass } + { ...rest } + checked={ this.state.checked } + onChange={ this.handleChange } + /> + ); + } +} + +CheckBoxEditor.propTypes = { + className: PropTypes.oneOfType([ + PropTypes.string, + PropTypes.object + ]), + value: PropTypes.string, + defaultValue: PropTypes.any, + onChange: PropTypes.func +}; +CheckBoxEditor.defaultProps = { + className: '', + value: 'on:off', + defaultValue: false, + onChange: undefined +}; +export default CheckBoxEditor; diff --git a/packages/react-bootstrap-table2-editor/src/const.js b/packages/react-bootstrap-table2-editor/src/const.js index acbef9d80..4455ad797 100644 --- a/packages/react-bootstrap-table2-editor/src/const.js +++ b/packages/react-bootstrap-table2-editor/src/const.js @@ -2,3 +2,11 @@ export const TIME_TO_CLOSE_MESSAGE = 3000; export const DELAY_FOR_DBCLICK = 200; export const CLICK_TO_CELL_EDIT = 'click'; export const DBCLICK_TO_CELL_EDIT = 'dbclick'; + +export const EDITTYPE = { + TEXT: 'text', + SELECT: 'select', + TEXTAREA: 'textarea', + CHECKBOX: 'checkbox', + DATE: 'date' +}; diff --git a/packages/react-bootstrap-table2-editor/src/date-editor.js b/packages/react-bootstrap-table2-editor/src/date-editor.js new file mode 100644 index 000000000..b712fe213 --- /dev/null +++ b/packages/react-bootstrap-table2-editor/src/date-editor.js @@ -0,0 +1,42 @@ +/* eslint no-return-assign: 0 */ +import React, { Component } from 'react'; +import cs from 'classnames'; +import PropTypes from 'prop-types'; + +class DateEditor extends Component { + componentDidMount() { + const { defaultValue } = this.props; + this.date.valueAsDate = new Date(defaultValue); + this.date.focus(); + } + + getValue() { + return this.date.value; + } + + render() { + const { defaultValue, className, ...rest } = this.props; + const editorClass = cs('form-control editor edit-date', className); + return ( + this.date = node } + type="date" + className={ editorClass } + { ...rest } + /> + ); + } +} + +DateEditor.propTypes = { + className: PropTypes.oneOfType([ + PropTypes.string, + PropTypes.object + ]), + defaultValue: PropTypes.string +}; +DateEditor.defaultProps = { + className: '', + defaultValue: '' +}; +export default DateEditor; diff --git a/packages/react-bootstrap-table2-editor/src/dropdown-editor.js b/packages/react-bootstrap-table2-editor/src/dropdown-editor.js new file mode 100644 index 000000000..cf6a2a682 --- /dev/null +++ b/packages/react-bootstrap-table2-editor/src/dropdown-editor.js @@ -0,0 +1,61 @@ +/* eslint no-return-assign: 0 */ +import React, { Component } from 'react'; +import cs from 'classnames'; +import PropTypes from 'prop-types'; + +class DropDownEditor extends Component { + componentDidMount() { + const { defaultValue } = this.props; + this.select.value = defaultValue; + this.select.focus(); + } + + getValue() { + return this.select.value; + } + + render() { + const { defaultValue, className, options, ...rest } = this.props; + const editorClass = cs('form-control editor edit-select', className); + + const attr = { + ...rest, + className: editorClass + }; + + return ( + + ); + } +} + +DropDownEditor.propTypes = { + defaultValue: PropTypes.oneOfType([ + PropTypes.string, + PropTypes.number + ]), + className: PropTypes.string, + style: PropTypes.object, + options: PropTypes.oneOfType([ + PropTypes.arrayOf(PropTypes.shape({ + label: PropTypes.string, + value: PropTypes.any + })) + ]).isRequired +}; +DropDownEditor.defaultProps = { + className: '', + defaultValue: '', + style: {} +}; +export default DropDownEditor; diff --git a/packages/react-bootstrap-table2-editor/src/editing-cell.js b/packages/react-bootstrap-table2-editor/src/editing-cell.js index 2c732de0d..2acda72c4 100644 --- a/packages/react-bootstrap-table2-editor/src/editing-cell.js +++ b/packages/react-bootstrap-table2-editor/src/editing-cell.js @@ -6,9 +6,13 @@ import React, { Component } from 'react'; import cs from 'classnames'; import PropTypes from 'prop-types'; +import DropdownEditor from './dropdown-editor'; +import TextAreaEditor from './textarea-editor'; +import CheckBoxEditor from './checkbox-editor'; +import DateEditor from './date-editor'; import TextEditor from './text-editor'; import EditorIndicator from './editor-indicator'; -import { TIME_TO_CLOSE_MESSAGE } from './const'; +import { TIME_TO_CLOSE_MESSAGE, EDITTYPE } from './const'; export default _ => class EditingCell extends Component { @@ -73,8 +77,8 @@ export default _ => }, timeToCloseMessage); } - beforeComplete(row, column, newValue) { - const { onUpdate } = this.props; + beforeComplete(newValue) { + const { onUpdate, row, column } = this.props; if (_.isFunction(column.validator)) { const validateForm = column.validator(newValue, row, column); if (_.isObject(validateForm) && !validateForm.valid) { @@ -89,28 +93,20 @@ export default _ => } handleBlur() { - const { onEscape, blurToSave, row, column } = this.props; + const { onEscape, blurToSave } = this.props; if (blurToSave) { - const value = this.editor.text.value; - if (!_.isDefined(value)) { - // TODO: for other custom or embed editor - } - this.beforeComplete(row, column, value); + this.beforeComplete(this.editor.getValue()); } else { onEscape(); } } handleKeyDown(e) { - const { onEscape, row, column } = this.props; + const { onEscape } = this.props; if (e.keyCode === 27) { // ESC onEscape(); } else if (e.keyCode === 13) { // ENTER - const value = e.currentTarget.value; - if (!_.isDefined(value)) { - // TODO: for other custom or embed editor - } - this.beforeComplete(row, column, value); + this.beforeComplete(this.editor.getValue()); } } @@ -124,17 +120,13 @@ export default _ => } render() { - const { invalidMessage } = this.state; + let editor; const { row, column, className, style, rowIndex, columnIndex } = this.props; const { dataField } = column; const value = _.get(row, dataField); - const editorAttrs = { - onKeyDown: this.handleKeyDown, - onBlur: this.handleBlur - }; + const hasError = _.isDefined(this.state.invalidMessage); - const hasError = _.isDefined(invalidMessage); let customEditorClass = column.editorClasses || ''; if (_.isFunction(column.editorClasses)) { customEditorClass = column.editorClasses(value, row, rowIndex, columnIndex); @@ -150,20 +142,51 @@ export default _ => shake: hasError }, customEditorClass); + let editorProps = { + ref: node => this.editor = node, + defaultValue: value, + style: editorStyle, + className: editorClass, + onKeyDown: this.handleKeyDown, + onBlur: this.handleBlur + }; + + const isDefaultEditorDefined = _.isObject(column.editor); + + if (isDefaultEditorDefined) { + editorProps = { + ...editorProps, + ...column.editor + }; + } else if (_.isFunction(column.editorRenderer)) { + editorProps = { + ...editorProps, + onUpdate: this.beforeComplete + }; + } + + if (_.isFunction(column.editorRenderer)) { + editor = column.editorRenderer(editorProps, value, row, column, rowIndex, columnIndex); + } else if (isDefaultEditorDefined && column.editor.type === EDITTYPE.SELECT) { + editor = ; + } else if (isDefaultEditorDefined && column.editor.type === EDITTYPE.TEXTAREA) { + editor = ; + } else if (isDefaultEditorDefined && column.editor.type === EDITTYPE.CHECKBOX) { + editor = ; + } else if (isDefaultEditorDefined && column.editor.type === EDITTYPE.DATE) { + editor = ; + } else { + editor = ; + } + return (
- this.editor = node } - defaultValue={ value } - style={ editorStyle } - className={ editorClass } - { ...editorAttrs } - /> - { hasError ? : null } + { editor } + { hasError ? : null }