Skip to content

Commit d79c167

Browse files
committed
refactor(pagination-table): moved table to its own component
1 parent 7352d39 commit d79c167

File tree

19 files changed

+349
-226
lines changed

19 files changed

+349
-226
lines changed

client/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
"axios": "^0.18.0",
99
"moment": "^2.24.0",
1010
"notistack": "0.5.0",
11-
"prop-types": "^15.7.2",
1211
"react": "^16.8.4",
1312
"react-big-calendar": "^0.20.3",
1413
"react-dom": "^16.8.0-alpha.1",
@@ -35,6 +34,7 @@
3534
],
3635
"proxy": "http://localhost:9000",
3736
"devDependencies": {
37+
"prop-types": "^15.7.2",
3838
"husky": "^1.3.1",
3939
"lint-staged": "^8.1.5",
4040
"prettier": "^1.16.4",

client/src/App.js

+5-5
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@ import * as PropTypes from 'prop-types';
44
import {MuiThemeProvider, withStyles} from '@material-ui/core/styles';
55
import CssBaseline from '@material-ui/core/CssBaseline';
66
import Hidden from '@material-ui/core/Hidden';
7-
import Navigator from './components/Navigator/Navigator';
8-
import Content from './components/Content/Content';
9-
import Header from './components/Header/Header';
10-
import LoginDialog from './components/application/LoginDialog/LoginDialog';
11-
import {SnackbarProvider, withSnackbar} from 'notistack';
7+
import Navigator from './frame/Navigator/Navigator';
8+
import Content from './frame/Content/Content';
9+
import Header from './frame/Header/Header';
10+
import LoginDialog from './application/LoginDialog/LoginDialog';
11+
import {SnackbarProvider} from 'notistack';
1212
import {BrowserRouter} from 'react-router-dom';
1313
import {connect} from 'react-redux';
1414
import {loginUser, toggleSidebar} from './redux/actions/login-actions';

client/src/components/application/Holidays/Holidays.js client/src/application/Holidays/Holidays.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import BigCalendar from 'react-big-calendar';
22
import moment from 'moment';
33
import React from 'react';
44
import {connect} from 'react-redux';
5-
import '../../../helpers/styles/react-big-calendar.css';
5+
import '../../helpers/styles/react-big-calendar.css';
66

77
const localize = BigCalendar.momentLocalizer(moment);
88
const Holidays = props => {
+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import React from 'react';
2+
import {connect} from 'react-redux';
3+
import {Button} from '@material-ui/core';
4+
import {toggleCalendar} from '../../redux/actions/leaves-actions';
5+
6+
const Leaves = props => {
7+
const {showCalendar, leaves} = props;
8+
9+
return (
10+
<>
11+
<Button onClick={() => props.toggleCalendar(showCalendar)}>{showCalendar ? 'View as Table' : 'View in Calendar'}</Button>
12+
</>
13+
);
14+
};
15+
16+
const mapStateToProps = state => {
17+
return {
18+
leaves: state.leaves.leaves,
19+
showCalendar: state.leaves.showCalendar
20+
};
21+
};
22+
23+
const mapDispatchToProps = dispatch => ({toggleCalendar: dispatch(toggleCalendar())});
24+
25+
export default connect(
26+
mapStateToProps,
27+
mapDispatchToProps
28+
)(Leaves);

client/src/components/application/LoginDialog/LoginDialog.js client/src/application/LoginDialog/LoginDialog.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,15 @@ import React, {useState} from 'react';
33
import AppBar from '@material-ui/core/AppBar/AppBar';
44
import Toolbar from '@material-ui/core/Toolbar/Toolbar';
55
import Typography from '@material-ui/core/Typography/Typography';
6-
import {loginDialogStyles} from '../../../helpers/styles/styles';
6+
import {loginDialogStyles} from '../../helpers/styles/styles';
77
import withStyles from '@material-ui/core/styles/withStyles';
88
import Paper from '@material-ui/core/Paper/Paper';
99
import TextField from '@material-ui/core/TextField/TextField';
1010
import Grid from '@material-ui/core/Grid/Grid';
1111
import Fab from '@material-ui/core/Fab/Fab';
1212
import NavigationIcon from '@material-ui/icons/Navigation';
1313
import axios from 'axios';
14-
import {apiUrls} from '../../../helpers/Constants/Constants';
14+
import {apiUrls} from '../../helpers/Constants/Constants';
1515
import {withSnackbar} from 'notistack';
1616
import Slide from '@material-ui/core/Slide/Slide';
1717

client/src/application/Users/Users.js

+59
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import React from 'react';
2+
import PaginationTable from '../../components/PaginationTable/PaginationTable';
3+
4+
class Users extends React.Component {
5+
state = {
6+
rows: [
7+
{label: 'Name', loggedHours: 'Logged Hours', leaves: 'Leaves', leavesLeft: 'Leaves Left', overtime: 'Overtime'},
8+
{label: 'A', loggedHours: 305, leaves: 0, leavesLeft: 30, overtime: 3.7},
9+
{label: 'B', loggedHours: 452, leaves: 0, leavesLeft: 30, overtime: 25.0},
10+
{label: 'C', loggedHours: 262, leaves: 0, leavesLeft: 30, overtime: 16.0},
11+
{label: 'D', loggedHours: 159, leaves: 0, leavesLeft: 30, overtime: 6.0},
12+
{label: 'E', loggedHours: 356, leaves: 0, leavesLeft: 30, overtime: 16.0},
13+
{label: 'F', loggedHours: 408, leaves: 0, leavesLeft: 30, overtime: 3.2},
14+
{label: 'G', loggedHours: 237, leaves: 0, leavesLeft: 30, overtime: 9.0},
15+
{label: 'H', loggedHours: 375, leaves: 0, leavesLeft: 30, overtime: 0.0},
16+
{label: 'I', loggedHours: 518, leaves: 0, leavesLeft: 30, overtime: 26.0},
17+
{label: 'J', loggedHours: 392, leaves: 0, leavesLeft: 30, overtime: 0.2}
18+
],
19+
page: 0,
20+
rowsPerPage: 10,
21+
order: 'asc',
22+
orderBy: 'label'
23+
};
24+
handleChangePage = (event, page) => {
25+
this.setState({page});
26+
};
27+
28+
handleChangeRowsPerPage = event => {
29+
this.setState({page: 0, rowsPerPage: event.target.value});
30+
};
31+
handleRequestSort = (event, property) => {
32+
const orderBy = property;
33+
let order = 'desc';
34+
35+
if (this.state.orderBy === property && this.state.order === 'desc') {
36+
order = 'asc';
37+
}
38+
39+
this.setState({order, orderBy});
40+
};
41+
42+
render() {
43+
const {rows, rowsPerPage, page, order, orderBy} = this.state;
44+
return (
45+
<PaginationTable
46+
rows={rows}
47+
handleChangePage={this.handleChangePage}
48+
handleChangeRowsPerPage={this.handleChangeRowsPerPage}
49+
rowsPerPage={rowsPerPage}
50+
handleRequestSort={this.handleRequestSort}
51+
order={order}
52+
orderBy={orderBy}
53+
page={page}
54+
/>
55+
);
56+
}
57+
}
58+
59+
export default Users;

client/src/components/Content/Content.js

-28
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import React from 'react';
2+
import * as PropTypes from 'prop-types';
3+
import TableRow from '@material-ui/core/TableRow';
4+
import TableCell from '@material-ui/core/TableCell';
5+
import Tooltip from '@material-ui/core/Tooltip';
6+
import TableSortLabel from '@material-ui/core/TableSortLabel';
7+
import TableHead from '@material-ui/core/TableHead';
8+
9+
class EnhancedTableHead extends React.Component {
10+
createSortHandler = property => event => {
11+
this.props.onRequestSort(event, property);
12+
};
13+
render() {
14+
const {order, orderBy, rows} = this.props;
15+
const firstRow = rows ? rows.slice(0, 1)[0] : {};
16+
return (
17+
<TableHead>
18+
<TableRow>
19+
{Object.keys(firstRow).map(
20+
key => (
21+
<TableCell
22+
key={key}
23+
align={key.numeric ? 'right' : 'left'}
24+
padding={key.disablePadding ? 'none' : 'default'}
25+
sortDirection={orderBy === key ? order : false}>
26+
<Tooltip title="Sort" placement={key.numeric ? 'bottom-end' : 'bottom-start'} enterDelay={300}>
27+
<TableSortLabel active={orderBy === key} direction={order} onClick={this.createSortHandler(key)}>
28+
{firstRow[key]}
29+
</TableSortLabel>
30+
</Tooltip>
31+
</TableCell>
32+
),
33+
this
34+
)}
35+
</TableRow>
36+
</TableHead>
37+
);
38+
}
39+
}
40+
41+
EnhancedTableHead.propTypes = {
42+
rows: PropTypes.array.isRequired,
43+
onRequestSort: PropTypes.func.isRequired,
44+
order: PropTypes.string.isRequired,
45+
orderBy: PropTypes.string.isRequired
46+
};
47+
48+
export default EnhancedTableHead;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
import TablePaginationActions from '@material-ui/core/TablePagination/TablePaginationActions';
2+
import React from 'react';
3+
import TableBody from '@material-ui/core/TableBody';
4+
import Table from '@material-ui/core/Table';
5+
import TableRow from '@material-ui/core/TableRow';
6+
import TableCell from '@material-ui/core/TableCell';
7+
import TableFooter from '@material-ui/core/TableFooter';
8+
import TablePagination from '@material-ui/core/TablePagination';
9+
import {userTableStyles} from '../../helpers/styles/styles';
10+
import {withStyles} from '@material-ui/core';
11+
import * as PropTypes from 'prop-types';
12+
import EnhancedTableHead from '../EnhancedTableHeader/EnhancedTableHeader';
13+
14+
function desc(a, b, orderBy) {
15+
if (b[orderBy] < a[orderBy]) {
16+
return -1;
17+
}
18+
if (b[orderBy] > a[orderBy]) {
19+
return 1;
20+
}
21+
return 0;
22+
}
23+
24+
function stableSort(array, cmp) {
25+
const stabilizedThis = array.map((el, index) => [el, index]);
26+
stabilizedThis.sort((a, b) => {
27+
const order = cmp(a[0], b[0]);
28+
if (order !== 0) return order;
29+
return a[1] - b[1];
30+
});
31+
return stabilizedThis.map(el => el[0]);
32+
}
33+
34+
function getSorting(order, orderBy) {
35+
return order === 'desc' ? (a, b) => desc(a, b, orderBy) : (a, b) => -desc(a, b, orderBy);
36+
}
37+
38+
const PaginationTable = props => {
39+
const {classes, rows, rowsPerPage, page, order, orderBy} = props;
40+
const filteredRows = rows.filter((_, index) => index !== 0);
41+
const emptyRows = rowsPerPage - Math.min(rowsPerPage, rows.length - page * rowsPerPage);
42+
return (
43+
<Table className={classes.table}>
44+
<EnhancedTableHead numSelected={0} onRequestSort={props.handleRequestSort} order={order} orderBy={orderBy} rows={rows} />
45+
<TableBody>
46+
{stableSort(filteredRows, getSorting(order, orderBy))
47+
.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage)
48+
.map(row => (
49+
<TableRow key={row.id}>
50+
{Object.values(row).map(value => (
51+
<TableCell component="th" scope="row">
52+
{value}
53+
</TableCell>
54+
))}
55+
</TableRow>
56+
))}
57+
{emptyRows > 0 && (
58+
<TableRow style={{height: 48 * emptyRows}}>
59+
<TableCell colSpan={6} />
60+
</TableRow>
61+
)}
62+
</TableBody>
63+
<TableFooter>
64+
<TableRow>
65+
<TablePagination
66+
rowsPerPageOptions={[5, 10, 25]}
67+
colSpan={5}
68+
count={rows.length}
69+
rowsPerPage={rowsPerPage}
70+
page={page}
71+
SelectProps={{
72+
native: true
73+
}}
74+
onChangePage={() => props.handleChangePage}
75+
onChangeRowsPerPage={() => props.handleChangeRowsPerPage}
76+
ActionsComponent={TablePaginationActions}
77+
/>
78+
</TableRow>
79+
</TableFooter>
80+
</Table>
81+
);
82+
};
83+
84+
PaginationTable.propTypes = {
85+
classes: PropTypes.object.isRequired,
86+
rows: PropTypes.array.isRequired,
87+
rowsPerPage: PropTypes.number.isRequired,
88+
page: PropTypes.number.isRequired,
89+
order: PropTypes.any,
90+
orderBy: PropTypes.any,
91+
handleChangePage: PropTypes.func.isRequired,
92+
handleChangeRowsPerPage: PropTypes.func.isRequired,
93+
handleRequestSort: PropTypes.func.isRequired
94+
};
95+
96+
export default withStyles(userTableStyles)(PaginationTable);

0 commit comments

Comments
 (0)