esaron-react-dynamic-data-table
Version:
Dynamic data table wrapping fixed-data-table.
966 lines (921 loc) • 42.3 kB
JavaScript
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; }
/**
* Created by esaron on 5/21/16.
*
* dynamic-data-table.js
******************************************************************************************************************************
* PaginationControls: Stateful component to reflect the current table pagination info and provide
* pagination controls.
*
* props
* pageNumber: The current page number. (Default: 1)
*
* rowsPerPage: The number of rows per page. (Default: 10)
*
* totalPages: The total number of pages. If undefined, jumping to the last page will be disabled.
*
* onGoFirst: A function to be performed when the "<<" button is clicked. (Default: No-op)
*
* onGoLast: A function to be performed when the ">>" button is clicked, if enabled. (Default: No-op)
*
* onGoNext: A function to be performed when the ">" button is clicked. (Default: No-op)
*
* onGoPrevious: A function to be performed when the "<" button is clicked. (Default: No-op)
*
* onSubmit: A function to be performed when the page input is submitted. (Default: No-op)
*
* onRowsPerPageChange:
* A function to be performed when the rowsPerPage dropdown changes. (Default: No-op)
*
* errorMsg: A customizable error message to be displayed when data can't be loaded.
*
******************************************************************************************************************************
* DynamicDataTable: Stateful table that is capable of displaying data and responding to user input to
* dynamically update and submit data.
*
* Internal Fields (Not for external manipulation)
* _data: Used as a pre-mount data store.
*
* _columns: Used for tracking dynamically constructed Columns (column config with nested row data).
*
* _state: Used to cache state until the setState method, which is asynchronous, can be called
* and expected to reliably propagate state.
*
* props
* Props will be passed to wrapped instance of fixed-data-table
* See https://facebook.github.io/fixed-data-table/api-table.html for details on supported fdt props
*
* initialData: If set, the table will be loaded with the provided data. See state.data for format.
*
* restUrl: If set, data is retrieved by making a GET request to the provided url. Note that this will
* overwrite any data provided via props.initialData.
*
* initialColumnFormats:
* (Required) An array of column format objects:
* [
* {
* id: columnId,
* editable: columnDataIsEditable, (Default: false)
* filterType: 'text', 'select', 'combobox', 'date', 'daterange',
* filterOptions: [{label: 'Option Label', value: 'optionValue'}, ...], (if 'select' is the filterType)
* filterRestUrl: urlForOptions, (if 'combobox' is the filterType)
* queryFcn: function(value), (function that produces query param objects or strings; if 'combobox' is the filterType)
* initialFilterValue: filterOnThis,
* sortable: canSortOnColumn, (Default: false)
* headerClass: cssClass,
* cellClass: cssClass,
* formatter: function(data, table) (Returns the cell content as text or React element)
* (Default: "return data[id];")
* sortField: The back-end field by which to sort, (Default: columnId)
* sortFcn: Optional sort function in the format of Array.sort with the addition of
* an argument for the sort direction 'asc' (default) or 'desc',
* (any keys defined by <Column> from fixed-data-table)
* ...
* }
* ]
*
* initialRowsPerPage: The number of rows per page. (Default: 10)
*
* initialPage: The page to start on. Only used if !props.useScrolling. (Default: 1)
*
* useScrolling: If truthy, use scrolling instead of pagination.
*
* rowsPerPageOptions: A sorted array of options users can select for the number of rows on the page. (Default: [10, 25, 50])
*
* sortFcn: A user function by which to sort data. (Default: case insensitive sort by sortField)
*
* initialSortField: The field on which to initially sort the data.
*
* initialSortDir: The initial sort direction.
*
* submitUrl: The URL to execute a PUT request against when submitting data.
*
* formatSubmitData: A function that takes table data as an argument and formats it
* for submission to props.submitUrl.
*
* state
* width: Used for dynamic width based on total column width (Can be overriden by providing props.width).
*
* height: Used for dynamic height based on row height and number (Can be overridden by providing props.height).
*
* data: The data to display, formatted as an array of row objects:
* [{
* columnId1: value (see fdt api for Cell types),
* columnId2: value,
* ...
* },
* ...
* }]
*
* columnFormats: The current column format objects.
*
* rowsPerPage: The number of rows per page.
*
* pageNumber: The current page number. Only used if !props.useScrolling. (Default: 1)
*
* totalRecords: The total number of records.
*
* totalPages: The total number of pages.
*
* sortField: If set, sort by this field.
* TODO allow for an array for sorting on additional columns when fields match
*
* sortDir: undefined (unsorted), 'asc', or 'desc'. (Default undefined)
*
* filters: An object of columnId to current filter value:
* {
* columnId: filterValue
* ...
* }
* TODO
*
* onSubmit: A function to be performed when data is submitted.
* Formats data using props.formatSubmitData and sends it to props.submitUrl
*/
var $ = require('jquery');
var React = require('react');
var PropTypes = React.PropTypes;
var FDT = require('fixed-data-table');
var Table = FDT.Table;
var Column = FDT.Column;
var Cell = FDT.Cell;
var FormControl = require('react-bootstrap/lib/FormControl');
var DatePicker = require('react-datepicker');
var Link = require('esaron-react-link');
var RestCombobox = require('esaron-react-rest-combobox');
var PaginationControls = React.createClass({
displayName: 'PaginationControls',
getInitialState: function getInitialState() {
return {
pageNumber: this.props.initialPageNumber,
rowsPerPage: this.props.initialRowsPerPage,
blankDisplay: false,
options: this.getInitialOptions()
};
},
getDefaultProps: function getDefaultProps() {
return {
initialPageNumber: 1,
initialRowsPerPage: 10,
rowsPerPageOptions: [10, 25, 50],
onGoFirst: function onGoFirst() {},
onGoLast: function onGoLast() {},
onGoNext: function onGoNext() {},
onGoPrevious: function onGoPrevious() {},
onSubmit: function onSubmit(pageNumber) {},
onRowsPerPageChange: function onRowsPerPageChange(rowsPerPage) {}
};
},
getInitialOptions: function getInitialOptions() {
var options = [];
this.props.rowsPerPageOptions.forEach(function (rowsPerPage) {
options.push(React.createElement(
'option',
{ key: rowsPerPage, value: rowsPerPage },
rowsPerPage
));
});
return options;
},
render: function render() {
var t = this;
return React.createElement(
'div',
null,
React.createElement(
'div',
{ className: 'rowsPerPage' },
React.createElement(
'select',
{
value: this.state.rowsPerPage,
onChange: function onChange(event) {
var value = Number(event.target.value);
t.setState({ rowsPerPage: value, pageNumber: 1 });
t.props.onRowsPerPageChange(value);
} },
t.state.options
)
),
React.createElement(
'div',
{ className: 'pageControls' },
React.createElement(Link, { id: t.props.id + "-first-page", className: 'firstPageIcon', onClick: function onClick() {
t.setState({ pageNumber: 1 });
t.props.onGoFirst();
} }),
React.createElement(Link, { id: t.props.id + "-previous-page", className: 'previousPageIcon', onClick: function onClick() {
if (t.state.pageNumber > 1) {
t.setState({ pageNumber: t.state.pageNumber - 1 });
}
t.props.onGoPrevious();
} }),
React.createElement(
'form',
{
onSubmit: function onSubmit(event) {
t.props.onSubmit(t.state.pageNumber);
event.preventDefault();
},
style: { display: "inline-block", margin: 0 } },
React.createElement('input', {
type: 'text',
value: !t.state.blankDisplay ? t.state.pageNumber : "",
onChange: function onChange(event) {
var display = event.target.value;
var value = Number(display);
if (display === "") {
t.setState({ blankDisplay: true });
}
if (value > 0 && value <= t.props.totalPages) {
t.setState({ pageNumber: value, blankDisplay: false });
}
},
style: { width: "30px", textAlign: "center" }
})
),
React.createElement(
'span',
null,
' / ',
!!t.props.totalPages ? t.props.totalPages : "?",
' '
),
React.createElement(Link, { id: t.props.id + "-next-page", className: 'nextPageIcon', onClick: function onClick() {
if (t.state.pageNumber < t.props.totalPages) {
t.setState({ pageNumber: t.state.pageNumber + 1 });
}
t.props.onGoNext();
} }),
React.createElement(Link, { id: t.props.id + "-last-page", className: 'lastPageIcon', onClick: function onClick() {
if (!!t.props.totalPages) {
t.setState({ pageNumber: t.props.totalPages });
}
t.props.onGoLast();
} })
)
);
}
});
var DynamicDataTable = React.createClass({
displayName: 'DynamicDataTable',
_state: {},
_data: [],
_columns: [],
_onColumnResizeEndCallback: function _onColumnResizeEndCallback(newColumnWidth, columnKey) {
var targetIdx = -1;
$.each(this._state.columnFormats, function (idx, columnFormat) {
if (columnFormat.id === columnKey) {
targetIdx = idx;
}
});
this._state.columnFormats[targetIdx].width = newColumnWidth;
this.refresh(true);
},
_sort: function _sort() {
var t = this;
var sortedData = t._data.slice();
var targetIdx = -1;
$.each(this._state.columnFormats, function (idx, columnFormat) {
if (!columnFormat.sortField && columnFormat.id === t._state.sortField || columnFormat.sortField === t._state.sortField) {
targetIdx = idx;
}
});
sortedData.sort(function (a, b) {
var sortFieldA = a[t._state.sortField] || "";
var sortFieldB = b[t._state.sortField] || "";
var columnFormat = t._state.columnFormats[targetIdx];
if (!!columnFormat.sortFcn) {
return columnFormat.sortFcn(sortFieldA, sortFieldB, t._state.sortDir);
}
return t.props.sortFcn(sortFieldA, sortFieldB, t._state.sortDir);
});
return sortedData;
},
_setFilterValue: function _setFilterValue(columnId, filterValue, idx) {
if (!idx) {
// We're just setting a single filter value
this._state.filters[columnId] = filterValue;
} else {
// We're setting a value for a specific index (date ranges)
if (!Array.isArray(this._state.filters[columnId])) {
this._state.filters[columnId] = [];
}
this._state.filters[columnId][idx] = filterValue;
}
this.constructPage();
},
_cycleSortDir: function _cycleSortDir() {
if (!this._state.sortDir) {
this._state.sortDir = "asc";
} else if (this._state.sortDir === "asc") {
this._state.sortDir = "desc";
} else if (this._state.sortDir === "desc") {
this._state.sortDir = undefined;
} else {
console.error("Unrecognized sortDir '" + this._state.sortDir + "'. Resetting to unsorted.");
this._state.sortDir = undefined;
}
},
_onSortClick: function _onSortClick(e, sortField) {
e.preventDefault();
if (this._state.sortField !== sortField) {
this._state.sortField = sortField;
this._state.sortDir = "asc";
} else {
this._cycleSortDir();
}
this.refresh(!this._state.serverSideOperations);
},
propTypes: {
errorMsg: PropTypes.string,
formatSubmitData: PropTypes.func,
initialColumnFormats: PropTypes.arrayOf(PropTypes.object).isRequired,
// initialData is expected to be an array, but jquery returns a psuedo-array, so we need to allow
// for objects too
initialData: PropTypes.oneOfType([PropTypes.object, PropTypes.arrayOf(PropTypes.object)]),
initialFilterValue: PropTypes.string,
initialPage: PropTypes.number,
initialRowsPerPage: PropTypes.number,
initialSortDir: PropTypes.string,
initialSortField: PropTypes.string,
restParams: PropTypes.object,
restUrl: PropTypes.string,
submitUrl: PropTypes.string,
useScrolling: PropTypes.bool
},
getDefaultProps: function getDefaultProps() {
return {
initialData: [],
initialPage: 1,
initialRowsPerPage: 10,
rowsPerPageOptions: [10, 25, 50],
serverSideOperations: false,
sortFcn: function sortFcn(a, b, sortDir) {
var comparison = a.toLowerCase().localeCompare(b.toLowerCase());
if (comparison === 0) {
comparison = a.localeCompare(b);
}
if (sortDir === 'desc') {
comparison = -comparison;
}
return comparison;
},
isColumnResizing: false,
sortable: true
};
},
getInitialState: function getInitialState() {
var t = this;
var totalRecords = void 0;
var totalPages = void 0;
if (!t.restUrl && t.props.initialData.length > 0) {
totalRecords = t.props.initialData.length;
totalPages = t.calculateTotalPages(totalRecords, t.props.initialRowsPerPage);
t._data = t.props.initialData;
}
var filters = {};
$.each(t.props.initialColumnFormats, function (idx, columnFormat) {
filters[columnFormat.id] = columnFormat.initialFilterValue;
});
this._state = {
rowsPerPage: t.props.initialRowsPerPage,
totalRecords: totalRecords,
totalPages: totalPages,
pageNumber: t.props.initialPage,
sortField: t.props.initialSortField,
columnFormats: t.props.initialColumnFormats,
sortDir: t.props.initialSortDir,
headerHeight: t.props.headerHeight,
filters: filters,
loading: false,
error: false,
onSubmit: function onSubmit() {
var deferred = $.Deferred();
var submitData = t._data;
if (!!t.props.formatSubmitData) {
submitData = t.props.formatSubmitData(t._data);
}
if (!!t.currentRequest) {
t.currentRequest.abort();
}
t.currentRequest = $.ajax({
url: t.props.submitUrl,
type: "PUT",
contentType: "application/json",
data: JSON.stringify(submitData),
success: function success(data) {
// TODO user feedback within table header/footer
console.log("Successfully submitted data to '" + t.props.submitUrl + "'");
deferred.resolve("Success");
},
error: function error(err) {
// TODO user feedback within table header/footer
console.error("Data submission to '" + t.props.submitUrl + "' failed");
deferred.reject("Error: " + err);
},
complete: function complete() {
t.currentRequest = null;
}
});
return deferred.promise();
}
};
if (!!t.props.restUrl && t.props.initialData.length > 0) {
// Log a warning. Initial data is ignored if we have a restUrl.
console.error("Both restUrl and initialData have been provided to dynamic-data-table. The value for " + "initialData is being ignored.");
t.props.initialData = [];
}
t._state.data = t.getPageData(t._data);
return t._state;
},
getInitialDimensions: function getInitialDimensions() {
return {
width: this.props.width || 0,
height: this.props.height || 0
};
},
resetDimensions: function resetDimensions() {
var dimensions = this.getInitialDimensions();
this._state.width = dimensions.width;
this._state.height = dimensions.height;
},
loadData: function loadData() {
var t = this;
var deferred = $.Deferred();
var params = t.props.restParams;
if (t.props.serverSideOperations && !t.props.useScrolling) {
params.pageNumber = t._state.pageNumber;
params.rowsPerPage = t._state.rowsPerPage;
}
if (!!t.currentRequest) {
t.currentRequest.abort();
}
t.currentRequest = $.get(t.props.restUrl, params);
t.currentRequest.done(function (response) {
var data = void 0;
if ((typeof response === 'undefined' ? 'undefined' : _typeof(response)) === 'object') {
data = response;
} else {
data = JSON.parse(response);
}
if (Array.isArray(data)) {
t._data = data;
} else {
// Payload is expected to have a 'records' key with the data array.
t._data = data["records"];
t._state.totalRecords = data.totalRecords;
if (!t.props.useScrolling) {
t._state.totalPages = t.calculateTotalPages();
}
}
if (!t._state.totalRecords && !t.props.serverSideOperations) {
t._state.totalRecords = t._data.length;
t._state.totalPages = t.calculateTotalPages();
}
deferred.resolve(response);
});
t.currentRequest.fail(function (err) {
// TODO user feedback within table header/footer
console.error("Failed to load data from '" + t.props.restUrl);
deferred.reject(err);
});
t.currentRequest.always(function () {
t.currentRequest = null;
});
return deferred.promise();
},
getPageData: function getPageData() {
var t = this;
var data = t._data;
if (!!t._state.sortDir && !!t._state.sortField) {
data = t._sort();
}
$.each(t._state.filters, function (columnId, filterValue) {
if (!!filterValue) {
var filterFcn = void 0;
if (Array.isArray(filterValue)) {
// It's a date range. We assume the filter values are Moments
var from = filterValue[0].valueOf();
var to = filterValue[1].valueOf();
// We assume the row values are unix ms time numbers and do an from/to inclusive filter
filterFcn = function filterFcn(row) {
var rowValue = row[columnId];
return rowValue >= from && rowValue <= to;
};
} else {
// It's a single value
var filterValueType = typeof filterValue === 'undefined' ? 'undefined' : _typeof(filterValue);
if (filterValueType !== 'number') {
// Mostly for Moments, but works for any non-number, non-generic-object
filterValue = filterValue.valueOf();
filterValueType = typeof filterValue === 'undefined' ? 'undefined' : _typeof(filterValue);
}
filterFcn = function filterFcn(row) {
var rowValueType = _typeof(row[columnId]);
// Base case is just a string
if (rowValueType === 'string' && filterValueType === 'string') {
return row[columnId].toLowerCase().includes(filterValue.toLowerCase());
}
// We expect numbers for date values (unix ms time)
else if (rowValueType === 'number' && filterValueType === 'number') {
return row[columnId] === filterValue;
}
};
}
data = data.filter(filterFcn);
}
});
// If we are paginating client-side, slice the data appropriately
if (!t.props.serverSideOperations && !t.props.useScrolling) {
var startIdx = (t._state.pageNumber - 1) * t._state.rowsPerPage;
var endIdx = startIdx + t._state.rowsPerPage;
data = data.slice(startIdx, endIdx);
}
return data;
},
goFirst: function goFirst() {
if (this._state.pageNumber > 1) {
this._state.pageNumber = 1;
this.refresh(!this._state.serverSideOperations);
}
},
goLast: function goLast() {
this.goToPage(this._state.totalPages);
},
goNext: function goNext() {
this.goToPage(this._state.pageNumber + 1);
},
goPrevious: function goPrevious() {
if (this._state.pageNumber > 1) {
this._state.pageNumber--;
this.refresh(!this._state.serverSideOperations);
}
},
goToPage: function goToPage(pageNumber) {
var t = this;
var previousPage = void 0;
var previousData = void 0;
if (pageNumber > 0 && (!t._state.totalPages || pageNumber !== t._state.pageNumber && pageNumber <= t._state.totalPages)) {
previousPage = t._state.pageNumber;
previousData = t._state.data;
t._state.pageNumber = pageNumber;
$.when(t.refresh(!this._state.serverSideOperations)).then(function () {
// If we've passed the record boundaries, jump back to the previous page
if (t._state.data.length === 0) {
t._state.pageNumber = previousPage;
t._state.data = previousData;
t.refresh(true);
}
});
}
},
updateRowsPerPage: function updateRowsPerPage(rowsPerPage) {
if (rowsPerPage !== this._state.rowsPerPage && rowsPerPage > 0 && rowsPerPage <= this.props.rowsPerPageOptions[this.props.rowsPerPageOptions.length - 1]) {
this._state.rowsPerPage = rowsPerPage;
this._state.pageNumber = 1;
this._state.totalPages = this.calculateTotalPages();
this.refresh(!this._state.serverSideOperations);
}
},
calculateTotalPages: function calculateTotalPages(totalRecords, rowsPerPage) {
if (!totalRecords) {
totalRecords = this._state.totalRecords;
}
if (!rowsPerPage) {
rowsPerPage = this._state.rowsPerPage;
}
return Math.ceil(totalRecords / rowsPerPage);
},
calculateBodyHeight: function calculateBodyHeight() {
return this.props.rowHeight * this.state.rowsPerPage;
},
calculateHeight: function calculateHeight() {
// The "+2" is 2px for styling from fdt for scroll shadows
var height = this.state.headerHeight + this.calculateBodyHeight() + 2;
if (!!this.props.footerHeight) {
height += this.props.footerHeight;
}
return height;
},
constructColumns: function constructColumns() {
var t = this;
t._columns = [];
$.each(t._state.columnFormats, function (columnIndex, columnFormat) {
// Cache the original header in the columnFormat for later usage
if (!columnFormat.origHeader) {
columnFormat.origHeader = columnFormat.header;
}
var columnId = columnFormat.id;
var columnFormatter = columnFormat["formatter"];
var sortIcon = "";
if (!t.props.width) {
t._state.width += columnFormat.width;
}
var columnSortField = columnFormat.sortField || columnFormat.id;
var header = columnFormat.origHeader;
if (columnFormat.sortable) {
if (t._state.sortField === columnSortField) {
if (t._state.sortDir === "asc") {
sortIcon = " ↓";
} else if (t._state.sortDir === "desc") {
sortIcon = " ↑";
}
}
header = React.createElement(
'a',
{ className: 'block link', onClick: function onClick(e) {
t._onSortClick(e, columnSortField);
} },
columnFormat.origHeader,
sortIcon
);
}
if (!!columnFormat["filterType"]) {
if (t._state.headerHeight === t.props.headerHeight) {
// We have at least one filter, but the header height hasn't been updated to fit the inputs
t._state.headerHeight = t._state.headerHeight + 34;
}
var filter = void 0;
var handleChange = function handleChange(e) {
t._setFilterValue(columnFormat.id, e.target.value);
};
if (columnFormat["filterType"] === 'text') {
filter = React.createElement(FormControl, {
id: t.props.id + '-' + columnFormat.id + '-text',
key: t.props.id + '-' + columnFormat.id + '-text',
type: 'text',
value: t._state.filters[columnFormat.id],
placeholder: 'Enter Text',
onChange: handleChange
});
} else if (columnFormat["filterType"] === 'select') {
filter = React.createElement(
FormControl,
{
id: t.props.id + '-' + columnFormat.id + '-select',
key: t.props.id + '-' + columnFormat.id + '-select',
componentClass: 'select',
onChange: handleChange
},
React.createElement('option', { value: '' }),
columnFormat["filterOptions"].map(function (option) {
return React.createElement(
'option',
{ key: option.value, value: option.value },
option.label
);
})
);
} else if (columnFormat["filterType"] === 'combobox') {
filter = React.createElement(RestCombobox, {
id: t.props.id + '-' + columnFormat.id + '-combobox',
key: t.props.id + '-' + columnFormat.id + '-combobox',
className: 'form-control',
placeholder: 'Enter Text',
showYearDropdown: true,
onSelect: function onSelect(value) {
t._setFilterValue(columnFormat.id, value);
},
initialValue: t._state.filters[columnFormat.id],
restUrl: columnFormat["filterRestUrl"],
queryFcn: columnFormat.queryFcn,
formatFcn: function formatFcn(value) {
var data = {};
data[columnFormat.id] = value;
return columnFormat["formatter"](data, t);
}
});
} else if (columnFormat["filterType"] === 'date') {
filter = React.createElement(DatePicker, {
id: t.props.id + '-' + columnFormat.id + '-date',
key: t.props.id + '-' + columnFormat.id + '-date',
className: 'form-control',
placeholderText: 'Select Date',
showYearDropdown: true,
onChange: function onChange(e) {
t._setFilterValue(columnFormat.id, e);
},
selected: t._state.filters[columnFormat.id]
});
} else if (columnFormat["filterType"] === 'daterange') {
filter = React.createElement(
'div',
{ className: 'daterange-filter' },
React.createElement(DatePicker, {
id: t.props.id + '-' + columnFormat.id + '-daterange-from',
key: t.props.id + '-' + columnFormat.id + '-daterange-from',
className: 'form-control',
placeholderText: 'From Date',
showYearDropdown: true,
onChange: function onChange(e) {
t._setFilterValue(columnFormat.id, e, 0);
},
selected: t._state.filters[columnFormat.id][0]
}),
React.createElement(DatePicker, {
id: t.props.id + '-' + columnFormat.id + '-daterange-to',
key: t.props.id + '-' + columnFormat.id + '-daterange-to',
className: 'form-control',
placeholderText: 'To Date',
showYearDropdown: true,
onChange: function onChange(e) {
t._setFilterValue(columnFormat.id, e, 1);
},
selected: t._state.filters[columnFormat.id][1]
})
);
} else {
console.error("Unknown filter type.");
}
header = React.createElement(
'div',
{ className: 'fullBlock' },
header,
filter
);
}
columnFormat.header = React.createElement(
Cell,
null,
header
);
var content = void 0;
var className = void 0;
var width = 0;
t._columns.push(React.createElement(Column, _extends({
key: columnId,
columnKey: columnId,
cell: function cell(cellData) {
if (t._state.loading || t._state.error) {
if (columnIndex === 0) {
className = 'preLoadCell';
width = t._state.width;
if (t._state.error) {
if (!!t.props.errorMsg) {
content = t.props.errorMsg;
} else {
content = 'Unable to load data. If this keeps happening, there may be an issue with the server, and you should contact your support representative.';
}
} else {
content = React.createElement(Link, { id: t.props.id + "-loading-icon", className: 'loading' });
}
} else {
return null;
}
} else {
className = "dataCell";
if (!!columnFormat["cellClass"]) {
className = className + " " + columnFormat["cellClass"];
}
if (!!columnFormatter) {
content = columnFormatter(t._state.data[cellData.rowIndex], t);
} else {
content = t._state.data[cellData.rowIndex][columnId];
}
if (!!columnFormat["editable"]) {
content = React.createElement('input', {
type: 'text',
id: columnId + cellData.rowIndex,
value: content,
onChange: function onChange(event) {
var value = event.target.value;
this.setState({ value: value });
t._state.data[cellData.rowIndex][columnId] = value;
}
});
}
}
return React.createElement(
Cell,
{ key: columnId + cellData.rowIndex, className: className, width: width },
content
);
}
}, columnFormat)));
});
},
constructPage: function constructPage() {
this.resetDimensions();
this._state.data = this.getPageData();
this.constructColumns();
this.setState(this._state);
},
refresh: function refresh(skipReload) {
var t = this;
var deferred = $.Deferred();
if (!skipReload && !!t.props.restUrl) {
t._state.loading = true;
t._state.error = false;
$.when(t.loadData()).then(function (result) {
t._state.loading = false;
t.constructPage();
deferred.resolve(result);
}, function (err) {
var aborted = err.statusText === 'abort';
// We don't count this as an error if we're aborting the request
t._state.loading = aborted;
t._state.error = !aborted;
t.constructPage();
deferred.reject(err);
});
} else {
deferred.resolve("Using local data.");
}
t.constructPage();
return deferred.promise();
},
componentDidMount: function componentDidMount() {
this.refresh();
},
componentWillUnmount: function componentWillUnmount() {
if (!!this.currentRequest) {
this.currentRequest.abort();
}
},
render: function render() {
var t = this;
var refreshButton = void 0;
var submitButton = void 0;
var pageNav = void 0;
var dimensions = {};
if (!!t.props.restUrl) {
refreshButton = React.createElement(Link, { id: t.props.id + "-refresh", className: 'reloadIcon', tooltip: 'Refresh table', onClick: function onClick() {
t.refresh();
} });
}
if (!!t.props.submitUrl) {
submitButton = React.createElement(Link, { id: t.props.id + "-submit", showLabel: true, label: 'Submit', onClick: function onClick(event) {
t.state.onSubmit(event);
event.preventDefault();
} });
}
if (!t.props.useScrolling) {
pageNav = React.createElement(PaginationControls, {
initialPageNumber: t.state.pageNumber,
initialRowsPerPage: t.state.rowsPerPage,
rowsPerPageOptions: t.props.rowsPerPageOptions,
totalPages: t.state.totalPages,
onGoFirst: t.goFirst,
onGoLast: t.goLast,
onGoNext: t.goNext,
onGoPrevious: t.goPrevious,
onSubmit: t.goToPage,
onRowsPerPageChange: t.updateRowsPerPage
});
}
if (!t.props.width) {
dimensions.width = t.state.width || 0;
}
if (!t.props.height) {
dimensions.height = t.calculateHeight() || 0;
}
var _t$props = t.props,
headerHeight = _t$props.headerHeight,
rowHeight = _t$props.rowHeight,
childProps = _objectWithoutProperties(_t$props, ['headerHeight', 'rowHeight']);
var rowsCount = t.state.data.length;
var className = "dataTable";
if (!!t.props.className) {
className += " " + t.props.className;
}
if (t.state.loading || t.state.error) {
rowHeight = t.calculateBodyHeight();
rowsCount = 1;
className += " dataTablePreload";
}
return React.createElement(
'div',
{ id: t.props.id, className: className,
style: { 'width': dimensions.width, 'height': dimensions.height + 20 } },
React.createElement(
Table,
_extends({ rowsCount: rowsCount,
onColumnResizeEndCallback: t._onColumnResizeEndCallback,
headerHeight: t.state.headerHeight || headerHeight,
rowHeight: rowHeight
}, dimensions, childProps),
t._columns
),
React.createElement(
'div',
{ className: 'dataTableFooter' },
React.createElement(
'div',
{ className: 'paginationWrapper' },
pageNav
),
React.createElement(
'div',
{ className: 'operationsWrapper' },
submitButton,
refreshButton
)
)
);
}
});
module.exports = DynamicDataTable;
;