mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2025-12-06 07:49:52 +03:00
improvements to #1169
This commit is contained in:
@@ -30,7 +30,7 @@ import { useRowSelect } from '@table-library/react-table-library/select';
|
|||||||
import { useSort, SortToggleType } from '@table-library/react-table-library/sort';
|
import { useSort, SortToggleType } from '@table-library/react-table-library/sort';
|
||||||
import { Table, Header, HeaderRow, HeaderCell, Body, Row, Cell } from '@table-library/react-table-library/table';
|
import { Table, Header, HeaderRow, HeaderCell, Body, Row, Cell } from '@table-library/react-table-library/table';
|
||||||
import { useTheme } from '@table-library/react-table-library/theme';
|
import { useTheme } from '@table-library/react-table-library/theme';
|
||||||
import { useState, useContext, useEffect, useCallback } from 'react';
|
import { useState, useContext, useEffect, useCallback, useLayoutEffect } from 'react';
|
||||||
|
|
||||||
import { IconContext } from 'react-icons';
|
import { IconContext } from 'react-icons';
|
||||||
import { toast } from 'react-toastify';
|
import { toast } from 'react-toastify';
|
||||||
@@ -50,24 +50,46 @@ import { AuthenticatedContext } from 'contexts/authentication';
|
|||||||
import { useI18nContext } from 'i18n/i18n-react';
|
import { useI18nContext } from 'i18n/i18n-react';
|
||||||
import { extractErrorMessage } from 'utils';
|
import { extractErrorMessage } from 'utils';
|
||||||
|
|
||||||
|
const useWindowSize = () => {
|
||||||
|
const [size, setSize] = useState([0, 0]);
|
||||||
|
useLayoutEffect(() => {
|
||||||
|
function updateSize() {
|
||||||
|
setSize([window.innerWidth, window.innerHeight]);
|
||||||
|
}
|
||||||
|
window.addEventListener('resize', updateSize);
|
||||||
|
updateSize();
|
||||||
|
return () => window.removeEventListener('resize', updateSize);
|
||||||
|
}, []);
|
||||||
|
return size;
|
||||||
|
};
|
||||||
|
|
||||||
const DashboardDevices: FC = () => {
|
const DashboardDevices: FC = () => {
|
||||||
|
useWindowSize();
|
||||||
|
|
||||||
const { me } = useContext(AuthenticatedContext);
|
const { me } = useContext(AuthenticatedContext);
|
||||||
const { LL } = useI18nContext();
|
const { LL } = useI18nContext();
|
||||||
const [deviceData, setDeviceData] = useState<DeviceData>({ data: [] });
|
const [deviceData, setDeviceData] = useState<DeviceData>({ data: [] });
|
||||||
const [selectedDeviceValue, setSelectedDeviceValue] = useState<DeviceValue>();
|
const [selectedDeviceValue, setSelectedDeviceValue] = useState<DeviceValue>();
|
||||||
const [selectedDeviceValueWriteable, setSelectedDeviceValueWriteable] = useState<boolean>(false);
|
|
||||||
const [onlyFav, setOnlyFav] = useState(false);
|
const [onlyFav, setOnlyFav] = useState(false);
|
||||||
const [deviceValueDialogOpen, setDeviceValueDialogOpen] = useState(false);
|
const [deviceValueDialogOpen, setDeviceValueDialogOpen] = useState(false);
|
||||||
|
|
||||||
const [showDeviceInfo, setShowDeviceInfo] = useState<boolean>(false);
|
const [showDeviceInfo, setShowDeviceInfo] = useState<boolean>(false);
|
||||||
|
|
||||||
const [selectedDevice, setSelectedDevice] = useState<number>();
|
const [selectedDevice, setSelectedDevice] = useState<number>();
|
||||||
|
|
||||||
const [coreData, setCoreData] = useState<CoreData>({
|
const [coreData, setCoreData] = useState<CoreData>({
|
||||||
connected: true,
|
connected: true,
|
||||||
devices: []
|
devices: []
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const leftOffset = () => {
|
||||||
|
const left = document.getElementById('devices-window')?.getBoundingClientRect().left;
|
||||||
|
const right = document.getElementById('devices-window')?.getBoundingClientRect().right;
|
||||||
|
|
||||||
|
if (!left || !right) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return left + (right - left < 400 ? 0 : 200);
|
||||||
|
};
|
||||||
|
|
||||||
const common_theme = useTheme({
|
const common_theme = useTheme({
|
||||||
BaseRow: `
|
BaseRow: `
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
@@ -104,7 +126,7 @@ const DashboardDevices: FC = () => {
|
|||||||
common_theme,
|
common_theme,
|
||||||
{
|
{
|
||||||
Table: `
|
Table: `
|
||||||
--data-table-library_grid-template-columns: 40px 130px repeat(1, minmax(0, 1fr));
|
--data-table-library_grid-template-columns: 40px repeat(1, minmax(0, 1fr)) 130px;
|
||||||
`,
|
`,
|
||||||
BaseRow: `
|
BaseRow: `
|
||||||
.td {
|
.td {
|
||||||
@@ -131,7 +153,7 @@ const DashboardDevices: FC = () => {
|
|||||||
common_theme,
|
common_theme,
|
||||||
{
|
{
|
||||||
Table: `
|
Table: `
|
||||||
--data-table-library_grid-template-columns: 200px 130px 40px;
|
--data-table-library_grid-template-columns: minmax(0, 1fr) 150px 40px;
|
||||||
height: auto;
|
height: auto;
|
||||||
max-height: 93%;
|
max-height: 93%;
|
||||||
overflow-y: scroll;
|
overflow-y: scroll;
|
||||||
@@ -215,7 +237,7 @@ const DashboardDevices: FC = () => {
|
|||||||
(event: any) => {
|
(event: any) => {
|
||||||
if (event.keyCode === 27) {
|
if (event.keyCode === 27) {
|
||||||
if (device_select) {
|
if (device_select) {
|
||||||
resetDeviceSelect();
|
device_select.fns.onRemoveAll();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -298,7 +320,6 @@ const DashboardDevices: FC = () => {
|
|||||||
{ accessor: (dv: any) => DeviceValueUOM_s[dv.u], name: 'UoM' }
|
{ accessor: (dv: any) => DeviceValueUOM_s[dv.u], name: 'UoM' }
|
||||||
];
|
];
|
||||||
|
|
||||||
// TODO create filename from selected device
|
|
||||||
const deviceIndex = coreData.devices.findIndex((d) => d.id === device_select.state.id);
|
const deviceIndex = coreData.devices.findIndex((d) => d.id === device_select.state.id);
|
||||||
if (deviceIndex === -1) {
|
if (deviceIndex === -1) {
|
||||||
return;
|
return;
|
||||||
@@ -344,7 +365,6 @@ const DashboardDevices: FC = () => {
|
|||||||
|
|
||||||
const renderDeviceDetails = () => {
|
const renderDeviceDetails = () => {
|
||||||
if (showDeviceInfo) {
|
if (showDeviceInfo) {
|
||||||
// find record based on device_seelct.state.id
|
|
||||||
const deviceIndex = coreData.devices.findIndex((d) => d.id === device_select.state.id);
|
const deviceIndex = coreData.devices.findIndex((d) => d.id === device_select.state.id);
|
||||||
if (deviceIndex === -1) {
|
if (deviceIndex === -1) {
|
||||||
return;
|
return;
|
||||||
@@ -405,8 +425,8 @@ const DashboardDevices: FC = () => {
|
|||||||
<Header>
|
<Header>
|
||||||
<HeaderRow>
|
<HeaderRow>
|
||||||
<HeaderCell stiff />
|
<HeaderCell stiff />
|
||||||
<HeaderCell stiff>{LL.TYPE(0)}</HeaderCell>
|
|
||||||
<HeaderCell resize>{LL.DESCRIPTION()}</HeaderCell>
|
<HeaderCell resize>{LL.DESCRIPTION()}</HeaderCell>
|
||||||
|
<HeaderCell stiff>{LL.TYPE(0)}</HeaderCell>
|
||||||
</HeaderRow>
|
</HeaderRow>
|
||||||
</Header>
|
</Header>
|
||||||
<Body>
|
<Body>
|
||||||
@@ -415,8 +435,8 @@ const DashboardDevices: FC = () => {
|
|||||||
<Cell stiff>
|
<Cell stiff>
|
||||||
<DeviceIcon type_id={device.t} />
|
<DeviceIcon type_id={device.t} />
|
||||||
</Cell>
|
</Cell>
|
||||||
<Cell stiff>{device.tn}</Cell>
|
|
||||||
<Cell>{device.n}</Cell>
|
<Cell>{device.n}</Cell>
|
||||||
|
<Cell stiff>{device.tn}</Cell>
|
||||||
</Row>
|
</Row>
|
||||||
))}
|
))}
|
||||||
</Body>
|
</Body>
|
||||||
@@ -435,10 +455,7 @@ const DashboardDevices: FC = () => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const sendCommand = (dv: DeviceValue) => {
|
const showDeviceValue = (dv: DeviceValue) => {
|
||||||
if (dv.c !== undefined) {
|
|
||||||
setSelectedDeviceValueWriteable(me.admin && !hasMask(dv.id, DeviceEntityMask.DV_READONLY));
|
|
||||||
}
|
|
||||||
setSelectedDeviceValue(dv);
|
setSelectedDeviceValue(dv);
|
||||||
setDeviceValueDialogOpen(true);
|
setDeviceValueDialogOpen(true);
|
||||||
};
|
};
|
||||||
@@ -458,12 +475,6 @@ const DashboardDevices: FC = () => {
|
|||||||
? deviceData.data.filter((dv) => hasMask(dv.id, DeviceEntityMask.DV_FAVORITE))
|
? deviceData.data.filter((dv) => hasMask(dv.id, DeviceEntityMask.DV_FAVORITE))
|
||||||
: deviceData.data;
|
: deviceData.data;
|
||||||
|
|
||||||
function truncate(str, length) {
|
|
||||||
if (str.length > length) {
|
|
||||||
return str.slice(0, length) + '...';
|
|
||||||
} else return str;
|
|
||||||
}
|
|
||||||
|
|
||||||
const deviceIndex = coreData.devices.findIndex((d) => d.id === device_select.state.id);
|
const deviceIndex = coreData.devices.findIndex((d) => d.id === device_select.state.id);
|
||||||
if (deviceIndex === -1) {
|
if (deviceIndex === -1) {
|
||||||
return;
|
return;
|
||||||
@@ -477,18 +488,19 @@ const DashboardDevices: FC = () => {
|
|||||||
right: 16,
|
right: 16,
|
||||||
bottom: 16,
|
bottom: 16,
|
||||||
top: 128,
|
top: 128,
|
||||||
|
left: () => leftOffset(),
|
||||||
border: '1px solid #177ac9',
|
border: '1px solid #177ac9',
|
||||||
zIndex: 'modal'
|
zIndex: 'modal'
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Grid container justifyContent="space-between">
|
<Grid container justifyContent="space-between">
|
||||||
<Box color="warning.main" ml={1}>
|
<Box color="warning.main" ml={1}>
|
||||||
<Typography variant="h6">
|
<Typography noWrap variant="h6">
|
||||||
{truncate(coreData.devices[deviceIndex].n, 31)}
|
{coreData.devices[deviceIndex].n}
|
||||||
({shown_data.length})
|
({shown_data.length})
|
||||||
</Typography>
|
</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
<Grid item justifyContent="flex-end">
|
<Grid item zeroMinWidth justifyContent="flex-end">
|
||||||
<IconButton onClick={resetDeviceSelect}>
|
<IconButton onClick={resetDeviceSelect}>
|
||||||
<CancelIcon color="info" sx={{ fontSize: 18, verticalAlign: 'middle' }} />
|
<CancelIcon color="info" sx={{ fontSize: 18, verticalAlign: 'middle' }} />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
@@ -549,12 +561,12 @@ const DashboardDevices: FC = () => {
|
|||||||
</Header>
|
</Header>
|
||||||
<Body>
|
<Body>
|
||||||
{tableList.map((dv: DeviceValue) => (
|
{tableList.map((dv: DeviceValue) => (
|
||||||
<Row key={dv.id} item={dv} onClick={() => sendCommand(dv)}>
|
<Row key={dv.id} item={dv} onClick={() => showDeviceValue(dv)}>
|
||||||
<Cell>{renderNameCell(dv)}</Cell>
|
<Cell>{renderNameCell(dv)}</Cell>
|
||||||
<Cell>{formatValue(LL, dv.v, dv.u)}</Cell>
|
<Cell>{formatValue(LL, dv.v, dv.u)}</Cell>
|
||||||
<Cell stiff>
|
<Cell stiff>
|
||||||
{dv.c && me.admin && !hasMask(dv.id, DeviceEntityMask.DV_READONLY) && (
|
{dv.c && me.admin && !hasMask(dv.id, DeviceEntityMask.DV_READONLY) && (
|
||||||
<IconButton size="small" onClick={() => sendCommand(dv)}>
|
<IconButton size="small" onClick={() => showDeviceValue(dv)}>
|
||||||
{dv.v === '' && dv.c ? (
|
{dv.v === '' && dv.c ? (
|
||||||
<PlayArrowIcon color="primary" sx={{ fontSize: 16 }} />
|
<PlayArrowIcon color="primary" sx={{ fontSize: 16 }} />
|
||||||
) : (
|
) : (
|
||||||
@@ -584,7 +596,11 @@ const DashboardDevices: FC = () => {
|
|||||||
onClose={deviceValueDialogClose}
|
onClose={deviceValueDialogClose}
|
||||||
onSave={deviceValueDialogSave}
|
onSave={deviceValueDialogSave}
|
||||||
selectedItem={selectedDeviceValue}
|
selectedItem={selectedDeviceValue}
|
||||||
writeable={selectedDeviceValueWriteable}
|
writeable={
|
||||||
|
me.admin &&
|
||||||
|
selectedDeviceValue.c !== undefined &&
|
||||||
|
!hasMask(selectedDeviceValue.id, DeviceEntityMask.DV_READONLY)
|
||||||
|
}
|
||||||
validator={deviceValueItemValidation(selectedDeviceValue)}
|
validator={deviceValueItemValidation(selectedDeviceValue)}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|||||||
Reference in New Issue
Block a user