import { FC, useState, useEffect, useCallback } from 'react'; import { Button, Table, TableBody, TableHead, TableRow, Typography, Box, MenuItem, Dialog, DialogActions, DialogContent, DialogTitle } from '@mui/material'; import TableCell, { tableCellClasses } from '@mui/material/TableCell'; import { styled } from '@mui/material/styles'; import { useSnackbar } from 'notistack'; import SaveIcon from '@mui/icons-material/Save'; import CloseIcon from '@mui/icons-material/Close'; import CancelIcon from '@mui/icons-material/Cancel'; import SettingsBackupRestoreIcon from '@mui/icons-material/SettingsBackupRestore'; import { ButtonRow, FormLoader, ValidatedTextField, SectionContent } from '../components'; import * as EMSESP from './api'; import { extractErrorMessage } from '../utils'; import { DeviceShort, Devices, DeviceEntity } from './types'; const StyledTableCell = styled(TableCell)(({ theme }) => ({ [`&.${tableCellClasses.head}`]: { backgroundColor: '#607d8b', color: theme.palette.common.white, fontSize: 11 }, [`&.${tableCellClasses.body}`]: { fontSize: 11 } })); const SettingsCustomization: FC = () => { const { enqueueSnackbar } = useSnackbar(); const [deviceEntities, setDeviceEntities] = useState(); const [devices, setDevices] = useState(); const [errorMessage, setErrorMessage] = useState(); const [selectedDevice, setSelectedDevice] = useState(0); const [confirmReset, setConfirmReset] = useState(false); const fetchDevices = useCallback(async () => { try { setDevices((await EMSESP.readDevices()).data); } catch (error: any) { setErrorMessage(extractErrorMessage(error, 'Failed to fetch device list')); } }, []); const fetchDeviceEntities = async (unique_id: number) => { try { setDeviceEntities((await EMSESP.readDeviceEntities({ id: unique_id })).data); } catch (error: any) { setErrorMessage(extractErrorMessage(error, 'Problem fetching device entities')); } }; useEffect(() => { fetchDevices(); }, [fetchDevices]); function formatValue(value: any) { if (typeof value === 'number') { return new Intl.NumberFormat().format(value); } else if (value === undefined) { return ''; } else if (typeof value === 'boolean') { return value ? 'true' : 'false'; } return value; } const renderDeviceList = () => { if (!devices) { return ; } function compareDevices(a: DeviceShort, b: DeviceShort) { if (a.s < b.s) { return -1; } if (a.s > b.s) { return 1; } return 0; } const changeSelectedDevice = (event: React.ChangeEvent) => { const selected_device = parseInt(event.target.value, 10); setSelectedDevice(selected_device); fetchDeviceEntities(selected_device); }; return ( <> Customize which entities to exclude from all all services (MQTT, API). This will have immediate effect. Select a device... {devices.devices.sort(compareDevices).map((device: DeviceShort, index) => ( {device.s} ))} ); }; const saveCustomization = async () => { if (deviceEntities && selectedDevice) { const exclude_entities = deviceEntities.filter((de) => de.x).map((new_de) => new_de.i); try { const response = await EMSESP.writeExcludeEntities({ id: selectedDevice, entity_ids: exclude_entities }); if (response.status === 200) { enqueueSnackbar('Customization saved', { variant: 'success' }); } else { enqueueSnackbar('Customization save failed', { variant: 'error' }); } } catch (error: any) { enqueueSnackbar(extractErrorMessage(error, 'Problem sending entity list'), { variant: 'error' }); } } }; const renderDeviceData = () => { if (devices?.devices.length === 0 || !deviceEntities) { return; } const toggleDeviceEntity = (id: number) => { setDeviceEntities( deviceEntities.map((o) => { if (o.i === id) { return { ...o, x: !o.x }; } return o; }) ); }; return ( <> ({deviceEntities.reduce((a, v) => (v.x ? a + 1 : a), 0)}/{deviceEntities.length}) ENTITY NAME CODE VALUE {deviceEntities.map((de) => ( toggleDeviceEntity(de.i)} sx={de.x ? { backgroundColor: '#f8696b' } : { backgroundColor: 'black' }} > {de.x && } {de.n} {de.s} {formatValue(de.v)} ))}
); }; const resetCustomization = async () => { try { await EMSESP.resetCustomizations(); enqueueSnackbar('All customizations have been removed. Restarting...', { variant: 'info' }); } catch (error: any) { enqueueSnackbar(extractErrorMessage(error, 'Problem resetting customizations'), { variant: 'error' }); } finally { setConfirmReset(false); } }; const renderResetDialog = () => ( setConfirmReset(false)}> Reset Are you sure you want remove all customizations? EMS-ESP will then restart. ); const content = () => { return ( <> Device Entities {renderDeviceList()} {renderDeviceData()} {renderResetDialog()} ); }; return ( {content()} ); }; export default SettingsCustomization;