From dc096a6c4e7d2d91f530775204d7849b1a48e594 Mon Sep 17 00:00:00 2001 From: AllenFang Date: Sun, 3 Dec 2017 17:11:36 +0800 Subject: [PATCH 1/5] implement loading overlay --- .../package.json | 14 ++ .../src/index.js | 29 +++ .../test/index.test.js | 77 +++++++ .../react-bootstrap-table2-overlay/yarn.lock | 200 ++++++++++++++++++ .../src/bootstrap-table.js | 14 +- 5 files changed, 333 insertions(+), 1 deletion(-) create mode 100644 packages/react-bootstrap-table2-overlay/package.json create mode 100644 packages/react-bootstrap-table2-overlay/src/index.js create mode 100644 packages/react-bootstrap-table2-overlay/test/index.test.js create mode 100644 packages/react-bootstrap-table2-overlay/yarn.lock diff --git a/packages/react-bootstrap-table2-overlay/package.json b/packages/react-bootstrap-table2-overlay/package.json new file mode 100644 index 0000000..d1cd573 --- /dev/null +++ b/packages/react-bootstrap-table2-overlay/package.json @@ -0,0 +1,14 @@ +{ + "name": "react-bootstrap-table2-overlay", + "version": "0.0.1", + "description": "it's a loading overlay component for react-bootstrap-table2", + "main": "src/index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "", + "license": "ISC", + "dependencies": { + "react-loading-overlay": "0.2.8" + } +} diff --git a/packages/react-bootstrap-table2-overlay/src/index.js b/packages/react-bootstrap-table2-overlay/src/index.js new file mode 100644 index 0000000..a5db872 --- /dev/null +++ b/packages/react-bootstrap-table2-overlay/src/index.js @@ -0,0 +1,29 @@ +/* eslint no-return-assign: 0 */ +import React from 'react'; +import LoadingOverlay from 'react-loading-overlay'; + +export default options => (element, loading) => + class TableLoadingOverlayWrapper extends React.Component { + componentDidMount() { + if (loading) { + const { wrapper } = this.overlay; + const masker = wrapper.firstChild; + const headerDOM = wrapper.parentElement.querySelector('thead'); + const bodyDOM = wrapper.parentElement.querySelector('tbody'); + masker.style.marginTop = window.getComputedStyle(headerDOM).height; + masker.style.height = window.getComputedStyle(bodyDOM).height; + } + } + + render() { + return ( + this.overlay = n } + { ...options } + active={ loading } + > + { element } + + ); + } + }; diff --git a/packages/react-bootstrap-table2-overlay/test/index.test.js b/packages/react-bootstrap-table2-overlay/test/index.test.js new file mode 100644 index 0000000..a8fdacb --- /dev/null +++ b/packages/react-bootstrap-table2-overlay/test/index.test.js @@ -0,0 +1,77 @@ +import React from 'react'; +import { shallow, render } from 'enzyme'; +import LoadingOverlay from 'react-loading-overlay'; + +import overlayFactory from '../src'; + +describe('overlayFactory', () => { + let wrapper; + // let instance; + + const createTable = () => ( + + + + + + + + + { [1, 2].map(row => ( + + ))} + +
column1column2
{ row }test
+ ); + + describe('when loading is false', () => { + beforeEach(() => { + const tableElm = createTable(); + const Overlay = overlayFactory()(tableElm, false); + wrapper = shallow(); + }); + + it('should rendering Overlay component correctly', () => { + const overlay = wrapper.find(LoadingOverlay); + expect(wrapper.length).toBe(1); + expect(overlay.length).toBe(1); + expect(overlay.prop('active')).toBeFalsy(); + }); + }); + + describe('when loading is true', () => { + beforeEach(() => { + const tableElm = createTable(); + const Overlay = overlayFactory()(tableElm, true); + wrapper = render(); + }); + + it('should rendering Overlay component correctly', () => { + const overlay = wrapper.find(LoadingOverlay); + expect(wrapper.length).toBe(1); + expect(overlay.length).toBe(0); + }); + }); + + describe('when options is given', () => { + const options = { + spinner: true, + background: 'red' + }; + beforeEach(() => { + const tableElm = createTable(); + const Overlay = overlayFactory(options)(tableElm, false); + wrapper = shallow(); + }); + + it('should rendering Overlay component with options correctly', () => { + const overlay = wrapper.find(LoadingOverlay); + expect(wrapper.length).toBe(1); + expect(overlay.length).toBe(1); + expect(overlay.prop('active')).toBeFalsy(); + Object.keys(options).forEach((key) => { + expect(overlay.prop(key)).toEqual(options[key]); + }); + }); + }); +}); diff --git a/packages/react-bootstrap-table2-overlay/yarn.lock b/packages/react-bootstrap-table2-overlay/yarn.lock new file mode 100644 index 0000000..f40152b --- /dev/null +++ b/packages/react-bootstrap-table2-overlay/yarn.lock @@ -0,0 +1,200 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +asap@~2.0.3: + version "2.0.6" + resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" + +base64-js@^1.0.2: + version "1.2.1" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.2.1.tgz#a91947da1f4a516ea38e5b4ec0ec3773675e0886" + +buffer@^5.0.3: + version "5.0.8" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.0.8.tgz#84daa52e7cf2fa8ce4195bc5cf0f7809e0930b24" + dependencies: + base64-js "^1.0.2" + ieee754 "^1.1.4" + +chain-function@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/chain-function/-/chain-function-1.0.0.tgz#0d4ab37e7e18ead0bdc47b920764118ce58733dc" + +core-js@^1.0.0: + version "1.2.7" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-1.2.7.tgz#652294c14651db28fa93bd2d5ff2983a4f08c636" + +css-color-keywords@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/css-color-keywords/-/css-color-keywords-1.0.0.tgz#fea2616dc676b2962686b3af8dbdbe180b244e05" + +css-to-react-native@^2.0.3: + version "2.0.4" + resolved "https://registry.yarnpkg.com/css-to-react-native/-/css-to-react-native-2.0.4.tgz#cf4cc407558b3474d4ba8be1a2cd3b6ce713101b" + dependencies: + css-color-keywords "^1.0.0" + fbjs "^0.8.5" + postcss-value-parser "^3.3.0" + +dom-helpers@^3.2.0: + version "3.2.1" + resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-3.2.1.tgz#3203e07fed217bd1f424b019735582fc37b2825a" + +encoding@^0.1.11: + version "0.1.12" + resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.12.tgz#538b66f3ee62cd1ab51ec323829d1f9480c74beb" + dependencies: + iconv-lite "~0.4.13" + +fbjs@^0.8.16, fbjs@^0.8.5, fbjs@^0.8.9: + version "0.8.16" + resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-0.8.16.tgz#5e67432f550dc41b572bf55847b8aca64e5337db" + dependencies: + core-js "^1.0.0" + isomorphic-fetch "^2.1.1" + loose-envify "^1.0.0" + object-assign "^4.1.0" + promise "^7.1.1" + setimmediate "^1.0.5" + ua-parser-js "^0.7.9" + +has-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" + +hoist-non-react-statics@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-1.2.0.tgz#aa448cf0986d55cc40773b17174b7dd066cb7cfb" + +iconv-lite@~0.4.13: + version "0.4.19" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.19.tgz#f7468f60135f5e5dad3399c0a81be9a1603a082b" + +ieee754@^1.1.4: + version "1.1.8" + resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.8.tgz#be33d40ac10ef1926701f6f08a2d86fbfd1ad3e4" + +is-function@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-function/-/is-function-1.0.1.tgz#12cfb98b65b57dd3d193a3121f5f6e2f437602b5" + +is-plain-object@^2.0.1: + version "2.0.4" + resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" + dependencies: + isobject "^3.0.1" + +is-stream@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" + +isobject@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" + +isomorphic-fetch@^2.1.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz#611ae1acf14f5e81f729507472819fe9733558a9" + dependencies: + node-fetch "^1.0.1" + whatwg-fetch ">=0.10.0" + +js-tokens@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" + +loose-envify@^1.0.0, loose-envify@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.3.1.tgz#d1a8ad33fa9ce0e713d65fdd0ac8b748d478c848" + dependencies: + js-tokens "^3.0.0" + +node-fetch@^1.0.1: + version "1.7.3" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.7.3.tgz#980f6f72d85211a5347c6b2bc18c5b84c3eb47ef" + dependencies: + encoding "^0.1.11" + is-stream "^1.0.1" + +object-assign@^4.1.0, object-assign@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + +postcss-value-parser@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-3.3.0.tgz#87f38f9f18f774a4ab4c8a232f5c5ce8872a9d15" + +promise@^7.1.1: + version "7.3.1" + resolved "https://registry.yarnpkg.com/promise/-/promise-7.3.1.tgz#064b72602b18f90f29192b8b1bc418ffd1ebd3bf" + dependencies: + asap "~2.0.3" + +prop-types@^15.5.10, prop-types@^15.5.4, prop-types@^15.5.6: + version "15.6.0" + resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.6.0.tgz#ceaf083022fc46b4a35f69e13ef75aed0d639856" + dependencies: + fbjs "^0.8.16" + loose-envify "^1.3.1" + object-assign "^4.1.1" + +react-loading-overlay@0.2.8: + version "0.2.8" + resolved "https://registry.yarnpkg.com/react-loading-overlay/-/react-loading-overlay-0.2.8.tgz#c1c5531c9cfa4be6caca6b9aa0c1eb19e22b03fe" + dependencies: + prop-types "^15.5.10" + react-transition-group "^1.2.1" + styled-components "^2.1.2" + +react-transition-group@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-1.2.1.tgz#e11f72b257f921b213229a774df46612346c7ca6" + dependencies: + chain-function "^1.0.0" + dom-helpers "^3.2.0" + loose-envify "^1.3.1" + prop-types "^15.5.6" + warning "^3.0.0" + +setimmediate@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" + +styled-components@^2.1.2: + version "2.2.4" + resolved "https://registry.yarnpkg.com/styled-components/-/styled-components-2.2.4.tgz#dd87fd3dafd359e7a0d570aec1bd07d691c0b5a2" + dependencies: + buffer "^5.0.3" + css-to-react-native "^2.0.3" + fbjs "^0.8.9" + hoist-non-react-statics "^1.2.0" + is-function "^1.0.1" + is-plain-object "^2.0.1" + prop-types "^15.5.4" + stylis "^3.4.0" + supports-color "^3.2.3" + +stylis@^3.4.0: + version "3.4.5" + resolved "https://registry.yarnpkg.com/stylis/-/stylis-3.4.5.tgz#d7b9595fc18e7b9c8775eca8270a9a1d3e59806e" + +supports-color@^3.2.3: + version "3.2.3" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6" + dependencies: + has-flag "^1.0.0" + +ua-parser-js@^0.7.9: + version "0.7.17" + resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.17.tgz#e9ec5f9498b9ec910e7ae3ac626a805c4d09ecac" + +warning@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/warning/-/warning-3.0.0.tgz#32e5377cb572de4ab04753bdf8821c01ed605b7c" + dependencies: + loose-envify "^1.0.0" + +whatwg-fetch@>=0.10.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-2.0.3.tgz#9c84ec2dcf68187ff00bc64e1274b442176e1c84" diff --git a/packages/react-bootstrap-table2/src/bootstrap-table.js b/packages/react-bootstrap-table2/src/bootstrap-table.js index fa5aee3..89f2bd8 100644 --- a/packages/react-bootstrap-table2/src/bootstrap-table.js +++ b/packages/react-bootstrap-table2/src/bootstrap-table.js @@ -1,4 +1,5 @@ /* eslint arrow-body-style: 0 */ + import React, { Component } from 'react'; import PropTypes from 'prop-types'; import cs from 'classnames'; @@ -26,6 +27,16 @@ class BootstrapTable extends PropsBaseResolver(Component) { } render() { + const { loading, overlay } = this.props; + const table = this.renderTable(); + if (loading && overlay) { + const LoadingOverlay = overlay(table, loading); + return ; + } + return table; + } + + renderTable() { const { store, columns, @@ -157,7 +168,8 @@ BootstrapTable.propTypes = { dataField: PropTypes.string.isRequired, order: PropTypes.oneOf([Const.SORT_DESC, Const.SORT_ASC]).isRequired })), - onTableChange: PropTypes.func + onTableChange: PropTypes.func, + overlay: PropTypes.func }; BootstrapTable.defaultProps = { From 70303617fbc3341c96e90a16d24910a5ccf32fe2 Mon Sep 17 00:00:00 2001 From: AllenFang Date: Sun, 3 Dec 2017 17:13:05 +0800 Subject: [PATCH 2/5] add stories for loading overlay --- .../.storybook/webpack.config.js | 3 +- .../loading-overlay/empty-table-overlay.js | 145 ++++++++++++++++ .../examples/loading-overlay/table-overlay.js | 158 ++++++++++++++++++ .../package.json | 3 +- .../stories/index.js | 8 + .../stylesheet/loading-overlay/_index.scss | 52 ++++++ .../stories/stylesheet/storybook.scss | 3 +- 7 files changed, 369 insertions(+), 3 deletions(-) create mode 100644 packages/react-bootstrap-table2-example/examples/loading-overlay/empty-table-overlay.js create mode 100644 packages/react-bootstrap-table2-example/examples/loading-overlay/table-overlay.js create mode 100644 packages/react-bootstrap-table2-example/stories/stylesheet/loading-overlay/_index.scss diff --git a/packages/react-bootstrap-table2-example/.storybook/webpack.config.js b/packages/react-bootstrap-table2-example/.storybook/webpack.config.js index 3e55ec8..8ebc72a 100644 --- a/packages/react-bootstrap-table2-example/.storybook/webpack.config.js +++ b/packages/react-bootstrap-table2-example/.storybook/webpack.config.js @@ -2,6 +2,7 @@ const path = require('path'); const sourcePath = path.join(__dirname, '../../react-bootstrap-table2/src'); const paginationSourcePath = path.join(__dirname, '../../react-bootstrap-table2-paginator/src'); +const overlaySourcePath = path.join(__dirname, '../../react-bootstrap-table2-overlay/src'); const sourceStylePath = path.join(__dirname, '../../react-bootstrap-table2/style'); const paginationStylePath = path.join(__dirname, '../../react-bootstrap-table2-paginator/style'); const storyPath = path.join(__dirname, '../stories'); @@ -25,7 +26,7 @@ const loaders = [{ test: /\.js?$/, use: ['babel-loader'], exclude: /node_modules/, - include: [sourcePath, paginationSourcePath, storyPath], + include: [sourcePath, paginationSourcePath, overlaySourcePath, storyPath], }, { test: /\.css$/, use: ['style-loader', 'css-loader'], diff --git a/packages/react-bootstrap-table2-example/examples/loading-overlay/empty-table-overlay.js b/packages/react-bootstrap-table2-example/examples/loading-overlay/empty-table-overlay.js new file mode 100644 index 0000000..6366f16 --- /dev/null +++ b/packages/react-bootstrap-table2-example/examples/loading-overlay/empty-table-overlay.js @@ -0,0 +1,145 @@ +/* eslint react/no-multi-comp: 0 */ +import React from 'react'; +import PropTypes from 'prop-types'; +import BootstrapTable from 'react-bootstrap-table2'; +import paginator from 'react-bootstrap-table2-paginator'; +import Code from 'components/common/code-block'; +import { productsGenerator } from 'utils/common'; + +const products = productsGenerator(87); + +const columns = [{ + dataField: 'id', + text: 'Product ID' +}, { + dataField: 'name', + text: 'Product Name' +}, { + dataField: 'price', + text: 'Product Price' +}]; + +const sourceCode = `\ +import BootstrapTable from 'react-bootstrap-table2'; +import paginator from 'react-bootstrap-table2-paginator'; +// ... +const RemotePagination = ({ data, page, sizePerPage, onTableChange, totalSize }) => ( +
+ + { sourceCode } +
+); + +class Container extends React.Component { + constructor(props) { + super(props); + this.state = { + page: 1, + data: products.slice(0, 10), + sizePerPage: 10 + }; + } + + handleTableChange = ({ page, sizePerPage }) => { + const currentIndex = (page - 1) * sizePerPage; + setTimeout(() => { + this.setState(() => ({ + page, + data: products.slice(currentIndex, currentIndex + sizePerPage), + sizePerPage + })); + }, 2000); + } + + render() { + const { data, sizePerPage, page } = this.state; + return ( + + ); + } +} +`; + +const NoDataIndication = () => ( +
+
+
+
+
+
+
+); + +const Table = ({ data, page, sizePerPage, onTableChange, totalSize }) => ( +
+ } + /> + { sourceCode } +
+); + +Table.propTypes = { + data: PropTypes.array.isRequired, + page: PropTypes.number.isRequired, + totalSize: PropTypes.number.isRequired, + sizePerPage: PropTypes.number.isRequired, + onTableChange: PropTypes.func.isRequired +}; + +class EmptyTableOverlay extends React.Component { + constructor(props) { + super(props); + this.state = { + page: 1, + data: products.slice(0, 10), + sizePerPage: 10 + }; + } + + handleTableChange = ({ page, sizePerPage }) => { + const currentIndex = (page - 1) * sizePerPage; + setTimeout(() => { + this.setState(() => ({ + page, + data: products.slice(currentIndex, currentIndex + sizePerPage), + sizePerPage + })); + }, 3000); + this.setState(() => ({ data: [] })); + } + + render() { + const { data, sizePerPage, page } = this.state; + return ( + + ); + } +} + +export default EmptyTableOverlay; diff --git a/packages/react-bootstrap-table2-example/examples/loading-overlay/table-overlay.js b/packages/react-bootstrap-table2-example/examples/loading-overlay/table-overlay.js new file mode 100644 index 0000000..b0dca04 --- /dev/null +++ b/packages/react-bootstrap-table2-example/examples/loading-overlay/table-overlay.js @@ -0,0 +1,158 @@ +/* eslint react/no-multi-comp: 0 */ +import React from 'react'; +import PropTypes from 'prop-types'; +import BootstrapTable from 'react-bootstrap-table2'; +import paginator from 'react-bootstrap-table2-paginator'; +import overlayFactory from 'react-bootstrap-table2-overlay'; +import Code from 'components/common/code-block'; +import { productsGenerator } from 'utils/common'; + +const products = productsGenerator(87); + +const columns = [{ + dataField: 'id', + text: 'Product ID' +}, { + dataField: 'name', + text: 'Product Name' +}, { + dataField: 'price', + text: 'Product Price' +}]; + +const sourceCode = `\ +import BootstrapTable from 'react-bootstrap-table2'; +import paginator from 'react-bootstrap-table2-paginator'; +import overlayFactory from 'react-bootstrap-table2-overlay'; + +// ... +const RemotePagination = ({ loading, data, page, sizePerPage, onTableChange, totalSize }) => ( +
+ + { sourceCode } +
+); + +RemotePagination.propTypes = { + data: PropTypes.array.isRequired, + page: PropTypes.number.isRequired, + loading: PropTypes.bool.isRequired, + totalSize: PropTypes.number.isRequired, + sizePerPage: PropTypes.number.isRequired, + onTableChange: PropTypes.func.isRequired +}; + +class Container extends React.Component { + constructor(props) { + super(props); + this.state = { + page: 1, + loading: false, + data: products.slice(0, 10), + sizePerPage: 10 + }; + } + + handleTableChange = ({ page, sizePerPage }) => { + const currentIndex = (page - 1) * sizePerPage; + setTimeout(() => { + this.setState(() => ({ + page, + loading: false, + data: products.slice(currentIndex, currentIndex + sizePerPage), + sizePerPage + })); + }, 3000); + this.setState(() => ({ loading: true })); + } + + render() { + const { data, sizePerPage, page, loading } = this.state; + return ( + + ); + } +} +`; + +const RemotePagination = ({ loading, data, page, sizePerPage, onTableChange, totalSize }) => ( +
+ + { sourceCode } +
+); + +RemotePagination.propTypes = { + data: PropTypes.array.isRequired, + page: PropTypes.number.isRequired, + loading: PropTypes.bool.isRequired, + totalSize: PropTypes.number.isRequired, + sizePerPage: PropTypes.number.isRequired, + onTableChange: PropTypes.func.isRequired +}; + +class Container extends React.Component { + constructor(props) { + super(props); + this.state = { + page: 1, + loading: false, + data: products.slice(0, 10), + sizePerPage: 10 + }; + } + + handleTableChange = ({ page, sizePerPage }) => { + const currentIndex = (page - 1) * sizePerPage; + setTimeout(() => { + this.setState(() => ({ + page, + loading: false, + data: products.slice(currentIndex, currentIndex + sizePerPage), + sizePerPage + })); + }, 3000); + this.setState(() => ({ loading: true })); + } + + render() { + const { data, sizePerPage, page, loading } = this.state; + return ( + + ); + } +} + +export default Container; diff --git a/packages/react-bootstrap-table2-example/package.json b/packages/react-bootstrap-table2-example/package.json index 563432b..a726ef5 100644 --- a/packages/react-bootstrap-table2-example/package.json +++ b/packages/react-bootstrap-table2-example/package.json @@ -18,7 +18,8 @@ "dependencies": { "bootstrap": "^3.3.7", "react-bootstrap-table2": "0.0.1", - "react-bootstrap-table2-paginator": "0.0.1" + "react-bootstrap-table2-paginator": "0.0.1", + "react-bootstrap-table2-overlay": "0.0.1" }, "devDependencies": { "@storybook/addon-console": "^1.0.0", diff --git a/packages/react-bootstrap-table2-example/stories/index.js b/packages/react-bootstrap-table2-example/stories/index.js index 71746da..a999782 100644 --- a/packages/react-bootstrap-table2-example/stories/index.js +++ b/packages/react-bootstrap-table2-example/stories/index.js @@ -74,6 +74,10 @@ import PaginationHooksTable from 'examples/pagination/pagination-hooks'; import CustomPaginationTable from 'examples/pagination/custom-pagination'; import RemotePaginationTable from 'examples/pagination/remote-pagination'; +// loading overlay +import EmptyTableOverlay from 'examples/loading-overlay/empty-table-overlay'; +import TableOverlay from 'examples/loading-overlay/table-overlay'; + // css style import 'bootstrap/dist/css/bootstrap.min.css'; import 'stories/stylesheet/tomorrow.min.css'; @@ -156,3 +160,7 @@ storiesOf('Pagination', module) .add('Pagination Hooks', () => ) .add('Custom Pagination', () => ) .add('Remote Pagination', () => ); + +storiesOf('EmptyTableOverlay', module) + .add('Empty Table Overlay', () => ) + .add('Table Overlay', () => ); diff --git a/packages/react-bootstrap-table2-example/stories/stylesheet/loading-overlay/_index.scss b/packages/react-bootstrap-table2-example/stories/stylesheet/loading-overlay/_index.scss new file mode 100644 index 0000000..982c07f --- /dev/null +++ b/packages/react-bootstrap-table2-example/stories/stylesheet/loading-overlay/_index.scss @@ -0,0 +1,52 @@ +.spinner { + margin: 100px auto; + width: 50px; + height: 40px; + text-align: center; + font-size: 10px; +} + +.spinner > div { + background-color: #333; + height: 100%; + width: 6px; + display: inline-block; + + -webkit-animation: sk-stretchdelay 1.2s infinite ease-in-out; + animation: sk-stretchdelay 1.2s infinite ease-in-out; +} + +.spinner .rect2 { + -webkit-animation-delay: -1.1s; + animation-delay: -1.1s; +} + +.spinner .rect3 { + -webkit-animation-delay: -1.0s; + animation-delay: -1.0s; +} + +.spinner .rect4 { + -webkit-animation-delay: -0.9s; + animation-delay: -0.9s; +} + +.spinner .rect5 { + -webkit-animation-delay: -0.8s; + animation-delay: -0.8s; +} + +@-webkit-keyframes sk-stretchdelay { + 0%, 40%, 100% { -webkit-transform: scaleY(0.4) } + 20% { -webkit-transform: scaleY(1.0) } +} + +@keyframes sk-stretchdelay { + 0%, 40%, 100% { + transform: scaleY(0.4); + -webkit-transform: scaleY(0.4); + } 20% { + transform: scaleY(1.0); + -webkit-transform: scaleY(1.0); + } +} diff --git a/packages/react-bootstrap-table2-example/stories/stylesheet/storybook.scss b/packages/react-bootstrap-table2-example/stories/stylesheet/storybook.scss index 3bbec85..07510ce 100644 --- a/packages/react-bootstrap-table2-example/stories/stylesheet/storybook.scss +++ b/packages/react-bootstrap-table2-example/stories/stylesheet/storybook.scss @@ -7,4 +7,5 @@ @import "columns/index"; @import "cell-edit/index"; @import "row-selection/index"; -@import "rows/index"; \ No newline at end of file +@import "rows/index"; +@import "loading-overlay/index"; \ No newline at end of file From fab06bf599c938963a33eb5f5ec4dfff44c6f210 Mon Sep 17 00:00:00 2001 From: AllenFang Date: Sun, 3 Dec 2017 17:35:00 +0800 Subject: [PATCH 3/5] patch docs for remote --- docs/README.md | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/docs/README.md b/docs/README.md index ec5f593..dc9b54d 100644 --- a/docs/README.md +++ b/docs/README.md @@ -8,6 +8,7 @@ * [columns (**required**)](#columns) #### Optional +* [remote](#remote) * [caption](#caption) * [striped](#striped) * [bordered](#bordered) @@ -20,6 +21,7 @@ * [rowEvents](#rowEvents) * [defaultSorted](#defaultSorted) * [pagination](#pagination) +* [onTableChange](#onTableChange) ### keyField(**required**) - [String] Tells `react-bootstrap-table2` which column is unique. @@ -30,6 +32,20 @@ Provides data for your table. It accepts a single Array object. ### columns(**required**) - [Object] Accepts a single Array object, please see [columns definition](./columns.md) for more detail. +### remote - [Bool | Object] +Default is `false`, if enable`remote`, you are suppose to handle all the table change events, like: pagination, insert, filtering etc. +This is a chance that you can connect to your remote server or database to manipulate your data. +For flexibility reason, you can control what functionality should be handled on remote via a object return: + +```js +remote={ { pagination: true } } +``` + +In above case, only pagination will be handled on remote. + +> Note: when remote is enable, you are suppose to give [`onTableChange`](#onTableChange) prop on `BootstrapTable` +> It's the only way to communicate to your remote server and update table states. + ### caption - [String | Node] Same as HTML [caption tag](https://www.w3schools.com/TAgs/tag_caption.asp), you can set it as String or a React JSX. @@ -148,3 +164,22 @@ paginator({ hidePageListOnlyOnePage: true// hide pagination bar when only one page, default is false }) ``` + +### onTableChange - [Function] +This callback function will be called when [`remote`](#remote) enabled only. + +```js +const onTableChange = (newState) => { + // handle any data change here +} + +``` + +There's only one argument will be passed to `onTableChange`, `newState`: + +```js +{ + page, // newest page + sizePerPage //newest sizePerPage +} +``` \ No newline at end of file From a363764ce90a93e36eb132b04c5ea39370f4a92b Mon Sep 17 00:00:00 2001 From: AllenFang Date: Sun, 3 Dec 2017 17:55:27 +0800 Subject: [PATCH 4/5] patch docs for overlay --- docs/README.md | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/docs/README.md b/docs/README.md index dc9b54d..2178334 100644 --- a/docs/README.md +++ b/docs/README.md @@ -9,6 +9,7 @@ #### Optional * [remote](#remote) +* [loading](#loading) * [caption](#caption) * [striped](#striped) * [bordered](#bordered) @@ -46,6 +47,33 @@ In above case, only pagination will be handled on remote. > Note: when remote is enable, you are suppose to give [`onTableChange`](#onTableChange) prop on `BootstrapTable` > It's the only way to communicate to your remote server and update table states. +### 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-table` will attend to render a overlay on table via [`overlay`](#overlay) prop, if [`overlay`](#overlay) prop is not given, `react-bootstrap-table` will ignore the overlay rendering. + +### overlay - [Function] +`overlay` accept a factory funtion which should returning a higher order component. By default, `react-bootstrap-table-overlay` can be a good option for you: + +```sh +$ npm install react-bootstrap-table-overlay +``` +```js +import overlayFactory from 'react-bootstrap-table-overlay'; + + +``` + +Actually, `react-bootstrap-table-overlay` is depends on [`react-loading-overlay`](https://github.com/derrickpelletier/react-loading-overlay) and `overlayFactory` just a factory function and you can pass any props which available for `react-loading-overlay`: + +```js +overlay={ overlayFactory({ spinner: true, background: 'rgba(192,192,192,0.3)' }) } +``` + ### caption - [String | Node] Same as HTML [caption tag](https://www.w3schools.com/TAgs/tag_caption.asp), you can set it as String or a React JSX. From 32b187ff9f47215837ad1137c924dd7244f4b0c3 Mon Sep 17 00:00:00 2001 From: AllenFang Date: Sun, 3 Dec 2017 18:22:05 +0800 Subject: [PATCH 5/5] no --pure-lockfile --ignore-scripts --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index bcff7b2..02a5492 100644 --- a/.travis.yml +++ b/.travis.yml @@ -17,4 +17,4 @@ before_install: - curl -o- -L https://yarnpkg.com/install.sh | bash -s - export PATH="$HOME/.yarn/bin:$PATH" -install: yarn install --pure-lockfile --ignore-scripts +install: yarn install