diff --git a/interface/src/app/main/Dashboard.tsx b/interface/src/app/main/Dashboard.tsx index f27a58201..061fa8165 100644 --- a/interface/src/app/main/Dashboard.tsx +++ b/interface/src/app/main/Dashboard.tsx @@ -3,6 +3,7 @@ import { IconContext } from 'react-icons/lib'; import { toast } from 'react-toastify'; import ChevronRightIcon from '@mui/icons-material/ChevronRight'; +import CircleIcon from '@mui/icons-material/Circle'; import EditIcon from '@mui/icons-material/Edit'; import ExpandMoreIcon from '@mui/icons-material/ExpandMore'; import UnfoldLessIcon from '@mui/icons-material/UnfoldLess'; @@ -12,8 +13,10 @@ import { IconButton, ToggleButton, ToggleButtonGroup, + Tooltip, Typography } from '@mui/material'; +import Grid from '@mui/material/Grid2'; import { Body, Cell, Row, Table } from '@table-library/react-table-library/table'; import { useTheme } from '@table-library/react-table-library/theme'; @@ -24,11 +27,17 @@ import { AuthenticatedContext } from 'contexts/authentication'; import { useI18nContext } from 'i18n/i18n-react'; import { useInterval } from 'utils'; -import { readDashboard, writeDeviceValue } from '../../api/app'; +import { readDashboard, writeDeviceValue, writeSchedule } from '../../api/app'; import DeviceIcon from './DeviceIcon'; -import DashboardDevicesDialog from './DevicesDialog'; +import DevicesDialog from './DevicesDialog'; import { formatValue } from './deviceValue'; -import { type DashboardItem, DeviceEntityMask, type DeviceValue } from './types'; +import { + type DashboardItem, + DeviceEntityMask, + DeviceType, + type DeviceValue, + type Schedule +} from './types'; import { deviceValueItemValidation } from './validators'; const Dashboard = () => { @@ -54,6 +63,13 @@ const Dashboard = () => { initialData: [] }); + const { send: updateSchedule } = useRequest( + (data: Schedule) => writeSchedule(data), + { + immediate: false + } + ); + const { loading: submitting, send: sendDeviceValue } = useRequest( (data: { id: number; c: string; v: unknown }) => writeDeviceValue(data), { @@ -104,14 +120,24 @@ const Dashboard = () => { const tree = useTree( { nodes: data }, { - onChange: null // not used but needed + onChange: undefined // not used but needed }, { treeIcon: { margin: '4px', iconDefault: null, - iconRight: , - iconDown: + iconRight: ( + + ), + iconDown: ( + + ) }, indentation: 50 } @@ -131,27 +157,78 @@ const Dashboard = () => { } }, [loading]); + const showType = (n?: string, t?: number) => { + // if we have a name show it + if (n) { + return n; + } + if (t) { + // otherwise pick translation based on type + switch (t) { + case DeviceType.CUSTOM: + return LL.CUSTOM_ENTITIES(0); + case DeviceType.ANALOGSENSOR: + return LL.ANALOG_SENSOR(0); + case DeviceType.TEMPERATURESENSOR: + return LL.TEMP_SENSOR(); + case DeviceType.SCHEDULER: + return LL.SCHEDULER(); + default: + break; + } + } + return ''; + }; + const showName = (di: DashboardItem) => { if (di.id < 100) { - // if its a device and has entities + // if its a device (parent node) and has entities if (di.nodes?.length) { return ( <> -   {di.n} +   {showType(di.n, di.t)}  ({di.nodes?.length}) ); } } - return {di.dv ? di.dv.id.slice(2) : ''}; + if (di.dv) { + return ( + // ids for scheduler, and sensors are between 9600 and 9900 + + {di.id >= 9600 && di.id < 9900 ? di.dv.id : di.dv.id.slice(2)} + + ); + } }; const hasMask = (id: string, mask: number) => (parseInt(id.slice(0, 2), 16) & mask) === mask; + const toggleSchedule = async (di: DashboardItem) => { + // create a dummy record, the id=0 picks it up + await updateSchedule({ + schedule: { + id: 0, // special number for only changing the active flag + active: !di.dv?.v, + flags: 0, // unused + time: '', // unused + cmd: '', // unused + value: '', // unused + name: di.dv?.id ?? '' + } + }) + .catch((error: Error) => { + toast.error(error.message); + }) + .finally(async () => { + await fetchDashboard(); + }); + }; + const editDashboardValue = (di: DashboardItem) => { setSelectedDashboardItem(di); setDeviceValueDialogOpen(true); @@ -174,32 +251,37 @@ const Dashboard = () => { return ( <> - - {LL.DASHBOARD_1()} - + + + + {LL.DASHBOARD_1()} + + - - - - - - - - + + + + + + + + + + + @@ -225,30 +307,65 @@ const Dashboard = () => { {tableList.map((di: DashboardItem) => ( - {/* TODO add a comment about the number 99 */} {di.id > 99 ? ( - {showName(di)} + <> + {showName(di)} + + + + {di.dv ? formatValue(LL, di.dv.v, di.dv.u) : ''} + + + + + + {me.admin && di.id < 9700 && di.id >= 9600 ? ( + toggleSchedule(di)} + > + {di.dv?.v ? ( + + ) : ( + + )} + + ) : ( + me.admin && + di.dv?.c && + !hasMask(di.dv.id, DeviceEntityMask.DV_READONLY) && ( + editDashboardValue(di)} + > + + + ) + )} + + ) : ( - {showName(di)} + <> + {showName(di)} + + + )} - - - {di.dv && formatValue(LL, di.dv.v, di.dv.u)} - - - - - {me.admin && - di.dv?.c && - !hasMask(di.dv.id, DeviceEntityMask.DV_READONLY) && ( - editDashboardValue(di)} - > - - - )} - ))} @@ -265,7 +382,7 @@ const Dashboard = () => { {renderContent()} {selectedDashboardItem && selectedDashboardItem.dv && ( - setDeviceValueDialogOpen(false)} onSave={deviceValueDialogSave}