@aappddeevv/dynamics-client-ui
Version:
## What is it? A library to help you create great dynamics applications.
485 lines (401 loc) • 18 kB
JavaScript
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.wrapTH = exports.wrapTD = exports.HorizontalScrollBar = exports.colLenses = exports.addTitleTransformer = exports.CrmTable = undefined;
var _extends2 = require('babel-runtime/helpers/extends');
var _extends3 = _interopRequireDefault(_extends2);
var _objectWithoutProperties2 = require('babel-runtime/helpers/objectWithoutProperties');
var _objectWithoutProperties3 = _interopRequireDefault(_objectWithoutProperties2);
var _getPrototypeOf = require('babel-runtime/core-js/object/get-prototype-of');
var _getPrototypeOf2 = _interopRequireDefault(_getPrototypeOf);
var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');
var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
var _createClass2 = require('babel-runtime/helpers/createClass');
var _createClass3 = _interopRequireDefault(_createClass2);
var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn');
var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);
var _inherits2 = require('babel-runtime/helpers/inherits');
var _inherits3 = _interopRequireDefault(_inherits2);
exports.controlOverflow = controlOverflow;
var _react = require('react');
var React = _interopRequireWildcard(_react);
var _reactabularTable = require('reactabular-table');
var Table = _interopRequireWildcard(_reactabularTable);
var _reactabularSticky = require('reactabular-sticky');
var Sticky = _interopRequireWildcard(_reactabularSticky);
var _sortabular = require('sortabular');
var sort = _interopRequireWildcard(_sortabular);
var _orderBy = require('lodash/orderBy');
var _orderBy2 = _interopRequireDefault(_orderBy);
var _selectabular = require('selectabular');
var select = _interopRequireWildcard(_selectabular);
var _Ellipsis = require('./Ellipsis');
var _Ellipsis2 = _interopRequireDefault(_Ellipsis);
var _BuildSettings = require('BuildSettings');
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var R = require("ramda"); // Similar searches augments
var styles = require("./CrmTable.css");
var fstyles = require("../Dynamics/flexutilities.css");
var cx = require("classnames");
/**
* Simple CRM styled table. Component can managed data state
* or you can pass in data through props "data". The table can perform
* local sorting so index based tracking of selection does not make
* alot of sense.
*
* @param data Data for grid if dataSource is null.
* @param columns Ready to go column array.
* @param sortingColumns Sorting state per the manual.
* @param dataSource Create a Promise that returns an array of data. Overrides `data`. Component
* will ignore data coming through props if dataSource is defined.
* @param columnGenerator Function to generate columns. Called with sortable.
* @param onSelectIndex Callback. Provides selected index. (only single selection?)
* @param onSelectId Callback. Provides selected id, if defined.
* @param selectedId Selected entity id or null.
* @param {string} idAttr Attribute of an entities' identity i.e. "id" attribute. Defaults to "id".
*/
var CrmTable = exports.CrmTable = function (_React$Component) {
(0, _inherits3.default)(CrmTable, _React$Component);
function CrmTable(props) {
(0, _classCallCheck3.default)(this, CrmTable);
var _this = (0, _possibleConstructorReturn3.default)(this, (CrmTable.__proto__ || (0, _getPrototypeOf2.default)(CrmTable)).call(this, props));
_this.doScroll = function (e) {
_this.tableHeader.scrollLeft = e.target.scrollLeft;
_this.tableBody.scrollLeft = e.target.scrollLeft;
};
_this.onSelectRowByIndex = function (byIndex, byId, rows) {
return function (idx) {
return _this.reportBack(byIndex, byId, null, rows, idx);
};
};
_this.onRow = function (byIndex, byId, selectedRowIndex) {
return function (row, _ref) {
var rowIndex = _ref.rowIndex;
//console.log("onRow",selectedRowIndex, rowIndex)
return {
className: cx(rowIndex % 2 ? "oddRow" : "evenRow", (row.selected || selectedRowIndex === rowIndex) && styles.selected),
onClick: function onClick() {
return _this.reportBack(byIndex, byId, row[_this.state.idAttr], null, rowIndex);
}
};
};
};
_this.reportBack = function (byIndex, byId, id, rows, idx) {
if (byIndex && idx !== null) byIndex(idx);
// should reverse engineer index if rows, id are defined
if (byId && !R.isNil(id)) byId(id);else if (!R.isNil(idx) && rows && byId) {
var idAttr = _this.state.idAttr;
var _id = rows[idx][idAttr];
if (!R.isNil(_id)) byId(_id);
}
};
var getSortingColumns = function getSortingColumns() {
return _this.state.sortingColumns || [];
};
_this.state = {
data: null,
dataInternallyManaged: false, // whether data is internally managed
columns: props.columns || [],
dataSource: props.dataSource,
sortingColumns: props.sortingColumns || {},
originalSortingColumns: props.sortingColumns || {},
columnGenerator: props.columnGenerator,
strategy: props.strategy || sort.strategies.byProperty,
getSortingColumns: props.getSortingColumns || getSortingColumns,
sortable: props.sortable || null,
resetable: props.resetable || null,
idAttr: props.idAttr || "id"
};
_this.tableHeader = null;
_this.tableBody = null;
if (!_this.state.sortable) {
_this.state.sortable = sort.sort({
getSortingColumns: _this.state.getSortingColumns,
strategy: _this.state.strategy,
onSort: function onSort(selectedColumn) {
_this.setState({
sortingColumns: sort.byColumn({
sortingColumns: _this.state.sortingColumns,
selectedColumn: selectedColumn
})
});
}
});
}
if (!_this.state.resetable) {
_this.state.resetable = sort.reset({
event: 'onDoubleClick',
getSortingColumns: _this.state.getSortingColumns,
onReset: function onReset(_ref2) {
var sortingColumns = _ref2.sortingColumns;
return _this.setState({ sortingColumns: sortingColumns });
},
strategy: _this.state.strategy
});
}
_this.refreshData = _this.refreshData.bind(_this);
return _this;
}
/** Call from external scrollbar. */
(0, _createClass3.default)(CrmTable, [{
key: 'componentWillMount',
value: function componentWillMount() {
var gen = this.state.columnGenerator;
if (gen) {
//console.log("CrmTable: Generating columns");
this.setState({ columns: gen({
getSortingColumns: this.state.getSortingColumns,
strategy: this.state.strategy,
sortable: this.state.sortable,
resetable: this.state.resetable
}) });
}
}
}, {
key: 'componentDidMount',
value: function componentDidMount() {
this.forceUpdate();
this.refreshData();
}
}, {
key: 'refreshData',
value: function refreshData() {
var _this2 = this;
if (this.state.dataSource) {
this.state.dataSource(this.state).then(function (data) {
_this2.setState({ data: data, dataInternallyManaged: true });
}).catch(function (e) {
// not sure the issue
console.log("CrmTable: error obtaining data", e);
_this2.setState({ dataInternallyManaged: true });
});
}
}
}, {
key: 'render',
value: function render() {
var _this3 = this;
var _state = this.state,
data = _state.data,
columns = _state.columns,
sortingColumns = _state.sortingColumns,
dataInternallyManaged = _state.dataInternallyManaged;
if (!dataInternallyManaged) {
data = this.props.data || data;
}
var _props = this.props,
onSelectIndex = _props.onSelectIndex,
onSelectId = _props.onSelectId,
selectedId = _props.selectedId,
className = _props.className;
// add some non-invasive properties to all columns if they render it
columns = columns.map(function (c) {
var current = R.view(colLenses.transforms, c) || [];
return R.set(colLenses.transforms, current.concat([addTitleTransformer]), c);
});
// Pre-sort if sorting criteria is set.
var sortedData = sort.sorter({
columns: columns,
sortingColumns: sortingColumns,
strategy: this.state.strategy,
sort: _orderBy2.default
})(data);
// Identify selected rows. Selected rows will be modified
// with a property added "selected: boolean" which means they will be re-rendered and
// onRow called again on those rows only.
var _ref3 = this.state.idAttr && selectedId ? R.pipe(select.none, // set selected = false
select.rows(function (row) {
return row[_this3.state.idAttr] === selectedId;
}))(sortedData) : { rows: sortedData, selectedRows: []
// After sorting and selection, find selectedRowIndex
},
rows = _ref3.rows,
selectedRows = _ref3.selectedRows;
var selectedRowIndex = this.state.idAttr && selectedId ? R.findIndex(R.propEq(this.state.idAttr, selectedId))(rows) : -1;
// add some space for a scrollbar if one is needed ever
var totalColumnsWidth = columns.reduce(function (sum, c) {
return sum += c.props.style.minWidth;
}, 0) + 17;
if (_BuildSettings.DEBUG) console.log("totalColumnsWidth", totalColumnsWidth);
var tableWidth = totalColumnsWidth;
//const tableHeight= this.props.tableHeight || 250
var tableStyle = {
width: tableWidth,
clear: "none"
};
var tableHeaderStyle = {
maxWidth: tableWidth,
overflow: "hidden"
};
var tableBodyStyle = {
maxWidth: tableWidth,
//maxHeight: tableHeight,
overflow: "auto"
//console.log("CrmTable.props", {selectedId, data}, selectedRowIndex)
// select.byArrowKeys introduces a in-the-wild div.
};return React.createElement(
'div',
{ className: cx(fstyles.flexVertical, styles.wrapper, className), 'data-ctag': 'CrmTable' },
select.byArrowKeys({
rows: sortedData,
selectedRowIndex: selectedRowIndex,
onSelectRow: this.onSelectRowByIndex(onSelectIndex, onSelectId, rows)
})(React.createElement(
Table.Provider,
{
className: styles.crmTable,
columns: columns,
style: tableStyle,
components: {
header: {
cell: wrapTH
},
body: {
cell: wrapTD
}
}
},
React.createElement(Sticky.Header, {
ref: function ref(h) {
_this3.tableHeader = h && h.getRef();
},
tableBody: this.tableBody,
style: tableHeaderStyle,
onScroll: this.doScroll
}),
React.createElement(Sticky.Body, {
className: styles.crmBody,
onRow: this.onRow(onSelectIndex, onSelectId, selectedRowIndex),
rows: rows,
rowKey: this.props.rowKey,
ref: function ref(b) {
_this3.tableBody = b && b.getRef();
},
tableHeader: this.tableHeader,
onScroll: this.doScroll,
style: tableBodyStyle
})
)),
React.createElement(HorizontalScrollBar, {
className: fstyles.flexNone,
width: tableWidth,
scrollWidth: totalColumnsWidth,
left: 0,
top: 0,
onScroll: this.doScroll })
);
}
}]);
return CrmTable;
}(React.Component);
CrmTable.defaultProps = {
rowKey: "id",
idAttr: "id" };
exports.default = CrmTable;
/** Take the property value for a cell and add a title property. */
var addTitleTransformer = exports.addTitleTransformer = function addTitleTransformer(value, ctx) {
return { title: value };
};
/** Column lenses. */
var colLenses = exports.colLenses = {
transforms: R.lensPath(["cell", "transforms"]),
formatters: R.lensPath(["cell", "formatters"])
/**
* See: https://reactabular.js.org/#/examples/header-body-aligned
*/
};
var HorizontalScrollBar = exports.HorizontalScrollBar = function (_React$PureComponent) {
(0, _inherits3.default)(HorizontalScrollBar, _React$PureComponent);
function HorizontalScrollBar() {
(0, _classCallCheck3.default)(this, HorizontalScrollBar);
return (0, _possibleConstructorReturn3.default)(this, (HorizontalScrollBar.__proto__ || (0, _getPrototypeOf2.default)(HorizontalScrollBar)).apply(this, arguments));
}
(0, _createClass3.default)(HorizontalScrollBar, [{
key: 'render',
value: function render() {
var _props2 = (0, _extends3.default)({}, this.props),
width = _props2.width,
scrollWidth = _props2.scrollWidth,
left = _props2.left,
top = _props2.top,
props = (0, _objectWithoutProperties3.default)(_props2, ['width', 'scrollWidth', 'left', 'top']);
left = left || 0;
top = top || 0;
var scrollbarOuterStyle = {
display: 'inline-block',
overflow: 'auto',
backgroundColor: 'transparent',
position: 'relative',
width: width,
height: 16,
left: { left: left },
top: { top: top }
};
var scrollbarInnerStyle = {
display: 'inline-block',
width: scrollWidth,
height: '100%'
};
return React.createElement(
'div',
(0, _extends3.default)({ style: scrollbarOuterStyle }, props),
React.createElement('span', {
style: scrollbarInnerStyle
})
);
}
}]);
return HorizontalScrollBar;
}(React.PureComponent);
function controlOverflow(content, title, _ref4) {
var className = _ref4.className;
var cls = cx(styles.textOverflowContainer, className);
return React.createElement(
'span',
{ className: cls },
React.createElement(
'span',
{ className: styles.textOverflowEllipsis, title: title },
content
)
);
}
var wrapTD = function wrapTD(_ref5) {
var children = _ref5.children,
className = _ref5.className,
title = _ref5.title,
rest = (0, _objectWithoutProperties3.default)(_ref5, ['children', 'className', 'title']);
//title = typeof title === "string" ? title || null
var cls = cx(className);
return React.createElement(
'td',
(0, _extends3.default)({}, rest, { className: cls, title: title }),
React.createElement(
_Ellipsis2.default,
null,
children
)
);
};
exports.wrapTD = wrapTD;
var wrapTH = function wrapTH(_ref6) {
var children = _ref6.children,
className = _ref6.className,
title = _ref6.title,
rest = (0, _objectWithoutProperties3.default)(_ref6, ['children', 'className', 'title']);
//title = (typeof title === "string") ? title || null
var cls = cx(className);
return React.createElement(
'th',
(0, _extends3.default)({}, rest, { className: cls }),
React.createElement(
_Ellipsis2.default,
null,
children
)
);
};
exports.wrapTH = wrapTH;
//# sourceMappingURL=CrmTable.js.map