added optional element to responsive table to render an element before the search bar

This commit is contained in:
Carter 2025-05-16 11:33:25 -06:00
parent ebf6bdb71a
commit 33988e3684
2 changed files with 37 additions and 9 deletions

View file

@ -92,6 +92,7 @@ interface Props<T> {
customElement?: JSX.Element //element that will be placed in the table head between the table actions and the column header rows customElement?: JSX.Element //element that will be placed in the table head between the table actions and the column header rows
mobileView?: boolean //can be used to force the table to use its mobile view for narrow containing elements ie, drawer mobileView?: boolean //can be used to force the table to use its mobile view for narrow containing elements ie, drawer
hidePagination?: boolean //when passed in will hide the pagination at the bottom of the table hidePagination?: boolean //when passed in will hide the pagination at the bottom of the table
endTitleElement?: string | JSX.Element | (() => string | JSX.Element);
} }
export default function ResponsiveTable<T extends Object>(props: Props<T>) { export default function ResponsiveTable<T extends Object>(props: Props<T>) {
@ -126,6 +127,7 @@ export default function ResponsiveTable<T extends Object>(props: Props<T>) {
const columns = typeof(props.columns) === "function" ? props.columns() : props.columns const columns = typeof(props.columns) === "function" ? props.columns() : props.columns
const subtitle = typeof(props.subtitle) === "function" ? props.subtitle() : props.subtitle const subtitle = typeof(props.subtitle) === "function" ? props.subtitle() : props.subtitle
const title = typeof(props.title) === "function" ? props.title() : props.title const title = typeof(props.title) === "function" ? props.title() : props.title
const endTitleElement = typeof(props.endTitleElement) === "function" ? props.endTitleElement() : props.endTitleElement
const isMobile = useMobile() const isMobile = useMobile()
@ -307,11 +309,13 @@ export default function ResponsiveTable<T extends Object>(props: Props<T>) {
if (isMobile || mobileView) return ( if (isMobile || mobileView) return (
<Box> <Box>
<Box className={classes.mobileTitleBox}> <Box className={classes.mobileTitleBox}>
{renderTitle()} {renderTitle()}
{renderSubtitle()} {renderSubtitle()}
{setSearchText && searchBar()} {setSearchText && searchBar()}
</Box> </Box>
{rows.map((row, index) => { {rows.map((row, index) => {
return ( return (
<Card className={classNames(classes.card)} key={"mobile-card-"+index} onClick={() => onRowClick&&onRowClick(row)}> <Card className={classNames(classes.card)} key={"mobile-card-"+index} onClick={() => onRowClick&&onRowClick(row)}>
@ -375,10 +379,9 @@ export default function ResponsiveTable<T extends Object>(props: Props<T>) {
return ( return (
<TableContainer className={classes.tableContainer} component={Paper}> <TableContainer className={classes.tableContainer} component={Paper}>
<Table> <Table>
<TableHead> <TableHead>
<TableRow sx={ !title && !setSearchText ? { display: "none" } : undefined}> <TableRow sx={ !title && !setSearchText ? { display: "none" } : undefined}>
<TableCell colSpan={10000} sx={{ border: "none" }}> <TableCell colSpan={10000} sx={{ border: "none" }}>
<Grid2 container justifyContent="space-between"> <Grid2 container justifyContent="space-between">
@ -393,6 +396,9 @@ export default function ResponsiveTable<T extends Object>(props: Props<T>) {
<Grid2> <Grid2>
{actions && actions} {actions && actions}
</Grid2> </Grid2>
<Grid2>
{endTitleElement}
</Grid2>
<Grid2> <Grid2>
{setSearchText &&<Box className={classes.searchContainer}> {setSearchText &&<Box className={classes.searchContainer}>
{searchBar()} {searchBar()}
@ -418,7 +424,6 @@ export default function ResponsiveTable<T extends Object>(props: Props<T>) {
</TableCell> </TableCell>
</TableRow> </TableRow>
} }
<TableRow sx={ hideKeys ? { display: "none" } : undefined } > <TableRow sx={ hideKeys ? { display: "none" } : undefined } >
{ rowSelect && <TableCell></TableCell> } { rowSelect && <TableCell></TableCell> }

View file

@ -1,5 +1,5 @@
import { DeveloperBoard as ProvisionIcon, LibraryAdd as CreateGroupIcon } from "@mui/icons-material"; import { DeveloperBoard as ProvisionIcon, LibraryAdd as CreateGroupIcon, Tune } from "@mui/icons-material";
import { Box, Chip, Grid2, IconButton, Skeleton, Tab, Tabs, Theme, Tooltip, Typography, useTheme } from "@mui/material"; import { Box, Chip, Dialog, DialogTitle, Grid2, IconButton, Menu, MenuItem, Skeleton, Tab, Tabs, Theme, Tooltip, Typography, useTheme } from "@mui/material";
import { blue, green, orange } from "@mui/material/colors"; import { blue, green, orange } from "@mui/material/colors";
import { makeStyles } from "@mui/styles"; import { makeStyles } from "@mui/styles";
import ResponsiveTable, { Column } from "common/ResponsiveTable"; import ResponsiveTable, { Column } from "common/ResponsiveTable";
@ -125,6 +125,8 @@ export default function Devices() {
const [fieldContains, setFieldContains] = useState<Map<string, string>>(new Map<string, string>()) const [fieldContains, setFieldContains] = useState<Map<string, string>>(new Map<string, string>())
const [seperateDust, setSeperateDust] = useState(true) const [seperateDust, setSeperateDust] = useState(true)
const [preferencesAnchor, setPreferencesAnchor] = useState<any>(null)
const [{ as }] = useGlobalState() const [{ as }] = useGlobalState()
const updateGroups = (newGroups: Group[]) => { const updateGroups = (newGroups: Group[]) => {
@ -282,7 +284,6 @@ export default function Devices() {
function insertGroupContext(groupID: string, deviceID: string): string { function insertGroupContext(groupID: string, deviceID: string): string {
const path = location.pathname const path = location.pathname
console.log(path)
const segments = path.split('/').filter(Boolean); const segments = path.split('/').filter(Boolean);
const deviceIndex = segments.findIndex(segment => segment === 'devices'); const deviceIndex = segments.findIndex(segment => segment === 'devices');
@ -305,10 +306,7 @@ export default function Devices() {
const toDevice = (device: Device) => { const toDevice = (device: Device) => {
let url = getGroup() ? insertGroupContext(getGroup().id().toString(), device.id().toString()) : "" let url = getGroup() ? insertGroupContext(getGroup().id().toString(), device.id().toString()) : ""
console.log(url)
if (url.length < 1) url = device.id().toString() if (url.length < 1) url = device.id().toString()
// url = url + "/" + device.id()
// navigate(url, { replace: true, state: {device: device} })
navigate(url, { state: {device: device} }) navigate(url, { state: {device: device} })
}; };
@ -527,6 +525,29 @@ export default function Devices() {
) )
} }
const preferencesButton = () => {
return (
<IconButton onClick={(event) => setPreferencesAnchor(event.currentTarget)}>
<Tune />
</IconButton>
)
}
const preferencesMenu = () => {
return (
<Menu
id="userMenu"
anchorEl={preferencesAnchor}
open={preferencesAnchor !== null}
onClose={() => setPreferencesAnchor(null)}
disableAutoFocusItem>
<MenuItem>
hi
</MenuItem>
</Menu>
)
}
return( return(
<PageContainer padding={isMobile ? 0 : 2}> <PageContainer padding={isMobile ? 0 : 2}>
<Box <Box
@ -572,6 +593,7 @@ export default function Devices() {
setSearchText={setSearch} setSearchText={setSearch}
isLoading={devicesLoading} isLoading={devicesLoading}
actions={getGroup() && <GroupActions removeCallback={removeGroupCallback} group={getGroup()} permissions={groupPermissions} devices={devices} refreshCallback={loadDevices}/>} actions={getGroup() && <GroupActions removeCallback={removeGroupCallback} group={getGroup()} permissions={groupPermissions} devices={devices} refreshCallback={loadDevices}/>}
endTitleElement={preferencesButton}
/> />
<ProvisionDevice <ProvisionDevice
isOpen={isProvisionDialogOpen} isOpen={isProvisionDialogOpen}
@ -590,6 +612,7 @@ export default function Devices() {
removeGroupCallback={removeGroupCallback} removeGroupCallback={removeGroupCallback}
addGroupCallback={addGroupCallback} addGroupCallback={addGroupCallback}
/> />
{preferencesMenu()}
</PageContainer> </PageContainer>
) )
} }