Commit 8c434d65 authored by Matija Obreza's avatar Matija Obreza
Browse files

Split PagedLoader to TableInfiniteLoader and InfiniteLoader

parent 2819a976
......@@ -8,7 +8,6 @@ import {ScrollToTopOnMount} from 'ui/common/page/scrollers';
interface IProps<T> extends React.Props<any> {
paged: Page<T>;
colSpan?: number; // if in table, set the colSpan to render <tr><td colSpan=...
roughItemHeight?: number; // px of height of element, defaults to 50px, determines when loadNextPage is called
itemRenderer: (item: T, index?: number) => any;
loadingIndicator?: any;
......@@ -36,14 +35,13 @@ export default class PagedLoader<T> extends React.Component<IProps<T>, any> {
}
public render() {
const { paged, itemRenderer, loadingIndicator, colSpan, roughItemHeight } = this.props;
const { paged, itemRenderer, loadingIndicator, roughItemHeight } = this.props;
if (! paged || ! paged.content || paged.content.length === 0) {
return null;
}
console.log(`Rendering ${paged.content.length} items`);
const inTable = colSpan ? true : false;
const visibilityOffset = (roughItemHeight && roughItemHeight || 50) * (paged.size * .4);
const myLoadingIndicator = loadingIndicator || <Loading />;
// log(`Visibility offset bottom: ${-visibilityOffset}`);
......@@ -51,14 +49,7 @@ export default class PagedLoader<T> extends React.Component<IProps<T>, any> {
const result = [
<ScrollToTopOnMount key="PAGED_LOADER_SCROLL" />,
...paged.content.map((item: T, index) => itemRenderer(item, index)),
inTable ? (
<tr key="pagedLoaderLastItem">
<td colSpan={ colSpan }>
<VisibilitySensor offset={ { bottom: -visibilityOffset } } onChange={ this.endOfListVisibilityChange } />
{ ! paged.last ? <div>{ myLoadingIndicator }</div> : null }
</td>
</tr>
) : (
(
<div key="pagedLoaderLastItem">
<VisibilitySensor offset={ { bottom: -visibilityOffset } } onChange={ this.endOfListVisibilityChange } />
{ ! paged.last ? myLoadingIndicator : null }
......
import * as React from 'react';
import {log} from 'utilities/debug';
import Page from 'model/Page';
import * as VisibilitySensor from 'react-visibility-sensor';
import Loading from 'ui/common/Loading';
import {ScrollToTopOnMount} from 'ui/common/page/scrollers';
interface IProps<T> extends React.Props<any> {
paged: Page<T>;
colSpan: number; // if in table, set the colSpan to render Loader as <tr><td colSpan=...
roughItemHeight?: number; // px of height of element, defaults to 50px, determines when loadNextPage is called
itemRenderer: (item: T, index?: number) => any;
loadingIndicator?: any;
loadPage: (page: number, pageSize: number) => Promise<Page<T>>;
}
export default class TableInfiniteLoader<T> extends React.Component<IProps<T>, any> {
public componentWillMount() {
// ?
}
private endOfListVisibilityChange = (isVisible: boolean): void => {
const { paged, loadPage } = this.props;
// log(`Visibility ${isVisible}`);
if (paged && isVisible) {
// we should load some stuff
if (paged && paged.content && paged.totalElements > paged.content.length) {
log('Calling for next page', paged.number + 1);
loadPage(paged.number + 1, paged.size);
}
}
}
public render() {
const { paged, itemRenderer, loadingIndicator, colSpan, roughItemHeight } = this.props;
if (! paged || ! paged.content || paged.content.length === 0) {
return null;
}
console.log(`Rendering ${paged.content.length} items`);
const visibilityOffset = (roughItemHeight && roughItemHeight || 50) * (paged.size * .4);
const myLoadingIndicator = loadingIndicator || <Loading />;
// log(`Visibility offset bottom: ${-visibilityOffset}`);
const result = [
<ScrollToTopOnMount key="PAGED_LOADER_SCROLL" />,
...paged.content.map((item: T, index) => itemRenderer(item, index)),
(
<tr key="pagedLoaderLastItem">
<td colSpan={ colSpan }>
<VisibilitySensor offset={ { bottom: -visibilityOffset } } onChange={ this.endOfListVisibilityChange } />
{ ! paged.last ? <div>{ myLoadingIndicator }</div> : null }
</td>
</tr>
),
];
// log('Done rendering');
return result;
}
}
import * as React from 'react';
import { translate } from 'react-i18next';
import FastForward from '@material-ui/icons/FastForward';
import FastRewind from '@material-ui/icons/FastRewind';
import PlayArrow from '@material-ui/icons/PlayArrow';
import Button from '@material-ui/core/Button';
import Grid from '@material-ui/core/Grid';
import {StyleRules, withStyles} from '@material-ui/core/styles';
import { StyleRules, withStyles } from '@material-ui/core/styles';
import Select from '@material-ui/core/Select';
import Input from '@material-ui/core/Input';
import MenuItem from '@material-ui/core/MenuItem';
import compose from 'recompose/compose';
import withWidth from '@material-ui/core/withWidth';
import Hidden from '@material-ui/core/Hidden';
import {Breakpoint} from '@material-ui/core/styles/createBreakpoints';
import Number from 'ui/common/Number';
import { Breakpoint } from '@material-ui/core/styles/createBreakpoints';
import Page from 'model/Page';
interface IPaginationComponentProps extends React.ClassAttributes<any> {
classes: any;
t: any;
width: Breakpoint;
pageObj: Page<any>;
onChange: (page?: number, results?: number, sortBy?: string, dir?: string) => void;
onSortChange: (sortBy?: string, dir?: string) => void;
displayName: string;
sortBy?: string;
sortOptions?: object;
infinite?: boolean;
}
const styles = (theme) => ({
......@@ -133,13 +127,20 @@ const styles = (theme) => ({
},
}) as StyleRules;
const results = [5, 10, 20, 40, 50, 75, 100];
const mobile = ['sm', 'xs'] as Breakpoint[];
class PaginationComponent extends React.Component<IPaginationComponentProps, any> {
private fireSortChange = (sortBy) => {
const { onSortChange, sortOptions } = this.props;
// console.log('Sort change', sortBy, sortOptions[sortBy]);
if (sortBy && sortOptions && sortOptions[sortBy] && typeof sortOptions[sortBy] !== 'string') {
onSortChange(sortOptions[sortBy].property || sortBy, sortOptions[sortBy].direction);
} else {
onSortChange(sortBy);
}
}
public render() {
const { t, classes, displayName, width, pageObj, onChange, sortOptions, infinite } = this.props;
const { t, classes, displayName, pageObj, sortOptions } = this.props;
let { sortBy } = this.props;
......@@ -172,17 +173,6 @@ class PaginationComponent extends React.Component<IPaginationComponentProps, any
sortBy = '';
}
const isMobile = mobile.indexOf(width) !== -1;
const fireSortChange = (page, results, sortBy) => {
console.log('Sort change', sortBy, sortOptions[sortBy]);
if (sortBy && sortOptions && sortOptions[sortBy] && typeof sortOptions[sortBy] !== 'string') {
onChange(page, results, sortOptions[sortBy].property || sortBy, sortOptions[sortBy].direction);
} else {
onChange(page, results, sortBy);
}
};
return (
<Grid container spacing={ 0 } className={ classes.root }>
<Grid item xs={ 12 }>
......@@ -190,131 +180,45 @@ class PaginationComponent extends React.Component<IPaginationComponentProps, any
{ t(pageObj && pageObj.totalElements < 10000 ? 'common:paginate.numberOfItems' : 'common:paginate.estimatedNumberOfItems',
{ count: pageObj ? pageObj.totalElements : '', what: t(displayName || 'common:label.item', { count: pageObj ? pageObj.totalElements : 0 }) }) }
</div>
{ ! infinite &&
<Select
value={ pageObj ? pageObj.size : 10 }
onChange={
(e: any) => { // tslint:disable-line
fireSortChange(0, e.target.value, sortBy);
}
}
className={ `float-left pr-5 ${classes.showResults} ${classes.bold}` }
input={ <Input id="results-count"/> }
MenuProps={ {
PaperProps: {
style: {
width: 188,
},
},
} }
>
{
results.map((e, i) => (
<MenuItem key={ i } value={ e } className={ classes.liItem }>
{ isMobile ? e : `Show ${e} results` }
</MenuItem>
))
}
</Select>
}
{
sortOptions && (
<Select
value={ sortBy }
displayEmpty
onChange={
(e: any) => { // tslint:disable-line
fireSortChange(0, pageObj ? pageObj.size : 10, e.target.value);
}
{ sortOptions && (
<Select
value={ sortBy }
displayEmpty
onChange={
(e: any) => { // tslint:disable-line
this.fireSortChange(e.target.value);
}
className={ `float-right pl-5 ${classes.showResults} ${classes.bold}` }
input={ <Input id="sort-by"/> }
MenuProps={ {
PaperProps: {
style: {
width: 250,
},
}
className={ `float-right pl-5 ${classes.showResults} ${classes.bold}` }
input={ <Input id="sort-by"/> }
MenuProps={ {
PaperProps: {
style: {
width: 250,
},
} }
>
<MenuItem value="" className={ classes.liItem }>{ t('common:label.sortBy') }</MenuItem>
{
Object.keys(sortOptions).map((key, i) => {
if (typeof sortOptions[key] === 'string') {
return (
<MenuItem key={ i } value={ key } className={ classes.liItem }>
{ t(sortOptions[key]) }
</MenuItem>
);
} else {
return (
<MenuItem key={ i } value={ key } className={ classes.liItem }>
{ t(sortOptions[key].label) }
</MenuItem>
);
}
})
}
</Select>
)
}
{ ! infinite &&
<div className={ isMobile ? classes.floatRight : classes.floatLeft }>
<Hidden implementation="css" mdUp className={ isMobile ? classes.inline : '' }>
<span className={ classes.verticalAlign }>
<span className={ classes.bold }>{ pageObj ? pageObj.number + 1 : 0 }</span>/{ pageObj ? pageObj.totalPages : 0 }
</span>
</Hidden>
<Hidden implementation="css" only={ mobile } className={ classes.inline }>
<Button
variant="fab"
color="inherit"
disabled={ ! pageObj || pageObj.first }
className={ classes.paginationBut }
onClick={ fireSortChange.bind(this, 0, pageObj ? pageObj.size : 10, sortBy) }
>
<FastRewind/>
</Button>
</Hidden>
<Button
variant="fab"
color="inherit"
disabled={ ! pageObj || pageObj.first }
className={ classes.paginationBut }
onClick={ fireSortChange.bind(this, pageObj ? pageObj.number - 1 : 0, pageObj ? pageObj.size : 10, sortBy) }
>
<PlayArrow className={ classes.arrowRevert }/>
</Button>
<Hidden implementation="js" only={ mobile } className={ classes.inline }>
<span className={ `${classes.checkedPage} ${classes.bold}` }>
{ pageObj ? pageObj.number + 1 : 0 }
</span>
</Hidden>
<Button
variant="fab"
color="inherit"
disabled={ ! pageObj || pageObj.last }
className={ classes.paginationBut }
onClick={ fireSortChange.bind(this, pageObj ? pageObj.number + 1 : 1, pageObj ? pageObj.size : 10, sortBy) }
},
} }
>
<PlayArrow/>
</Button>
<Hidden implementation="css" only={ mobile } className={ classes.inline }>
<Button
variant="fab"
color="inherit"
disabled={ ! pageObj || pageObj.last }
className={ classes.paginationBut }
onClick={ fireSortChange.bind(this, pageObj ? pageObj.totalPages - 1 : 0, pageObj ? pageObj.size : 10, sortBy) }
>
<FastForward/>
</Button>
</Hidden>
<Hidden implementation="css" only={ mobile } className={ classes.inline }>
<span className={ classes.verticalAlign }>of <Number value={ pageObj ? pageObj.totalPages : 0 } /> pages</span>
</Hidden>
</div>
}
<MenuItem value="" className={ classes.liItem }>{ t('common:label.sortBy') }</MenuItem>
{
Object.keys(sortOptions).map((key, i) => {
if (typeof sortOptions[key] === 'string') {
return (
<MenuItem key={ i } value={ key } className={ classes.liItem }>
{ t(sortOptions[key]) }
</MenuItem>
);
} else {
return (
<MenuItem key={ i } value={ key } className={ classes.liItem }>
{ t(sortOptions[key].label) }
</MenuItem>
);
}
})
}
</Select>
) }
</Grid>
</Grid>
);
......
......@@ -7,7 +7,7 @@ import Grid from '@material-ui/core/Grid';
import {Table, TableRow, TableCell} from 'ui/common/tables';
import PaginationComponent from 'ui/common/pagination';
import { ScrollToTopOnMount } from 'ui/common/page/scrollers';
import PagedLoader from 'ui/common/PagedLoader';
import TableInfiniteLoader from 'ui/common/TableInfiniteLoader';
import Loading from 'ui/common/Loading';
import Page from 'model/Page';
......@@ -69,7 +69,7 @@ function MyDataTable({
{ headerProps.map((prop) => <TableCell key={ prop.title } style={ {maxWidth: prop.width} }>{ t(prop.title) }</TableCell>) }
</TableRow>
) }>
<PagedLoader
<TableInfiniteLoader
paged={ paged }
loadPage={ loadNextPage }
roughItemHeight={ 100 }
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment