frontend/src/pages/Groups.tsx

188 lines
No EOL
5.3 KiB
TypeScript

import { Box, Chip, Grid2, IconButton, Theme, Tooltip, Typography } from "@mui/material";
import { LibraryAdd as CreateGroupIcon } from "@mui/icons-material"
import { makeStyles } from "@mui/styles";
import ResponsiveTable, { Column } from "common/ResponsiveTable";
import SmartBreadcrumb from "common/SmartBreadcrumb";
import { useMobile } from "hooks";
import { appendToUrl } from "navigation/Router";
import { pond } from "protobuf-ts/pond";
import { useGroupAPI } from "providers";
import { useEffect, useState } from "react";
import { useNavigate } from "react-router-dom";
import { or } from "utils/types";
import PageContainer from "./PageContainer";
import GroupSettings from "group/GroupSettings";
import { green } from "@mui/material/colors";
import { cloneDeep } from "lodash";
const useStyles = makeStyles((theme: Theme) => {
const isMobile = useMobile()
return ({
cellContainer: {
margin: theme.spacing(1),
marginLeft: theme.spacing(2),
display: "flex",
maxWidth: theme.spacing(isMobile ? 18 : 32),
},
bigCellContainer: {
margin: theme.spacing(1),
marginLeft: theme.spacing(2),
display: "flex",
width: "auto",
},
smallCellContainer: {
margin: theme.spacing(1),
marginLeft: theme.spacing(2),
display: "flex",
width: theme.spacing(1),
},
green: {
color: green["600"]
},
});
});
export default function GroupsPage() {
const groupAPI = useGroupAPI()
const navigate = useNavigate()
const [limit, setLimit] = useState(10)
const [page, setPage] = useState(0)
const [order, ] = useState<"asc" | "desc">("asc")
const [orderBy, ] = useState("")
const [search, setSearch] = useState("")
const [total, setTotal] = useState(0)
const [loading, setLoading] = useState(false)
const [groups, setGroups] = useState<pond.Group[]>([])
const [groupSettingsIsOpen, setGroupSettingsIsOpen] = useState(false)
const classes = useStyles()
const loadGroups = () => {
setLoading(true)
groupAPI.listGroups(limit, page*limit, order, orderBy, search).then(resp => {
setGroups(or(resp.data.groups, []))
setTotal(resp.data.total)
}).finally(() => {
setLoading(false)
})
}
useEffect(() => {
loadGroups()
}, [limit, page, order, orderBy, search])
const handleRowsPerPageChange = (event: any) => {
setLimit(event.target.value);
};
const columns = (): Column<pond.Group>[] => {
return [
// {
// title: "Size",
// render: (group) => {
// return (
// <Box className={classes.smallCellContainer}>
// {group.settings?.devices?.length ? group.settings.devices.length : 0}
// </Box>
// )
// }
// },
{
title: "Group Name",
render: (group) => {
return (
<Box className={classes.cellContainer}>
<Chip
variant="outlined"
label={group.settings?.name ? group.settings.name : "Group " + group.settings?.groupId}
/>
</Box>
)
}
},
{
title: "Description",
render: device => {
const description = device.settings?.description ?? ""
return (
<Box className={classes.bigCellContainer}>
<Tooltip title={device.settings?.description}>
<Typography variant="body2">
{description}
</Typography>
</Tooltip>
</Box>
)
}
},
]
}
const handleRowClick = (row: pond.Group) => {
if (row.settings?.groupId) navigate(appendToUrl(or(row.settings?.groupId, "")), { state: {group: row} })
}
const groupButton = () => {
return (
<Tooltip title="Create Group">
<IconButton
onClick={() => setGroupSettingsIsOpen(true)}
aria-label="Create Group"
size="small"
>
<CreateGroupIcon className={classes.green} />
</IconButton>
</Tooltip>
)
}
const title = () => {
return (
<Grid2 container alignItems={"center"} spacing={1}>
<Grid2>
<SmartBreadcrumb />
</Grid2>
<Grid2>
{groupButton()}
</Grid2>
</Grid2>
)
}
return (
<PageContainer >
<ResponsiveTable<pond.Group>
title={title()}
rows={groups}
columns={columns()}
total={total}
pageSize={limit}
page={page}
setPage={setPage}
handleRowsPerPageChange={handleRowsPerPageChange}
isLoading={loading}
setSearchText={setSearch}
onRowClick={handleRowClick}
loadMore={()=>{
let current = cloneDeep(groups)
setLoading(true)
groupAPI.listGroups(limit, current.length, order, orderBy, search).then(resp => {
setGroups(or(current.concat(resp.data.groups), current))
}).finally(() => {
setLoading(false)
})
}}
/>
<GroupSettings
// initialGroup={selectedGroup}
// mode={groupSettingsMode}
mode={"add"}
isDialogOpen={groupSettingsIsOpen}
closeDialogCallback={() => setGroupSettingsIsOpen(false)}
refreshCallback={loadGroups}
canEdit={true}
/>
</PageContainer>
)
}