Newer
Older
piotr.kupczyk@id.ethz.ch
committed
import _ from 'lodash'
import React from 'react'
piotr.kupczyk@id.ethz.ch
committed
import { withStyles } from '@material-ui/core/styles'
piotr.kupczyk@id.ethz.ch
committed
import Typography from '@material-ui/core/Typography'
import FormControlLabel from '@material-ui/core/FormControlLabel'
piotr.kupczyk@id.ethz.ch
committed
import IconButton from '@material-ui/core/IconButton'
import FirstPageIcon from '@material-ui/icons/FirstPage'
import KeyboardArrowLeft from '@material-ui/icons/KeyboardArrowLeft'
import KeyboardArrowRight from '@material-ui/icons/KeyboardArrowRight'
import LastPageIcon from '@material-ui/icons/LastPage'
import SelectField from '@src/js/components/common/form/SelectField.jsx'
piotr.kupczyk@id.ethz.ch
committed
import GridPagingOptions from '@src/js/components/common/grid/GridPagingOptions.js'
piotr.kupczyk@id.ethz.ch
committed
import messages from '@src/js/common/messages.js'
piotr.kupczyk@id.ethz.ch
committed
import logger from '@src/js/common/logger.js'
piotr.kupczyk@id.ethz.ch
committed
const styles = theme => ({
piotr.kupczyk@id.ethz.ch
committed
container: {
piotr.kupczyk@id.ethz.ch
committed
display: 'flex',
alignItems: 'center',
piotr.kupczyk@id.ethz.ch
committed
flexShrink: 0
piotr.kupczyk@id.ethz.ch
committed
},
piotr.kupczyk@id.ethz.ch
committed
pageSize: {
piotr.kupczyk@id.ethz.ch
committed
marginLeft: -theme.spacing(2)
piotr.kupczyk@id.ethz.ch
committed
},
piotr.kupczyk@id.ethz.ch
committed
pageSizeLabelPlacement: {
piotr.kupczyk@id.ethz.ch
committed
marginRight: 0,
marginBottom: 0
piotr.kupczyk@id.ethz.ch
committed
},
pageSizeLabel: {
piotr.kupczyk@id.ethz.ch
committed
fontSize: theme.typography.body2.fontSize,
marginRight: '12px',
whiteSpace: 'nowrap',
lineHeight: '46px'
piotr.kupczyk@id.ethz.ch
committed
},
pageRange: {
piotr.kupczyk@id.ethz.ch
committed
marginLeft: theme.spacing(1),
marginRight: theme.spacing(2)
piotr.kupczyk@id.ethz.ch
committed
},
piotr.kupczyk@id.ethz.ch
committed
pagePrevButtons: {},
pageNextButtons: {},
separator: {
borderLeftWidth: '1px',
borderLeftStyle: 'solid',
borderLeftColor: theme.palette.border.secondary,
height: theme.spacing(3),
piotr.kupczyk@id.ethz.ch
committed
marginLeft: theme.spacing(2),
marginRight: theme.spacing(2)
piotr.kupczyk@id.ethz.ch
committed
}
})
piotr.kupczyk@id.ethz.ch
committed
class GridPaging extends React.PureComponent {
piotr.kupczyk@id.ethz.ch
committed
constructor(props) {
piotr.kupczyk@id.ethz.ch
committed
super(props)
this.handlePageSizeChange = this.handlePageSizeChange.bind(this)
this.handleFirstPageButtonClick = this.handleFirstPageButtonClick.bind(this)
this.handleBackButtonClick = this.handleBackButtonClick.bind(this)
this.handleNextButtonClick = this.handleNextButtonClick.bind(this)
this.handleLastPageButtonClick = this.handleLastPageButtonClick.bind(this)
}
piotr.kupczyk@id.ethz.ch
committed
handlePageSizeChange(event) {
piotr.kupczyk@id.ethz.ch
committed
this.props.onPageSizeChange(event.target.value)
}
handleFirstPageButtonClick() {
this.props.onPageChange(0)
}
handleBackButtonClick() {
this.props.onPageChange(this.props.page - 1)
}
handleNextButtonClick() {
this.props.onPageChange(this.props.page + 1)
}
handleLastPageButtonClick() {
piotr.kupczyk@id.ethz.ch
committed
this.props.onPageChange(
Math.max(0, Math.ceil(this.props.count / this.props.pageSize) - 1)
)
piotr.kupczyk@id.ethz.ch
committed
}
render() {
piotr.kupczyk@id.ethz.ch
committed
logger.log(logger.DEBUG, 'GridPaging.render')
piotr.kupczyk@id.ethz.ch
committed
const { id, classes, count, page, pageSize, showRowsPerPage } = this.props
const doShowRowsPerPage = typeof showRowsPerPage === 'boolean' ? showRowsPerPage : true
piotr.kupczyk@id.ethz.ch
committed
return (
<div className={classes.container}>
piotr.kupczyk@id.ethz.ch
committed
<div className={classes.pagePrevButtons}>
piotr.kupczyk@id.ethz.ch
committed
<IconButton
piotr.kupczyk@id.ethz.ch
committed
id={id + '.first-page-id'}
piotr.kupczyk@id.ethz.ch
committed
onClick={this.handleFirstPageButtonClick}
disabled={page === 0}
piotr.kupczyk@id.ethz.ch
committed
aria-label={messages.get(messages.FIRST_PAGE)}
piotr.kupczyk@id.ethz.ch
committed
data-part='firstPage'
piotr.kupczyk@id.ethz.ch
committed
>
<FirstPageIcon fontSize='small' />
piotr.kupczyk@id.ethz.ch
committed
</IconButton>
piotr.kupczyk@id.ethz.ch
committed
<IconButton
piotr.kupczyk@id.ethz.ch
committed
id={id + '.prev-page-id'}
piotr.kupczyk@id.ethz.ch
committed
onClick={this.handleBackButtonClick}
disabled={page === 0}
piotr.kupczyk@id.ethz.ch
committed
aria-label={messages.get(messages.PREVIOUS_PAGE)}
piotr.kupczyk@id.ethz.ch
committed
data-part='prevPage'
piotr.kupczyk@id.ethz.ch
committed
>
<KeyboardArrowLeft fontSize='small' />
piotr.kupczyk@id.ethz.ch
committed
</IconButton>
piotr.kupczyk@id.ethz.ch
committed
</div>
piotr.kupczyk@id.ethz.ch
committed
<div id={id + '.page-range-id'} className={classes.pageRange}>
piotr.kupczyk@id.ethz.ch
committed
<Typography variant='body2' data-part='range'>
{this.renderRange()}
</Typography>
</div>
<div className={classes.pageNextButtons}>
piotr.kupczyk@id.ethz.ch
committed
<IconButton
piotr.kupczyk@id.ethz.ch
committed
id={id + '.next-page-id'}
piotr.kupczyk@id.ethz.ch
committed
onClick={this.handleNextButtonClick}
disabled={page >= Math.ceil(count / pageSize) - 1}
piotr.kupczyk@id.ethz.ch
committed
aria-label={messages.get(messages.NEXT_PAGE)}
piotr.kupczyk@id.ethz.ch
committed
data-part='nextPage'
piotr.kupczyk@id.ethz.ch
committed
>
<KeyboardArrowRight fontSize='small' />
piotr.kupczyk@id.ethz.ch
committed
</IconButton>
<IconButton
piotr.kupczyk@id.ethz.ch
committed
id={id + '.last-page-id'}
piotr.kupczyk@id.ethz.ch
committed
onClick={this.handleLastPageButtonClick}
disabled={page >= Math.ceil(count / pageSize) - 1}
piotr.kupczyk@id.ethz.ch
committed
aria-label={messages.get(messages.LAST_PAGE)}
piotr.kupczyk@id.ethz.ch
committed
data-part='lastPage'
piotr.kupczyk@id.ethz.ch
committed
>
<LastPageIcon fontSize='small' />
piotr.kupczyk@id.ethz.ch
committed
</IconButton>
</div>
piotr.kupczyk@id.ethz.ch
committed
<div className={classes.separator}></div>
{doShowRowsPerPage && [
<div id={id + '.page-size-id'} key={id + '.page-size-id'} className={classes.pageSize}>
<FormControlLabel
control={
<SelectField
value={pageSize}
options={GridPagingOptions.PAGE_SIZE_OPTIONS.map(pageSize => ({
label: pageSize,
value: pageSize
}))}
onChange={this.handlePageSizeChange}
variant='standard'
/>
}
classes={{
label: classes.pageSizeLabel,
labelPlacementStart: classes.pageSizeLabelPlacement
}}
label={messages.get(messages.ROWS_PER_PAGE)}
labelPlacement='start'
piotr.kupczyk@id.ethz.ch
committed
/>
</div>,
<div key={id + '.separator'} className={classes.separator}></div>
]
}
piotr.kupczyk@id.ethz.ch
committed
</div>
)
}
piotr.kupczyk@id.ethz.ch
committed
renderRange() {
const { count, page, pageSize } = this.props
if (count === 0) {
return <span>{messages.get(messages.NO_RESULTS_FOUND)}</span>
} else if (count === 1) {
return <span>{messages.get(messages.RESULTS_RANGE, 1, 1)}</span>
} else {
const from = Math.min(count, page * pageSize + 1)
const to = Math.min(count, (page + 1) * pageSize)
return (
<span>
{messages.get(messages.RESULTS_RANGE, from + '-' + to, count)}
</span>
)
}
}
piotr.kupczyk@id.ethz.ch
committed
}
piotr.kupczyk@id.ethz.ch
committed
export default _.flow(withStyles(styles))(GridPaging)