diff options
Diffstat (limited to 'src/tools/emcoui/src/compositeApps/dialogs/SortableTable.jsx')
-rw-r--r-- | src/tools/emcoui/src/compositeApps/dialogs/SortableTable.jsx | 410 |
1 files changed, 410 insertions, 0 deletions
diff --git a/src/tools/emcoui/src/compositeApps/dialogs/SortableTable.jsx b/src/tools/emcoui/src/compositeApps/dialogs/SortableTable.jsx new file mode 100644 index 00000000..f1a6ac2d --- /dev/null +++ b/src/tools/emcoui/src/compositeApps/dialogs/SortableTable.jsx @@ -0,0 +1,410 @@ +//======================================================================= +// Copyright (c) 2017-2020 Aarna Networks, Inc. +// All rights reserved. +// ====================================================================== +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ======================================================================== +import Table from "@material-ui/core/Table"; +import TableBody from "@material-ui/core/TableBody"; +import TableCell from "@material-ui/core/TableCell"; +import TableContainer from "@material-ui/core/TableContainer"; +import TableHead from "@material-ui/core/TableHead"; +import TableRow from "@material-ui/core/TableRow"; +import TableSortLabel from "@material-ui/core/TableSortLabel"; +import { makeStyles } from "@material-ui/core/styles"; +import React, { useEffect, useState } from "react"; +import Checkbox from "@material-ui/core/Checkbox"; +import PropTypes from "prop-types"; +import Typography from "@material-ui/core/Typography"; +import Toolbar from "@material-ui/core/Toolbar"; + +import clsx from "clsx"; +import TablePagination from "@material-ui/core/TablePagination"; +import { lighten } from "@material-ui/core/styles"; + +function descendingComparator(a, b, orderBy) { + if (b[orderBy] < a[orderBy]) { + return -1; + } + if (b[orderBy] > a[orderBy]) { + return 1; + } + return 0; +} + +function getComparator(order, orderBy) { + return order === "desc" + ? (a, b) => descendingComparator(a, b, orderBy) + : (a, b) => -descendingComparator(a, b, orderBy); +} + +function stableSort(array, comparator) { + const stabilizedThis = array.map((el, index) => [el, index]); + stabilizedThis.sort((a, b) => { + const order = comparator(a[0], b[0]); + if (order !== 0) return order; + return a[1] - b[1]; + }); + return stabilizedThis.map((el) => el[0]); +} + +const headCells = [ + { + id: "name", + numeric: false, + sortable: true, + disablePadding: true, + label: "Cluster", + }, + { + id: "description", + numeric: true, + sortable: false, + disablePadding: false, + label: "Description", + }, +]; + +function EnhancedTableHead(props) { + const { + classes, + onSelectAllClick, + order, + orderBy, + numSelected, + rowCount, + onRequestSort, + } = props; + const createSortHandler = (property) => (event) => { + onRequestSort(event, property); + }; + + return ( + <TableHead> + <TableRow> + <TableCell padding="checkbox"> + <Checkbox + indeterminate={numSelected > 0 && numSelected < rowCount} + checked={rowCount > 0 && numSelected === rowCount} + onChange={onSelectAllClick} + /> + </TableCell> + {headCells.map((headCell) => + headCell.sortable ? ( + <TableCell + style={{ fontWeight: "520" }} + key={headCell.id} + align={headCell.numeric ? "right" : "left"} + padding={headCell.disablePadding ? "none" : "default"} + sortDirection={orderBy === headCell.id ? order : false} + > + <TableSortLabel + active={orderBy === headCell.id} + direction={orderBy === headCell.id ? order : "asc"} + onClick={createSortHandler(headCell.id)} + > + {headCell.label} + {orderBy === headCell.id ? ( + <span className={classes.visuallyHidden}> + {order === "desc" + ? "sorted descending" + : "sorted ascending"} + </span> + ) : null} + </TableSortLabel> + </TableCell> + ) : ( + <TableCell + key={headCell.id} + style={{ fontWeight: "520" }} + padding={headCell.disablePadding ? "none" : "default"} + align={headCell.numeric ? "right" : "left"} + > + {headCell.label} + </TableCell> + ) + )} + </TableRow> + </TableHead> + ); +} + +EnhancedTableHead.propTypes = { + classes: PropTypes.object.isRequired, + numSelected: PropTypes.number.isRequired, + onRequestSort: PropTypes.func.isRequired, + onSelectAllClick: PropTypes.func.isRequired, + order: PropTypes.oneOf(["asc", "desc"]).isRequired, + orderBy: PropTypes.string.isRequired, + rowCount: PropTypes.number.isRequired, +}; + +const useToolbarStyles = makeStyles((theme) => ({ + root: { + paddingLeft: theme.spacing(2), + paddingRight: theme.spacing(1), + }, + highlight: + theme.palette.type === "light" + ? { + color: theme.palette.primary.main, + backgroundColor: lighten(theme.palette.primary.light, 0.85), + } + : { + color: theme.palette.text.primary, + backgroundColor: theme.palette.primary.dark, + }, + title: { + flex: "1 1 100%", + }, +})); + +const EnhancedTableToolbar = (props) => { + const classes = useToolbarStyles(); + const { numSelected } = props; + + return ( + <Toolbar + className={clsx(classes.root, { + [classes.highlight]: numSelected > 0, + })} + > + <Typography + className={classes.title} + variant="h6" + id="tableTitle" + component="div" + > + {props.tableName} + </Typography> + + <Typography + className={classes.title} + style={{ textAlign: "right" }} + color="inherit" + variant="subtitle1" + component="div" + > + {numSelected} selected + </Typography> + </Toolbar> + ); +}; + +EnhancedTableToolbar.propTypes = { + numSelected: PropTypes.number.isRequired, +}; + +const useStyles = makeStyles((theme) => ({ + tableRoot: { + width: "100%", + }, + paper: { + width: "100%", + marginBottom: theme.spacing(2), + }, + table: { + minWidth: 550, + }, + visuallyHidden: { + border: 0, + clip: "rect(0 0 0 0)", + height: 1, + margin: -1, + overflow: "hidden", + padding: 0, + position: "absolute", + top: 20, + width: 1, + }, + appBar: { + position: "relative", + }, + title: { + marginLeft: theme.spacing(2), + flex: 1, + }, + demo: { + backgroundColor: theme.palette.background.paper, + }, + root: { + flexGrow: 1, + backgroundColor: theme.palette.background.paper, + display: "flex", + height: 424, + }, + tabs: { + borderRight: `1px solid ${theme.palette.divider}`, + }, +})); + +function EnhancedTable({ + clusters, + formikValues, + tableName, + onRowSelect, + ...props +}) { + const classes = useStyles(); + const [order, setOrder] = useState("asc"); + const [orderBy, setOrderBy] = useState("name"); + const [selected, setSelected] = useState([]); + const [page, setPage] = useState(0); + const [rowsPerPage, setRowsPerPage] = useState(5); + const [rows, setRows] = useState([]); + + const handleRequestSort = (event, property) => { + const isAsc = orderBy === property && order === "asc"; + setOrder(isAsc ? "desc" : "asc"); + setOrderBy(property); + }; + + useEffect(() => { + if (formikValues) { + let formikClusterData = formikValues.filter( + (cluster) => cluster.provider === tableName + ); + if (formikClusterData && formikClusterData.length > 0) { + let data = []; + formikClusterData[0].selectedClusters.forEach((selectedCluster) => { + data.push(selectedCluster.name); + }); + setSelected(data); + } + } + setRows(clusters); + }, []); + + useEffect(() => { + onRowSelect(tableName, selected); + }, [selected]); + + const handleSelectAllClick = (event) => { + if (event.target.checked) { + const newSelecteds = rows.map((n) => n.name); + setSelected(newSelecteds); + return; + } + setSelected([]); + }; + + const handleClick = (event, name) => { + const selectedIndex = selected.indexOf(name); + let newSelected = []; + + if (selectedIndex === -1) { + newSelected = newSelected.concat(selected, name); + } else if (selectedIndex === 0) { + newSelected = newSelected.concat(selected.slice(1)); + } else if (selectedIndex === selected.length - 1) { + newSelected = newSelected.concat(selected.slice(0, -1)); + } else if (selectedIndex > 0) { + newSelected = newSelected.concat( + selected.slice(0, selectedIndex), + selected.slice(selectedIndex + 1) + ); + } + setSelected(newSelected); + }; + + const handleChangePage = (event, newPage) => { + setPage(newPage); + }; + + const handleChangeRowsPerPage = (event) => { + setRowsPerPage(parseInt(event.target.value, 10)); + setPage(0); + }; + + const isSelected = (name) => selected.indexOf(name) !== -1; + + const emptyRows = + rowsPerPage - Math.min(rowsPerPage, rows.length - page * rowsPerPage); + + return ( + <div className={classes.tableRoot}> + <EnhancedTableToolbar + tableName={tableName} + numSelected={selected.length} + /> + <TableContainer> + <Table + className={classes.table} + aria-labelledby="tableTitle" + size={"small"} + aria-label="enhanced table" + > + <EnhancedTableHead + classes={classes} + numSelected={selected.length} + order={order} + orderBy={orderBy} + onSelectAllClick={handleSelectAllClick} + onRequestSort={handleRequestSort} + rowCount={rows.length} + /> + <TableBody> + {stableSort(rows, getComparator(order, orderBy)) + .slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage) + .map((row, index) => { + const isItemSelected = isSelected(row.name); + const labelId = `enhanced-table-checkbox-${index}`; + + return ( + <TableRow + hover + onClick={(event) => handleClick(event, row.name)} + role="checkbox" + aria-checked={isItemSelected} + tabIndex={-1} + key={row.name} + selected={isItemSelected} + > + <TableCell padding="checkbox"> + <Checkbox + checked={isItemSelected} + inputProps={{ "aria-labelledby": labelId }} + /> + </TableCell> + <TableCell + component="th" + id={labelId} + scope="row" + padding="none" + > + {row.name} + </TableCell> + <TableCell align="right">{row.description}</TableCell> + </TableRow> + ); + })} + {emptyRows > 0 && ( + <TableRow style={{ height: 33 * emptyRows }}> + <TableCell colSpan={6} /> + </TableRow> + )} + </TableBody> + </Table> + </TableContainer> + <TablePagination + rowsPerPageOptions={[5, 10, 25]} + component="div" + count={rows.length} + rowsPerPage={rowsPerPage} + page={page} + onChangePage={handleChangePage} + onChangeRowsPerPage={handleChangeRowsPerPage} + /> + </div> + ); +} + +export default EnhancedTable; |