@nodeject/ui-components
Version:
UI library for non-trivial components
173 lines (172 loc) • 8.12 kB
JavaScript
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
import { Button, Input, message, Space, Table, Typography } from 'antd';
import * as _ from 'lodash';
import * as React from 'react';
import { useCallback, useEffect, useState } from 'react';
import Highlighter from 'react-highlight-words';
import { convertTreeDataToDataSource } from './data-transform';
var Text = Typography.Text;
var Search = Input.Search;
var useDndTreeTable = function (props) {
var _a = useState([]), flatTreeNodes = _a[0], setFlatTreeNodes = _a[1];
var _b = useState(convertTreeDataToDataSource(props.treeNodes)), dataSource = _b[0], setDataSource = _b[1];
var _c = React.useState({
searchText: '',
searchedColumn: ''
}), state = _c[0], setState = _c[1];
useEffect(function () {
setFlatTreeNodes(props.treeNodes);
}, [props.treeNodes]);
useEffect(function () {
setDataSource(convertTreeDataToDataSource(flatTreeNodes));
}, [flatTreeNodes]);
var _d = useState(false), showNotFoundMsg = _d[0], setShowNotFoundMsg = _d[1];
// filter nodes finding all ancestors of provided array of ids.
var filterNodes = function (nodes) {
var ars = [];
nodes.map(function (n) {
ars.push(getAncestorsFromOrderedArray(n));
});
var filteredNodeIds = _.union.apply(_, ars);
var filteredFlatTreeNodes = [];
filteredNodeIds.map(function (id) {
filteredFlatTreeNodes.push(flatTreeNodes.find(function (n) { return n.data.id === id; }));
});
setFlatTreeNodes(filteredFlatTreeNodes);
};
useEffect(function () {
if (showNotFoundMsg) {
setShowNotFoundMsg(false);
}
}, [showNotFoundMsg]);
var onFilter = useCallback(function (value, dataIndex, properties) {
if (value !== '' && value !== undefined && value !== null) {
// List all node ids that contains the searched value within any of provided props
var nodeIdsMatchingSearchedValues_1 = [];
flatTreeNodes.map(function (n) {
// 'some' allows to exit as soon as 1 prop contains the value
var valueIsMatched = properties.some(function (prop) {
return n.data[prop]
.toString()
.toLowerCase()
.includes(value.toLowerCase());
});
if (valueIsMatched) {
nodeIdsMatchingSearchedValues_1.push(n.data.id);
}
});
if (nodeIdsMatchingSearchedValues_1.length > 0) {
filterNodes(nodeIdsMatchingSearchedValues_1);
setShowNotFoundMsg(false);
}
else {
setShowNotFoundMsg(true);
}
}
}, [flatTreeNodes]);
var reset = useCallback(function () {
setShowNotFoundMsg(false);
setFlatTreeNodes(props.treeNodes);
setState({ searchText: '', searchedColumn: '' });
}, [props.treeNodes]);
var getAncestorsFromOrderedArray = function (nodeId) {
// Our array is ordered. Hence by reversing it, we will just have to iterate each node
// from the nodeId, to find all ancestors
var reverseFlatTreeNodes = flatTreeNodes.slice().reverse(); // slice avoids mutating original array
var nodeIndex = reverseFlatTreeNodes.findIndex(function (n) { return n.data.id === nodeId; });
var node = reverseFlatTreeNodes[nodeIndex];
var nodeParentId = node.data.parent;
var filteredFlatTreeNodes = [];
filteredFlatTreeNodes.push(node.data.id);
for (var i = nodeIndex + 1; i < reverseFlatTreeNodes.length; i++) {
var n = reverseFlatTreeNodes[i];
if (n.data.id === nodeParentId) {
filteredFlatTreeNodes.push(n.data.id);
nodeParentId = n.data.parent;
}
}
return filteredFlatTreeNodes.reverse();
};
var search = useCallback(function (searchText, dataIndex) {
reset();
setState({
searchText: searchText,
searchedColumn: dataIndex
});
}, []);
return {
reset: reset,
dataSource: dataSource,
onFilter: onFilter,
search: search,
state: state,
showNotFoundMsg: showNotFoundMsg
};
};
export var DnDTreeTable = function (props) {
var _a = useDndTreeTable(props), reset = _a.reset, dataSource = _a.dataSource, onFilter = _a.onFilter, search = _a.search, state = _a.state, showNotFoundMsg = _a.showNotFoundMsg;
// This completely replaces columns' onFilter
useEffect(function () {
onFilter(state.searchText, state.searchedColumn, ['title', 'wbsId']);
}, [state.searchText]);
if (showNotFoundMsg) {
message.info("No match for " + state.searchText);
}
var getColumnSearchProps = function (dataIndex) {
return {
title: (React.createElement(TitleRender, { dataIndex: dataIndex, handleSearch: handleSearch })),
render: function (data) { return (React.createElement(TitleRow, { searchText: state.searchText, title: data.title, wbsId: data.wbsId })); }
};
};
var handleSearch = function (searchText, dataIndex) {
search(searchText, dataIndex);
};
var columns = [
__assign({ title: 'Title', dataIndex: 'data', key: 'title' }, getColumnSearchProps('data'))
];
return (React.createElement(TestInner, { columns: columns, dataSource: dataSource, reset: reset, onRowClick: props.onRowClick }));
};
var TitleRender = function (props) {
var dataIndex = props.dataIndex, handleSearch = props.handleSearch;
var _a = useState(''), searchVal = _a[0], setSearchVal = _a[1];
return (React.createElement(Search, { placeholder: "Search hierarchy", style: { width: 188 }, onChange: function (e) {
setSearchVal(e.target.value);
}, onSearch: function () {
handleSearch(searchVal, dataIndex);
} }));
};
var TestInner = function (props) {
var columns = props.columns, dataSource = props.dataSource, onRowClick = props.onRowClick, reset = props.reset;
return (React.createElement(React.Fragment, null,
React.createElement(Button, { onClick: function () { return reset(); } }, "Clear Filters"),
React.createElement(Table, { dataSource: dataSource, columns: columns, expandable: { defaultExpandAllRows: true }, scroll: { y: 500 }, pagination: false, onRow: function (node, index) { return ({
onClick: function () { return onRowClick(node.data.id, node); }
}); }, size: "small" })));
};
var titleColumnHeaderPropsAreEqual = function (prevProps, nextProps) {
return JSON.stringify(prevProps) === JSON.stringify(nextProps);
};
var TitleRow = React.memo(function (props) {
var searchText = props.searchText, title = props.title, wbsId = props.wbsId;
return (React.createElement(Space, null,
React.createElement(Text, { type: "secondary" },
React.createElement(Highlighter, { highlightStyle: {
backgroundColor: '#ffc069',
padding: 0
}, searchWords: [searchText], autoEscape: true, textToHighlight: wbsId })),
React.createElement(Text, { strong: true },
React.createElement(Highlighter, { highlightStyle: {
backgroundColor: '#ffc069',
padding: 0
}, searchWords: [searchText], autoEscape: true, textToHighlight: title }))));
}, titleColumnHeaderPropsAreEqual);