mirror of
https://github.com/scinote-eln/scinote-web.git
synced 2024-11-11 10:06:53 +08:00
Merge pull request #773 from Ducz0r/lm-sci-1496
Add basic datatables & datagrid [SCI-1496]
This commit is contained in:
commit
5ab524dbd3
6 changed files with 313 additions and 4 deletions
|
@ -3,3 +3,7 @@ export const WHITE_COLOR = "#fff";
|
|||
export const BORDER_GRAY_COLOR = "#d2d2d2";
|
||||
export const WILD_SAND_COLOR = "#f5f5f5";
|
||||
export const MYSTIC_COLOR = "#eaeff2";
|
||||
|
||||
export const COLOR_ALTO = "#dddddd";
|
||||
export const COLOR_GRAY = "#909088";
|
||||
export const COLOR_ALABASTER = "#fcfcfc";
|
||||
|
|
149
app/javascript/packs/shared/data_grid/index.jsx
Normal file
149
app/javascript/packs/shared/data_grid/index.jsx
Normal file
|
@ -0,0 +1,149 @@
|
|||
import React, { Component } from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import ReactDataGrid from 'react-data-grid';
|
||||
import styled from "styled-components";
|
||||
import {
|
||||
WHITE_COLOR,
|
||||
COLOR_GRAY
|
||||
} from "../../app/constants/colors";
|
||||
|
||||
const StyledReactDataGrid = styled(ReactDataGrid)`
|
||||
background-color: inherit;
|
||||
|
||||
.react-grid-Grid {
|
||||
background-color: inherit;
|
||||
}
|
||||
|
||||
.react-grid-Header {
|
||||
.react-grid-HeaderCell {
|
||||
background-color: ${COLOR_GRAY};
|
||||
|
||||
color: ${WHITE_COLOR};
|
||||
font-weight: normal;
|
||||
vertical-align: bottom;
|
||||
|
||||
&:first-child {
|
||||
border-left: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.react-grid-Canvas {
|
||||
background-color: inherit;
|
||||
}
|
||||
`;
|
||||
|
||||
class DataGrid extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.cleanProps = this.cleanProps.bind(this);
|
||||
this.transformColumns = this.transformColumns.bind(this);
|
||||
this.setupDefaultProps = this.setupDefaultProps.bind(this);
|
||||
|
||||
this.transformColumns();
|
||||
this.setupDefaultProps();
|
||||
|
||||
// Store the original rows array, and make a copy that
|
||||
// can be used for modifying eg.filtering, sorting
|
||||
this.state = {
|
||||
originalRows: this.props.data,
|
||||
rows: this.props.data.slice(0)
|
||||
};
|
||||
}
|
||||
|
||||
setupDefaultProps() {
|
||||
// Setup the default props if they're not provided
|
||||
if ('rowGetter' in this.props) {
|
||||
this._rowGetter = this.props.rowGetter;
|
||||
} else {
|
||||
this._rowGetter = ((i) => this.state.rows[i]);
|
||||
}
|
||||
this._rowGetter = this._rowGetter.bind(this);
|
||||
|
||||
if ('rowsCount' in this.props) {
|
||||
this._rowsCount = this.props.rowsCount;
|
||||
} else {
|
||||
this._rowsCount = this.props.data.length;
|
||||
}
|
||||
|
||||
if ('onGridSort' in this.props) {
|
||||
this._onGridSort = this.props.onGridSort;
|
||||
} else {
|
||||
this._onGridSort = ((sortColumn, sortDirection) => {
|
||||
const comparer = (a, b) => {
|
||||
if (sortDirection === 'ASC') {
|
||||
return (a[sortColumn] > b[sortColumn]) ? 1 : -1;
|
||||
} else if (sortDirection === 'DESC') {
|
||||
return (a[sortColumn] < b[sortColumn]) ? 1 : -1;
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
let rows;
|
||||
if (sortDirection === 'NONE') {
|
||||
rows = this.state.originalRows.slice(0);
|
||||
} else {
|
||||
rows = this.state.rows.sort(comparer);
|
||||
}
|
||||
|
||||
this.setState({ rows });
|
||||
});
|
||||
}
|
||||
this._onGridSort = this._onGridSort.bind(this);
|
||||
}
|
||||
|
||||
transformColumns() {
|
||||
// Transform columns from the "sciNote" representation into
|
||||
// ReactDataGrid-compatible representation
|
||||
this._columns =
|
||||
this.props.columns
|
||||
.sort((a, b) => a.position - b.position)
|
||||
.filter((col) => (!('visible' in col) || col.visible))
|
||||
.map((col) => ({
|
||||
key: col.textId,
|
||||
name: col.name,
|
||||
locked: col.locked,
|
||||
sortable: col.sortable
|
||||
}));
|
||||
}
|
||||
|
||||
cleanProps() {
|
||||
// Remove additional props from the props value
|
||||
const {
|
||||
columns, rowGetter, rowsCount, ...cleanProps
|
||||
} = this.props;
|
||||
return cleanProps;
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<StyledReactDataGrid
|
||||
columns={this._columns}
|
||||
rowGetter={this._rowGetter}
|
||||
rowsCount={this._rowsCount}
|
||||
onGridSort={this._onGridSort}
|
||||
{...this.cleanProps()}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
DataGrid.propTypes = {
|
||||
columns: PropTypes.arrayOf(
|
||||
PropTypes.shape({
|
||||
id: PropTypes.number.isRequired,
|
||||
isKey: PropTypes.bool.isRequired,
|
||||
textId: PropTypes.string.isRequired,
|
||||
name: PropTypes.string.isRequired,
|
||||
position: PropTypes.number.isRequired,
|
||||
visible: PropTypes.bool,
|
||||
sortable: PropTypes.bool,
|
||||
locked: PropTypes.bool
|
||||
})
|
||||
).isRequired,
|
||||
data: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||
rowGetter: PropTypes.func,
|
||||
rowsCount: PropTypes.number,
|
||||
onGridSort: PropTypes.func
|
||||
};
|
||||
|
||||
export default DataGrid;
|
111
app/javascript/packs/shared/data_table/index.jsx
Normal file
111
app/javascript/packs/shared/data_table/index.jsx
Normal file
|
@ -0,0 +1,111 @@
|
|||
import React, { Component } from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import { BootstrapTable, TableHeaderColumn } from 'react-bootstrap-table';
|
||||
import styled from "styled-components";
|
||||
import {
|
||||
WHITE_COLOR,
|
||||
COLOR_GRAY,
|
||||
COLOR_ALTO,
|
||||
COLOR_ALABASTER
|
||||
} from "../../app/constants/colors";
|
||||
|
||||
const StyledBootstrapTable = styled(BootstrapTable)`
|
||||
thead {
|
||||
background-color: ${COLOR_GRAY};
|
||||
|
||||
> tr > th,
|
||||
>tr > td {
|
||||
padding: 6px;
|
||||
padding-right: 30px;
|
||||
}
|
||||
|
||||
> tr > th {
|
||||
border-bottom: 2px solid ${COLOR_ALTO};
|
||||
border-bottom-width: 0;
|
||||
border-left: 2px solid ${COLOR_ALABASTER};
|
||||
color: ${WHITE_COLOR};
|
||||
font-weight: normal;
|
||||
vertical-align: bottom;
|
||||
|
||||
&:first-child {
|
||||
border-left: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
td, th {
|
||||
box-sizing: content-box;
|
||||
}
|
||||
|
||||
td {
|
||||
overflow-wrap: break-word;
|
||||
text-overflow: ellipsis;
|
||||
word-break: break-word;
|
||||
}
|
||||
`;
|
||||
|
||||
class DataTable extends Component {
|
||||
static cleanColumnAttributes(col) {
|
||||
// Remove additional attributes from the columns
|
||||
const {
|
||||
id, isKey, textId, name, position, visible,
|
||||
sortable, locked, ...cleanCol
|
||||
} = col;
|
||||
return cleanCol;
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.cleanProps = this.cleanProps.bind(this);
|
||||
this.displayHeader = this.displayHeader.bind(this);
|
||||
}
|
||||
|
||||
cleanProps() {
|
||||
// Remove additional props from the props value
|
||||
const {columns, ...cleanProps} = this.props;
|
||||
return cleanProps;
|
||||
}
|
||||
|
||||
|
||||
displayHeader() {
|
||||
const orderedCols = this.props.columns.sort((a, b) => a.position - b.position);
|
||||
return orderedCols.map((col) =>
|
||||
<TableHeaderColumn
|
||||
key={col.id}
|
||||
dataField={col.textId}
|
||||
isKey={col.isKey}
|
||||
hidden={('visible' in col) && !col.visible}
|
||||
dataSort={col.sortable}
|
||||
{...DataTable.cleanColumnAttributes(col)}
|
||||
>
|
||||
{col.name}
|
||||
</TableHeaderColumn>
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<StyledBootstrapTable {...this.cleanProps()}>
|
||||
{this.displayHeader()}
|
||||
</StyledBootstrapTable>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
DataTable.propTypes = {
|
||||
columns: PropTypes.arrayOf(
|
||||
PropTypes.shape({
|
||||
id: PropTypes.number.isRequired,
|
||||
isKey: PropTypes.bool.isRequired,
|
||||
textId: PropTypes.string.isRequired,
|
||||
name: PropTypes.string.isRequired,
|
||||
position: PropTypes.number.isRequired,
|
||||
visible: PropTypes.bool,
|
||||
sortable: PropTypes.bool,
|
||||
locked: PropTypes.bool
|
||||
})
|
||||
).isRequired,
|
||||
data: PropTypes.arrayOf(PropTypes.object).isRequired
|
||||
};
|
||||
|
||||
export default DataTable;
|
|
@ -1,4 +1,5 @@
|
|||
@import 'constants';
|
||||
@import '~react-bootstrap-table/dist/react-bootstrap-table.min';
|
||||
|
||||
body {
|
||||
background-color: $color-concrete;
|
||||
|
|
|
@ -76,6 +76,8 @@
|
|||
"styled-components": "^2.1.1",
|
||||
"webpack": "^3.2.0",
|
||||
"webpack-manifest-plugin": "^1.1.2",
|
||||
"webpack-merge": "^4.1.0"
|
||||
"webpack-merge": "^4.1.0",
|
||||
"react-bootstrap-table": "^4.0.0",
|
||||
"react-data-grid": "^2.0.2"
|
||||
}
|
||||
}
|
||||
|
|
48
yarn.lock
48
yarn.lock
|
@ -1281,7 +1281,7 @@ clap@^1.0.9:
|
|||
dependencies:
|
||||
chalk "^1.1.3"
|
||||
|
||||
classnames@^2.2.5:
|
||||
classnames@^2.1.2, classnames@^2.2.5:
|
||||
version "2.2.5"
|
||||
resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.5.tgz#fb3801d453467649ef3603c7d61a02bd129bde6d"
|
||||
|
||||
|
@ -1538,7 +1538,7 @@ create-hmac@^1.1.0, create-hmac@^1.1.2, create-hmac@^1.1.4:
|
|||
safe-buffer "^5.0.1"
|
||||
sha.js "^2.4.8"
|
||||
|
||||
create-react-class@^15.5.3, create-react-class@^15.6.0:
|
||||
create-react-class@^15.5.2, create-react-class@^15.5.3, create-react-class@^15.6.0:
|
||||
version "15.6.0"
|
||||
resolved "https://registry.yarnpkg.com/create-react-class/-/create-react-class-15.6.0.tgz#ab448497c26566e1e29413e883207d57cfe7bed4"
|
||||
dependencies:
|
||||
|
@ -1879,6 +1879,10 @@ electron-to-chromium@^1.2.7, electron-to-chromium@^1.3.14:
|
|||
version "1.3.15"
|
||||
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.15.tgz#08397934891cbcfaebbd18b82a95b5a481138369"
|
||||
|
||||
element-class@^0.2.0:
|
||||
version "0.2.2"
|
||||
resolved "https://registry.yarnpkg.com/element-class/-/element-class-0.2.2.tgz#9d3bbd0767f9013ef8e1c8ebe722c1402a60050e"
|
||||
|
||||
elliptic@^6.0.0:
|
||||
version "6.4.0"
|
||||
resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.4.0.tgz#cac9af8762c85836187003c8dfe193e5e2eae5df"
|
||||
|
@ -2211,6 +2215,10 @@ evp_bytestokey@^1.0.0:
|
|||
dependencies:
|
||||
create-hash "^1.1.1"
|
||||
|
||||
exenv@1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/exenv/-/exenv-1.2.0.tgz#3835f127abf075bfe082d0aed4484057c78e3c89"
|
||||
|
||||
exit-hook@^1.0.0:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/exit-hook/-/exit-hook-1.1.1.tgz#f05ca233b48c05d54fff07765df8507e95c02ff8"
|
||||
|
@ -4547,7 +4555,7 @@ prop-types-extra@^1.0.1:
|
|||
dependencies:
|
||||
warning "^3.0.0"
|
||||
|
||||
prop-types@^15.5.10, prop-types@^15.5.4, prop-types@^15.5.8:
|
||||
prop-types@^15.5.10, prop-types@^15.5.4, prop-types@^15.5.7, prop-types@^15.5.8:
|
||||
version "15.5.10"
|
||||
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.5.10.tgz#2797dfc3126182e3a95e3dfbb2e893ddd7456154"
|
||||
dependencies:
|
||||
|
@ -4651,6 +4659,15 @@ rc@^1.1.7:
|
|||
minimist "^1.2.0"
|
||||
strip-json-comments "~2.0.1"
|
||||
|
||||
react-bootstrap-table@^4.0.0:
|
||||
version "4.0.2"
|
||||
resolved "https://registry.yarnpkg.com/react-bootstrap-table/-/react-bootstrap-table-4.0.2.tgz#7e504141c8662fb203f0bcddab365c331b0e7106"
|
||||
dependencies:
|
||||
classnames "^2.1.2"
|
||||
prop-types "^15.5.10"
|
||||
react-modal "^1.4.0"
|
||||
react-s-alert "^1.3.0"
|
||||
|
||||
react-bootstrap@^0.31.1:
|
||||
version "0.31.1"
|
||||
resolved "https://registry.yarnpkg.com/react-bootstrap/-/react-bootstrap-0.31.1.tgz#679c9f73ae77ff207867d536496207291f3a3ed7"
|
||||
|
@ -4667,6 +4684,14 @@ react-bootstrap@^0.31.1:
|
|||
uncontrollable "^4.1.0"
|
||||
warning "^3.0.0"
|
||||
|
||||
react-data-grid@^2.0.2:
|
||||
version "2.0.58"
|
||||
resolved "https://registry.yarnpkg.com/react-data-grid/-/react-data-grid-2.0.58.tgz#83946bf9cc34d144552349c343e15888c2c6293c"
|
||||
|
||||
react-dom-factories@^1.0.0:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/react-dom-factories/-/react-dom-factories-1.0.1.tgz#c50692ac5ff1adb39d86dfe6dbe3485dacf58455"
|
||||
|
||||
react-dom@^15.6.1:
|
||||
version "15.6.1"
|
||||
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-15.6.1.tgz#2cb0ed4191038e53c209eb3a79a23e2a4cf99470"
|
||||
|
@ -4692,6 +4717,17 @@ react-intl@^2.3.0:
|
|||
intl-relativeformat "^1.3.0"
|
||||
invariant "^2.1.1"
|
||||
|
||||
react-modal@^1.4.0:
|
||||
version "1.9.7"
|
||||
resolved "https://registry.yarnpkg.com/react-modal/-/react-modal-1.9.7.tgz#07ef56790b953e3b98ef1e2989e347983c72871d"
|
||||
dependencies:
|
||||
create-react-class "^15.5.2"
|
||||
element-class "^0.2.0"
|
||||
exenv "1.2.0"
|
||||
lodash.assign "^4.2.0"
|
||||
prop-types "^15.5.7"
|
||||
react-dom-factories "^1.0.0"
|
||||
|
||||
react-overlays@^0.7.0:
|
||||
version "0.7.0"
|
||||
resolved "https://registry.yarnpkg.com/react-overlays/-/react-overlays-0.7.0.tgz#531898ff566c7e5c7226ead2863b8cf9fbb5a981"
|
||||
|
@ -4747,6 +4783,12 @@ react-router@^4.1.1:
|
|||
prop-types "^15.5.4"
|
||||
warning "^3.0.0"
|
||||
|
||||
react-s-alert@^1.3.0:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/react-s-alert/-/react-s-alert-1.3.0.tgz#d81224a474f15e89c35c0ea6c2a73f232a767128"
|
||||
dependencies:
|
||||
babel-runtime "^6.23.0"
|
||||
|
||||
react@^15.6.1:
|
||||
version "15.6.1"
|
||||
resolved "https://registry.yarnpkg.com/react/-/react-15.6.1.tgz#baa8434ec6780bde997cdc380b79cd33b96393df"
|
||||
|
|
Loading…
Reference in a new issue