mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2025-12-06 07:49:52 +03:00
removed SAVE
This commit is contained in:
@@ -46,7 +46,6 @@ const de: Translation = {
|
|||||||
CHANGE_VALUE: 'Wert ändern',
|
CHANGE_VALUE: 'Wert ändern',
|
||||||
CANCEL: 'Abbrechen',
|
CANCEL: 'Abbrechen',
|
||||||
RESET: 'Zurücksetzen',
|
RESET: 'Zurücksetzen',
|
||||||
SEND: 'Senden',
|
|
||||||
APPLY_CHANGES: 'Apply Changes ({0})', // TODO translate
|
APPLY_CHANGES: 'Apply Changes ({0})', // TODO translate
|
||||||
UPDATE: 'Update', // TODO translate
|
UPDATE: 'Update', // TODO translate
|
||||||
REMOVE: 'Entfernen',
|
REMOVE: 'Entfernen',
|
||||||
|
|||||||
@@ -46,7 +46,6 @@ const en: Translation = {
|
|||||||
CHANGE_VALUE: 'Change Value',
|
CHANGE_VALUE: 'Change Value',
|
||||||
CANCEL: 'Cancel',
|
CANCEL: 'Cancel',
|
||||||
RESET: 'Reset',
|
RESET: 'Reset',
|
||||||
SEND: 'Send',
|
|
||||||
APPLY_CHANGES: 'Apply Changes ({0})',
|
APPLY_CHANGES: 'Apply Changes ({0})',
|
||||||
UPDATE: 'Update',
|
UPDATE: 'Update',
|
||||||
REMOVE: 'Remove',
|
REMOVE: 'Remove',
|
||||||
|
|||||||
@@ -46,7 +46,6 @@ const fr: Translation = {
|
|||||||
CHANGE_VALUE: 'Changer la valeur',
|
CHANGE_VALUE: 'Changer la valeur',
|
||||||
CANCEL: 'Annuler',
|
CANCEL: 'Annuler',
|
||||||
RESET: 'Réinitialiser',
|
RESET: 'Réinitialiser',
|
||||||
SEND: 'Envoyer',
|
|
||||||
APPLY_CHANGES: 'Apply Changes ({0})', // TODO translate
|
APPLY_CHANGES: 'Apply Changes ({0})', // TODO translate
|
||||||
UPDATE: 'Update', // TODO translate
|
UPDATE: 'Update', // TODO translate
|
||||||
REMOVE: 'Enlever',
|
REMOVE: 'Enlever',
|
||||||
|
|||||||
@@ -46,7 +46,6 @@ const nl: Translation = {
|
|||||||
CHANGE_VALUE: 'Wijzig waarde',
|
CHANGE_VALUE: 'Wijzig waarde',
|
||||||
CANCEL: 'Annuleren',
|
CANCEL: 'Annuleren',
|
||||||
RESET: 'Reset',
|
RESET: 'Reset',
|
||||||
SEND: 'Verzenden',
|
|
||||||
APPLY_CHANGES: 'Apply Changes ({0})', // TODO translate
|
APPLY_CHANGES: 'Apply Changes ({0})', // TODO translate
|
||||||
UPDATE: 'Update', // TODO translate
|
UPDATE: 'Update', // TODO translate
|
||||||
REMOVE: 'Verwijderen',
|
REMOVE: 'Verwijderen',
|
||||||
|
|||||||
@@ -46,7 +46,6 @@ const no: Translation = {
|
|||||||
CHANGE_VALUE: 'Endre Verdi',
|
CHANGE_VALUE: 'Endre Verdi',
|
||||||
CANCEL: 'Avbryt',
|
CANCEL: 'Avbryt',
|
||||||
RESET: 'Nullstill',
|
RESET: 'Nullstill',
|
||||||
SEND: 'Send',
|
|
||||||
APPLY_CHANGES: 'Utfør endringer({0})',
|
APPLY_CHANGES: 'Utfør endringer({0})',
|
||||||
UPDATE: 'Oppdater',
|
UPDATE: 'Oppdater',
|
||||||
REMOVE: 'Fjern',
|
REMOVE: 'Fjern',
|
||||||
|
|||||||
@@ -46,7 +46,6 @@ const pl: BaseTranslation = {
|
|||||||
CHANGE_VALUE: 'Zmień wartość',
|
CHANGE_VALUE: 'Zmień wartość',
|
||||||
CANCEL: 'Anuluj',
|
CANCEL: 'Anuluj',
|
||||||
RESET: 'Reset{{uj|owanie|}}',
|
RESET: 'Reset{{uj|owanie|}}',
|
||||||
SEND: 'Wyślij',
|
|
||||||
APPLY_CHANGES: 'Zapisz zmiany ({0})',
|
APPLY_CHANGES: 'Zapisz zmiany ({0})',
|
||||||
UPDATE: 'Uaktualnij',
|
UPDATE: 'Uaktualnij',
|
||||||
REMOVE: 'Usuń',
|
REMOVE: 'Usuń',
|
||||||
|
|||||||
@@ -46,7 +46,6 @@ const sv: Translation = {
|
|||||||
CHANGE_VALUE: 'Ändra Värde',
|
CHANGE_VALUE: 'Ändra Värde',
|
||||||
CANCEL: 'Avbryt',
|
CANCEL: 'Avbryt',
|
||||||
RESET: 'Nollställ',
|
RESET: 'Nollställ',
|
||||||
SEND: 'Skicka',
|
|
||||||
APPLY_CHANGES: 'Apply Changes ({0})', // TODO translate
|
APPLY_CHANGES: 'Apply Changes ({0})', // TODO translate
|
||||||
UPDATE: 'Update', // TODO translate
|
UPDATE: 'Update', // TODO translate
|
||||||
REMOVE: 'Ta bort',
|
REMOVE: 'Ta bort',
|
||||||
|
|||||||
@@ -46,7 +46,6 @@ const tr: Translation = {
|
|||||||
CHANGE_VALUE: 'Değeri Değiştir',
|
CHANGE_VALUE: 'Değeri Değiştir',
|
||||||
CANCEL: 'İptal',
|
CANCEL: 'İptal',
|
||||||
RESET: 'Reset',
|
RESET: 'Reset',
|
||||||
SEND: 'Gönder',
|
|
||||||
APPLY_CHANGES: 'Apply Changes ({0})',
|
APPLY_CHANGES: 'Apply Changes ({0})',
|
||||||
UPDATE: 'Update',
|
UPDATE: 'Update',
|
||||||
REMOVE: 'Kaldır',
|
REMOVE: 'Kaldır',
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
import AddCircleOutlineOutlinedIcon from '@mui/icons-material/AddCircleOutlineOutlined';
|
|
||||||
import CancelIcon from '@mui/icons-material/Cancel';
|
|
||||||
import CommentsDisabledOutlinedIcon from '@mui/icons-material/CommentsDisabledOutlined';
|
import CommentsDisabledOutlinedIcon from '@mui/icons-material/CommentsDisabledOutlined';
|
||||||
import EditIcon from '@mui/icons-material/Edit';
|
import EditIcon from '@mui/icons-material/Edit';
|
||||||
import EditOffOutlinedIcon from '@mui/icons-material/EditOffOutlined';
|
import EditOffOutlinedIcon from '@mui/icons-material/EditOffOutlined';
|
||||||
@@ -9,27 +7,19 @@ import KeyboardArrowDownOutlinedIcon from '@mui/icons-material/KeyboardArrowDown
|
|||||||
import KeyboardArrowUpOutlinedIcon from '@mui/icons-material/KeyboardArrowUpOutlined';
|
import KeyboardArrowUpOutlinedIcon from '@mui/icons-material/KeyboardArrowUpOutlined';
|
||||||
import PlayArrowIcon from '@mui/icons-material/PlayArrow';
|
import PlayArrowIcon from '@mui/icons-material/PlayArrow';
|
||||||
import RefreshIcon from '@mui/icons-material/Refresh';
|
import RefreshIcon from '@mui/icons-material/Refresh';
|
||||||
import RemoveIcon from '@mui/icons-material/RemoveCircleOutline';
|
|
||||||
import StarIcon from '@mui/icons-material/Star';
|
import StarIcon from '@mui/icons-material/Star';
|
||||||
import SendIcon from '@mui/icons-material/TrendingFlat';
|
|
||||||
import UnfoldMoreOutlinedIcon from '@mui/icons-material/UnfoldMoreOutlined';
|
import UnfoldMoreOutlinedIcon from '@mui/icons-material/UnfoldMoreOutlined';
|
||||||
import WarningIcon from '@mui/icons-material/Warning';
|
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
Typography,
|
Typography,
|
||||||
Box,
|
|
||||||
Dialog,
|
Dialog,
|
||||||
DialogTitle,
|
DialogTitle,
|
||||||
DialogContent,
|
DialogContent,
|
||||||
DialogActions,
|
DialogActions,
|
||||||
MenuItem,
|
|
||||||
InputAdornment,
|
|
||||||
FormHelperText,
|
|
||||||
IconButton,
|
IconButton,
|
||||||
List,
|
List,
|
||||||
ListItem,
|
ListItem,
|
||||||
ListItemText,
|
ListItemText,
|
||||||
Grid,
|
|
||||||
FormControlLabel,
|
FormControlLabel,
|
||||||
Checkbox
|
Checkbox
|
||||||
} from '@mui/material';
|
} from '@mui/material';
|
||||||
@@ -41,35 +31,34 @@ import { useState, useContext, useCallback, useEffect } from 'react';
|
|||||||
|
|
||||||
import { IconContext } from 'react-icons';
|
import { IconContext } from 'react-icons';
|
||||||
import { toast } from 'react-toastify';
|
import { toast } from 'react-toastify';
|
||||||
|
import DashboarDevicesDialog from './DashboardDevicesDialog';
|
||||||
import DeviceIcon from './DeviceIcon';
|
import DeviceIcon from './DeviceIcon';
|
||||||
|
|
||||||
import * as EMSESP from './api';
|
import * as EMSESP from './api';
|
||||||
|
|
||||||
import { DeviceValueUOM, DeviceValueUOM_s, DeviceEntityMask } from './types';
|
import { DeviceValueUOM, DeviceValueUOM_s, DeviceEntityMask } from './types';
|
||||||
import type { SensorData, Device, CoreData, DeviceData, DeviceValue, TemperatureSensor, AnalogSensor } from './types';
|
import type { Device, CoreData, DeviceData, DeviceValue } from './types';
|
||||||
import type { FC } from 'react';
|
import type { FC } from 'react';
|
||||||
import { ButtonRow, ValidatedTextField, SectionContent, MessageBox } from 'components';
|
import { ButtonRow, SectionContent, MessageBox } from 'components';
|
||||||
import { AuthenticatedContext } from 'contexts/authentication';
|
import { AuthenticatedContext } from 'contexts/authentication';
|
||||||
|
|
||||||
import { useI18nContext } from 'i18n/i18n-react';
|
import { useI18nContext } from 'i18n/i18n-react';
|
||||||
import { numberValue, updateValue, extractErrorMessage } from 'utils';
|
import { extractErrorMessage } from 'utils';
|
||||||
|
|
||||||
const DashboardDevices: FC = () => {
|
const DashboardDevices: FC = () => {
|
||||||
const { me } = useContext(AuthenticatedContext);
|
const { me } = useContext(AuthenticatedContext);
|
||||||
const { LL } = useI18nContext();
|
const { LL } = useI18nContext();
|
||||||
const [deviceData, setDeviceData] = useState<DeviceData>({ label: '', data: [] });
|
const [deviceData, setDeviceData] = useState<DeviceData>({ label: '', data: [] });
|
||||||
const [deviceValue, setDeviceValue] = useState<DeviceValue>();
|
const [selectedDeviceValue, setSelectedDeviceValue] = useState<DeviceValue>();
|
||||||
const [deviceDialog, setDeviceDialog] = useState<number>(-1);
|
const [deviceDetails, setDeviceDetails] = useState<number>(-1);
|
||||||
const [onlyFav, setOnlyFav] = useState(false);
|
const [onlyFav, setOnlyFav] = useState(false);
|
||||||
|
const [selectedDevice, setSelectedDevice] = useState<number>();
|
||||||
|
const [deviceValueDialogOpen, setDeviceValueDialogOpen] = useState(false);
|
||||||
|
|
||||||
const [coreData, setCoreData] = useState<CoreData>({
|
const [coreData, setCoreData] = useState<CoreData>({
|
||||||
connected: true,
|
connected: true,
|
||||||
devices: []
|
devices: []
|
||||||
});
|
});
|
||||||
const [selectedDevice, setSelectedDevice] = useState<number>();
|
|
||||||
|
|
||||||
const [sensorData, setSensorData] = useState<SensorData>({ ts: [], as: [] });
|
|
||||||
const [analog, setAnalog] = useState<AnalogSensor>();
|
|
||||||
const [sensor, setSensor] = useState<TemperatureSensor>();
|
|
||||||
|
|
||||||
const common_theme = useTheme({
|
const common_theme = useTheme({
|
||||||
BaseRow: `
|
BaseRow: `
|
||||||
@@ -198,14 +187,6 @@ const DashboardDevices: FC = () => {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
// const fetchSensorData = async () => {
|
|
||||||
// try {
|
|
||||||
// setSensorData((await EMSESP.readSensorData()).data);
|
|
||||||
// } catch (error) {
|
|
||||||
// toast.error(extractErrorMessage(error, LL.PROBLEM_LOADING()));
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
|
|
||||||
const fetchDeviceData = async (id: number) => {
|
const fetchDeviceData = async (id: number) => {
|
||||||
try {
|
try {
|
||||||
setDeviceData((await EMSESP.readDeviceData({ id })).data);
|
setDeviceData((await EMSESP.readDeviceData({ id })).data);
|
||||||
@@ -224,46 +205,19 @@ const DashboardDevices: FC = () => {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
void fetchCoreData();
|
void fetchCoreData();
|
||||||
}, [fetchCoreData]);
|
}, []);
|
||||||
|
|
||||||
// const refreshDataIndex = (selectedDevice: string) => {
|
|
||||||
// // if (selectedDevice === 'sensor') {
|
|
||||||
// // void fetchSensorData();
|
|
||||||
// // return;
|
|
||||||
// // }
|
|
||||||
|
|
||||||
// // setSensorData({ sensors: [], analogs: [] });
|
|
||||||
// if (selectedDevice) {
|
|
||||||
// void fetchDeviceData(selectedDevice);
|
|
||||||
// } else {
|
|
||||||
// void fetchCoreData();
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
|
|
||||||
const refreshData = () => {
|
const refreshData = () => {
|
||||||
// const selectedDevice = device_select.state.id;
|
|
||||||
// if (selectedDevice === 'sensor') {
|
|
||||||
// // void fetchSensorData();
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// setSensorData({ sensors: [], analogs: [] });
|
|
||||||
if (selectedDevice) {
|
if (selectedDevice) {
|
||||||
void fetchDeviceData(selectedDevice);
|
void fetchDeviceData(selectedDevice);
|
||||||
} else {
|
} else {
|
||||||
void fetchCoreData();
|
void fetchCoreData();
|
||||||
}
|
}
|
||||||
|
|
||||||
// refreshDataIndex(device_select.state.id);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
function onSelectChange(action: any, state: any) {
|
function onSelectChange(action: any, state: any) {
|
||||||
setSelectedDevice(device_select.state.id);
|
setSelectedDevice(device_select.state.id);
|
||||||
if (action.type === 'ADD_BY_ID_EXCLUSIVELY') {
|
refreshData();
|
||||||
refreshData();
|
|
||||||
} else {
|
|
||||||
// setSensorData({ sensors: [], analogs: [] });
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const escapeCsvCell = (cell: any) => {
|
const escapeCsvCell = (cell: any) => {
|
||||||
@@ -322,7 +276,7 @@ const DashboardDevices: FC = () => {
|
|||||||
return () => {
|
return () => {
|
||||||
clearInterval(timer);
|
clearInterval(timer);
|
||||||
};
|
};
|
||||||
}, [analog, sensor, deviceValue, sensorData]);
|
}, []);
|
||||||
|
|
||||||
const isCmdOnly = (dv: DeviceValue) => dv.v === '' && dv.c;
|
const isCmdOnly = (dv: DeviceValue) => dv.v === '' && dv.c;
|
||||||
|
|
||||||
@@ -375,140 +329,60 @@ const DashboardDevices: FC = () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const setUom = (uom: number) => {
|
const deviceValueDialogSave = async (dv: DeviceValue) => {
|
||||||
switch (uom) {
|
try {
|
||||||
case DeviceValueUOM.HOURS:
|
const response = await EMSESP.writeDeviceValue({
|
||||||
return LL.HOURS();
|
id: Number(device_select.state.id),
|
||||||
case DeviceValueUOM.MINUTES:
|
devicevalue: dv
|
||||||
return LL.MINUTES();
|
});
|
||||||
case DeviceValueUOM.SECONDS:
|
if (response.status === 204) {
|
||||||
return LL.SECONDS();
|
toast.error(LL.WRITE_CMD_FAILED());
|
||||||
default:
|
} else if (response.status === 403) {
|
||||||
return DeviceValueUOM_s[uom];
|
toast.error(LL.ACCESS_DENIED());
|
||||||
}
|
} else {
|
||||||
};
|
toast.success(LL.WRITE_CMD_SENT());
|
||||||
|
|
||||||
const sendDeviceValue = async () => {
|
|
||||||
if (deviceValue) {
|
|
||||||
try {
|
|
||||||
const response = await EMSESP.writeDeviceValue({
|
|
||||||
id: Number(device_select.state.id),
|
|
||||||
devicevalue: deviceValue
|
|
||||||
});
|
|
||||||
if (response.status === 204) {
|
|
||||||
toast.error(LL.WRITE_CMD_FAILED());
|
|
||||||
} else if (response.status === 403) {
|
|
||||||
toast.error(LL.ACCESS_DENIED());
|
|
||||||
} else {
|
|
||||||
toast.success(LL.WRITE_CMD_SENT());
|
|
||||||
}
|
|
||||||
setDeviceValue(undefined);
|
|
||||||
} catch (error) {
|
|
||||||
toast.error(extractErrorMessage(error, LL.PROBLEM_UPDATING()));
|
|
||||||
} finally {
|
|
||||||
refreshData();
|
|
||||||
setDeviceValue(undefined);
|
|
||||||
}
|
}
|
||||||
|
} catch (error) {
|
||||||
|
toast.error(extractErrorMessage(error, LL.PROBLEM_UPDATING()));
|
||||||
|
} finally {
|
||||||
|
setDeviceValueDialogOpen(false);
|
||||||
|
setSelectedDeviceValue(undefined);
|
||||||
|
refreshData();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const renderDeviceValueDialog = () => {
|
const renderDeviceDetails = () => {
|
||||||
if (deviceValue) {
|
if (coreData && coreData.devices.length > 0 && deviceDetails !== -1) {
|
||||||
return (
|
return (
|
||||||
<Dialog open={deviceValue !== undefined} onClose={() => setDeviceValue(undefined)}>
|
<Dialog open={deviceDetails !== -1} onClose={() => setDeviceDetails(-1)}>
|
||||||
<DialogTitle>{isCmdOnly(deviceValue) ? LL.RUN_COMMAND() : LL.CHANGE_VALUE()}</DialogTitle>
|
|
||||||
<DialogContent dividers>
|
|
||||||
{deviceValue.l && (
|
|
||||||
<ValidatedTextField
|
|
||||||
name="v"
|
|
||||||
label={deviceValue.id.slice(2)}
|
|
||||||
value={deviceValue.v}
|
|
||||||
autoFocus
|
|
||||||
sx={{ width: '30ch' }}
|
|
||||||
select
|
|
||||||
onChange={updateValue(setDeviceValue)}
|
|
||||||
>
|
|
||||||
{deviceValue.l.map((val) => (
|
|
||||||
<MenuItem value={val} key={val}>
|
|
||||||
{val}
|
|
||||||
</MenuItem>
|
|
||||||
))}
|
|
||||||
</ValidatedTextField>
|
|
||||||
)}
|
|
||||||
{!deviceValue.l && (
|
|
||||||
<ValidatedTextField
|
|
||||||
name="v"
|
|
||||||
label={deviceValue.id.slice(2)}
|
|
||||||
value={typeof deviceValue.v === 'number' ? Math.round(deviceValue.v * 10) / 10 : deviceValue.v}
|
|
||||||
autoFocus
|
|
||||||
multiline={deviceValue.u ? false : true}
|
|
||||||
sx={{ width: '30ch' }}
|
|
||||||
type={deviceValue.u ? 'number' : 'text'}
|
|
||||||
onChange={updateValue(setDeviceValue)}
|
|
||||||
inputProps={deviceValue.u ? { min: deviceValue.m, max: deviceValue.x, step: deviceValue.s } : {}}
|
|
||||||
InputProps={{
|
|
||||||
startAdornment: <InputAdornment position="start">{setUom(deviceValue.u)}</InputAdornment>
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
{deviceValue.h && <FormHelperText>{deviceValue.h}</FormHelperText>}
|
|
||||||
</DialogContent>
|
|
||||||
<DialogActions>
|
|
||||||
<Button
|
|
||||||
startIcon={<CancelIcon />}
|
|
||||||
variant="outlined"
|
|
||||||
onClick={() => setDeviceValue(undefined)}
|
|
||||||
color="secondary"
|
|
||||||
>
|
|
||||||
{LL.CANCEL()}
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
startIcon={<SendIcon />}
|
|
||||||
variant="outlined"
|
|
||||||
type="submit"
|
|
||||||
onClick={() => sendDeviceValue()}
|
|
||||||
color="warning"
|
|
||||||
>
|
|
||||||
{LL.SEND()}
|
|
||||||
</Button>
|
|
||||||
</DialogActions>
|
|
||||||
</Dialog>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const renderDeviceDialog = () => {
|
|
||||||
if (coreData && coreData.devices.length > 0 && deviceDialog !== -1) {
|
|
||||||
return (
|
|
||||||
<Dialog open={deviceDialog !== -1} onClose={() => setDeviceDialog(-1)}>
|
|
||||||
<DialogTitle>{LL.DEVICE_DETAILS()}</DialogTitle>
|
<DialogTitle>{LL.DEVICE_DETAILS()}</DialogTitle>
|
||||||
<DialogContent dividers>
|
<DialogContent dividers>
|
||||||
<List dense={true}>
|
<List dense={true}>
|
||||||
<ListItem>
|
<ListItem>
|
||||||
<ListItemText primary={LL.TYPE(0)} secondary={coreData.devices[deviceDialog].tn} />
|
<ListItemText primary={LL.TYPE(0)} secondary={coreData.devices[deviceDetails].tn} />
|
||||||
</ListItem>
|
</ListItem>
|
||||||
<ListItem>
|
<ListItem>
|
||||||
<ListItemText primary={LL.NAME(0)} secondary={coreData.devices[deviceDialog].n} />
|
<ListItemText primary={LL.NAME(0)} secondary={coreData.devices[deviceDetails].n} />
|
||||||
</ListItem>
|
</ListItem>
|
||||||
<ListItem>
|
<ListItem>
|
||||||
<ListItemText primary={LL.BRAND()} secondary={coreData.devices[deviceDialog].b} />
|
<ListItemText primary={LL.BRAND()} secondary={coreData.devices[deviceDetails].b} />
|
||||||
</ListItem>
|
</ListItem>
|
||||||
<ListItem>
|
<ListItem>
|
||||||
<ListItemText
|
<ListItemText
|
||||||
primary={LL.ID_OF(LL.DEVICE())}
|
primary={LL.ID_OF(LL.DEVICE())}
|
||||||
secondary={'0x' + ('00' + coreData.devices[deviceDialog].d.toString(16).toUpperCase()).slice(-2)}
|
secondary={'0x' + ('00' + coreData.devices[deviceDetails].d.toString(16).toUpperCase()).slice(-2)}
|
||||||
/>
|
/>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
<ListItem>
|
<ListItem>
|
||||||
<ListItemText primary={LL.ID_OF(LL.PRODUCT())} secondary={coreData.devices[deviceDialog].p} />
|
<ListItemText primary={LL.ID_OF(LL.PRODUCT())} secondary={coreData.devices[deviceDetails].p} />
|
||||||
</ListItem>
|
</ListItem>
|
||||||
<ListItem>
|
<ListItem>
|
||||||
<ListItemText primary={LL.VERSION()} secondary={coreData.devices[deviceDialog].v} />
|
<ListItemText primary={LL.VERSION()} secondary={coreData.devices[deviceDetails].v} />
|
||||||
</ListItem>
|
</ListItem>
|
||||||
</List>
|
</List>
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
<DialogActions>
|
<DialogActions>
|
||||||
<Button variant="outlined" onClick={() => setDeviceDialog(-1)} color="secondary">
|
<Button variant="outlined" onClick={() => setDeviceDetails(-1)} color="secondary">
|
||||||
{LL.CLOSE()}
|
{LL.CLOSE()}
|
||||||
</Button>
|
</Button>
|
||||||
</DialogActions>
|
</DialogActions>
|
||||||
@@ -546,7 +420,7 @@ const DashboardDevices: FC = () => {
|
|||||||
<Cell>{device.n}</Cell>
|
<Cell>{device.n}</Cell>
|
||||||
<Cell stiff>{device.e}</Cell>
|
<Cell stiff>{device.e}</Cell>
|
||||||
<Cell stiff>
|
<Cell stiff>
|
||||||
<IconButton size="small" onClick={() => setDeviceDialog(index)}>
|
<IconButton size="small" onClick={() => setDeviceDetails(index)}>
|
||||||
<InfoOutlinedIcon color="info" sx={{ fontSize: 16, verticalAlign: 'middle' }} />
|
<InfoOutlinedIcon color="info" sx={{ fontSize: 16, verticalAlign: 'middle' }} />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
</Cell>
|
</Cell>
|
||||||
@@ -559,14 +433,19 @@ const DashboardDevices: FC = () => {
|
|||||||
</IconContext.Provider>
|
</IconContext.Provider>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const deviceValueDialogClose = () => {
|
||||||
|
setDeviceValueDialogOpen(false);
|
||||||
|
};
|
||||||
|
|
||||||
const renderDeviceData = () => {
|
const renderDeviceData = () => {
|
||||||
if (!device_select.state.id || device_select.state.id === 'sensor') {
|
if (!device_select.state.id) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const sendCommand = (dv: DeviceValue) => {
|
const sendCommand = (dv: DeviceValue) => {
|
||||||
if (dv.c && me.admin && !hasMask(dv.id, DeviceEntityMask.DV_READONLY)) {
|
if (dv.c && me.admin && !hasMask(dv.id, DeviceEntityMask.DV_READONLY)) {
|
||||||
setDeviceValue(dv);
|
setSelectedDeviceValue(dv);
|
||||||
|
setDeviceValueDialogOpen(true);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -662,8 +541,17 @@ const DashboardDevices: FC = () => {
|
|||||||
<SectionContent title={LL.DEVICE_DATA()} titleGutter>
|
<SectionContent title={LL.DEVICE_DATA()} titleGutter>
|
||||||
{renderCoreData()}
|
{renderCoreData()}
|
||||||
{renderDeviceData()}
|
{renderDeviceData()}
|
||||||
{renderDeviceDialog()}
|
{renderDeviceDetails()}
|
||||||
{renderDeviceValueDialog()}
|
{console.log('redndering device data')}
|
||||||
|
|
||||||
|
{selectedDeviceValue && (
|
||||||
|
<DashboarDevicesDialog
|
||||||
|
open={deviceValueDialogOpen}
|
||||||
|
onClose={deviceValueDialogClose}
|
||||||
|
onSave={deviceValueDialogSave}
|
||||||
|
selectedItem={selectedDeviceValue}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
<ButtonRow>
|
<ButtonRow>
|
||||||
<Button startIcon={<RefreshIcon />} variant="outlined" color="secondary" onClick={refreshData}>
|
<Button startIcon={<RefreshIcon />} variant="outlined" color="secondary" onClick={refreshData}>
|
||||||
|
|||||||
123
interface/src/project/DashboardDevicesDialog.tsx
Normal file
123
interface/src/project/DashboardDevicesDialog.tsx
Normal file
@@ -0,0 +1,123 @@
|
|||||||
|
import CancelIcon from '@mui/icons-material/Cancel';
|
||||||
|
import WarningIcon from '@mui/icons-material/Warning';
|
||||||
|
|
||||||
|
import {
|
||||||
|
Button,
|
||||||
|
Dialog,
|
||||||
|
DialogTitle,
|
||||||
|
DialogContent,
|
||||||
|
DialogActions,
|
||||||
|
InputAdornment,
|
||||||
|
MenuItem,
|
||||||
|
TextField,
|
||||||
|
FormHelperText,
|
||||||
|
Grid
|
||||||
|
} from '@mui/material';
|
||||||
|
import { useState, useEffect } from 'react';
|
||||||
|
|
||||||
|
import { DeviceValueUOM, DeviceValueUOM_s } from './types';
|
||||||
|
import type { DeviceValue } from './types';
|
||||||
|
|
||||||
|
import { useI18nContext } from 'i18n/i18n-react';
|
||||||
|
import { updateValue } from 'utils';
|
||||||
|
|
||||||
|
type DashboardDevicesDialogProps = {
|
||||||
|
open: boolean;
|
||||||
|
onClose: () => void;
|
||||||
|
onSave: (as: DeviceValue) => void;
|
||||||
|
selectedItem: DeviceValue;
|
||||||
|
};
|
||||||
|
|
||||||
|
const DashboarDevicesDialog = ({ open, onClose, onSave, selectedItem }: DashboardDevicesDialogProps) => {
|
||||||
|
const { LL } = useI18nContext();
|
||||||
|
const [editItem, setEditItem] = useState<DeviceValue>(selectedItem);
|
||||||
|
const updateFormValue = updateValue(setEditItem);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (open) {
|
||||||
|
setEditItem(selectedItem);
|
||||||
|
}
|
||||||
|
}, [open, selectedItem]);
|
||||||
|
|
||||||
|
const close = () => {
|
||||||
|
onClose();
|
||||||
|
};
|
||||||
|
|
||||||
|
const save = () => {
|
||||||
|
onSave(editItem);
|
||||||
|
};
|
||||||
|
|
||||||
|
const isCmdOnly = (dv: DeviceValue) => dv.v === '' && dv.c;
|
||||||
|
|
||||||
|
const setUom = (uom: number) => {
|
||||||
|
switch (uom) {
|
||||||
|
case DeviceValueUOM.HOURS:
|
||||||
|
return LL.HOURS();
|
||||||
|
case DeviceValueUOM.MINUTES:
|
||||||
|
return LL.MINUTES();
|
||||||
|
case DeviceValueUOM.SECONDS:
|
||||||
|
return LL.SECONDS();
|
||||||
|
default:
|
||||||
|
return DeviceValueUOM_s[uom];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Dialog open={open} onClose={close}>
|
||||||
|
<DialogTitle>
|
||||||
|
<DialogTitle>{isCmdOnly(editItem) ? LL.RUN_COMMAND() : LL.CHANGE_VALUE()}</DialogTitle>
|
||||||
|
</DialogTitle>
|
||||||
|
<DialogContent dividers>
|
||||||
|
<Grid container spacing={1}>
|
||||||
|
<Grid item>
|
||||||
|
{editItem.l && (
|
||||||
|
<TextField
|
||||||
|
name="v"
|
||||||
|
label={editItem.id.slice(2)}
|
||||||
|
value={editItem.v}
|
||||||
|
autoFocus
|
||||||
|
sx={{ width: '30ch' }}
|
||||||
|
select
|
||||||
|
onChange={updateFormValue}
|
||||||
|
>
|
||||||
|
{editItem.l.map((val) => (
|
||||||
|
<MenuItem value={val} key={val}>
|
||||||
|
{val}
|
||||||
|
</MenuItem>
|
||||||
|
))}
|
||||||
|
</TextField>
|
||||||
|
)}
|
||||||
|
{!editItem.l && (
|
||||||
|
<TextField
|
||||||
|
name="v"
|
||||||
|
label={editItem.id.slice(2)}
|
||||||
|
value={typeof editItem.v === 'number' ? Math.round(editItem.v * 10) / 10 : editItem.v}
|
||||||
|
autoFocus
|
||||||
|
multiline={editItem.u ? false : true}
|
||||||
|
sx={{ width: '30ch' }}
|
||||||
|
type={editItem.u ? 'number' : 'text'}
|
||||||
|
onChange={updateFormValue}
|
||||||
|
inputProps={editItem.u ? { min: editItem.m, max: editItem.x, step: editItem.s } : {}}
|
||||||
|
InputProps={{
|
||||||
|
startAdornment: <InputAdornment position="start">{setUom(editItem.u)}</InputAdornment>
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</Grid>
|
||||||
|
{editItem.h && <FormHelperText>{editItem.h}</FormHelperText>}
|
||||||
|
</Grid>
|
||||||
|
</DialogContent>
|
||||||
|
|
||||||
|
<DialogActions>
|
||||||
|
<Button startIcon={<CancelIcon />} variant="outlined" onClick={close} color="secondary">
|
||||||
|
{LL.CANCEL()}
|
||||||
|
</Button>
|
||||||
|
<Button startIcon={<WarningIcon color="warning" />} variant="contained" onClick={save} color="info">
|
||||||
|
{LL.UPDATE()}
|
||||||
|
</Button>
|
||||||
|
</DialogActions>
|
||||||
|
</Dialog>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default DashboarDevicesDialog;
|
||||||
@@ -69,7 +69,7 @@ const DashboardSensorsTemperatureDialog = ({
|
|||||||
return (
|
return (
|
||||||
<Dialog open={open} onClose={close}>
|
<Dialog open={open} onClose={close}>
|
||||||
<DialogTitle>
|
<DialogTitle>
|
||||||
{LL.EDIT()} {LL.TEMP_SENSOR()}
|
{LL.EDIT()} {LL.TEMP_SENSOR()}
|
||||||
</DialogTitle>
|
</DialogTitle>
|
||||||
<DialogContent dividers>
|
<DialogContent dividers>
|
||||||
<Box color="warning.main" p={0} pl={0} pr={0} mt={0} mb={2}>
|
<Box color="warning.main" p={0} pl={0} pr={0} mt={0} mb={2}>
|
||||||
|
|||||||
@@ -67,13 +67,11 @@ const SettingsCustomizationDialog = ({ open, onClose, onSave, selectedItem }: Se
|
|||||||
<DialogTitle>{LL.EDIT() + ' ' + LL.ENTITY()}</DialogTitle>
|
<DialogTitle>{LL.EDIT() + ' ' + LL.ENTITY()}</DialogTitle>
|
||||||
<DialogContent dividers>
|
<DialogContent dividers>
|
||||||
<Box color="warning.main">
|
<Box color="warning.main">
|
||||||
<Typography variant="body2">
|
<Typography variant="body2">{editItem.id}</Typography>
|
||||||
{LL.ENTITY()}: {editItem.id}
|
|
||||||
</Typography>
|
|
||||||
</Box>
|
</Box>
|
||||||
<Box color="warning.main" mt={1} mb={2}>
|
<Box color="warning.main" mt={1} mb={2}>
|
||||||
<Typography variant="body2">
|
<Typography variant="body2">
|
||||||
{LL.DEFAULT(1) + ' ' + LL.NAME(1)}: {editItem.n}
|
{LL.DEFAULT(1) + ' ' + LL.ENTITY_NAME()}: {editItem.n}
|
||||||
</Typography>
|
</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
<Box mb={3}>
|
<Box mb={3}>
|
||||||
|
|||||||
@@ -131,7 +131,7 @@ const SettingsSchedulerDialog = ({
|
|||||||
return (
|
return (
|
||||||
<Dialog open={open} onClose={close}>
|
<Dialog open={open} onClose={close}>
|
||||||
<DialogTitle>
|
<DialogTitle>
|
||||||
{creating ? LL.ADD(1) + ' ' + LL.NEW(1) : LL.EDIT()} {LL.ENTITY()}
|
{creating ? LL.ADD(1) + ' ' + LL.NEW(1) : LL.EDIT()} {LL.SCHEDULE(0)}
|
||||||
</DialogTitle>
|
</DialogTitle>
|
||||||
<DialogContent dividers>
|
<DialogContent dividers>
|
||||||
<Box display="flex" flexWrap="wrap" mb={1}>
|
<Box display="flex" flexWrap="wrap" mb={1}>
|
||||||
@@ -215,7 +215,7 @@ const SettingsSchedulerDialog = ({
|
|||||||
/>
|
/>
|
||||||
<TextField
|
<TextField
|
||||||
name="value"
|
name="value"
|
||||||
label={LL.VALUE(0)}
|
label={LL.VALUE(1)}
|
||||||
multiline
|
multiline
|
||||||
margin="normal"
|
margin="normal"
|
||||||
fullWidth
|
fullWidth
|
||||||
|
|||||||
Reference in New Issue
Block a user