Files
verver-client/src/components/user/UserList.js
T
Leonard Krause 586bff6e58 more layout fixes
2018-04-27 10:12:53 +02:00

283 lines
7.9 KiB
JavaScript

import React from "react";
import PropTypes from "prop-types";
import { withStyles } from "material-ui/styles";
import Table, {
TableHead,
TableBody,
TableCell,
TableFooter,
TablePagination,
TableRow
} from "material-ui/Table";
import IconButton from "material-ui/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 CreateIcon from "material-ui-icons/Create";
import { connect } from "react-redux";
import { translate } from "react-i18next";
import { Link } from "react-router-dom";
import { CircularProgress, Card, CardContent, Typography } from "material-ui";
import { apiMethod } from "../../config";
import { entity } from "../../lib/entity";
import {
getMeta,
getItems,
getIsFetching,
getTimeFetched
} from "../../redux/selectors";
import { fetchList } from "../../redux/actions";
import Screen from "../Screen";
const actionsStyles = theme => ({
root: {
flexShrink: 0,
color: theme.palette.text.secondary,
marginLeft: theme.spacing.unit * 2.5
}
});
class TablePaginationActions extends React.Component {
handleFirstPageButtonClick = event => {
this.props.onChangePage(event, 0);
};
handleBackButtonClick = event => {
this.props.onChangePage(event, this.props.page - 1);
};
handleNextButtonClick = event => {
this.props.onChangePage(event, this.props.page + 1);
};
handleLastPageButtonClick = event => {
this.props.onChangePage(event, this.props.totalPages - 1);
};
render() {
const { classes, page, theme, meta } = this.props;
return (
<div className={classes.root}>
<IconButton
onClick={this.handleFirstPageButtonClick}
disabled={page === 0}
aria-label="First Page"
>
{theme.direction === "rtl" ? <LastPageIcon /> : <FirstPageIcon />}
</IconButton>
<IconButton
onClick={this.handleBackButtonClick}
disabled={page === 0}
aria-label="Previous Page"
>
{theme.direction === "rtl" ? (
<KeyboardArrowRight />
) : (
<KeyboardArrowLeft />
)}
</IconButton>
<IconButton
onClick={this.handleNextButtonClick}
disabled={!meta.hasNext}
aria-label="Next Page"
>
{theme.direction === "rtl" ? (
<KeyboardArrowLeft />
) : (
<KeyboardArrowRight />
)}
</IconButton>
<IconButton
onClick={this.handleLastPageButtonClick}
disabled={page === meta.totalPages - 1}
aria-label="Last Page"
>
{theme.direction === "rtl" ? <FirstPageIcon /> : <LastPageIcon />}
</IconButton>
</div>
);
}
}
TablePaginationActions.propTypes = {
classes: PropTypes.object.isRequired,
count: PropTypes.number.isRequired,
onChangePage: PropTypes.func.isRequired,
page: PropTypes.number.isRequired,
rowsPerPage: PropTypes.number.isRequired,
theme: PropTypes.object.isRequired
};
const TablePaginationActionsWrapped = withStyles(actionsStyles, {
withTheme: true
})(TablePaginationActions);
const ConnectedTablePaginationActionsWrapped = connect(
state => ({ meta: getMeta(apiMethod.list)(entity.user)(state) }),
null
)(TablePaginationActionsWrapped);
const styles = theme => ({
progress: {
margin: theme.spacing.unit * 2
},
progressContainer: {
width: "100%",
flex: 1,
display: "flex",
flexDirection: "row",
justifyContent: "center"
},
card: {
height: "100%",
width: "100%",
padding: theme.spacing.unit * 2
},
root: {
width: "100%",
marginTop: theme.spacing.unit * 3
},
table: {
minWidth: 500
},
wrapper: {
flexGrow: 1,
display: "flex",
width: "100%"
},
tableWrapper: {
overflowX: "auto"
}
});
class UserList extends React.Component {
componentWillMount = () => {
const { fetchUserList, meta } = this.props;
const { page = 0, size = 10 } = meta || {};
fetchUserList({ page, size });
};
handleChangePage = (event, page) => {
const { fetchUserList, meta = {} } = this.props;
fetchUserList({ page, size: meta.size });
};
handleChangeSize = event => {
const { fetchUserList, meta = {} } = this.props;
fetchUserList({ page: meta.page, size: event.target.value });
};
render() {
const { classes, isLoading, users, meta = {}, t } = this.props;
const emptyRows = 0;
if (isLoading) {
return (
<Screen>
<div className={classes.progressContainer}>
<CircularProgress className={classes.progress} />
</div>
</Screen>
);
}
return (
<Screen>
<div className={classes.wrapper}>
<Card className={classes.card}>
<CardContent>
<Typography className={classes.title} color="textSecondary">
{t(`user.listScreen.title`)}
</Typography>
<Typography variant="headline" component="h2">
{t(`user.listScreen.headline`)}
</Typography>
</CardContent>
<CardContent>
<div className={classes.tableWrapper}>
<Table className={classes.table}>
<TableHead>
<TableRow>
<TableCell>{t("user.label.id")}</TableCell>
<TableCell>{t("user.label.username")}</TableCell>
<TableCell>{t("user.label.edit")}</TableCell>
</TableRow>
</TableHead>
<TableBody>
{users.map(user => {
return (
<TableRow key={user.id}>
<TableCell>{user.id}</TableCell>
<TableCell>{user.username}</TableCell>
<TableCell>
<Link to={`/user/edit/${user.id}`}>
<CreateIcon />
</Link>
</TableCell>
</TableRow>
);
})}
{emptyRows > 0 && (
<TableRow style={{ height: 48 * emptyRows }}>
<TableCell colSpan={6} />
</TableRow>
)}
</TableBody>
<TableFooter>
<TableRow>
<TablePagination
colSpan={3}
count={meta.totalElements}
rowsPerPage={meta.size}
page={meta.page}
onChangePage={this.handleChangePage}
onChangeRowsPerPage={this.handleChangeSize}
Actions={ConnectedTablePaginationActionsWrapped}
/>
</TableRow>
</TableFooter>
</Table>
</div>
</CardContent>
</Card>
</div>
</Screen>
);
}
}
const mapStateToProps = (state, ownProps) => {
const users = getItems(apiMethod.list)(entity.user)(state);
const meta = getMeta(apiMethod.list)(entity.user)(state);
const isFetchingUsers = getIsFetching(apiMethod.list)(entity.user)(state);
const timeFetchedUsers = getTimeFetched(apiMethod.list)(entity.user)(state);
return {
isLoading: !timeFetchedUsers || isFetchingUsers,
isLoaded: !!timeFetchedUsers,
users,
meta
};
};
const mapDispatchToProps = {
fetchUserList: fetchList(entity.user)
};
UserList.propTypes = {
classes: PropTypes.object.isRequired,
t: PropTypes.func.isRequired
};
const ConnectedUserList = connect(mapStateToProps, mapDispatchToProps)(
UserList
);
export default translate()(withStyles(styles)(ConnectedUserList));