index.tsx 11.2 KB
Newer Older
1
2
3
4
5
6
import * as React from 'react';
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/Button';
import Grid from 'material-ui/Grid';
Valeriy Panov's avatar
Valeriy Panov committed
7
import {StyleRules, withStyles} from 'material-ui/styles';
Valeriy Panov's avatar
Valeriy Panov committed
8
9
import Select from 'material-ui/Select';
import Input from 'material-ui/Input';
10
11
12
13
14
import {MenuItem} from 'material-ui/Menu';
import compose from 'recompose/compose';
import withWidth from 'material-ui/utils/withWidth';
import Hidden from 'material-ui/Hidden';
import {Breakpoint} from 'material-ui/styles/createBreakpoints';
Matija Obreza's avatar
Matija Obreza committed
15
import Number from 'ui/common/Number';
16
import {Page} from 'model/common.model';
17

Valeriy Panov's avatar
Valeriy Panov committed
18
interface IPaginationComponentProps extends React.ClassAttributes<any> {
19
    classes: any;
20
    width: Breakpoint;
Valeriy Panov's avatar
Valeriy Panov committed
21
    pageObj: Page<any>;
22
    onChange: (page?: number, results?: number, sortBy?: string, dir?: string) => void;
23
    displayName: string;
24
    sortBy?: string;
25
    sortOptions?: object;
26
27
}

Svetlana Alieksieieva's avatar
Svetlana Alieksieieva committed
28
const styles = (theme) => ({
29
30
    root: {
        backgroundColor: '#D4D2C6',
Svetlana Alieksieieva's avatar
Svetlana Alieksieieva committed
31
        padding: '1px 20px 1px',
32
        fontFamily: 'Roboto',
33
34
35
36
37
38
39
40
41
42
    },
    arrowRevert: {
        webkitTransform: 'rotate(180deg)',
        transform: 'rotate(180deg)',
    },
    checkedPage: {
        width: '50px',
        borderBottom: '1px solid black',
        display: 'inline-block',
        textAlign: 'center',
43
44
45
46
        padding: '0 0 3px',
        margin: '0 8px',
        position: 'relative',
        bottom: '2px',
47
    },
48
    /* tslint:disable */
49
    paginationBut: {
50
51
52
53
54
55
56
57
58
        backgroundColor: '#e8e6e0',
        width: '30px',
        height: '30px',
        margin: '10px 5px',
        minHeight: 'auto',
        '& > span > svg': {
            width: '17px',
            height: '17px',
        },
59
60
    },
    showResults: {
Svetlana Alieksieieva's avatar
Svetlana Alieksieieva committed
61
        float: 'right',
62
        marginTop: '12px',
63
        marginLeft: '12px',
64
65
        '& > div > div': {
            marginRight: '35px',
Svetlana Alieksieieva's avatar
Svetlana Alieksieieva committed
66
67
68
            [theme.breakpoints.down('md')]: {
                marginRight: '0px',
            },
69
70
71
72
73
74
        },
        '& > div > svg': {
            top: '1px',
            width: '26px',
            height: '26px',
            color: '#050708',
Svetlana Alieksieieva's avatar
Svetlana Alieksieieva committed
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
            [theme.breakpoints.down('md')]: {
                top: '0px',
            },
        },
        '& > div > div:focus': {
            backgroundColor: 'transparent',
        },
        [theme.breakpoints.down('md')]: {
            border: '1px #e8e6e0 solid',
            borderRadius: '3px',
            padding: '2px 0 0 7px',
            margin: '9px 0 0 4px',
            '&:before': {
                content: 'none',
            },
        },
    },
    floatRight: {
        float: 'right',
        '&:after': {
            content: 'none',
        },
    },
    liItem: {
        height: '34px',
        fontSize: '14px',
        '&:focus': {
            backgroundColor: '#E8E5E0',
        },
        '&:hover': {
            backgroundColor: '#E8E5E0',
106
107
108
109
        },
    },
    /* tslint:enable */
    textPagination: {
Svetlana Alieksieieva's avatar
Svetlana Alieksieieva committed
110
        lineHeight: '50px',
111
112
113
    },
    bold: {
        fontWeight: 'bold',
114
    },
115
116
    floatLeft: {
        float: 'left',
Svetlana Alieksieieva's avatar
Svetlana Alieksieieva committed
117
118
119
120
121
122
123
124
        paddingRight: '5px',
    },
    verticalAlign: {
        verticalAlign: 'text-bottom',
        paddingLeft: '5px',
        [theme.breakpoints.down('md')]: {
            padding: '0 5px 0px 2px',
        },
125
    },
Svetlana Alieksieieva's avatar
Svetlana Alieksieieva committed
126
}) as StyleRules;
127

128
129
130
const results = [5, 10, 20, 40, 50, 75, 100];
const mobile = ['sm', 'xs'] as Breakpoint[];

Valeriy Panov's avatar
Valeriy Panov committed
131
class PaginationComponent extends React.Component<IPaginationComponentProps, any> {
132
133

    public render() {
134
135
136
137
138
        const {classes, displayName, width, pageObj, onChange, sortOptions} = this.props;
        let {sortBy} = this.props;

        if (!sortBy) {
          sortBy = pageObj && pageObj.sort ? pageObj.sort[0].property : null;
139
          if (sortBy && sortOptions && sortOptions[sortBy]) {
Matija Obreza's avatar
Matija Obreza committed
140
            // console.log('Using auto-detected sortBy', sortBy);
141
142
143
144
          } else {
            sortBy = '';
          }
        }
145
146

        const isMobile = mobile.indexOf(width) !== -1;
147

148
        const fireSortChange = (page, results, sortBy) => {
149
            if (sortBy && sortOptions && sortOptions[sortBy] && typeof sortOptions[sortBy] !== 'string') {
150
151
152
153
154
155
                onChange(page, results, sortBy, sortOptions[sortBy].dir);
            } else {
                onChange(page, results, sortBy);
            }
        };

156
        return (
Valeriy Panov's avatar
Valeriy Panov committed
157
            <Grid container spacing={ 0 } className={ classes.root }>
158
                <Grid item xs={ 12 }>
Svetlana Alieksieieva's avatar
Svetlana Alieksieieva committed
159
                    <div className={ `${classes.floatLeft} ${classes.bold} ${classes.textPagination}` }>
Matija Obreza's avatar
Matija Obreza committed
160
                        <Number value={ pageObj ? pageObj.totalElements : 0 } /> { displayName || 'items' }
161
                    </div>
Valeriy Panov's avatar
Valeriy Panov committed
162
                    <Select
163
                        value={ pageObj ? pageObj.size : 10 }
Valeriy Panov's avatar
Valeriy Panov committed
164
165
                        onChange={
                            (e: any) => { // tslint:disable-line
166
                                fireSortChange(0, e.target.value, sortBy);
Valeriy Panov's avatar
Valeriy Panov committed
167
168
                            }
                        }
Svetlana Alieksieieva's avatar
Svetlana Alieksieieva committed
169
                        className={ `${classes.floatRight} ${classes.showResults} ${classes.bold}` }
170
                        input={ <Input id="results-count"/> }
Svetlana Alieksieieva's avatar
Svetlana Alieksieieva committed
171
                        MenuProps={ {
172
173
174
175
                            PaperProps: {
                                style: {
                                    width: 188,
                                },
Svetlana Alieksieieva's avatar
Svetlana Alieksieieva committed
176
177
                            },
                        } }
Valeriy Panov's avatar
Valeriy Panov committed
178
                    >
179
180
                        {
                            results.map((e, i) => (
181
182
183
                                <MenuItem key={ i } value={ e } className={ classes.liItem }>
                                    { isMobile ? e : `Show ${e} results` }
                                </MenuItem>
184
185
                            ))
                        }
Valeriy Panov's avatar
Valeriy Panov committed
186
                    </Select>
187
188
189
190
191
192
193
                    {
                        sortOptions && (
                            <Select
                                value={ sortBy }
                                displayEmpty
                                onChange={
                                    (e: any) => { // tslint:disable-line
194
                                        fireSortChange(0, pageObj ? pageObj.size : 10, e.target.value);
195
196
197
198
199
200
201
202
203
204
205
206
207
208
                                    }
                                }
                                className={ `${classes.floatRight} ${classes.showResults} ${classes.bold}` }
                                input={ <Input id="sort-by"/> }
                                MenuProps={ {
                                    PaperProps: {
                                        style: {
                                            width: 188,
                                        },
                                    },
                                } }
                            >
                                <MenuItem value="" className={ classes.liItem }>Sort By</MenuItem>
                                {
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
                                    Object.keys(sortOptions).map((key, i) => {
                                      if (typeof sortOptions[key] === 'string') {
                                        return (
                                          <MenuItem key={ i } value={ key } className={ classes.liItem }>
                                              { sortOptions[key] }
                                          </MenuItem>
                                        );
                                      } else {
                                        return (
                                          <MenuItem key={ i } value={ key } className={ classes.liItem }>
                                              { sortOptions[key].label }
                                          </MenuItem>
                                        );
                                      }
                                    })
224
225
226
227
                                }
                            </Select>
                        )
                    }
228
                    <div className={ isMobile ? classes.floatRight : classes.floatLeft }>
Matija Obreza's avatar
Matija Obreza committed
229
                        <Hidden implementation="css" mdUp>
Svetlana Alieksieieva's avatar
Svetlana Alieksieieva committed
230
                            <span className={ classes.verticalAlign }>
231
                               <span className={ classes.bold }>{ pageObj ? pageObj.number + 1 : 0 }</span>/{ pageObj ? pageObj.totalPages : 0 }
232
233
                            </span>
                        </Hidden>
Matija Obreza's avatar
Matija Obreza committed
234
                        <Hidden implementation="css" only={ mobile }>
235
236
237
                            <Button
                                fab
                                color="inherit"
238
                                disabled={ ! pageObj || pageObj.first }
239
                                className={ classes.paginationBut }
240
                                onClick={ fireSortChange.bind(this, 0, pageObj ? pageObj.size : 10, sortBy) }
241
242
243
244
245
246
247
                            >
                                <FastRewind/>
                            </Button>
                        </Hidden>
                        <Button
                            fab
                            color="inherit"
248
                            disabled={ ! pageObj || pageObj.first }
249
                            className={ classes.paginationBut }
250
                            onClick={ fireSortChange.bind(this, pageObj ? pageObj.number - 1 : 0, pageObj ? pageObj.size : 10, sortBy) }
251
252
253
                        >
                            <PlayArrow className={ classes.arrowRevert }/>
                        </Button>
Matija Obreza's avatar
Matija Obreza committed
254
                        <Hidden implementation="css" only={ mobile }>
Svetlana Alieksieieva's avatar
Svetlana Alieksieieva committed
255
                            <span className={ `${classes.checkedPage} ${classes.bold}` }>
256
                                { pageObj ? pageObj.number + 1 : 0 }
257
258
259
260
261
                            </span>
                        </Hidden>
                        <Button
                            fab
                            color="inherit"
262
                            disabled={ ! pageObj || pageObj.last }
263
                            className={ classes.paginationBut }
264
                            onClick={ fireSortChange.bind(this, pageObj ? pageObj.number + 1 : 1, pageObj ? pageObj.size : 10, sortBy) }
265
266
267
                        >
                            <PlayArrow/>
                        </Button>
Matija Obreza's avatar
Matija Obreza committed
268
                        <Hidden implementation="css" only={ mobile }>
269
270
271
                            <Button
                                fab
                                color="inherit"
272
                                disabled={ ! pageObj || pageObj.last }
273
                                className={ classes.paginationBut }
274
                                onClick={ fireSortChange.bind(this, pageObj ? pageObj.totalPages - 1 : 0, pageObj ? pageObj.size : 10, sortBy) }
275
276
277
278
                            >
                                <FastForward/>
                            </Button>
                        </Hidden>
Matija Obreza's avatar
Matija Obreza committed
279
                        <Hidden implementation="css" only={ mobile }>
Matija Obreza's avatar
Matija Obreza committed
280
                            <span className={ classes.verticalAlign }>of <Number value={ pageObj ? pageObj.totalPages : 0 } /> pages</span>
281
282
                        </Hidden>
                    </div>
283
284
285
                </Grid>
            </Grid>
        );
Matija Obreza's avatar
Matija Obreza committed
286
    }
287
288
}

289
export default compose(withStyles(styles), withWidth())(PaginationComponent);