Newer
Older
import React from 'react';
import PropTypes from 'prop-types';
import { withStyles } from '@material-ui/core/styles';
import Table from '@material-ui/core/Table';
import TableBody from '@material-ui/core/TableBody';
import ResultTableCell from './ResultTableCell';
import TableRow from '@material-ui/core/TableRow';
import TableCell from '@material-ui/core/TableCell';
import IconButton from '@material-ui/core/IconButton';
import CircularProgress from '@material-ui/core/CircularProgress';
import ExpandMoreIcon from '@material-ui/icons/ExpandMore';
import purple from '@material-ui/core/colors/purple';
import ResultTableHead from './ResultTableHead';
import TablePagination from '@material-ui/core/TablePagination';
import ResultTablePaginationActions from './ResultTablePaginationActions';
height: 'auto',
[theme.breakpoints.up('md')]: {
},
backgroundColor: theme.palette.background.paper,
paginationRoot: {
display: 'flex',
borderTop: '1px solid rgba(224, 224, 224, 1);',
},
paginationCaption: {
minWidth: 94
},
paginationToolbar: {
[theme.breakpoints.down('xs')]: {
display: 'flex',
flexWrap: 'wrap',
height: 100
},
},
progressContainer: {
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
},
paddingTop: 0,
paddingBottom: 0
},
expand: {
transform: 'rotate(0deg)',
marginLeft: 'auto',
transition: theme.transitions.create('transform', {
duration: theme.transitions.duration.shortest,
}),
},
expandOpen: {
transform: 'rotate(180deg)',
},
});
class ResultTable extends React.Component {
constructor(props) {
super(props);
this.state = {
expandedRows: new Set(),
};
}
componentDidMount = () => {
let page;
// first check if page was given as url parameter
if (this.props.routeProps.location.search === '') {
page = this.props.data.page === -1 ? 0 : this.props.data.page;
} else {
const qs = this.props.routeProps.location.search.replace('?', '');
page = parseInt(querystring.parse(qs).page);
}
// then update app state and url accordingly
this.props.updatePage(this.props.resultClass, page);
pathname: `/${this.props.resultClass}/faceted-search/table`,
// check if facet updates have been made before
if (this.props.facetUpdateID > 0) {
this.fetchResults();
}
componentDidUpdate = prevProps => {
// always fetch new results when page has updated
if (prevProps.data.page != this.props.data.page) {
pathname: `/${this.props.resultClass}/faceted-search/table`,
});
}
// when sort property or direction changes, return to first page
if (this.needNewResults(prevProps)) {
this.fetchResults();
} else {
this.props.updatePage(this.props.resultClass, 0);
window.onpopstate = () => {
const qs = this.props.routeProps.location.search.replace('?', '');
const newPage = parseInt(querystring.parse(qs).page);
if (newPage != this.props.data.page) {
this.props.updatePage(this.props.resultClass, newPage);
}
};
}
fetchResults = () => {
this.props.fetchPaginatedResults(this.props.resultClass, this.props.facetClass, this.props.data.sortBy, this.props.variant);
}
needNewResults = prevProps => {
return (
prevProps.data.sortBy != this.props.data.sortBy
|| prevProps.data.sortDirection != this.props.data.sortDirection
|| prevProps.facetUpdateID != this.props.facetUpdateID
|| prevProps.data.pagesize != this.props.data.pagesize
}
handleChangePage = (event, page) => {
if (event != null && !this.props.data.fetching) {
this.props.updatePage(this.props.resultClass, page);
}
handleOnChangeRowsPerPage = event => {
const rowsPerPage = event.target.value;
if (rowsPerPage != this.props.data.pagesize) {
this.props.updateRowsPerPage(this.props.resultClass, rowsPerPage);
}
}
handleSortBy = sortBy => event => {
if (event != null) {
this.props.sortResults(this.props.resultClass, sortBy);
handleExpandRow = rowId => () => {
let expandedRows = this.state.expandedRows;
if (expandedRows.has(rowId)) {
expandedRows.delete(rowId);
} else {
expandedRows.add(rowId);
}
this.setState({ expandedRows});
rowRenderer = row => {
const { classes } = this.props;
const expanded = this.state.expandedRows.has(row.id);
let hasExpandableContent = false;
const dataCells = this.props.data.properties.map(column => {
if (column.onlyOnInstancePage) { return null; }
const columnData = row[column.id] == null ? '-' : row[column.id];
const isArray = Array.isArray(columnData);
if (isArray) {
hasExpandableContent = true;
}
if (!isArray
&& column.valueType === 'string'
&& column.collapsedMaxWords
&& columnData.split(' ').length > column.collapsedMaxWords
) {
hasExpandableContent = true;
}
return (
<ResultTableCell
key={column.id}
columnId={column.id}
valueType={column.valueType}
makeLink={column.makeLink}
externalLink={column.externalLink}
sortValues={column.sortValues}
numberedList={column.numberedList}
minWidth={column.minWidth}
container='cell'
expanded={expanded}
linkAsButton={has(column, 'linkAsButton')
? column.linkAsButton
: null
}
collapsedMaxWords={has(column, 'collapsedMaxWords')
? column.collapsedMaxWords
: null
}
return (
<TableRow key={row.id}>
{hasExpandableContent &&
<IconButton
className={clsx(classes.expand, {
[classes.expandOpen]: expanded,
})}
onClick={this.handleExpandRow(row.id)}
aria-expanded={expanded}
aria-label="Show more"
>
<ExpandMoreIcon />
</IconButton>
}
</TableRow>
);
}
const { resultCount, paginatedResults, page, pagesize, sortBy, sortDirection, fetching } = this.props.data;
<TablePagination
component='div'
classes={{
root: classes.paginationRoot,
caption: classes.paginationCaption,
}}
count={resultCount}
rowsPerPage={pagesize}
labelRowsPerPage={intl.get('table.rowsPerPage')}
rowsPerPageOptions={[5, 10, 15, 25, 30, 50, 100]}
page={page == -1 || resultCount == 0 ? 0 : page}
onChangePage={this.handleChangePage}
onChangeRowsPerPage={this.handleOnChangeRowsPerPage}
ActionsComponent={ResultTablePaginationActions}
/>
<div className={classes.tableContainer}>
{fetching ?
<div className={classes.progressContainer}>
<CircularProgress style={{ color: purple[500] }} thickness={5} />
</div>
:
resultClass={this.props.resultClass}
columns={this.props.data.properties}
onSortBy={this.handleSortBy}
sortBy={sortBy}
sortDirection={sortDirection}
routeProps={this.props.routeProps}
/>
<TableBody>
{paginatedResults.map(row => this.rowRenderer(row))}
</TableBody>
</Table>
}
</div>
</React.Fragment>
}
}
ResultTable.propTypes = {
classes: PropTypes.object.isRequired,
resultClass: PropTypes.string.isRequired,
facetClass: PropTypes.string.isRequired,
fetchPaginatedResults: PropTypes.func.isRequired,
sortResults: PropTypes.func.isRequired,
updateRowsPerPage: PropTypes.func.isRequired,
routeProps: PropTypes.object.isRequired
};
export default withStyles(styles)(ResultTable);