diff --git a/app/javascript/packs/shared/data_grid/DataGrid.jsx b/app/javascript/packs/shared/data_grid/DataGrid.jsx
index 3f46438ad..00f6c6045 100644
--- a/app/javascript/packs/shared/data_grid/DataGrid.jsx
+++ b/app/javascript/packs/shared/data_grid/DataGrid.jsx
@@ -11,6 +11,53 @@ class DataGrid extends Component {
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() {
@@ -18,41 +65,21 @@ class DataGrid extends Component {
// ReactDataGrid-compatible representation
this._columns =
this.props.columns
- .sort((a, b) => b.position - a.position)
- .filter((col) => col.visible)
- .map((col) => {
- return {
- key: col.textId,
- name: col.name,
- locked: col.locked
- };
- });
- }
-
- setupDefaultProps() {
- // Setup the default props if they're not provided
- const self = this;
-
- if ('rowGetter' in this.props) {
- this._rowGetter = this.props.rowGetter;
- } else {
- this._rowGetter = function(i) {
- return this.props.data[i];
- }.bind(this);
- }
- if ('rowsCount' in this.props) {
- this._rowsCount = this.props.rowsCount;
- } else {
- this._rowsCount = this.props.data.length;
- }
+ .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 cleanProps = {...this.props};
- delete cleanProps.columns;
- delete cleanProps.rowGetter;
- delete cleanProps.rowsCount;
+ const {
+ columns, rowGetter, rowsCount, ...cleanProps
+ } = this.props;
return cleanProps;
}
@@ -62,6 +89,7 @@ class DataGrid extends Component {
columns={this._columns}
rowGetter={this._rowGetter}
rowsCount={this._rowsCount}
+ onGridSort={this._onGridSort}
{...this.cleanProps()}
/>
);
@@ -69,6 +97,22 @@ class DataGrid extends Component {
}
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;
\ No newline at end of file
diff --git a/app/javascript/packs/shared/data_table/DataTable.jsx b/app/javascript/packs/shared/data_table/DataTable.jsx
index a313ca56d..58ddf0d53 100644
--- a/app/javascript/packs/shared/data_table/DataTable.jsx
+++ b/app/javascript/packs/shared/data_table/DataTable.jsx
@@ -3,6 +3,15 @@ import PropTypes from "prop-types";
import { BootstrapTable, TableHeaderColumn } from 'react-bootstrap-table';
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);
@@ -11,25 +20,25 @@ class DataTable extends Component {
cleanProps() {
// Remove additional props from the props value
- const cleanProps = {...this.props};
- delete cleanProps.columns;
+ const {columns, ...cleanProps} = this.props;
return cleanProps;
}
+
displayHeader() {
- const orderedCols = [...this.props.columns].sort((a, b) => b.position - a.position);
- return orderedCols.map((col) => {
- return (
-
- {col.name}
-
- );
- });
+ const orderedCols = [...this.props.columns].sort((a, b) => a.position - b.position);
+ return orderedCols.map((col) =>
+
+ {col.name}
+
+ );
}
render() {
@@ -53,7 +62,8 @@ DataTable.propTypes = {
sortable: PropTypes.bool,
locked: PropTypes.bool
})
- ).isRequired
+ ).isRequired,
+ data: PropTypes.arrayOf(PropTypes.object).isRequired
};
export default DataTable;
\ No newline at end of file
diff --git a/app/javascript/packs/styles/main.scss b/app/javascript/packs/styles/main.scss
index 772249944..6d077be06 100644
--- a/app/javascript/packs/styles/main.scss
+++ b/app/javascript/packs/styles/main.scss
@@ -7,3 +7,44 @@ body {
font-family: "Open Sans",Arial,Helvetica,sans-serif;
font-size: 13px;
}
+
+.react-bs-table {
+ thead {
+ background-color: #909088;
+
+ > tr > th,
+ >tr > td {
+ padding: 6px;
+ padding-right: 30px;
+ }
+
+ > tr > th {
+ border-bottom: 2px solid #ddd;
+ border-bottom-width: 0;
+ border-left: 2px solid #fcfcfc;
+ color: #fff;
+ 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;
+ }
+
+ .sorting_desc,
+ .sorting_asc {
+ background-color: #37a0d9;
+ }
+}
+