UNPKG

@nodeject/ui-components

Version:

UI library for non-trivial components

173 lines (172 loc) 8.12 kB
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);