ffr-components
Version:
Fiori styled UI components
449 lines (388 loc) • 15.2 kB
JavaScript
import _extends from "@babel/runtime/helpers/esm/extends";
import _defineProperty from "@babel/runtime/helpers/esm/defineProperty";
import _classCallCheck from "@babel/runtime/helpers/esm/classCallCheck";
import _createClass from "@babel/runtime/helpers/esm/createClass";
import _possibleConstructorReturn from "@babel/runtime/helpers/esm/possibleConstructorReturn";
import _getPrototypeOf from "@babel/runtime/helpers/esm/getPrototypeOf";
import _inherits from "@babel/runtime/helpers/esm/inherits";
import classnames from 'classnames';
import React from 'react';
import Icon from '../icon';
import { FormInput } from '../dynamic-form';
import ListGroup, { ListItem } from '../list-group';
import ColGroup from './ColGroup';
import { isLeadingCheckbox, CheckboxHeader } from './LeadingCheckboxRenderer';
import { connect } from './TableContext';
import Popover from '../popover';
import { isDefaultFocusAble, generateTableIndex } from './tableUtil';
import oType, { KeyCode } from '../utils';
import { REF_TYPE } from './constant';
var defaultSortDirectionKey = [{
key: 'ascend',
text: 'Ascending',
sapIcon: 'sort-ascending'
}, {
key: 'descend',
text: 'Descending',
sapIcon: 'sort-descending'
}];
export var TableHeader =
/*#__PURE__*/
function (_React$Component) {
_inherits(TableHeader, _React$Component);
function TableHeader(props) {
var _this;
_classCallCheck(this, TableHeader);
_this = _possibleConstructorReturn(this, _getPrototypeOf(TableHeader).call(this, props));
_this.renderFilerItem = function (col, key, onFilter) {
var _this$props = _this.props,
filterLabel = _this$props.filterLabel,
tableContext = _this$props.tableContext;
var classes = classnames('ffr-table-menu-item', {
'ffr-table-menu-item-compact': tableContext.isCompact()
});
return col.filterable && React.createElement(ListItem, {
className: classes
}, React.createElement(Icon, {
glyph: "filter"
}), React.createElement("span", null, filterLabel), React.createElement(FormInput, {
className: "fd-input",
onKeyDown: onFilter,
value: _this.state[key] || '',
onChange: function onChange(e) {
return _this.onFilterChange(e, key);
}
}));
};
_this.sortTable = function (sortKey, data, comparedCol) {
var tableContext = _this.props.tableContext;
var currentSorter = tableContext.getCurrentSorter();
if (!currentSorter && !comparedCol) {
return;
}
/*
when sorted by one column, then remove filter from another column,
that filtered column is not the sorted column, even not in same table
*/
var sorter = comparedCol ? comparedCol.sorter : currentSorter.sorter;
var dataKey = comparedCol ? _this.getDataKey(comparedCol) : currentSorter.dataKey;
if (oType.isFunction(sorter.sortFunction)) {
data.sort(function () {
var _sorter$sortFunction;
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
return (_sorter$sortFunction = sorter.sortFunction).call.apply(_sorter$sortFunction, [sorter].concat(args, [sortKey]));
});
} else {
var _ascendSortFunction = function _ascendSortFunction(a, b) {
var firstAsString = String(a[dataKey]);
var secondAsString = String(b[dataKey]);
if (firstAsString < secondAsString) {
return -1;
} else if (firstAsString > secondAsString) {
return 1;
} else {
return 0;
}
};
if (sortKey === 'ascend') {
data.sort(_ascendSortFunction);
} else {
data.sort(_ascendSortFunction).reverse();
}
}
};
_this.renderSortItem = function (col, popRef) {
var sorter = col.sorter;
var tableContext = _this.props.tableContext;
if (!sorter) {
return null;
}
var onSortTable = function onSortTable(e, key) {
var tableContext = _this.props.tableContext;
var data = tableContext.getData() || [];
var dataKey = _this.getDataKey(col);
var currentSorter = tableContext.getCurrentSorter();
popRef.current.triggerBody();
if (!currentSorter || currentSorter.dataKey !== dataKey || currentSorter.value !== key) {
_this.sortTable(key, data, col);
tableContext.updateData(data);
tableContext.updateCurrentSorter({
dataKey: dataKey,
value: key,
sorter: sorter
});
}
};
var sorterList = sorter.sortDirections || defaultSortDirectionKey;
var classes = classnames('ffr-table-menu-item', {
'ffr-table-menu-item-compact': tableContext.isCompact()
});
return sorterList.map(function (sorter, inx) {
return React.createElement(ListItem, {
key: sorter.key,
className: classes,
onClick: function onClick(e) {
return onSortTable(e, sorter.key);
}
}, sorter.sapIcon && React.createElement(Icon, {
glyph: sorter.sapIcon
}), React.createElement("span", null, sorter.text));
});
};
_this.wrapWithMenu = function (control, col, isLast) {
var _this$props2 = _this.props,
tableContext = _this$props2.tableContext,
filterCondition = _this$props2.filterCondition;
var key = col.attribute || col.key;
var popRef = React.createRef();
var onFilter = function onFilter(e) {
var keyCode = e.keyCode;
if (keyCode !== KeyCode.ENTER) return;
var data = tableContext.getData();
var value = _this.state[key];
var filterSingleCondition = function filterSingleCondition(val, _data, _col) {
if (_col.onFilter) {
return _col.onFilter(val, _data);
} else {
return _data.filter(function (__data) {
return String(__data[_col.attribute]).indexOf(val) >= 0;
});
}
};
var changeMode = function changeMode() {
if (!filterCondition[key] && value) {
return 'A';
}
if (value === filterCondition[key]) return 'N';
if (!value) return 'D';
return 'C';
};
var mode = changeMode();
if (mode === 'N') {
return;
}
filterCondition[key] = value;
var results = [];
if (mode === 'C' || mode === 'D') {
var currentSorter = tableContext.getCurrentSorter();
var fullData = tableContext.getOriginData();
var cols = tableContext.getCurrentFilteredColumn();
results = Object.keys(filterCondition).reduce(function (_data, k) {
if ((col.attribute === k || col.key === k) && mode === 'D') return _data;
var targetCol = cols.find(function (clm) {
return clm.attribute === k || clm.key === k;
});
var val = filterCondition[k];
return filterSingleCondition(val, _data, targetCol);
}, fullData);
if (currentSorter) {
_this.sortTable(currentSorter.value, results);
}
} else {
results = filterSingleCondition(value, data, col);
}
popRef.current.triggerBody();
tableContext.updateData(results);
if (tableContext.getSelectionColumn()) {
tableContext.updateSelectAll(false);
}
};
var menu = React.createElement(ListGroup, {
className: "ffr-table-menu"
}, _this.renderSortItem(col, popRef), _this.renderFilerItem(col, key, onFilter));
return React.createElement(React.Fragment, null, React.createElement(Popover, {
ref: popRef,
body: menu,
control: control,
placement: isLast && _this.isLastTableHeader ? Popover.POPPER_PLACEMENTS.bottomEnd : Popover.POPPER_PLACEMENTS.bottomStart,
toggleMenu: function toggleMenu(flag) {
if (flag && col.filterable) {
_this.setState(_defineProperty({}, key, filterCondition[key]));
}
},
referenceProps: {
style: {
height: '100%'
}
},
noArrow: true,
popperModifiers: {
preventOverflow: {
enabled: true,
escapeWithReference: true,
boundariesElement: 'scrollParent'
}
}
}), React.createElement("span", {
className: "ffr-shadow-header"
}, col.title));
};
_this.onFilterChange = function (e, key) {
var value = e.target.value;
_this.setState(_defineProperty({}, key, value));
};
_this.renderSorter = function (col) {
var sorter = col.sorter;
var tableContext = _this.props.tableContext;
var currentSorter = tableContext.getCurrentSorter();
var dKey = _this.getDataKey(col);
if (!sorter || !currentSorter) {
return null;
}
var dataKey = currentSorter.dataKey,
sorterKey = currentSorter.value;
if (dKey !== dataKey) {
return null;
}
var target = (sorter === true || !sorter.sortDirections ? defaultSortDirectionKey : sorter.sortDirections).find(function (ds) {
return ds.key === sorterKey;
});
var iconStr = target && target.sapIcon;
return iconStr ? React.createElement(Icon, {
glyph: iconStr,
className: "ffr-table-action-id"
}) : null;
};
_this.renderFilterFlag = function (col) {
var filterCondition = _this.props.filterCondition;
return filterCondition[col.attribute || col.key] ? React.createElement(Icon, {
glyph: "filter",
className: "ffr-table-action-id"
}) : null;
};
_this.getDataKey = function (col) {
return col.attribute || col.key;
};
_this.assignHeaderRef = function (ref) {
var innerHeaderRef = _this.props.innerHeaderRef;
_this.headerRef.current = ref;
if (typeof innerHeaderRef === 'function') {
innerHeaderRef(ref);
} else if (innerHeaderRef) {
innerHeaderRef.current = ref;
}
};
var columns = props.columns,
fixed = props.fixed,
_tableContext = props.tableContext;
_this.headerRef = React.createRef();
_this.state = {};
_this.isLastTableHeader = false;
var withMenuHeader = false;
columns.forEach(function (row) {
row.forEach(function (col) {
var sorter = col.sorter,
filterable = col.filterable;
withMenuHeader = withMenuHeader || !!sorter || !!filterable;
if (oType.isObject(sorter) && !oType.isFunction(sorter.sortFunction)) {
if (Object.keys(sorter).some(function (k) {
return defaultSortDirectionKey.every(function (def) {
return def.key !== k;
});
})) {
throw new Error('sortFunction must be supplied if sort key is other than ascend or descend');
}
}
});
});
if (withMenuHeader) {
_this.isLastTableHeader = fixed === 'right' || fixed === undefined && !_tableContext.hasRightFixedTable();
}
return _this;
}
_createClass(TableHeader, [{
key: "componentDidMount",
value: function componentDidMount() {
var _this$props3 = this.props,
tableContext = _this$props3.tableContext,
fixed = _this$props3.fixed;
var clientHeight = this.headerRef.current.clientHeight;
if (!fixed) {
tableContext.updateHeaderHeight(clientHeight);
}
}
}, {
key: "render",
value: function render() {
var _this2 = this;
var _this$props4 = this.props,
columns = _this$props4.columns,
lastLine = _this$props4.lastLine,
headerAlignment = _this$props4.headerAlignment,
tableID = _this$props4.tableID,
tableContext = _this$props4.tableContext,
fixed = _this$props4.fixed,
handleMoveFocus = _this$props4.handleMoveFocus;
var className = classnames('fd-table__header', "ffr-align-".concat(headerAlignment), {
'ffr-multiple-header': columns.length > 1
});
return React.createElement(React.Fragment, null, React.createElement(ColGroup, {
lastColumns: lastLine
}), React.createElement("thead", {
ref: this.assignHeaderRef,
className: className
}, columns.map(function (row, rowInx) {
return React.createElement("tr", {
key: rowInx,
role: "row",
className: "fd-table__row"
}, row.map(function (col, inx) {
var thProps = {};
var isLast = inx === row.length - 1;
if (col.colSpan) {
thProps.colSpan = col.colSpan;
}
if (col.rowSpan) {
thProps.rowSpan = col.rowSpan;
}
var classes = classnames('fd-table__cell', {
'ffr-clickable-column': col.filterable || col.sorter
});
var contentClass = classnames({
'ffr-clickable-content': col.filterable || col.sorter
});
if (isLeadingCheckbox(col)) {
return React.createElement(CheckboxHeader, {
col: col,
className: classes,
spanProps: thProps,
key: inx,
fixed: fixed,
handleMoveFocus: handleMoveFocus
});
}
var thComponent = React.createElement("div", {
className: "".concat(contentClass, " ffr-clickable-content-").concat(headerAlignment)
}, React.createElement("span", {
className: "ffr-column-title",
id: "".concat(tableID, "-l").concat(rowInx, "-h").concat(inx)
}, col.title), col.sorter ? _this2.renderSorter(col) : null, col.filterable ? _this2.renderFilterFlag(col) : null);
var tabIndex = rowInx === columns.length - 1 && isDefaultFocusAble(tableContext, fixed, inx) ? 0 : -1;
var dataIndex = generateTableIndex(REF_TYPE.header, fixed, rowInx, inx);
if (tabIndex === 0) {
tableContext.updateHeaderFocusIndex(dataIndex);
}
return React.createElement("th", _extends({
key: col.key || col.attribute
}, thProps, {
className: classes,
role: "columnheader",
"aria-labelledby": "".concat(tableID, "-l").concat(rowInx, "-h").concat(inx),
tabIndex: tabIndex,
"data-index": dataIndex,
onKeyDown: handleMoveFocus
}), col.filterable || col.sorter ? _this2.wrapWithMenu(thComponent, col, isLast) : thComponent);
}));
})));
}
}]);
return TableHeader;
}(React.Component);
TableHeader.defaultProps = {
columns: [],
handleMoveFocus: function handleMoveFocus() {}
};
TableHeader.displayName = 'TableHeader';
export default connect('headerAlignment', 'filterLabel', 'filterCondition', 'tableID', 'currentSorter')(TableHeader);