UNPKG

labo-components

Version:
190 lines (164 loc) 6.1 kB
import AnnotationUtil from '../../../util/AnnotationUtil'; import IDUtil from '../../../util/IDUtil'; import PropTypes from 'prop-types'; /** * Display a bookmark/annotation result list and handle the filtering and sorting */ class NestedTable extends React.PureComponent { constructor(props) { super(props); // retrieve persistent filters from localstorage this.filterKey = props.uid + '-filter'; const filter = { keywords:''} this.state = { filteredItems: [], visibleItems: [], loading: true, order: 'created', filter, }; } //load and filter data reloadData() { // filter const filtered = this.props.filterItems( this.props.items, this.state.filter ); // sort const sorted = this.props.sortItems(filtered, this.state.order); // update state this.setState({ filteredItems: filtered, visibleItems: sorted }); } setSort(field) { this.setState({ order: field, // filter list from original items to keep sort list consistent visibleItems: this.props.sortItems(this.state.filteredItems, field) }); } //Listen for update, request new data if filter has been changed componentDidUpdate(prevProps, prevState) { //listen for items change if (prevProps.items != this.props.items) { this.reloadData(); return; } // listen for filter change if (this.lastFilter !== this.state.filter) { this.lastFilter = this.state.filter; // throttle data requests if (this.requestDataTimeout) { clearTimeout(this.requestDataTimeout); this.requestDataTimeout = setTimeout(this.reloadData.bind(this), 300); } else { // firstrun this.reloadData(); } } } // user changes a filter filterChange(key, e) { let filter = {}; filter[key] = e.target.value; // create filter filter = Object.assign({}, this.state.filter, filter); // update state this.setState({ filter }); } //when the sort type changes sortChange(e) { this.setSort(e.target.value); } // render filters renderFilters(filters){ return filters.map((filter, index)=>{ switch(filter.type){ case 'search': return(<div className="filter-container"> <input key={index} className="search" type="text" placeholder={filter.placeholder || "Search"} value={this.state.filter[filter.key]} onChange={this.filterChange.bind(this, filter.key)} /> </div>) break; case 'select': return (<div className="filter-container"> <span key={index}> <label className="type-label" title={filter.titleAttr ? filter.titleAttr : null}>{filter.title}</label> <select disabled={filter.options.length == 0} className="type-select" value={this.state.filter[filter.key]} onChange={this.filterChange.bind(this, filter.key)}> <option /> {filter.options.map((option, index) => ( <option key={index} value={option.value} disabled={option.disabled}> {option.name} </option> ))} </select> </span> </div>) break; default: console.error("Unknown filter type", filter); } return null }); } render() { return ( <div className={IDUtil.cssClassName('nested-table')}> <div className="tools"> {/*<div className="export-button btn primary" onClick={this.props.onExport.bind(this, this.state.visibleItems)}> Export all </div>*/} <div className="left"> <h3>Filters</h3> {this.renderFilters(this.props.filters)} </div> </div> <div className="results"> <div className="sort"> <h3>Order</h3> <select value={this.state.order} onChange={this.sortChange.bind(this)}> {this.props.orders.map((type, index) => ( <option key={index} value={type.value}> {type.name} </option> ))} </select> </div> {this.props.renderResults(this.state)} </div> </div> ) } } NestedTable.propTypes = { filterItems: PropTypes.func.isRequired, filters: PropTypes.object, items: PropTypes.array.isRequired, onExport: PropTypes.func.isRequired, orders: PropTypes.array.isRequired, renderResults: PropTypes.func.isRequired, selection: PropTypes.array, sortItems: PropTypes.func.isRequired }; NestedTable.defaultProps = { filters: {} }; export default NestedTable;