diff --git a/README.md b/README.md
index 4b194e9..857747f 100644
--- a/README.md
+++ b/README.md
@@ -5,21 +5,24 @@
[![npm package][npm-badge]][npm]
[![Codacy Badge][codacy-badge]][codacy]
-Datatable built using React and Redux to fetch JSON data asynchronously using REST API.
-
-- Filterable columns by date ranges, numeric ranges and text.
-- Pagination
-- Sortable columns
-- Configurable column widths
-- Built in windowing to handle large dataset with thousands of rows
-- Customizable limiter options
-- Customizable toolbar with the ability to add custom renderers
-- Completely configurable headers, filters, toolbar and pagination with options to enable/disable them individual
-- Custom row level actions
-- Thunks to handle custom mass or row actions externally.
-- Compatible with normalizr to handle externally managed states
-- Easily stylable with styled-components.
-- Show or hide columns dynamically using the Columns item in the toolbar.
+Datatable built using React and Redux to fetch JSON data asynchronously
+using REST API.
+
+- Filterable columns by date ranges, numeric ranges and text.
+- Pagination
+- Sortable columns
+- Configurable column widths
+- Built in windowing to handle large dataset with thousands of rows
+- Customizable limiter options
+- Customizable toolbar with the ability to add custom renderers
+- Completely configurable headers, filters, toolbar and pagination
+ with options to enable/disable them individual
+- Custom row level actions
+- Thunks to handle custom mass or row actions externally.
+- Compatible with normalizr to handle externally managed states
+- Easily stylable with styled-components.
+- Show or hide columns dynamically using the Columns item in the
+ toolbar.
## Installation
@@ -31,7 +34,7 @@ npm i @flipbyte/redux-datatable
## Usage
-#### Add the table reducer and epics to your store.
+### Add the table reducer and epics to your store
```javascript
// Get the table reducer and epics as follows
@@ -40,7 +43,7 @@ import { reducer, epics } from '@flipbyte/redux-datatable';
// Add the above reducer and epics to your store.
```
-#### Preparing your table config object
+### Preparing your table config object
```javascript
{
@@ -170,7 +173,8 @@ import { reducer, epics } from '@flipbyte/redux-datatable';
}
```
-#### Render table component
+### Render table component
+
```javascript
import ReduxDatatable from '@flipbyte/redux-datatable';
@@ -183,107 +187,109 @@ const YourComponent = () =>
### Table config props
-| Key | Type | Required | Default | Description |
-| ------------ | ------------ | ------------ | ------------ | ------------ |
-| name | string | true | - | A unique key where the data for the table is saved in the table state object |
-| height | integer | true | - | The maximum height of the table |
-| rowHeight | integer | true | - | The maximum height of each table body row |
-| filterable | boolean | false | true | Whether to show/hide filters row |
-| headers | boolean | false | true | Whether to show/hide headers row |
-| pagination | object | false | {} | Pagination bar configuration (Check below) |
-| routes | object | true | - | Routes definition to fetch data and other custom routes config for custom handling (Check below) |
-| toolbar | array | false | [] | Toolbar definition (Check below) |
-| columns | array | true | - | Columns to display |
-| styles | object | false | {} | Custom styles for your table |
+| Key | Type | Required | Default | Description |
+| ---------- | ------- | -------- | ------- | ------------------------------------------------------------------------------------------------ |
+| name | string | true | - | A unique key where the data for the table is saved in the table state object |
+| height | integer | true | - | The maximum height of the table |
+| rowHeight | integer | true | - | The maximum height of each table body row |
+| filterable | boolean | false | true | Whether to show/hide filters row |
+| headers | boolean | false | true | Whether to show/hide headers row |
+| pagination | object | false | {} | Pagination bar configuration (Check below) |
+| routes | object | true | - | Routes definition to fetch data and other custom routes config for custom handling (Check below) |
+| toolbar | array | false | \[] | Toolbar definition (Check below) |
+| columns | array | true | - | Columns to display |
+| styles | object | false | {} | Custom styles for your table |
#### Pagination object
-| Key | Type | Required | Default | Description |
-| ------------ | ------------ | ------------ | ------------ | ------------ |
-| items | object | false | {} | Items available for display in the pagination bar. Check below for items available |
-| visible | boolean/object | false | true | Whether the pagination is visible or not |
+| Key | Type | Required | Default | Description |
+| ------- | -------------- | -------- | ------- | ---------------------------------------------------------------------------------- |
+| items | object | false | {} | Items available for display in the pagination bar. Check below for items available |
+| visible | boolean/object | false | true | Whether the pagination is visible or not |
-##### Pagination items object:
+##### Pagination items object
-| Key | Type | Required | Default | Description |
-| ------------ | ------------ | ------------ | ------------ | ------------ |
-| type | string | true | - | One of the following: limiter, pages, resultCount |
-| visible | boolean | false | true | Whether the item is visible |
-| **Limiter specific options** | | | | |
-| options | array | true | - | Array of integers with limiter options |
-| default | array | true | - | One of the values in the limiter options key |
+| Key | Type | Required | Default | Description |
+| ---------------------------- | ------- | -------- | ------- | ------------------------------------------------- |
+| type | string | true | - | One of the following: limiter, pages, resultCount |
+| visible | boolean | false | true | Whether the item is visible |
+| **Limiter specific options** | | | | |
+| options | array | true | - | Array of integers with limiter options |
+| default | array | true | - | One of the values in the limiter options key |
#### Routes object
-| Key | Type | Required | Default | Description |
-| ------------ | ------------ | ------------ | ------------ | ------------ |
-| get | object | true | - | The configuration for fetching data |
-| **- get** | | | | |
-| route | string | true | - | Your data fetching route |
-| sort | string | true | - | Your key to sort with |
-| dir | string | true | - | Sort by 'asc' or 'desc' order |
-| resultPath | object | true | - | The keys object to your data. Required { data: '{your data path in json response. Ex: result.data}'} |
+| Key | Type | Required | Default | Description |
+| ---------- | ------ | -------- | ------- | ---------------------------------------------------------------------------------------------------- |
+| get | object | true | - | The configuration for fetching data |
+| **- get** | | | | |
+| route | string | true | - | Your data fetching route |
+| sort | string | true | - | Your key to sort with |
+| dir | string | true | - | Sort by 'asc' or 'desc' order |
+| resultPath | object | true | - | The keys object to your data. Required { data: '{your data path in json response. Ex: result.data}'} |
#### Toolbar
-Toolbar config is an array of array of object where objects are the toolbar items. Each inner array represents a different row.
-
-| Key | Type | Required | Default | Description |
-| ------------ | ------------ | ------------ | ------------ | ------------ |
-| type | string | false | actions | Available values reset-filters and columns |
-| label | string | true | - | Label for the toolbar item |
-| visible | boolean | false | true | Whether the item is visible |
-| state | boolean | false | false | Whether to pass the state object as item prop |
-| **For type: actions** | | | | |
-| options | array | true | - | Array of option objects |
-| **-- options** | | | | |
-| type | string | true | action | Available option: action |
-| name | string | true | - | Unique name for the action |
-| label | string | true | - | Label for the action |
-| thunk | function | true | - | An action creator which is dispatched on action click. Check demo schema. |
+Toolbar config is an array of array of object where objects are the
+toolbar items. Each inner array represents a different row.
+
+| Key | Type | Required | Default | Description |
+| --------------------- | -------- | -------- | ------- | ------------------------------------------------------------------------- |
+| type | string | false | actions | Available values reset-filters and columns |
+| label | string | true | - | Label for the toolbar item |
+| visible | boolean | false | true | Whether the item is visible |
+| state | boolean | false | false | Whether to pass the state object as item prop |
+| **For type: actions** | | | | |
+| options | array | true | - | Array of option objects |
+| **-- options** | | | | |
+| type | string | true | action | Available option: action |
+| name | string | true | - | Unique name for the action |
+| label | string | true | - | Label for the action |
+| thunk | function | true | - | An action creator which is dispatched on action click. Check demo schema. |
#### Columns object
-| Key | Type | Required | Default | Description |
-| ------------ | ------------ | ------------ | ------------ | ------------ |
-| name | string | true | - | Unique name for the column |
-| label | string | true | - | Label for the column |
-| sortable | boolean | false | true | Whether the column is sortable |
-| filterable | boolean | false | true | Whether the column is filterable |
-| type | string | true | string | Available types: selection, number, date, string, image, actions |
-| width | integer | true | - | Width of the column |
-| extraData | string/array | fasle | - | properties from the state to pass as in the extra object |
-| textAlign | string | false | left | Text alignment in the column |
-| **type: actions** | | | | |
-| items | array | true | - | array of item configuration object |
-| **- item configuration object** | | | | |
-| name | string | true | - | Unique name for the action |
-| label | string | true | - | Label for the action |
-| thunk | function | true | - | An action creator which is dispatched on action click. Check demo schema. |
+| Key | Type | Required | Default | Description |
+| ------------------------------- | ------------ | -------- | ------- | ------------------------------------------------------------------------- |
+| name | string | true | - | Unique name for the column |
+| label | string | true | - | Label for the column |
+| sortable | boolean | false | true | Whether the column is sortable |
+| filterable | boolean | false | true | Whether the column is filterable |
+| type | string | true | string | Available types: selection, number, date, string, image, actions |
+| width | integer | true | - | Width of the column |
+| extraData | string/array | false | - | properties from the state to pass as in the extra object |
+| textAlign | string | false | left | Text alignment in the column |
+| **type: actions** | | | | |
+| items | array | true | - | array of item configuration object |
+| **- item configuration object** | | | | |
+| name | string | true | - | Unique name for the action |
+| label | string | true | - | Label for the action |
+| thunk | function | true | - | An action creator which is dispatched on action click. Check demo schema. |
#### Styles object
-Styles has the following properties avaailable:
-
-| Key | Type | Required | Default | Description |
-| ------------ | ------------ | ------------ | ------------ | ------------ |
-| tableContainer | styled-components style object | false | - | Outer table container |
-| table | styled-components style object | false | - | Table component |
-| thead | styled-components style object | false | - | Table header component |
-| tbody | styled-components style object | false | - | Table body component |
-| tr | object | false | - | Table rows - the object can contain the following keys `header`, `filter`, `body`, each of whose values is a styled-components style object| |
-| th | styled-components style object | false | - | Table header columns |
-| td | object | false | - | Table columns - the object contain the following keys `filter`, `body` whose value is a styled-components style object |
-| toolbar | object | false | - | Keys `container` and `row` which are styled-components style object and `item` which is an object with keys that are the names of the respective items (as defined in the config) and the value is a styled-components style object |
-| pagination | object | false | - | Keys `container` - a styled-components style object and `item` - same as above toolbar item |
-| filter | object | false | - | Each key is the name of the column and the value is the styled-components style object |
-| body | object | false | - | Same as `filter` (above) |
+Styles has the following properties available:
+
+| Key | Type | Required | Default | Description |
+| -------------- | ------------------------------ | -------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| tableContainer | styled-components style object | false | - | Outer table container |
+| table | styled-components style object | false | - | Table component |
+| thead | styled-components style object | false | - | Table header component |
+| tbody | styled-components style object | false | - | Table body component |
+| tr | object | false | - | Table rows - the object can contain the following keys `header`, `filter`, `body`, each of whose values is a styled-components style object |
+| th | styled-components style object | false | - | Table header columns |
+| td | object | false | - | Table columns - the object contain the following keys `filter`, `body` whose value is a styled-components style object |
+| toolbar | object | false | - | Keys `container` and `row` which are styled-components style object and `item` which is an object with keys that are the names of the respective items (as defined in the config) and the value is a styled-components style object |
+| pagination | object | false | - | Keys `container` - a styled-components style object and `item` - same as above toolbar item |
+| filter | object | false | - | Each key is the name of the column and the value is the styled-components style object |
+| body | object | false | - | Same as `filter` (above) |
## License
+
The MIT License (MIT)
[npm-badge]: https://img.shields.io/npm/v/@flipbyte/redux-datatable.svg
[npm]: https://www.npmjs.com/package/@flipbyte/redux-datatable
[codacy-badge]: https://api.codacy.com/project/badge/Grade/67274650b4874f5db55ede76156ab4d2
-[codacy]: https://www.codacy.com/app/flipbyte/redux-datatable?utm_source=github.com&utm_medium=referral&utm_content=flipbyte/redux-datatable&utm_campaign=Badge_Grade
+[codacy]: https://www.codacy.com/app/flipbyte/redux-datatable?utm_source=github.com&utm_medium=referral&utm_content=flipbyte/redux-datatable&utm_campaign=Badge_Grade
diff --git a/demo/src/index.js b/demo/src/index.js
index 22b41c8..bf01e1c 100644
--- a/demo/src/index.js
+++ b/demo/src/index.js
@@ -12,7 +12,7 @@ import './css/styles.css';
const store = configureStore(config);
-const Demo = () =>
+const Demo = () => (
+);
render(
diff --git a/demo/src/schema/basic.js b/demo/src/schema/basic.js
index d3dd6ba..56a2513 100644
--- a/demo/src/schema/basic.js
+++ b/demo/src/schema/basic.js
@@ -137,7 +137,7 @@ export default {
label: 'Delete',
indexField: '@id',
thunk: ( payload ) => ( dispatch, getState ) => {
- confirm("Are your sure you want to delete the selected items?")
+ confirm('Are your sure you want to delete the selected items?')
? console.log('delete items', getState())
: console.log(false);
@@ -211,7 +211,7 @@ export default {
id: '@id'
},
thunk: ( payload ) => ( dispatch, getState ) => {
- confirm("Are your sure you want to delete this page?")
+ confirm('Are your sure you want to delete this page?')
? console.log('delete', getState())
: console.log(false);
diff --git a/demo/src/schema/index.js b/demo/src/schema/index.js
index 3524b97..63df699 100644
--- a/demo/src/schema/index.js
+++ b/demo/src/schema/index.js
@@ -2,9 +2,9 @@ import basic from './basic';
export default [
{
- title: "Basic Table",
- id: "basic-table",
- className: "mb-4",
+ title: 'Basic Table',
+ id: 'basic-table',
+ className: 'mb-4',
config: basic
}
]
diff --git a/nwb.config.js b/nwb.config.js
index a7e1c20..cf35913 100644
--- a/nwb.config.js
+++ b/nwb.config.js
@@ -9,4 +9,4 @@ module.exports = {
}
}
}
-}
+};
diff --git a/package-lock.json b/package-lock.json
index 91a8c09..02b5ca4 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,6 +1,6 @@
{
"name": "@flipbyte/redux-datatable",
- "version": "0.2.0",
+ "version": "0.2.1",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
@@ -31,9 +31,9 @@
}
},
"@babel/types": {
- "version": "7.3.4",
- "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.3.4.tgz",
- "integrity": "sha512-WEkp8MsLftM7O/ty580wAmZzN1nDmCACc5+jFzUt+GUFNNIi3LdRlueYz0YIlmJhlZx1QYDMZL5vdWCL0fNjFQ==",
+ "version": "7.4.0",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.4.0.tgz",
+ "integrity": "sha512-aPvkXyU2SPOnztlgo8n9cEiXW755mgyvueUPcpStqdzoSPm0fjO0vQBjLkt3JKJW7ufikfcnMTTPsN1xaTsBPA==",
"dev": true,
"requires": {
"esutils": "^2.0.2",
@@ -7964,9 +7964,9 @@
}
},
"memoize-one": {
- "version": "4.0.3",
- "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-4.0.3.tgz",
- "integrity": "sha512-QmpUu4KqDmX0plH4u+tf0riMc1KHE1+lw95cMrLlXQAFOx/xnBtwhZ52XJxd9X2O6kwKBqX32kmhbhlobD0cuw==",
+ "version": "5.0.4",
+ "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.0.4.tgz",
+ "integrity": "sha512-P0z5IeAH6qHHGkJIXWw0xC2HNEgkx/9uWWBQw64FJj3/ol14VYdfVGWWr0fXfjhhv3TKVIqUq65os6O4GUNksA==",
"dev": true
},
"memory-fs": {
@@ -9882,15 +9882,15 @@
}
},
"react": {
- "version": "16.8.4",
- "resolved": "https://registry.npmjs.org/react/-/react-16.8.4.tgz",
- "integrity": "sha512-0GQ6gFXfUH7aZcjGVymlPOASTuSjlQL4ZtVC5YKH+3JL6bBLCVO21DknzmaPlI90LN253ojj02nsapy+j7wIjg==",
+ "version": "16.8.6",
+ "resolved": "https://registry.npmjs.org/react/-/react-16.8.6.tgz",
+ "integrity": "sha512-pC0uMkhLaHm11ZSJULfOBqV4tIZkx87ZLvbbQYunNixAAvjnC+snJCg0XQXn9VIsttVsbZP/H/ewzgsd5fxKXw==",
"dev": true,
"requires": {
"loose-envify": "^1.1.0",
"object-assign": "^4.1.1",
"prop-types": "^15.6.2",
- "scheduler": "^0.13.4"
+ "scheduler": "^0.13.6"
}
},
"react-deep-force-update": {
@@ -9900,15 +9900,15 @@
"dev": true
},
"react-dom": {
- "version": "16.8.4",
- "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.8.4.tgz",
- "integrity": "sha512-Ob2wK7XG2tUDt7ps7LtLzGYYB6DXMCLj0G5fO6WeEICtT4/HdpOi7W/xLzZnR6RCG1tYza60nMdqtxzA8FaPJQ==",
+ "version": "16.8.6",
+ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.8.6.tgz",
+ "integrity": "sha512-1nL7PIq9LTL3fthPqwkvr2zY7phIPjYrT0jp4HjyEQrEROnw4dG41VVwi/wfoCneoleqrNX7iAD+pXebJZwrwA==",
"dev": true,
"requires": {
"loose-envify": "^1.1.0",
"object-assign": "^4.1.1",
"prop-types": "^15.6.2",
- "scheduler": "^0.13.4"
+ "scheduler": "^0.13.6"
}
},
"react-is": {
@@ -10730,9 +10730,9 @@
"dev": true
},
"scheduler": {
- "version": "0.13.4",
- "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.13.4.tgz",
- "integrity": "sha512-cvSOlRPxOHs5dAhP9yiS/6IDmVAVxmk33f0CtTJRkmUWcb1Us+t7b1wqdzoC0REw2muC9V5f1L/w5R5uKGaepA==",
+ "version": "0.13.6",
+ "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.13.6.tgz",
+ "integrity": "sha512-IWnObHt413ucAYKsD9J1QShUKkbKLQQHdxRyw73sw4FN26iWr3DY/H34xGPe4nmL1DwXyWmSWmMrA9TfQbE/XQ==",
"dev": true,
"requires": {
"loose-envify": "^1.1.0",
@@ -11602,9 +11602,9 @@
}
},
"styled-components": {
- "version": "4.1.3",
- "resolved": "https://registry.npmjs.org/styled-components/-/styled-components-4.1.3.tgz",
- "integrity": "sha512-0quV4KnSfvq5iMtT0RzpMGl/Dg3XIxIxOl9eJpiqiq4SrAmR1l1DLzNpMzoy3DyzdXVDMJS2HzROnXscWA3SEw==",
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/styled-components/-/styled-components-4.2.0.tgz",
+ "integrity": "sha512-L/LzkL3ZbBhqIVHdR7DbYujy4tqvTNRfc+4JWDCYyhTatI+8CRRQUmdaR0+ARl03DWsfKLhjewll5uNLrqrl4A==",
"dev": true,
"requires": {
"@babel/helper-module-imports": "^7.0.0",
@@ -11612,7 +11612,7 @@
"@emotion/unitless": "^0.7.0",
"babel-plugin-styled-components": ">= 1",
"css-to-react-native": "^2.2.2",
- "memoize-one": "^4.0.0",
+ "memoize-one": "^5.0.0",
"prop-types": "^15.5.4",
"react-is": "^16.6.0",
"stylis": "^3.5.0",
diff --git a/package.json b/package.json
index 23c9b37..1e5a7b1 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "@flipbyte/redux-datatable",
- "version": "0.2.0",
+ "version": "0.2.1",
"description": "React-Redux data table",
"main": "lib/index.js",
"module": "es/index.js",
@@ -20,13 +20,13 @@
"test:watch": "nwb test-react --server"
},
"peerDependencies": {
- "react": "^16.8.4",
- "react-dom": "^16.8.4",
+ "react": "^16.8.6",
+ "react-dom": "^16.8.6",
"rxjs": "^6.4.0",
"prop-types": "^15.6.2",
"react-redux": "^6.0.1",
"redux": "^4.0.1",
- "styled-components": "^4.1.3"
+ "styled-components": "^4.2.0"
},
"dependencies": {
"lodash": ">=4.17.10",
@@ -44,13 +44,13 @@
"bootstrap": "^4.3.1",
"nwb": "0.23.x",
"path-to-regexp": "^3.0.0",
- "react": "^16.8.4",
- "react-dom": "^16.8.4",
+ "react": "^16.8.6",
+ "react-dom": "^16.8.6",
"react-redux": "^6.0.1",
"redux": "^4.0.1",
"redux-logger": "^3.0.6",
"rxjs": "^6.4.0",
- "styled-components": "^4.1.3"
+ "styled-components": "^4.2.0"
},
"author": "",
"homepage": "",
diff --git a/src/Renderer.js b/src/Renderer.js
index 42ebb51..4565481 100644
--- a/src/Renderer.js
+++ b/src/Renderer.js
@@ -50,7 +50,7 @@ const getRenderers = ( ofType ) => renderers[ofType] || {};
const Renderer = ({ ofType, forItem, ...props }) => {
const renderers = getRenderers(ofType);
const Renderer = renderers[forItem] || renderers['default'];
- return
-}
+ return ;
+};
export default Renderer;
diff --git a/src/Renderer/Body/Actions.js b/src/Renderer/Body/Actions.js
index b186f7a..ccfc655 100644
--- a/src/Renderer/Body/Actions.js
+++ b/src/Renderer/Body/Actions.js
@@ -3,7 +3,7 @@ import { connect } from 'react-redux';
import React, { Component } from 'react';
import { deleteData } from '../../actions';
import { withTableConfig } from '../../TableProvider';
-import { paramsResolver, prepareActionPayload } from '../../utils'
+import { paramsResolver, prepareActionPayload } from '../../utils';
import Button from '../../components/Button';
const Actions = ({
diff --git a/src/Renderer/Body/Date.js b/src/Renderer/Body/Date.js
index 27f05cc..71eb4a8 100644
--- a/src/Renderer/Body/Date.js
+++ b/src/Renderer/Body/Date.js
@@ -1,7 +1,6 @@
import _ from 'lodash';
import Time from 'react-pure-time';
import React, { Component } from 'react';
-import { shouldUpdate } from '../../utils';
const Date = ({
data,
@@ -9,6 +8,6 @@ const Date = ({
colConfig: { name, textAlign, format }
}) => (
-)
+);
export default Date;
diff --git a/src/Renderer/Body/Image.js b/src/Renderer/Body/Image.js
index f68c716..40273b9 100644
--- a/src/Renderer/Body/Image.js
+++ b/src/Renderer/Body/Image.js
@@ -1,5 +1,4 @@
import _ from 'lodash';
-import { shouldUpdate } from '../../utils';
import React, { Fragment, Component } from 'react';
const Image = ({
@@ -8,6 +7,6 @@ const Image = ({
colConfig: { name, imgWidth, imgHeight }
}) => (
-)
+);
export default Image;
diff --git a/src/Renderer/Body/Options.js b/src/Renderer/Body/Options.js
index f27e71e..68f24b8 100644
--- a/src/Renderer/Body/Options.js
+++ b/src/Renderer/Body/Options.js
@@ -1,6 +1,5 @@
import _ from 'lodash';
import Time from 'react-pure-time';
-import { shouldUpdate } from '../../utils';
import React, { Fragment, Component } from 'react';
const Options = ({
@@ -10,7 +9,7 @@ const Options = ({
const value = _.get(data, name);
if(!options || !options[value]) {
- return { value }
+ return { value } ;
}
return (
@@ -18,6 +17,6 @@ const Options = ({
{ options[value].value }
);
-}
+};
export default Options;
diff --git a/src/Renderer/Body/Selection.js b/src/Renderer/Body/Selection.js
index a679f5a..84a4a0b 100644
--- a/src/Renderer/Body/Selection.js
+++ b/src/Renderer/Body/Selection.js
@@ -1,5 +1,5 @@
import _ from 'lodash';
-import PropTypes from "prop-types";
+import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import React, { Component } from 'react';
import { SET_SELECTION } from '../../actions';
@@ -11,7 +11,7 @@ const handleSelection = ({ data, indexField, action }, event ) => {
let paramKey = getConfigParam(indexField);
let key = getParam(indexField, data);
action(SET_SELECTION)({ paramKey, key, value: event.target.checked });
-}
+};
const Selection = ({
action,
@@ -31,6 +31,6 @@ const Selection = ({
onChange={ handleSelection.bind(this, { data, indexField, action }) } />
);
-}
+};
export default Selection;
diff --git a/src/Renderer/Body/Text.js b/src/Renderer/Body/Text.js
index 481dd54..ee90047 100644
--- a/src/Renderer/Body/Text.js
+++ b/src/Renderer/Body/Text.js
@@ -1,5 +1,4 @@
import _ from 'lodash';
-import { shouldUpdate } from '../../utils';
import React, { Fragment, Component } from 'react';
const Text = ({
diff --git a/src/Renderer/Filter/Date.js b/src/Renderer/Filter/Date.js
index d44e224..fa010d5 100644
--- a/src/Renderer/Filter/Date.js
+++ b/src/Renderer/Filter/Date.js
@@ -9,7 +9,7 @@ var dateTo = null;
const applyFilter = ( key, filterer, event ) => {
let filter = {};
- if (key == 0) {
+ if (key === 0) {
dateFrom = event.target.value;
} else {
dateTo = event.target.value;
diff --git a/src/Renderer/Filter/Number.js b/src/Renderer/Filter/Number.js
index f88be69..c1967a9 100644
--- a/src/Renderer/Filter/Number.js
+++ b/src/Renderer/Filter/Number.js
@@ -9,7 +9,7 @@ var valTo = null;
const applyFilter = ( key, filterer, event ) => {
let filter = {};
- if (key == 0) {
+ if (key === 0) {
valFrom = event.target.value;
} else {
valTo = event.target.value;
diff --git a/src/Renderer/Pagination/Limiter.js b/src/Renderer/Pagination/Limiter.js
index 056e40b..1254cd2 100644
--- a/src/Renderer/Pagination/Limiter.js
+++ b/src/Renderer/Pagination/Limiter.js
@@ -17,6 +17,6 @@ const Limiter = ({ options, limit, action, style, default: defaultLimit }) => {
per page
);
-}
+};
export default Limiter;
diff --git a/src/Renderer/Pagination/Pages.js b/src/Renderer/Pagination/Pages.js
index 257758b..ffab04d 100644
--- a/src/Renderer/Pagination/Pages.js
+++ b/src/Renderer/Pagination/Pages.js
@@ -9,8 +9,8 @@ export const List = styled.div `
background: ${props => props.background || '#fff'};
border: ${props => props.border || '1px solid rgba(34,36,38,.15)'};
border-radius: ${props => props.borderRadius || 'none'};
- height: ${props => props.height || '40px'}
-`
+ height: ${props => props.height || '40px'};
+`;
const NUM_LINKS = 5;
@@ -23,18 +23,18 @@ const getPages = ( currentPage, total ) => {
var left = (currentPage - padding < padding) ? 1 : currentPage - padding;
var right = (left + NUM_LINKS - 1 > total) ? total : left + NUM_LINKS - 1;
- left = (right == total) ?
+ left = (right === total) ?
(right - NUM_LINKS < 1) ? 1 : right - NUM_LINKS + 1
: left;
return fillRange(left, right);
-}
+};
const Pages = ({ page, total, action, style }) => {
const setPage = ( page ) => action(SET_PAGE)({ page });
return (
- First
+ First
Previous
{ getPages(page, total).map( (link, index) =>
{
>{ link }
) }
= total }>Next
- Last
+ Last
);
-}
+};
-export default Pages
+export default Pages;
diff --git a/src/Renderer/Pagination/ResultCount.js b/src/Renderer/Pagination/ResultCount.js
index b34d49b..24c8cba 100644
--- a/src/Renderer/Pagination/ResultCount.js
+++ b/src/Renderer/Pagination/ResultCount.js
@@ -3,8 +3,9 @@ import React from 'react';
const lowerLimit = ( page, limit ) => ((page - 1) * limit) + 1;
const upperLimit = ( page, limit, count ) => (page * limit) > count ? count : page * limit;
-const ResultCount = ({ page, limit, count }) =>
+const ResultCount = ({ page, limit, count }) => (
!!count > 0 &&
Showing { lowerLimit(page, limit) } to { upperLimit(page, limit, count) } of { count } entries
+);
-export default ResultCount
+export default ResultCount;
diff --git a/src/Renderer/Toolbar/Columns.js b/src/Renderer/Toolbar/Columns.js
index d5de94d..8be32fd 100644
--- a/src/Renderer/Toolbar/Columns.js
+++ b/src/Renderer/Toolbar/Columns.js
@@ -18,9 +18,9 @@ class Columns extends Component {
const { columnUpdater } = this.props;
if(event.target.checked) {
- columnUpdater({ type: 'add', index })
+ columnUpdater({ type: 'add', index });
} else {
- columnUpdater({ type: 'remove', index })
+ columnUpdater({ type: 'remove', index });
}
}
@@ -40,7 +40,7 @@ class Columns extends Component {
// this.manageEvents(true);
// }
//
- this.setState({ open: !open })
+ this.setState({ open: !open });
}
manageEvents(remove = false) {
diff --git a/src/Renderer/Toolbar/MassActions.js b/src/Renderer/Toolbar/MassActions.js
index b37164e..a8fc38a 100644
--- a/src/Renderer/Toolbar/MassActions.js
+++ b/src/Renderer/Toolbar/MassActions.js
@@ -23,7 +23,7 @@ class MassActions extends Component {
toggle( e ) {
const { open } = this.state;
- this.setState({ open: !open })
+ this.setState({ open: !open });
}
manageEvents(remove = false) {
@@ -69,8 +69,8 @@ class MassActions extends Component {
)}
- )
+ );
}
}
-export default MassActions
+export default MassActions;
diff --git a/src/Renderer/Toolbar/ResetFilters.js b/src/Renderer/Toolbar/ResetFilters.js
index 625d254..c10af2a 100644
--- a/src/Renderer/Toolbar/ResetFilters.js
+++ b/src/Renderer/Toolbar/ResetFilters.js
@@ -3,12 +3,12 @@ import { SET_FILTER } from '../../actions';
import Button from '../../components/Button';
const ResetFilters = ({ itemConfig, action }) => {
- const clearFilter = () => action(SET_FILTER)({ clear: true })
+ const clearFilter = () => action(SET_FILTER)({ clear: true });
return (
{ itemConfig.label || 'Reset Filters' }
- )
+ );
};
export default ResetFilters;
diff --git a/src/TableProvider.js b/src/TableProvider.js
index 7503c49..585136d 100644
--- a/src/TableProvider.js
+++ b/src/TableProvider.js
@@ -3,36 +3,40 @@ import _ from 'lodash';
const ConfigContext = React.createContext({});
-const TableProvider = ({ config, children }) => {
- return { children }
-}
+const TableProvider = ({ config, children }) => (
+ { children }
+);
-export const TableConsumer = ({ children }) =>
+export const TableConsumer = ({ children }) => (
- { config => (
+ { (config) => (
children({ config })
)}
+);
export const withTableConfig = ( paths ) => ( WrappedComponent ) => {
- const ComponentWithConfig = ( props ) =>
+ const ComponentWithConfig = ( props ) => (
- { config => {
+ { (config) => {
var tableConfig = {};
if(_.isObject(paths)) {
- _.forEach(paths, function( value, key ) {
- tableConfig[key] = _.get(config.config, value, undefined)
+ _.forEach(paths, ( value, key ) => {
+ tableConfig = {
+ ...tableConfig,
+ [key]: _.get(config.config, value)
+ };
});
} else {
tableConfig = paths ? _.get(config.config, paths, false) : config;
}
- return
+ return ;
} }
+ );
return ComponentWithConfig;
-}
-
+};
export default TableProvider;
diff --git a/src/components/Button.js b/src/components/Button.js
index d4e03d4..59102ff 100644
--- a/src/components/Button.js
+++ b/src/components/Button.js
@@ -46,7 +46,7 @@ const Button = styled.button `
border-left: 0.3rem solid transparent;
margin-left: 0.255rem;
}
- `}
+ `};
${!disabled && !active && css `
cursor: pointer;
@@ -55,17 +55,17 @@ const Button = styled.button `
color: ${hover.color || '#fff'};
background-color: ${hover.backgroundColor || '#5a6268'};
}
- `}
+ `};
${active && css `
background: ${props => props.activeBackground || '#007bff'};
color: ${props => props.activeColor || '#fff'};
- font-weight: ${props => props.activeFontWeight || 'normal'}
- `}
+ font-weight: ${props => props.activeFontWeight || 'normal'};
+ `};
${disabled && css `
opacity: 0.5;
- `}
+ `};
`}
`;
diff --git a/src/components/Container.js b/src/components/Container.js
index b0f66b7..9b5e154 100644
--- a/src/components/Container.js
+++ b/src/components/Container.js
@@ -10,7 +10,7 @@ const Container = styled.div `
clear: both;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial,
sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
-`
+`;
const ExtendedContainer = styled(Container)(getExtendedStyles());
export default ExtendedContainer;
diff --git a/src/components/Dropdown.js b/src/components/Dropdown.js
index f136804..70371a1 100644
--- a/src/components/Dropdown.js
+++ b/src/components/Dropdown.js
@@ -3,7 +3,7 @@ import styled, { css } from 'styled-components';
const Container = styled.div `
position: relative;
-`
+`;
export const Menu = styled.div `
position: absolute;
@@ -32,11 +32,8 @@ export const Menu = styled.div `
background-color: ${backgroundColor};
border: ${border};
border-radius: ${borderRadius};
- ${hidden
- ? `display: none`
- : `display: block`
- }
- `}
+ ${hidden ? 'display: none' : 'display: block' };
+ `};
`;
export const Item = styled.div `
@@ -71,13 +68,13 @@ export const Item = styled.div `
text-decoration: none;
color: ${active.color || '#fff'};
background-color: ${active.backgroundColor || '#007bff'};
- `}
+ `};
${isDisabled && disabled && `
color: ${disabled.color || '#6c757d'};
background-color: transparent;
- `}
- `}
+ `};
+ `};
`;
diff --git a/src/components/ExtendedDiv.js b/src/components/ExtendedDiv.js
index 15ed0e5..1f25373 100644
--- a/src/components/ExtendedDiv.js
+++ b/src/components/ExtendedDiv.js
@@ -2,5 +2,5 @@ import React from 'react';
import styled from 'styled-components';
import { getExtendedStyles } from '../utils';
-const ExtendedDiv = styled.div(getExtendedStyles())
+const ExtendedDiv = styled.div(getExtendedStyles());
export default ExtendedDiv;
diff --git a/src/components/Field.js b/src/components/Field.js
index 6e99eb9..8ccb83d 100644
--- a/src/components/Field.js
+++ b/src/components/Field.js
@@ -26,19 +26,19 @@ const formControl = ({
&:focus {
box-shadow: ${focusShadow || 'none'};
border-color: ${focusBorderColor || '#80bdff'}
- }
-`
+ };
+`;
const Input = styled.input `
- ${props => formControl(props)}
-`
+ ${props => formControl(props)};
+`;
const Select = styled.select `
- ${props => formControl(props)}
+ ${props => formControl(props)};
width: ${props => props.width || '100%'};
-`
+`;
export default {
Select,
Input
-}
+};
diff --git a/src/components/Label.js b/src/components/Label.js
index 18c0ccd..f661fff 100644
--- a/src/components/Label.js
+++ b/src/components/Label.js
@@ -5,9 +5,9 @@ const Label = styled.label `
display: inline-block;
line-height: 2.5;
${({ flex, noWrap }) => css `
- ${flex && `display: flex`};
- ${noWrap && `white-space: nowrap`};
- `}
-`
+ ${flex && 'display: flex'};
+ ${noWrap && 'white-space: nowrap'};
+ `};
+`;
export default Label;
diff --git a/src/components/Pagination.js b/src/components/Pagination.js
index ddd655b..e2ba24d 100644
--- a/src/components/Pagination.js
+++ b/src/components/Pagination.js
@@ -14,15 +14,15 @@ const Item = styled.div `
${props => props.first && css `
margin-left: 0;
- `}
-`
+ `};
+`;
const ExtendedItem = styled(Item)(getExtendedStyles());
const isVisible = (visible, position) => (
visible === true || (
typeof visible === 'object' && (
- visible[position] === true || visible[position] === undefined
+ visible[position] === true || typeof visible[position] === 'undefined'
)
)
);
@@ -31,21 +31,21 @@ export const calculatePaginationProps = (
{ page, limit = 0, count = 0 },
defaultLimit = 10
) => {
- page = page > 1 ? page : 1
- limit = limit != 0 ? limit : defaultLimit;
+ page = page > 1 ? page : 1;
+ limit = limit !== 0 ? limit : defaultLimit;
- let start = (page - 1) * limit
- let end = start + limit - 1
+ let start = (page - 1) * limit;
+ let end = start + limit - 1;
return {
- page: page,
- start: start,
+ page,
+ start,
end: (count > end && end >= 0) ? end : count,
- count: count,
- limit: limit,
+ count,
+ limit,
total: Math.ceil(count / limit)
- }
-}
+ };
+};
const Pagination = ({
children,
@@ -73,15 +73,15 @@ const Pagination = ({
>
{ children(items[key], paginationProps, index) }
- )
+ );
})}
- )
-}
+ );
+};
const StyledPagination = styled(Pagination) `
display: block;
width: 100%;
-`
+`;
const ExtendedStyledPagination = styled(StyledPagination)(getExtendedStyles('container'));
export default ExtendedStyledPagination;
diff --git a/src/components/Row.js b/src/components/Row.js
index 815de64..7e11f6b 100644
--- a/src/components/Row.js
+++ b/src/components/Row.js
@@ -13,7 +13,7 @@ const Row = styled.div.attrs(({ top }) => ({
${props => props.even && css `
background: ${props.evenBackground || 'none'};
- `}
-`
+ `};
+`;
export default Row;
diff --git a/src/components/SortCaret.js b/src/components/SortCaret.js
index 459512e..e330ddb 100644
--- a/src/components/SortCaret.js
+++ b/src/components/SortCaret.js
@@ -1,7 +1,7 @@
import React from 'react';
import styled, { css } from 'styled-components';
-const SortCaret = styled.div `
+const SortCaret = styled.span `
display: inline-block;
width: 0;
height: 0;
@@ -15,7 +15,7 @@ const SortCaret = styled.div `
border-right: 4px solid transparent;
border-bottom: 4px solid #000000;
border-left: 4px solid transparent;
- `}
+ `};
${props => props.dir === 'desc' && css `
vertical-align: super;
@@ -23,7 +23,7 @@ const SortCaret = styled.div `
border-right: 4px solid transparent;
border-bottom: none;
border-left: 4px solid transparent;
- `}
-`
+ `};
+`;
export default SortCaret;
diff --git a/src/components/Table.js b/src/components/Table.js
index 0c027fb..dcc43ca 100644
--- a/src/components/Table.js
+++ b/src/components/Table.js
@@ -10,7 +10,7 @@ const Table = styled.div `
border-collapse: collapse;
clear: both;
margin: 10px 0;
-`
+`;
const ExtendedTable = styled(Table)(getExtendedStyles());
export default ExtendedTable;
diff --git a/src/components/Tbody.js b/src/components/Tbody.js
index 7dafddd..355ec7c 100644
--- a/src/components/Tbody.js
+++ b/src/components/Tbody.js
@@ -32,14 +32,13 @@ const Tbody = React.forwardRef(({
{ slicedData.map((item, index) => {
let currentIndex = startIndex + index;
- return children({ item, top: currentIndex * rowHeight, index: currentIndex })
+ return children({ item, top: currentIndex * rowHeight, index: currentIndex });
})}
);
});
-
const StyledTbody = styled(Tbody).attrs(({ height }) => ({
style: { height }
})) `
@@ -49,6 +48,6 @@ const StyledTbody = styled(Tbody).attrs(({ height }) => ({
overflow-y: scroll;
overflow-x: scroll;
border-bottom: 1px solid #ddd;
-`
-const ExtendedStyledTbody = styled(StyledTbody)(getExtendedStyles())
+`;
+const ExtendedStyledTbody = styled(StyledTbody)(getExtendedStyles());
export default ExtendedStyledTbody;
diff --git a/src/components/Td.js b/src/components/Td.js
index 9c16f8d..5c9a514 100644
--- a/src/components/Td.js
+++ b/src/components/Td.js
@@ -18,7 +18,7 @@ const Td = styled.div.attrs(({ width: maxWidth }) => ({
position: relative;
overflow: hidden;
font-size: 14px;
-`
+`;
-const ExtendedTd = styled(Td)(getExtendedStyles())
+const ExtendedTd = styled(Td)(getExtendedStyles());
export default ExtendedTd;
diff --git a/src/components/Th.js b/src/components/Th.js
index 5583774..2b524b1 100644
--- a/src/components/Th.js
+++ b/src/components/Th.js
@@ -1,5 +1,5 @@
import React from 'react';
-import styled from 'styled-components';
+import styled, { css } from 'styled-components';
import { getExtendedStyles } from '../utils';
import Td from './Td';
@@ -8,7 +8,14 @@ const Th = styled(Td) `
font-weight: bold;
background: #f9fafb;
border-bottom: 1px solid rgba(34, 36, 38, .1);
- cursor: ${props => props.sortable ? 'pointer': 'default'};
-`
-const ExtendedTh = styled(Th)(getExtendedStyles())
+
+ ${props => props.sortable && css `
+ cursor: pointer;
+
+ & > label {
+ cursor: pointer;
+ }
+ `};
+`;
+const ExtendedTh = styled(Th)(getExtendedStyles());
export default ExtendedTh;
diff --git a/src/components/Thead.js b/src/components/Thead.js
index ecaa635..98b8e28 100644
--- a/src/components/Thead.js
+++ b/src/components/Thead.js
@@ -16,7 +16,7 @@ const StyledThead = styled(Thead) `
margin-left: auto;
overflow: hidden;
border-bottom: 1px solid #ddd;
-`
+`;
const ExtendedStyledThead = styled(StyledThead)(getExtendedStyles());
export default ExtendedStyledThead;
diff --git a/src/components/Toolbar.js b/src/components/Toolbar.js
index fc6e82a..0fd8603 100644
--- a/src/components/Toolbar.js
+++ b/src/components/Toolbar.js
@@ -5,15 +5,15 @@ import { getExtendedStyles, getStyles } from '../utils';
const Row = styled.div `
display: inline-block;
width: 100%;
-`
-const ExtendedRow = styled(Row)(getExtendedStyles())
+`;
+const ExtendedRow = styled(Row)(getExtendedStyles());
const Item = styled.div `
display: block;
width: auto;
float: left;
-`
-const ExtendedItem = styled(Item)(getExtendedStyles())
+`;
+const ExtendedItem = styled(Item)(getExtendedStyles());
const toolbarItem = ( children, item, index, first, last, styles ) => {
const { visible } = item;
@@ -22,7 +22,7 @@ const toolbarItem = ( children, item, index, first, last, styles ) => {
{ visible !== false && children(item, index) }
);
-}
+};
const Toolbar = ({
className,
diff --git a/src/components/Tr.js b/src/components/Tr.js
index b6896ab..6e2814c 100644
--- a/src/components/Tr.js
+++ b/src/components/Tr.js
@@ -20,7 +20,6 @@ const StyledTr = styled(Tr).attrs(({ top }) => ({
position: relative;
background: none;
position: ${props => props.position || 'relative'};
-
-`
-const ExtendedStyledTr = styled(StyledTr)(getExtendedStyles())
+`;
+const ExtendedStyledTr = styled(StyledTr)(getExtendedStyles());
export default ExtendedStyledTr;
diff --git a/src/constants.js b/src/constants.js
index cb5f77d..a7c3532 100644
--- a/src/constants.js
+++ b/src/constants.js
@@ -4,4 +4,4 @@ export const OPERATOR = {
NOT_IN: 'not_in',
BETWEEN: 'between',
CONTAINS: 'contains'
-}
+};
diff --git a/src/createTable.js b/src/createTable.js
index 5641ed3..211d6f4 100755
--- a/src/createTable.js
+++ b/src/createTable.js
@@ -1,7 +1,8 @@
import _ from 'lodash';
import React, { useState, useEffect, useReducer, useRef } from 'react';
import ReactDOM from 'react-dom';
-import { connect } from "react-redux";
+import { connect } from 'react-redux';
+import { denormalize } from 'normalizr';
import TableProvider from './TableProvider';
import Renderer from './Renderer';
@@ -35,7 +36,7 @@ const useTableScroll = ( tableBody, tableHeader ) => {
tableHeader.current.scrollLeft = tableBody.current.scrollLeft;
setPointerEvents('none');
setTop(tableBody.current.scrollTop);
- }
+ };
useEffect(() => {
if(typeof tableBody.current.addEventListener === 'function') {
@@ -43,23 +44,23 @@ const useTableScroll = ( tableBody, tableHeader ) => {
}
return () => {
tableBody.current.removeEventListener('scroll', handleScroll, true);
- }
- }, [ tableBody.current ])
+ };
+ }, [ tableBody.current ]);
return [ top, pointerEvents ];
-}
+};
const columnsReducer = (state, { type, index }) => {
- var visibleColumns = [ ...state ];
+ var visibleColumnIds = [ ...state ];
if(type === 'add') {
- visibleColumns.push(index);
- visibleColumns.sort();
+ visibleColumnIds.push(index);
+ visibleColumnIds.sort();
} else {
- visibleColumns.splice(visibleColumns.indexOf(index), 1).sort();
+ visibleColumnIds.splice(visibleColumnIds.indexOf(index), 1).sort();
}
- return visibleColumns;
-}
+ return visibleColumnIds;
+};
const useTableWidth = ( tableBody, minWidth, visibleColumns ) => {
const [ width, setWidth ] = useState(minWidth);
@@ -72,15 +73,15 @@ const useTableWidth = ( tableBody, minWidth, visibleColumns ) => {
: tableBodyEl.clientWidth;
const percentage = computedTableWidth / calculateWidth(visibleColumns);
- setWidth(calculateWidth(visibleColumns, percentage))
+ setWidth(calculateWidth(visibleColumns, percentage));
setWidthAdjustment(percentage);
- }
+ };
useEffect(() => {
window.addEventListener('resize', updateTableDimensions);
return () => {
window.removeEventListener('resize', updateTableDimensions);
- }
+ };
}, []);
useEffect(() => {
@@ -88,16 +89,16 @@ const useTableWidth = ( tableBody, minWidth, visibleColumns ) => {
}, [ visibleColumns ]);
return [ width, widthAdjustment ];
-}
+};
const changeSortOrder = ( query, colName, sorter ) => {
let dir = null;
- if( query.sort != colName ) {
+ if( query.sort !== colName ) {
dir = 'asc';
} else {
- if(query.dir == 'asc') {
+ if(query.dir === 'asc') {
dir = 'desc';
- } else if(query.dir == 'desc') {
+ } else if(query.dir === 'desc') {
colName = '';
dir = '';
} else {
@@ -106,7 +107,15 @@ const changeSortOrder = ( query, colName, sorter ) => {
}
sorter({ sort: colName, dir });
-}
+};
+
+const prepareData = ( item, schema, state ) => {
+ if (_.isEmpty(schema) || _.isObject(item)) {
+ return item;
+ }
+
+ return denormalize(item, schema, state);
+};
const renderToolbar = ( config = [], action, thunk, columnUpdater, columns, visibleColumns, styles = {} ) => (
@@ -157,10 +166,10 @@ const getExtraBodyRowProps = (data, columns) => (
return edResult;
}, {})
: { [extraData]: _.get(data, extraData) }
- : {}
+ : {};
return result;
}, {})
-)
+);
const renderTable = ({
action,
@@ -170,6 +179,9 @@ const renderTable = ({
items,
query = {},
rowHeight,
+ schema,
+ state = {},
+ styles = {},
tableHeader,
tableBody,
thunk,
@@ -177,7 +189,6 @@ const renderTable = ({
visibleHeight,
width,
widthAdjustment = 1,
- styles = {}
}) => (
@@ -192,12 +203,14 @@ const renderTable = ({
width={ width * widthAdjustment }
textAlign={ textAlign }
styles={ styles.th }
- onClick={ sortable ? changeSortOrder.bind(this, query, name, action(SET_SORT)) : undefined }
+ onClick={ sortable ? changeSortOrder.bind(this, query, name, action(SET_SORT)) : null }
>
- { label }
- { sortable && sort === name && }
+
+ { label }
+ { sortable && sort === name && }
+
- )
+ );
}}
@@ -220,7 +233,7 @@ const renderTable = ({
/>
}
- )
+ );
}}
@@ -235,53 +248,62 @@ const renderTable = ({
rowHeight={ rowHeight }
styles={ getStyles(styles, 'tbody') }
>
- {({ item, top, index: rowIndex }) => (
-
- {(column, index) => {
- const { width, textAlign, name, type } = column;
- return (
-
-
-
-
-
- );
- }}
-
- )}
+ {({ item, top, index: rowIndex }) => {
+ var data = prepareData(item, schema, state);
+ return (
+
+ {(column, index) => {
+ const { width, textAlign, name, type } = column;
+ return (
+
+
+
+
+
+ );
+ }}
+
+ );
+ }}
-)
+);
const ReduxDatatable = ( props ) => {
- const { config = {}, reducerName, tableData, action, thunk, loadData } = props;
- const [ visibleColumns, dispatch ] = useReducer(columnsReducer, _.range(config.columns.length));
- const { toolbar = [], pagination = {}, filterable, headers, height, rowHeight, styles = {}, columns } = config;
+ const { config = {}, reducerName, tableData, action, thunk, loadData, state } = props;
+ const [ visibleColumnIds, dispatch ] = useReducer(columnsReducer, _.range(config.columns.length));
+ const { toolbar = [], pagination = {}, filterable, headers, height, rowHeight, styles = {}, columns, entity = {} } = config;
+
+ const visibleColumns = visibleColumnIds.reduce((result, currentIndex) => {
+ const { [currentIndex]: column } = columns;
+ return [ ...result, column ];
+ }, []);
+
const tableConfig = {
...config,
updateTableState: dispatch,
- visibleColumns: visibleColumns.reduce((result, currentIndex) => [ ...result, columns[currentIndex]], [])
+ visibleColumns
};
useEffect(() => {
@@ -295,13 +317,13 @@ const ReduxDatatable = ( props ) => {
// Set min-width of the table
const [ minWidth ] = useState(calculateWidth(columns));
// Handle table columns and width
- const [ width, widthAdjustment ] = useTableWidth(tableBody, minWidth, tableConfig.visibleColumns);
+ const [ width, widthAdjustment ] = useTableWidth(tableBody, minWidth, visibleColumns);
if(!tableData) {
return (
- The table failed to initialise. Please check you are connected to the internet and try again.
+ The table failed to initialise. Please make sure you are connected to the internet and try again.
);
@@ -311,17 +333,20 @@ const ReduxDatatable = ( props ) => {
return (
- { renderToolbar(toolbar, action, thunk, dispatch, columns, visibleColumns, styles.toolbar) }
+ { renderToolbar(toolbar, action, thunk, dispatch, columns, visibleColumnIds, styles.toolbar) }
{ renderPagination('top', query, pagination, action, thunk, styles.pagination) }
{ renderTable({
action,
bodyExtraData: getExtraBodyRowProps(tableData, tableConfig.visibleColumns),
- columns: tableConfig.visibleColumns,
+ columns: visibleColumns,
height: rowHeight * ( tableData.items || [] ).length,
items: tableData.items || [],
pointerEvents,
query,
rowHeight,
+ schema: entity.schema,
+ state,
+ styles,
tableHeader,
tableBody,
thunk,
@@ -329,28 +354,29 @@ const ReduxDatatable = ( props ) => {
visibleHeight: height,
width,
widthAdjustment,
- styles
}) }
{ renderPagination('bottom', query, pagination, action, thunk, styles.pagination) }
);
-}
+};
-const prepareActionPayload = ({ reducerName, config: { name, routes, entity }}) =>
+const prepareActionPayload = ({ reducerName, config: { name, routes, entity }}) => (
( payload = {} ) => ({ name, reducerName, routes, entity, payload })
+);
-const mapStateToProps = ( state, { reducerName, config: { name } } ) => ({
- tableData: state[reducerName][name]
+const mapStateToProps = ( state, { reducerName, config: { name, entity } } ) => ({
+ tableData: state[reducerName][name],
+ state
});
const mapDispatchToProps = ( dispatch, ownProps ) => {
let preparePayload = prepareActionPayload(ownProps);
return {
loadData: ( ) => {
- dispatch(setPage(preparePayload({ page: 1 })))
- dispatch(setLimit(preparePayload({ limit: ownProps.config.pagination.items.limiter.default || 10 })))
- dispatch(setSort(preparePayload({ dir: 'desc' })))
+ dispatch(setPage(preparePayload({ page: 1 })));
+ dispatch(setLimit(preparePayload({ limit: ownProps.config.pagination.items.limiter.default || 10 })));
+ dispatch(setSort(preparePayload({ dir: 'desc' })));
},
action: ( type ) => ( payload ) => dispatch(createActionCreator(type)(preparePayload(payload))),
thunk: ( thunk, payload ) => dispatch(thunk(preparePayload(payload)))
diff --git a/src/epics.js b/src/epics.js
index db11d94..0ef49bd 100644
--- a/src/epics.js
+++ b/src/epics.js
@@ -25,7 +25,7 @@ const getResult = (response, resultPath) => resultPath
export const setParamsEpic = ( action$, state$ ) => action$.pipe(
ofType(SET_PAGE, SET_FILTER, SET_SORT, SET_LIMIT),
- concatMap(action => {
+ concatMap((action) => {
const { meta: { name, routes, reducerName, entity } } = action;
return of(
@@ -33,13 +33,13 @@ export const setParamsEpic = ( action$, state$ ) => action$.pipe(
requestData({
name, routes, reducerName, entity, payload: { query: _.get(state$.value, [reducerName, name]).query }
})
- )
+ );
})
);
export const fetchDataEpic = ( action$, state$, { api }) => action$.pipe(
ofType(REQUEST_DATA),
- switchMap(action => {
+ switchMap((action) => {
const {
meta: { name, routes, entity },
payload
@@ -51,7 +51,7 @@ export const fetchDataEpic = ( action$, state$, { api }) => action$.pipe(
...payload.query
}
}).pipe(
- map(response => {
+ map((response) => {
if(entity) {
const normalizedData = normalize(response, entity.responseSchema);
if(!_.isEmpty(normalizedData.entities)) {
@@ -63,26 +63,26 @@ export const fetchDataEpic = ( action$, state$, { api }) => action$.pipe(
const data = getResult(response, _.get(routes, 'get.resultPath.data', null));
return { response, data };
}),
- map(payload => receiveData({ name, payload })),
- catchError(error => of(createNotification({ type: NOTIFICATION_TYPE_ERROR, message: error.message }))),
+ map((payload) => receiveData({ name, payload })),
+ catchError((error) => of(createNotification({ type: NOTIFICATION_TYPE_ERROR, message: error.message }))),
takeUntil(action$.pipe(
ofType(REQUEST_DATA_CANCEL),
- filter(cancelAction => cancelAction.name == name)
+ filter((cancelAction) => cancelAction.name === name)
))
- )
+ );
})
);
export const deleteDataEpic = ( action$, state$, { api }) => action$.pipe(
ofType(DELETE_DATA),
- switchMap(action => {
+ switchMap((action) => {
const {
meta: { name, routes, reducerName, entity },
payload
} = action;
return api.delete(routes.delete.route, { params: payload.params }).pipe(
- concatMap(response => {
+ concatMap((response) => {
if(!response.success) {
return of(createNotification({ type: NOTIFICATION_TYPE_ERROR, message: response.result }));
}
@@ -96,7 +96,7 @@ export const deleteDataEpic = ( action$, state$, { api }) => action$.pipe(
})
);
}),
- catchError(error => of(createNotification({ type: NOTIFICATION_TYPE_ERROR, message: error.message })))
- )
+ catchError((error) => of(createNotification({ type: NOTIFICATION_TYPE_ERROR, message: error.message })))
+ );
})
-)
+);
diff --git a/src/index.js b/src/index.js
index 5026327..38e0b9f 100755
--- a/src/index.js
+++ b/src/index.js
@@ -5,5 +5,5 @@ import TableProvider, { TableConsumer, withTableConfig } from './TableProvider';
import * as actions from './actions';
import * as utils from './utils';
-export { TableProvider, TableConsumer, withTableConfig, actions, utils, reducer, epics }
+export { TableProvider, TableConsumer, withTableConfig, actions, utils, reducer, epics };
export default ReduxDatatable;
diff --git a/src/reducer.js b/src/reducer.js
index b206538..1772879 100644
--- a/src/reducer.js
+++ b/src/reducer.js
@@ -17,84 +17,75 @@ let initialTableState = {
search: {}
},
selection: {}
-}
+};
const updateState = ( state, tableName ) => ( newState ) => {
- var updatedState = objectAssignDeep({}, initialTableState, state[tableName], newState);
+ const { [tableName]: tableState = {} } = state;
+ var updatedState = objectAssignDeep({}, initialTableState, tableState, newState);
return {
...state,
[tableName]: {
- ...state[tableName],
+ ...tableState,
...updatedState
}
- }
-}
+ };
+};
const getTableState = ( name ) => ( state ) => {
- return state[name] ? state[name] : initialTableState;
-}
+ const { [name]: tableState } = state;
+ return tableState || initialTableState;
+};
export default function reducer(state = {}, action) {
- if(!action.meta) {
+ if (!action.meta) {
return state;
}
const { payload, meta: { name } } = action;
- const tableState = getTableState(name);
+ const tableState = getTableState(name)(state);
const stateUpdater = updateState(state, name);
-
- switch (action.type) {
- case actions.REQUEST_DATA:
- return stateUpdater({ isFetching: true });
-
- case actions.REQUEST_DATA_CANCEL:
- return stateUpdater({ isFetching: false });
-
- case actions.RECEIVE_DATA:
- return stateUpdater({
- isFetching: false,
- query: {
- count: parseInt(payload.response.total)
- },
- items: payload.data,
- selection: {}
- });
-
- case actions.SET_PAGE:
- let offset = ( (payload.page - 1) * tableState(state).query.limit );
+ const acceptedActions = {
+ [actions.REQUEST_DATA]: () => stateUpdater({ isFetching: true }),
+ [actions.REQUEST_DATA_CANCEL]: () => stateUpdater({ isFetching: false }),
+ [actions.RECEIVE_DATA]: () => stateUpdater({
+ isFetching: false,
+ query: {
+ count: parseInt(payload.response.total, 10)
+ },
+ items: payload.data,
+ selection: {}
+ }),
+ [actions.SET_PAGE]: () => {
+ let offset = ( (payload.page - 1) * tableState.query.limit );
offset = offset > 0 ? offset : 0;
return stateUpdater({
isFetching: true,
query: {
page: payload.page,
- offset: offset
+ offset
},
});
-
- case actions.SET_SORT:
- return stateUpdater({
- isFetching: true,
- query: {
- sort: payload.sort,
- dir: payload.dir
- },
- });
-
- case actions.SET_LIMIT:
- return stateUpdater({
- isFetching: true,
- query: {
- limit: parseInt(payload.limit),
- offset: (tableState(state).query.page - 1) * tableState(state).query.limit
- },
- });
-
- case actions.SET_FILTER:
+ },
+ [actions.SET_SORT]: () => stateUpdater({
+ isFetching: true,
+ query: {
+ sort: payload.sort,
+ dir: payload.dir
+ },
+ }),
+ [actions.SET_LIMIT]: () => stateUpdater({
+ isFetching: true,
+ query: {
+ limit: parseInt(payload.limit, 10),
+ offset: (tableState.query.page - 1) * tableState.query.limit
+ },
+ }),
+ [actions.SET_FILTER]: () => {
var updatedFilters = {};
if(!payload.clear) {
updatedFilters = {
- ...state[name].query.search,
+ ...tableState.query.search,
[payload.key]: payload.filter
};
}
@@ -102,9 +93,9 @@ export default function reducer(state = {}, action) {
return {
...state,
[name]: {
- ...state[name],
+ ...tableState,
query: {
- ...state[name].query,
+ ...tableState.query,
search: {
...updatedFilters
}
@@ -112,15 +103,15 @@ export default function reducer(state = {}, action) {
isFetching: true
}
};
-
- case actions.SET_SELECTION:
+ },
+ [actions.SET_SELECTION]: () => {
let selection = {};
if( typeof payload.key == 'object') {
selection[payload.paramKey] = payload.key;
} else {
- selection = _.get(tableState(state), 'selection', {});
+ selection = _.get(tableState, 'selection', {});
if(_.isEmpty(selection[payload.paramKey])) {
- selection[payload.paramKey] = {}
+ selection[payload.paramKey] = {};
}
selection[payload.paramKey][payload.key] = payload.value;
}
@@ -128,33 +119,19 @@ export default function reducer(state = {}, action) {
return {
...state,
[name]: {
- ...state[name],
+ ...tableState,
selection: {
- ...state[name].selection,
+ ...tableState.selection,
...selection
}
}
- }
-
- // return stateUpdater({
- // selection: {
- // [payload.paramKey]: {
- // ...selection
- // }
- // }
- // });
- // return {
- // ...state,
- // selection: {
- // ...state.selection,
- // [payload.paramKey]: {
- // ...state.selection[payload.paramKey],
- // ...selection
- // }
- // }
- // }
+ };
+ }
+ };
- default:
- return state;
+ if (acceptedActions.hasOwnProperty(action.type)) {
+ return acceptedActions[action.type]();
}
+
+ return state;
}
diff --git a/src/utils.js b/src/utils.js
index c8d561c..9610380 100755
--- a/src/utils.js
+++ b/src/utils.js
@@ -8,88 +8,95 @@ export const defaultLimiterCongig = {
export const isArray = (value) => Array.isArray(value);
-export const getUrl = ( baseUrl, endpoint ) => baseUrl + endpoint;
+export const getUrl = (baseUrl, endpoint) => baseUrl + endpoint;
-export const getSelectedKeys = ( data, dataKey ) => {
- if( !data[dataKey] ) {
+export const getSelectedKeys = (data, dataKey) => {
+ const { [dataKey]: dataForFilter } = data;
+ if (dataForFilter) {
return false;
}
- let selectedItems = {};
- selectedItems[dataKey] = Object.keys(data[dataKey])
- .filter(key => {
- if(data[dataKey][key] == true) return key
- });
+ let selectedItems = {
+ [dataKey]: Object.keys(dataForFilter).filter((key) => {
+ const { [key]: value } = dataForFilter;
+ return value === true;
+ })
+ };
const paramsObject = Object.assign({}, selectedItems);
paramsObject.get = () => selectedItems;
paramsObject.toString = () => qs.stringify(selectedItems);
return paramsObject;
-}
+};
-export const getConfigParam = ( param ) => {
- if( !param.startsWith('@') ) {
+export const getConfigParam = (param) => {
+ if (!param.startsWith('@')) {
return false;
}
return param.substr(1);
};
-export const getParam = ( param, data ) => {
+export const getParam = (param, data) => {
var dataKey = getConfigParam(param);
- if( !dataKey ) {
- return false;
- }
-
- if(!data[dataKey]) {
+ if (!dataKey) {
return false;
}
- return data[dataKey];
-}
+ const { [dataKey]: paramData } = data;
+ return paramData || false;
+};
-export const paramsResolver = ( params, data ) => {
+export const paramsResolver = (params, data) => {
let processedParams = {};
- for(var key in params) {
- let resolvedParam = getParam(params[key], data);
- if( false === resolvedParam ) {
- continue;
+ for (var key in params) {
+ if (params.hasOwnProperty(key)) {
+ const { [key]: param } = params;
+ let resolvedParam = getParam(param, data);
+ if (false === resolvedParam) {
+ continue;
+ }
+
+ processedParams = {
+ ...processedParams,
+ [key]: resolvedParam
+ };
}
-
- processedParams[key] = resolvedParam;
}
const paramsObject = Object.assign({}, processedParams);
paramsObject.get = () => processedParams;
- paramsObject.toString = () => qs.stringify(processedParams);;
+ paramsObject.toString = () => qs.stringify(processedParams);
return paramsObject;
-}
+};
-export const createActionCreator = ( type ) => ( data ) => {
+export const createActionCreator = (type) => (data) => {
const { name, reducerName, routes, entity, payload } = data;
let action = ({ type, meta: { name, routes, reducerName, entity }, payload });
action.toString = () => type;
return action;
-}
+};
export const createReducer = (reducer, predicate) => (state, action) => (
- predicate(action) || state === undefined ? reducer(state, action) : state
+ predicate(action) || typeof state === 'undefined' ? reducer(state, action) : state
);
-export const prepareActionPayload = ({ name, reducerName, routes, entity }) => ( payload = {} ) => ({
+export const prepareActionPayload = ({ name, reducerName, routes, entity }) => (payload = {}) => ({
name, reducerName, routes, entity, payload
-})
+});
-export const shouldUpdate = ( currentData, nextData, index ) => (
- _.get(currentData, index, '') != _.get(nextData, index, '')
-)
+export const getStyles = (styles = {}, name) => {
+ const { [name]: style } = styles;
+ return style;
+};
-export const getStyles = ( styles, name ) => (
- name && styles ? styles[name] : undefined
-)
+export const getExtendedStyles = (name) => ({ styles }) => {
+ if (!name) {
+ return styles;
+ }
-export const getExtendedStyles = ( name ) => ({ styles }) => (
- name ? styles ? styles[name] : undefined : styles
-)
+ const { [name]: style } = styles;
+ return style;
+};