-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(ui-common): add GroupedDataTable
- Loading branch information
Showing
10 changed files
with
770 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
86 changes: 86 additions & 0 deletions
86
webapp/src/components/common/DynamicDataTable/TableRowGroup.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
import { | ||
TableRow, | ||
TableCell, | ||
IconButton, | ||
Box, | ||
Typography, | ||
} from "@mui/material"; | ||
import KeyboardArrowDownIcon from "@mui/icons-material/KeyboardArrowDown"; | ||
import KeyboardArrowUpIcon from "@mui/icons-material/KeyboardArrowUp"; | ||
import { ChangeEvent, useMemo, useState } from "react"; | ||
import TableRowItem from "./TableRowItem"; | ||
import { Item, Column, calculateColumnResults } from "./utils"; | ||
|
||
interface Props { | ||
itemsByGroup: { group?: string; items: Item[] }; | ||
columns: Column[]; | ||
selected: string[]; | ||
onClick: (e: ChangeEvent<HTMLInputElement>, id: string) => void; | ||
} | ||
|
||
function TableRowGroup({ | ||
itemsByGroup: { group, items }, | ||
columns, | ||
selected, | ||
onClick, | ||
}: Props) { | ||
const [openRow, setOpenRow] = useState(false); | ||
const columnResults = useMemo( | ||
() => calculateColumnResults(columns, items), | ||
[columns, items] | ||
); | ||
|
||
//////////////////////////////////////////////////////////////// | ||
// JSX | ||
//////////////////////////////////////////////////////////////// | ||
|
||
return ( | ||
<> | ||
{group && ( | ||
<TableRow | ||
sx={{ | ||
borderBottom: "2px solid rgba(224, 224, 224, 0.3)", | ||
}} | ||
> | ||
{/* Merge the first two columns into one. The first column, which is always "name", | ||
* does not contain an operation so no value will be displayed on the TableRowGroup header. */} | ||
<TableCell colSpan={2} sx={{ py: 0 }}> | ||
<Box sx={{ display: "flex", alignItems: "center", my: 1 }}> | ||
<IconButton size="small" onClick={() => setOpenRow(!openRow)}> | ||
{openRow ? <KeyboardArrowUpIcon /> : <KeyboardArrowDownIcon />} | ||
</IconButton> | ||
<Typography sx={{ ml: 2 }}>{group}</Typography> | ||
</Box> | ||
</TableCell> | ||
{/* Skip the first column since it's already included in the merged TableCell above. */} | ||
{columns.slice(1).map((column) => ( | ||
<TableCell key={column.name} align="center"> | ||
{column.operation && ( | ||
<Typography | ||
variant="body2" | ||
sx={{ | ||
color: "rgba(255, 255, 255, 0.5)", | ||
}} | ||
> | ||
{columnResults[column.name]} | ||
</Typography> | ||
)} | ||
</TableCell> | ||
))} | ||
</TableRow> | ||
)} | ||
{openRow && | ||
items.map((item) => ( | ||
<TableRowItem | ||
key={item.id} | ||
item={item} | ||
columns={columns} | ||
selected={selected} | ||
onClick={onClick} | ||
/> | ||
))} | ||
</> | ||
); | ||
} | ||
|
||
export default TableRowGroup; |
66 changes: 66 additions & 0 deletions
66
webapp/src/components/common/DynamicDataTable/TableRowItem.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
import { TableCell, Checkbox, Chip, TableRow } from "@mui/material"; | ||
import { ChangeEvent, memo, useCallback } from "react"; | ||
import { Item, Column } from "./utils"; | ||
|
||
interface Props { | ||
item: Item; | ||
columns: Column[]; | ||
selected: string[]; | ||
onClick: (e: ChangeEvent<HTMLInputElement>, name: string) => void; | ||
} | ||
|
||
function TableRowItem({ item, columns, selected, onClick }: Props) { | ||
const isSelected = selected.includes(item.id); | ||
|
||
//////////////////////////////////////////////////////////////// | ||
// Event handlers | ||
//////////////////////////////////////////////////////////////// | ||
|
||
const handleChange = useCallback( | ||
(e: ChangeEvent<HTMLInputElement>) => { | ||
onClick(e, item.id); | ||
}, | ||
[item.id, onClick] | ||
); | ||
|
||
//////////////////////////////////////////////////////////////// | ||
// JSX | ||
//////////////////////////////////////////////////////////////// | ||
|
||
return ( | ||
<TableRow | ||
sx={{ "& > *": { borderBottom: "none !important" } }} | ||
selected={isSelected} | ||
> | ||
<TableCell padding="none"> | ||
<Checkbox | ||
color="primary" | ||
checked={isSelected} | ||
onChange={handleChange} | ||
/> | ||
</TableCell> | ||
{columns.map((column) => { | ||
const cellValue = item.columns[column.name]; | ||
return ( | ||
<TableCell | ||
key={column.name} | ||
sx={{ py: 0 }} | ||
align={typeof cellValue === "number" ? "center" : "left"} | ||
> | ||
{column.chipColorMap && typeof cellValue === "string" ? ( | ||
<Chip | ||
label={cellValue} | ||
size="small" | ||
color={column.chipColorMap[cellValue]} | ||
/> | ||
) : ( | ||
cellValue | ||
)} | ||
</TableCell> | ||
); | ||
})} | ||
</TableRow> | ||
); | ||
} | ||
|
||
export default memo(TableRowItem); |
54 changes: 54 additions & 0 deletions
54
webapp/src/components/common/DynamicDataTable/TableToolbar.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
import { | ||
Toolbar, | ||
alpha, | ||
Typography, | ||
Tooltip, | ||
IconButton, | ||
Fade, | ||
} from "@mui/material"; | ||
import DeleteIcon from "@mui/icons-material/Delete"; | ||
import { useTranslation } from "react-i18next"; | ||
|
||
interface Props { | ||
numSelected: number; | ||
handleDelete: () => void; | ||
} | ||
|
||
function TableToolbar({ numSelected, handleDelete }: Props) { | ||
const { t } = useTranslation(); | ||
|
||
//////////////////////////////////////////////////////////////// | ||
// JSX | ||
//////////////////////////////////////////////////////////////// | ||
|
||
return ( | ||
<Fade in={numSelected > 0} timeout={300}> | ||
<Toolbar | ||
sx={{ | ||
...(numSelected > 0 && { | ||
bgcolor: (theme) => | ||
alpha( | ||
theme.palette.primary.main, | ||
theme.palette.action.activatedOpacity | ||
), | ||
}), | ||
}} | ||
> | ||
{numSelected > 0 && ( | ||
<> | ||
<Typography sx={{ flex: 1 }}> | ||
{numSelected} {t("global.selected")} | ||
</Typography> | ||
<Tooltip title={t("global.delete")}> | ||
<IconButton onClick={handleDelete}> | ||
<DeleteIcon /> | ||
</IconButton> | ||
</Tooltip> | ||
</> | ||
)} | ||
</Toolbar> | ||
</Fade> | ||
); | ||
} | ||
|
||
export default TableToolbar; |
Oops, something went wrong.