TableTemplate.js 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. import React, { useEffect } from 'react';
  2. import PropTypes from 'prop-types';
  3. import { makeStyles } from '@material-ui/core/styles';
  4. import Table from '@material-ui/core/Table';
  5. import TableBody from '@material-ui/core/TableBody';
  6. import TableCell from '@material-ui/core/TableCell';
  7. import TableContainer from '@material-ui/core/TableContainer';
  8. import TableHead from '@material-ui/core/TableHead';
  9. import TablePagination from '@material-ui/core/TablePagination';
  10. import TableRow from '@material-ui/core/TableRow';
  11. import TableSortLabel from '@material-ui/core/TableSortLabel';
  12. import { Grid } from '@material-ui/core';
  13. function descendingComparator(a, b, orderBy) {
  14. if (b[orderBy] < a[orderBy]) {
  15. return -1;
  16. }
  17. if (b[orderBy] > a[orderBy]) {
  18. return 1;
  19. }
  20. return 0;
  21. }
  22. function getComparator(order, orderBy) {
  23. return order === 'desc'
  24. ? (a, b) => descendingComparator(a, b, orderBy)
  25. : (a, b) => -descendingComparator(a, b, orderBy);
  26. }
  27. function stableSort(array, comparator) {
  28. const stabilizedThis = array.map((el, index) => [el, index]);
  29. stabilizedThis.sort((a, b) => {
  30. const order = comparator(a[0], b[0]);
  31. if (order !== 0) return order;
  32. return a[1] - b[1];
  33. });
  34. return stabilizedThis.map((el) => el[0]);
  35. }
  36. function EnhancedTableHead(props) {
  37. const { classes,
  38. order,
  39. orderBy,
  40. onRequestSort,
  41. onRefreshData,
  42. headCells } = props;
  43. const createSortHandler = (property) => (event) => {
  44. onRequestSort(event, property);
  45. onRefreshData();
  46. };
  47. return (
  48. <TableHead>
  49. <TableRow>
  50. {headCells.map((headCell) => (
  51. <TableCell
  52. key={headCell.id}
  53. align={headCell.numeric ? 'right' : 'left'}
  54. padding={headCell.disablePadding ? 'none' : 'default'}
  55. sortDirection={orderBy === headCell.id ? order : false}
  56. >
  57. {headCell.id != 'id' ?
  58. <TableSortLabel
  59. active={orderBy === headCell.id}
  60. direction={orderBy === headCell.id ? order : 'asc'}
  61. onClick={createSortHandler(headCell.id)}
  62. >
  63. {headCell.label}
  64. {orderBy === headCell.id ? (
  65. <span className={classes.visuallyHidden}>
  66. {order === 'desc' ? 'sorted descending' : 'sorted ascending'}
  67. </span>
  68. ) : null}
  69. </TableSortLabel>
  70. : <TableSortLabel
  71. hideSortIcon={true}
  72. >
  73. {headCell.label}
  74. </TableSortLabel>
  75. }
  76. </TableCell>
  77. ))}
  78. </TableRow>
  79. </TableHead>
  80. );
  81. }
  82. EnhancedTableHead.propTypes = {
  83. classes: PropTypes.object.isRequired,
  84. numSelected: PropTypes.number.isRequired,
  85. onRequestSort: PropTypes.func.isRequired,
  86. onRefreshData: PropTypes.func.isRequired,
  87. onSelectAllClick: PropTypes.func.isRequired,
  88. order: PropTypes.oneOf(['asc', 'desc']).isRequired,
  89. orderBy: PropTypes.string.isRequired,
  90. rowCount: PropTypes.number.isRequired,
  91. };
  92. const useStyles = makeStyles((theme) => ({
  93. root: {
  94. width: '100%',
  95. },
  96. paper: {
  97. width: '100%',
  98. marginBottom: theme.spacing(2),
  99. },
  100. table: {
  101. minWidth: 750,
  102. },
  103. visuallyHidden: {
  104. border: 0,
  105. clip: 'rect(0 0 0 0)',
  106. height: 1,
  107. margin: -1,
  108. overflow: 'hidden',
  109. padding: 0,
  110. position: 'absolute',
  111. top: 20,
  112. width: 1,
  113. },
  114. underline: {
  115. "&&&:before": {
  116. borderBottom: "none"
  117. },
  118. "&&:after": {
  119. borderBottom: "none"
  120. }
  121. }
  122. }));
  123. function TableTemplate(props) {
  124. const classes = useStyles();
  125. const {
  126. data = [],
  127. headers = [],
  128. onUpdateData,
  129. onReloadData,
  130. onChangePage,
  131. onChangeRowsPerPage,
  132. rowsPerPage = 10,
  133. page = 0,
  134. order = 'asc',
  135. orderBy
  136. } = props;
  137. const [selected, setSelected] = React.useState([]);
  138. const [dense, setDense] = React.useState(false);
  139. const [rowDataPerPage, setRowsPerPage] = React.useState(rowsPerPage != undefined ? rowsPerPage : 10);
  140. const [paginatePage, setPage] = React.useState(page != undefined ? page : 0);
  141. const [paginateOrder, setOrder] = React.useState(order != undefined ? order : 'asc');
  142. const [paginateOrderBy, setOrderBy] = React.useState(orderBy != undefined ? orderBy : 'name');
  143. var offset = paginatePage * rowDataPerPage;
  144. const handleRequestSort = (event, property) => {
  145. const isAsc = orderBy === property && order === 'asc';
  146. setOrder(isAsc ? 'desc' : 'asc');
  147. setOrderBy(property);
  148. };
  149. const handleSelectAllClick = (event) => {
  150. if (event.target.checked) {
  151. const newSelecteds = data.map((n) => n.name);
  152. setSelected(newSelecteds);
  153. return;
  154. }
  155. setSelected([]);
  156. };
  157. const handleClick = (event, rowdata) => {
  158. onUpdateData(true, rowdata);
  159. };
  160. const handleChangePage = (event, newPage) => {
  161. onChangePage(newPage);
  162. };
  163. const handleReloadData = () => {
  164. onReloadData();
  165. }
  166. const handleChangeRowsPerPage = (event) => {
  167. setRowsPerPage(parseInt(event.target.value, 10));
  168. onChangeRowsPerPage(parseInt(event.target.value));
  169. onReloadData();
  170. };
  171. const isSelected = (name) => selected.indexOf(name) !== -1;
  172. const emptyRows = rowsPerPage - Math.min(rowsPerPage, data.length - page * rowsPerPage);
  173. return (
  174. <div className={classes.root}>
  175. <Grid container>
  176. <Grid item style={{ marginRight: '10%' }}>
  177. <TableContainer>
  178. <Table
  179. className={classes.table}
  180. aria-labelledby="tableTitle"
  181. size={dense ? 'small' : 'medium'}
  182. aria-label="enhanced table"
  183. >
  184. <EnhancedTableHead
  185. classes={classes}
  186. numSelected={selected.length}
  187. headCells={headers}
  188. order={order}
  189. orderBy={orderBy}
  190. onSelectAllClick={handleSelectAllClick}
  191. onRequestSort={handleRequestSort}
  192. onRefreshData={handleReloadData}
  193. rowCount={data.length}
  194. />
  195. <TableBody>
  196. {data.length != 0 ? stableSort(data, getComparator(order, orderBy))
  197. .slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage)
  198. .map((row, index) => {
  199. const isItemSelected = isSelected(row.name);
  200. const labelId = `enhanced-table-checkbox-${index}`;
  201. return (
  202. <TableRow
  203. hover
  204. onClick={(event) => handleClick(event, row)}
  205. role="checkbox"
  206. aria-checked={isItemSelected}
  207. tabIndex={-1}
  208. key={index}
  209. selected={isItemSelected}
  210. >
  211. {headers.map((h, i) => {
  212. if (h.id == 'id') {
  213. return (<TableCell key={h.id} align="right">{++offset}</TableCell>);
  214. } else {
  215. return (<TableCell key={h.id} align="right">{row[h.id]}</TableCell>);
  216. }
  217. })}
  218. </TableRow>
  219. );
  220. }) : <div></div>}
  221. {emptyRows > 0 && (
  222. <TableRow style={{ height: (dense ? 33 : 53) * emptyRows }}>
  223. <TableCell colSpan={6} />
  224. </TableRow>
  225. )}
  226. </TableBody>
  227. </Table>
  228. </TableContainer>
  229. <TablePagination
  230. rowsPerPageOptions={[5, 10, 20, 30]}
  231. labelDisplayedRows={function ({ from, to, count }) { }}
  232. component="div"
  233. count={data.length}
  234. rowsPerPage={rowsPerPage}
  235. rowsPerPage={rowsPerPage}
  236. page={page}
  237. onChangePage={handleChangePage}
  238. onChangeRowsPerPage={handleChangeRowsPerPage}
  239. />
  240. </Grid></Grid>
  241. </div>
  242. );
  243. }
  244. TableTemplate.propTypes = {
  245. history: PropTypes.object,
  246. headers: PropTypes.array.isRequired,
  247. data: PropTypes.array.isRequired,
  248. onUpdateData: PropTypes.func,
  249. onReloadData: PropTypes.func,
  250. onChangePage: PropTypes.func,
  251. onChangeRowsPerPage: PropTypes.func,
  252. query: PropTypes.object,
  253. page: PropTypes.any,
  254. rowsPerPage: PropTypes.any,
  255. order: PropTypes.any,
  256. orderBy: PropTypes.any
  257. };
  258. export default (TableTemplate);