123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362 |
- import { FC } from 'react';
- import Table from '@mui/material/Table';
- import TableBody from '@mui/material/TableBody';
- import TableCell from '@mui/material/TableCell';
- import TableContainer from '@mui/material/TableContainer';
- import TableRow from '@mui/material/TableRow';
- import Checkbox from '@mui/material/Checkbox';
- import Box from '@mui/material/Box';
- import Button from '@mui/material/Button';
- import Typography from '@mui/material/Typography';
- import EnhancedTableHead from './TableHead';
- import EditableTableHead from './TableEditableHead';
- import ActionBar from './ActionBar';
- import LoadingTable from './LoadingTable';
- import CopyButton from '../advancedSearch/CopyButton';
- import type { Theme } from '@mui/material/styles';
- import type { TableType } from './Types';
- const EnhancedTable: FC<TableType> = props => {
- let {
- selected,
- onSelected,
- isSelected,
- onSelectedAll,
- rows = [],
- colDefinitions,
- primaryKey,
- // whether show checkbox in the first column
- // set true as default
- openCheckBox = true,
- disableSelect,
- noData,
- // whether change table row background color when mouse hover
- // set true as default
- showHoverStyle = true,
- isLoading,
- headEditable = false,
- // editable heads required param, contains heads components and its value
- editHeads = [],
- // if table cell max width not be passed, table row will use 300px as default
- tableCellMaxWidth = '300px',
- handleSort,
- order,
- orderBy,
- rowDecorator = () => ({}),
- rowHeight,
- } = props;
- const hasData = rows && rows.length > 0;
- return (
- <TableContainer
- sx={theme => ({
- width: '100%',
- flexGrow: 1,
- color: theme.palette.text.primary,
- backgroundColor: theme.palette.background.paper,
- })}
- >
- <Box height="100%">
- <Table
- stickyHeader
- sx={{
- minWidth: '100%',
- height: hasData ? 'auto' : '100%',
- }}
- aria-labelledby="tableTitle"
- size="medium"
- aria-label="enhanced table"
- >
- {!headEditable ? (
- <EnhancedTableHead
- colDefinitions={colDefinitions}
- numSelected={selected.length}
- order={order}
- orderBy={orderBy}
- onSelectAllClick={onSelectedAll}
- handleSort={handleSort}
- rowCount={rows.length}
- openCheckBox={openCheckBox}
- disableSelect={disableSelect}
- />
- ) : (
- <EditableTableHead editHeads={editHeads} />
- )}
- {!isLoading ? (
- <TableBody>
- {hasData ? (
- rows.map((row, index) => {
- const isItemSelected = isSelected(row);
- const labelId = `enhanced-table-checkbox-${index}`;
- return (
- <TableRow
- hover={showHoverStyle}
- key={'row' + row[primaryKey] + index}
- onClick={event => onSelected(event, row)}
- aria-checked={isItemSelected}
- tabIndex={-1}
- selected={isItemSelected && !disableSelect}
- sx={
- [
- showHoverStyle && {
- '&:hover': {
- '& td': {
- background: 'inherit',
- },
- '& .hoverActionCell': {
- '& span': {
- opacity: 1,
- },
- },
- },
- },
- isItemSelected &&
- !disableSelect && {
- '& td': {
- background: 'inherit',
- },
- },
- rowDecorator(row),
- ].filter(Boolean) as any
- }
- >
- {openCheckBox && (
- <TableCell
- padding="checkbox"
- sx={theme => ({
- width: '38px',
- borderBottom: `1px solid ${theme.palette.divider}`,
- })}
- >
- <Checkbox
- checked={isItemSelected}
- color="primary"
- size="small"
- disabled={disableSelect}
- inputProps={{
- 'aria-labelledby': labelId,
- role: 'checkbox',
- }}
- />
- </TableCell>
- )}
- {colDefinitions.map((colDef, i) => {
- const { actionBarConfigs = [], needCopy = false } =
- colDef;
- const cellStyleFromDef = colDef.getStyle
- ? colDef.getStyle(row[colDef.id])
- : {};
- return colDef.showActionCell ? (
- <TableCell
- sx={
- [
- (theme: Theme) => ({
- borderBottom: `1px solid ${theme.palette.divider}`,
- '& p': {
- display: 'inline-block',
- verticalAlign: 'middle',
- overflow: 'hidden',
- textOverflow: 'ellipsis',
- whiteSpace: 'nowrap',
- maxWidth: tableCellMaxWidth,
- },
- }),
- (theme: Theme) => ({
- padding: theme.spacing(1, 1.5),
- }),
- colDef.isHoverAction && {
- transition: '0.2s all',
- padding: 0,
- width: '50px',
- '& span': {
- opacity: 0,
- },
- },
- cellStyleFromDef,
- ].filter(Boolean) as any
- }
- className={
- colDef.isHoverAction ? 'hoverActionCell' : ''
- } // Keep class for targeting in rowHoverStyles
- key={colDef.id}
- >
- <ActionBar
- configs={actionBarConfigs}
- isHoverType={colDef.isHoverAction}
- row={row}
- ></ActionBar>
- </TableCell>
- ) : (
- <TableCell
- key={'cell' + row[primaryKey] + i}
- align={colDef.align || 'left'}
- sx={
- [
- (theme: Theme) => ({
- overflow: 'hidden',
- borderBottom: `1px solid ${theme.palette.divider}`,
- '& p': {
- display: 'inline-block',
- verticalAlign: 'middle',
- overflow: 'hidden',
- textOverflow: 'ellipsis',
- whiteSpace: 'nowrap',
- maxWidth: tableCellMaxWidth,
- },
- }),
- (theme: Theme) => ({
- padding: theme.spacing(1),
- }),
- cellStyleFromDef,
- ].filter(Boolean) as any
- }
- >
- <Box
- sx={{
- display: 'flex',
- whiteSpace: 'nowrap',
- alignItems: 'center',
- minHeight: rowHeight - 16, // 16 is the padding of the table cell
- }}
- >
- {typeof row[colDef.id] !== 'undefined' && (
- <>
- {colDef.formatter ? (
- colDef.onClick ? (
- <Button
- color="primary"
- data-data={row[colDef.id]}
- data-index={index}
- size="small"
- onClick={e => {
- colDef.onClick &&
- colDef.onClick(e, row);
- }}
- >
- <Typography
- component="div"
- variant="body2"
- title={String(row[colDef.id])}
- >
- {colDef.formatter(
- row,
- row[colDef.id],
- i
- )}
- </Typography>
- </Button>
- ) : (
- <Typography
- component="div"
- title={String(row[colDef.id])}
- variant="body2"
- >
- {colDef.formatter(
- row,
- row[colDef.id],
- i
- )}
- </Typography>
- )
- ) : colDef.onClick ? (
- <Button
- color="primary"
- data-data={row[colDef.id]}
- data-index={index}
- size="small"
- onClick={e => {
- colDef.onClick &&
- colDef.onClick(e, row);
- }}
- >
- <Typography
- component="div"
- title={String(row[colDef.id])}
- variant="body2"
- >
- {row[colDef.id]}
- </Typography>
- </Button>
- ) : (
- <Typography
- component="div"
- title={String(row[colDef.id])}
- variant="body2"
- >
- {row[colDef.id]}
- </Typography>
- )}
- {needCopy && (
- <CopyButton
- copyValue={row[colDef.id]}
- size="small"
- sx={theme => ({
- '& svg': {
- fontSize: '13px',
- },
- marginLeft: theme.spacing(0.5),
- })}
- />
- )}
- </>
- )}
- </Box>
- </TableCell>
- );
- })}
- </TableRow>
- );
- })
- ) : (
- <TableRow>
- <TableCell
- sx={theme => ({
- paddingTop: theme.spacing(6),
- textAlign: 'center',
- letterSpacing: '0.5px',
- color: theme.palette.text.secondary,
- })}
- colSpan={
- openCheckBox
- ? colDefinitions.length + 1
- : colDefinitions.length
- }
- >
- {noData}
- </TableCell>
- </TableRow>
- )}
- </TableBody>
- ) : (
- <TableBody>
- <TableRow>
- <TableCell
- sx={theme => ({
- paddingTop: theme.spacing(6),
- textAlign: 'center',
- letterSpacing: '0.5px',
- color: theme.palette.text.secondary,
- })}
- colSpan={
- openCheckBox
- ? colDefinitions.length + 1
- : colDefinitions.length
- }
- >
- <LoadingTable />
- </TableCell>
- </TableRow>
- </TableBody>
- )}
- </Table>
- </Box>
- </TableContainer>
- );
- };
- export default EnhancedTable;
|