enable write in dashboard

This commit is contained in:
proddy
2024-10-04 13:32:42 +02:00
parent 01db9db6ae
commit fd7d8ca532
8 changed files with 286 additions and 165 deletions

View File

@@ -1,24 +1,38 @@
import { useEffect, useState } from 'react';
import { useContext, useEffect, useState } from 'react';
import { IconContext } from 'react-icons/lib';
import { toast } from 'react-toastify';
import ChevronRightIcon from '@mui/icons-material/ChevronRight';
import EditIcon from '@mui/icons-material/Edit';
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
import UnfoldLessIcon from '@mui/icons-material/UnfoldLess';
import UnfoldMoreIcon from '@mui/icons-material/UnfoldMore';
import { Box, ToggleButton, ToggleButtonGroup, Typography } from '@mui/material';
import {
Box,
IconButton,
ToggleButton,
ToggleButtonGroup,
Typography
} from '@mui/material';
import { Body, Cell, Row, Table } from '@table-library/react-table-library/table';
import { useTheme } from '@table-library/react-table-library/theme';
import { CellTree, useTree } from '@table-library/react-table-library/tree';
import { useAutoRequest } from 'alova/client';
import { useAutoRequest, useRequest } from 'alova/client';
import { FormLoader, SectionContent, useLayoutTitle } from 'components';
import { AuthenticatedContext } from 'contexts/authentication';
import { useI18nContext } from 'i18n/i18n-react';
import { readDashboard } from '../../api/app';
import { readDashboard, writeDeviceValue } from '../../api/app';
import DeviceIcon from './DeviceIcon';
import DashboardDevicesDialog from './DevicesDialog';
import { formatValue } from './deviceValue';
import type { DashboardItem } from './types';
import { type DashboardItem, type DeviceValue } from './types';
import { deviceValueItemValidation } from './validators';
const Dashboard = () => {
const { LL } = useI18nContext();
const { me } = useContext(AuthenticatedContext);
useLayoutTitle('Dashboard'); // TODO translate
@@ -34,9 +48,39 @@ const Dashboard = () => {
pollingTime: 1500
});
const { loading: submitting, send: sendDeviceValue } = useRequest(
(data: { id: number; c: string; v: unknown }) => writeDeviceValue(data),
{
immediate: false
}
);
const [deviceValueDialogOpen, setDeviceValueDialogOpen] = useState(false);
const [selectedDeviceValue, setSelectedDeviceValue] = useState<DeviceValue>();
const deviceValueDialogClose = () => {
setDeviceValueDialogOpen(false);
void sendDeviceData(selectedDevice);
};
const deviceValueDialogSave = async (devicevalue: DeviceValue) => {
const id = Number(device_select.state.id);
await sendDeviceValue({ id, c: devicevalue.c ?? '', v: devicevalue.v })
.then(() => {
toast.success(LL.WRITE_CMD_SENT());
})
.catch((error: Error) => {
toast.error(error.message);
})
.finally(async () => {
setDeviceValueDialogOpen(false);
await sendDeviceData(id);
setSelectedDeviceValue(undefined);
});
};
const dashboard_theme = useTheme({
Table: `
--data-table-library_grid-template-columns: minmax(80px, auto) 120px;
--data-table-library_grid-template-columns: minmax(80px, auto) 120px 40px;
`,
BaseRow: `
font-size: 14px;
@@ -46,10 +90,8 @@ const Dashboard = () => {
`,
Row: `
background-color: #1e1e1e;
// position: relative;
// cursor: pointer;
.td {
height: 24px;
height: 22px;
}
&:hover .td {
border-top: 1px solid #177ac9;
@@ -58,15 +100,8 @@ const Dashboard = () => {
`
});
function onTreeChange(action, state) {
// do nothing for now
}
const tree = useTree(
{ nodes: data },
{
onChange: onTreeChange
},
{
treeIcon: {
margin: '4px',
@@ -84,22 +119,38 @@ const Dashboard = () => {
tree.fns.onToggleAll({});
setFirstLoad(false);
}
}, [data]);
});
const showName = (di: DashboardItem) => {
if (di.id < 100) {
// if its a device row
if (di.nodes?.length) {
return (
<span>
<span style={{ color: '#2196f3' }}>{di.n}</span>
<>
<span style="font-size: 14px;">
<DeviceIcon type_id={di.t} />
&nbsp;&nbsp;{di.n}
</span>
<span style={{ color: 'lightblue' }}>&nbsp;({di.nodes?.length})</span>
</span>
</>
);
}
return <div style={{ color: '#2196f3' }}>{di.n}</div>;
}
return <div style={{ color: '#d3d3d3' }}>{di.n}</div>;
};
return <div>{di.n}</div>;
const showDeviceValue = (di: DashboardItem) => {
// convert di to dv
// TODO should we not just use dv?
const dv: DeviceValue = {
id: ' ' + di.n,
v: di.v,
u: di.u,
c: di.c,
l: di.l
};
setSelectedDeviceValue(dv);
setDeviceValueDialogOpen(true);
};
const handleShowAll = (
@@ -129,6 +180,7 @@ const Dashboard = () => {
return (
<>
<Typography mb={2} variant="body2" color="warning">
{/* TODO translate */}
The dashboard shows all EMS entities that are marked as favorite, and the
sensors.
</Typography>
@@ -158,33 +210,71 @@ const Dashboard = () => {
border: '1px solid grey'
}}
>
<Table
data={{ nodes: data }}
theme={dashboard_theme}
layout={{ custom: true }}
tree={tree}
<IconContext.Provider
value={{
color: 'lightblue',
size: '16',
style: { verticalAlign: 'middle' }
}}
>
{(tableList: DashboardItem[]) => (
<Body>
{tableList.map((di: DashboardItem) => (
<Row key={di.id} item={di} disabled={di.nodes?.length === 0}>
{di.nodes?.length === 0 ? (
<Cell>{showName(di)}</Cell>
) : (
<CellTree item={di}>{showName(di)}</CellTree>
)}
<Cell pinRight>{formatValue(LL, di.v, di.u)}</Cell>
</Row>
))}
</Body>
)}
</Table>
<Table
data={{ nodes: data }}
theme={dashboard_theme}
layout={{ custom: true }}
tree={tree}
>
{(tableList: DashboardItem[]) => (
<Body>
{tableList.map((di: DashboardItem) => (
<Row key={di.id} item={di} disabled={di.nodes?.length === 0}>
{di.nodes?.length === 0 ? (
<Cell>{showName(di)}</Cell>
) : (
<CellTree item={di}>{showName(di)}</CellTree>
)}
<Cell pinRight>
<div style={{ color: '#d3d3d3' }}>
{formatValue(LL, di.v, di.u)}
</div>
</Cell>
<Cell stiff>
{me.admin && di.c && (
<IconButton
size="small"
onClick={() => showDeviceValue(di)}
>
<EditIcon color="primary" sx={{ fontSize: 16 }} />
</IconButton>
)}
</Cell>
</Row>
))}
</Body>
)}
</Table>
</IconContext.Provider>
</Box>
</>
);
};
return <SectionContent>{renderContent()}</SectionContent>;
return (
<SectionContent>
{renderContent()}
{selectedDeviceValue && (
<DashboardDevicesDialog
open={deviceValueDialogOpen}
onClose={deviceValueDialogClose}
onSave={deviceValueDialogSave}
selectedItem={selectedDeviceValue}
writeable={true}
validator={deviceValueItemValidation(selectedDeviceValue)}
progress={submitting}
/>
)}
</SectionContent>
);
};
export default Dashboard;