added table sorting to responsive table
This commit is contained in:
parent
4bd66d3d24
commit
8143ef4c37
2 changed files with 60 additions and 10 deletions
|
|
@ -1,6 +1,6 @@
|
||||||
import { Box, Card, Checkbox, CircularProgress, Collapse, darken, Divider, Grid2, IconButton, InputAdornment, ListItemButton, ListItemIcon, ListItemText, Menu, MenuItem, Paper, SxProps, Table, TableBody, TableCell, TableContainer, TableHead, TablePagination, TableRow, TextField, Theme, Typography } from "@mui/material";
|
import { Box, Card, Checkbox, CircularProgress, Collapse, darken, Divider, Grid2, IconButton, InputAdornment, ListItemButton, ListItemIcon, ListItemText, Menu, MenuItem, Paper, SxProps, Table, TableBody, TableCell, TableContainer, TableHead, TablePagination, TableRow, TextField, Theme, Typography } from "@mui/material";
|
||||||
import { makeStyles } from "@mui/styles";
|
import { makeStyles } from "@mui/styles";
|
||||||
import { ChevronRight, Close, Search, ViewColumn } from "@mui/icons-material"
|
import { ArrowDownward, ArrowUpward, ChevronRight, Close, Search, ViewColumn } from "@mui/icons-material"
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { useMobile } from "hooks";
|
import { useMobile } from "hooks";
|
||||||
|
|
@ -64,6 +64,8 @@ export interface Column<T> {
|
||||||
cellStyle?: SxProps<Theme>;
|
cellStyle?: SxProps<Theme>;
|
||||||
hidden?: boolean;
|
hidden?: boolean;
|
||||||
render: (row: T) => JSX.Element;
|
render: (row: T) => JSX.Element;
|
||||||
|
sortKey?: string;
|
||||||
|
disableSort?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Props<T> {
|
interface Props<T> {
|
||||||
|
|
@ -92,6 +94,10 @@ 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
|
||||||
|
orderBy?: string;
|
||||||
|
setOrderBy?: React.Dispatch<React.SetStateAction<string>>;
|
||||||
|
order?: string;
|
||||||
|
setOrder?: React.Dispatch<React.SetStateAction<"asc" | "desc">>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function ResponsiveTable<T extends Object>(props: Props<T>) {
|
export default function ResponsiveTable<T extends Object>(props: Props<T>) {
|
||||||
|
|
@ -120,12 +126,17 @@ export default function ResponsiveTable<T extends Object>(props: Props<T>) {
|
||||||
selectedRows,
|
selectedRows,
|
||||||
customElement,
|
customElement,
|
||||||
mobileView,
|
mobileView,
|
||||||
hidePagination
|
hidePagination,
|
||||||
|
orderBy,
|
||||||
|
setOrderBy,
|
||||||
|
order,
|
||||||
|
setOrder
|
||||||
} = props
|
} = props
|
||||||
const classes = useStyles();
|
const classes = useStyles();
|
||||||
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 order = props.order ? props.order : "asc"
|
||||||
|
|
||||||
const isMobile = useMobile()
|
const isMobile = useMobile()
|
||||||
|
|
||||||
|
|
@ -373,12 +384,30 @@ export default function ResponsiveTable<T extends Object>(props: Props<T>) {
|
||||||
setFilterList(newFilterList)
|
setFilterList(newFilterList)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const columnClick = (column: Column<T>) => {
|
||||||
|
const sortKey = column.sortKey ? column.sortKey : column.title
|
||||||
|
console.log(column.sortKey)
|
||||||
|
if (setOrderBy) setOrderBy(sortKey)
|
||||||
|
if (setOrder && order) setOrder(order === "asc" ? "desc" : "asc")
|
||||||
|
}
|
||||||
|
|
||||||
|
const showOrderIcon = (column: Column<T>) => {
|
||||||
|
if (!orderBy) return
|
||||||
|
const sortKey = column.sortKey ? column.sortKey : column.title
|
||||||
|
if (sortKey === orderBy) {
|
||||||
|
if (order === "asc") {
|
||||||
|
return <ArrowDownward/>
|
||||||
|
} else {
|
||||||
|
return <ArrowUpward/>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
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">
|
||||||
|
|
@ -419,7 +448,6 @@ export default function ResponsiveTable<T extends Object>(props: Props<T>) {
|
||||||
</TableRow>
|
</TableRow>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
<TableRow sx={ hideKeys ? { display: "none" } : undefined } >
|
<TableRow sx={ hideKeys ? { display: "none" } : undefined } >
|
||||||
{ rowSelect && <TableCell></TableCell> }
|
{ rowSelect && <TableCell></TableCell> }
|
||||||
{ renderGutter && <TableCell></TableCell>}
|
{ renderGutter && <TableCell></TableCell>}
|
||||||
|
|
@ -427,8 +455,14 @@ export default function ResponsiveTable<T extends Object>(props: Props<T>) {
|
||||||
columns.map((column, index) => {
|
columns.map((column, index) => {
|
||||||
if (filterList.includes(column.title) || column.hidden) return null
|
if (filterList.includes(column.title) || column.hidden) return null
|
||||||
return (
|
return (
|
||||||
<TableCell key={"header-cell-"+index}>
|
<TableCell
|
||||||
{column.title}
|
key={"header-cell-"+index}
|
||||||
|
onClick={() => !column.disableSort && columnClick(column)}
|
||||||
|
sx={{ cursor: column.disableSort ? "default" : "pointer" }}
|
||||||
|
>
|
||||||
|
<Grid2 container spacing={1}>
|
||||||
|
{column.title} {showOrderIcon(column)}
|
||||||
|
</Grid2>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -92,8 +92,8 @@ export default function Devices() {
|
||||||
const [devicesLoading, setDevicesLoading] = useState(false)
|
const [devicesLoading, setDevicesLoading] = useState(false)
|
||||||
const [limit, setLimit] = useState(10);
|
const [limit, setLimit] = useState(10);
|
||||||
const [page, setPage] = useState(0);
|
const [page, setPage] = useState(0);
|
||||||
const [order, ] = useState<"asc" | "desc">("asc");
|
const [order, setOrder] = useState<"asc" | "desc">("asc");
|
||||||
const [orderBy, ] = useState("name");
|
const [orderBy, setOrderBy] = useState("name");
|
||||||
const [search, setSearch] = useState("");
|
const [search, setSearch] = useState("");
|
||||||
const [total, setTotal] = useState(0);
|
const [total, setTotal] = useState(0);
|
||||||
const [devices, setDevices] = useState<Device[]>([])
|
const [devices, setDevices] = useState<Device[]>([])
|
||||||
|
|
@ -293,10 +293,15 @@ export default function Devices() {
|
||||||
if (newValue === "never") openGroupSettings(undefined, "add");
|
if (newValue === "never") openGroupSettings(undefined, "add");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
console.log(devices)
|
||||||
|
}, [devices])
|
||||||
|
|
||||||
const columns = (): Column<Device>[] => {
|
const columns = (): Column<Device>[] => {
|
||||||
let columns = [
|
let columns: Column<Device>[] = [
|
||||||
{
|
{
|
||||||
title: "State",
|
title: "State",
|
||||||
|
sortKey: "state",
|
||||||
render: (device: Device) => {
|
render: (device: Device) => {
|
||||||
const status = device.status ?? pond.DeviceStatus.create()
|
const status = device.status ?? pond.DeviceStatus.create()
|
||||||
const deviceStateHelper = getDeviceStateHelper(status.state);
|
const deviceStateHelper = getDeviceStateHelper(status.state);
|
||||||
|
|
@ -309,12 +314,14 @@ export default function Devices() {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "ID",
|
title: "ID",
|
||||||
|
sortKey: "deviceId",
|
||||||
render: (device: Device) => <span className={classes.cellContainer}>
|
render: (device: Device) => <span className={classes.cellContainer}>
|
||||||
{device.settings?.deviceId}
|
{device.settings?.deviceId}
|
||||||
</span>
|
</span>
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Device",
|
title: "Device",
|
||||||
|
sortKey: "name",
|
||||||
render: (device: Device) => {
|
render: (device: Device) => {
|
||||||
return (
|
return (
|
||||||
<Box className={classes.cellContainer}>
|
<Box className={classes.cellContainer}>
|
||||||
|
|
@ -346,6 +353,7 @@ export default function Devices() {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Tags",
|
title: "Tags",
|
||||||
|
sortKey: "tags",
|
||||||
render: (device: Device) => {
|
render: (device: Device) => {
|
||||||
return (
|
return (
|
||||||
<Grid2 container spacing={1} className={classes.tagsCellContainer}>
|
<Grid2 container spacing={1} className={classes.tagsCellContainer}>
|
||||||
|
|
@ -362,6 +370,8 @@ export default function Devices() {
|
||||||
if (hasPlenums) {
|
if (hasPlenums) {
|
||||||
columns.push({
|
columns.push({
|
||||||
title: "Plenum",
|
title: "Plenum",
|
||||||
|
sortKey: "hi",
|
||||||
|
disableSort: true,
|
||||||
render: (device: Device) => {
|
render: (device: Device) => {
|
||||||
if (device.status.plenum?.temperature) {
|
if (device.status.plenum?.temperature) {
|
||||||
return (
|
return (
|
||||||
|
|
@ -380,6 +390,8 @@ export default function Devices() {
|
||||||
if (hasSen5x) {
|
if (hasSen5x) {
|
||||||
columns.push({
|
columns.push({
|
||||||
title: "Sen5X",
|
title: "Sen5X",
|
||||||
|
sortKey: "hi",
|
||||||
|
disableSort: true,
|
||||||
render: (device: Device) => {
|
render: (device: Device) => {
|
||||||
if (device.status.sen5x?.temperature) {
|
if (device.status.sen5x?.temperature) {
|
||||||
return (
|
return (
|
||||||
|
|
@ -532,6 +544,10 @@ 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}/>}
|
||||||
|
order={order}
|
||||||
|
setOrder={setOrder}
|
||||||
|
orderBy={orderBy}
|
||||||
|
setOrderBy={setOrderBy}
|
||||||
/>
|
/>
|
||||||
<ProvisionDevice
|
<ProvisionDevice
|
||||||
isOpen={isProvisionDialogOpen}
|
isOpen={isProvisionDialogOpen}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue