mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2025-12-08 00:39:50 +03:00
introduce system status in WebUI for easier monitoring of tasks
This commit is contained in:
@@ -38,7 +38,7 @@ import {
|
||||
import { useTheme } from '@table-library/react-table-library/theme';
|
||||
import { dialogStyle } from 'CustomTheme';
|
||||
import { useRequest } from 'alova/client';
|
||||
import RestartMonitor from 'app/status/RestartMonitor';
|
||||
import SystemMonitor from 'app/status/SystemMonitor';
|
||||
import {
|
||||
BlockNavigation,
|
||||
ButtonRow,
|
||||
@@ -737,7 +737,7 @@ const Customizations = () => {
|
||||
return (
|
||||
<SectionContent>
|
||||
{blocker ? <BlockNavigation blocker={blocker} /> : null}
|
||||
{restarting ? <RestartMonitor /> : renderContent()}
|
||||
{restarting ? <SystemMonitor /> : renderContent()}
|
||||
{selectedDeviceEntity && (
|
||||
<SettingsCustomizationsDialog
|
||||
open={dialogOpen}
|
||||
|
||||
@@ -19,7 +19,7 @@ import {
|
||||
import { readSystemStatus } from 'api/system';
|
||||
|
||||
import { useRequest } from 'alova/client';
|
||||
import RestartMonitor from 'app/status/RestartMonitor';
|
||||
import SystemMonitor from 'app/status/SystemMonitor';
|
||||
import type { ValidateFieldsError } from 'async-validator';
|
||||
import {
|
||||
BlockFormControlLabel,
|
||||
@@ -859,7 +859,7 @@ const ApplicationSettings = () => {
|
||||
return (
|
||||
<SectionContent>
|
||||
{blocker ? <BlockNavigation blocker={blocker} /> : null}
|
||||
{restarting ? <RestartMonitor /> : content()}
|
||||
{restarting ? <SystemMonitor /> : content()}
|
||||
</SectionContent>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -9,7 +9,7 @@ import { API, callAction } from 'api/app';
|
||||
|
||||
import { useRequest } from 'alova/client';
|
||||
import type { APIcall } from 'app/main/types';
|
||||
import RestartMonitor from 'app/status/RestartMonitor';
|
||||
import SystemMonitor from 'app/status/SystemMonitor';
|
||||
import {
|
||||
FormLoader,
|
||||
SectionContent,
|
||||
@@ -123,7 +123,7 @@ const DownloadUpload = () => {
|
||||
};
|
||||
|
||||
return (
|
||||
<SectionContent>{restarting ? <RestartMonitor /> : content()}</SectionContent>
|
||||
<SectionContent>{restarting ? <SystemMonitor /> : content()}</SectionContent>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -151,7 +151,7 @@ const Settings = () => {
|
||||
bgcolor="#5d89f7"
|
||||
label={LL.DOWNLOAD_UPLOAD()}
|
||||
text={LL.DOWNLOAD_UPLOAD_1()}
|
||||
to="upload"
|
||||
to="downloadUpload"
|
||||
/>
|
||||
</List>
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ import { getDevVersion, getStableVersion } from 'api/system';
|
||||
|
||||
import { dialogStyle } from 'CustomTheme';
|
||||
import { useRequest } from 'alova/client';
|
||||
import RestartMonitor from 'app/status/RestartMonitor';
|
||||
import SystemMonitor from 'app/status/SystemMonitor';
|
||||
import { FormLoader, SectionContent, useLayoutTitle } from 'components';
|
||||
import { useI18nContext } from 'i18n/i18n-react';
|
||||
|
||||
@@ -224,7 +224,7 @@ const Version = () => {
|
||||
<>
|
||||
<Box p={2} border="1px solid grey" borderRadius={2}>
|
||||
<Typography mb={2} variant="h6" color="primary">
|
||||
Firmware Version
|
||||
Firmware {LL.VERSION()}
|
||||
</Typography>
|
||||
|
||||
<Grid
|
||||
@@ -360,7 +360,7 @@ const Version = () => {
|
||||
};
|
||||
|
||||
return (
|
||||
<SectionContent>{restarting ? <RestartMonitor /> : content()}</SectionContent>
|
||||
<SectionContent>{restarting ? <SystemMonitor /> : content()}</SectionContent>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ import { updateValueDirty, useRest } from 'utils';
|
||||
import { validate } from 'validators';
|
||||
import { createNetworkSettingsValidator } from 'validators/network';
|
||||
|
||||
import RestartMonitor from '../../status/RestartMonitor';
|
||||
import SystemMonitor from '../../status/SystemMonitor';
|
||||
import { WiFiConnectionContext } from './WiFiConnectionContext';
|
||||
import { isNetworkOpen, networkSecurityMode } from './WiFiNetworkSelector';
|
||||
|
||||
@@ -400,7 +400,7 @@ const NetworkSettings = () => {
|
||||
return (
|
||||
<SectionContent>
|
||||
{blocker ? <BlockNavigation blocker={blocker} /> : null}
|
||||
{restarting ? <RestartMonitor /> : content()}
|
||||
{restarting ? <SystemMonitor /> : content()}
|
||||
</SectionContent>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,85 +0,0 @@
|
||||
import { useState } from 'react';
|
||||
|
||||
import {
|
||||
Box,
|
||||
CircularProgress,
|
||||
Dialog,
|
||||
DialogContent,
|
||||
Typography
|
||||
} from '@mui/material';
|
||||
|
||||
import { readSystemStatus } from 'api/system';
|
||||
|
||||
import { dialogStyle } from 'CustomTheme';
|
||||
import { useRequest } from 'alova/client';
|
||||
import MessageBox from 'components/MessageBox';
|
||||
import { useI18nContext } from 'i18n/i18n-react';
|
||||
import { useInterval } from 'utils';
|
||||
|
||||
const RestartMonitor = () => {
|
||||
const [errorMessage, setErrorMessage] = useState<string>();
|
||||
|
||||
const { LL } = useI18nContext();
|
||||
|
||||
let count = 0;
|
||||
|
||||
const { data, send } = useRequest(readSystemStatus, {
|
||||
force: true,
|
||||
initialData: { status: 'Getting ready...' },
|
||||
async middleware(_, next) {
|
||||
if (count++ >= 1) {
|
||||
// skip first request (1 second) to allow AsyncWS to send its response
|
||||
await next();
|
||||
}
|
||||
}
|
||||
})
|
||||
.onSuccess((event) => {
|
||||
if (event.data.status === 'ready' || event.data.status === undefined) {
|
||||
document.location.href = '/';
|
||||
}
|
||||
})
|
||||
.onError((error) => {
|
||||
setErrorMessage(error.message);
|
||||
});
|
||||
|
||||
useInterval(() => {
|
||||
void send();
|
||||
}, 1000); // check every second
|
||||
|
||||
return (
|
||||
<Dialog fullWidth={true} sx={dialogStyle} open={true}>
|
||||
<DialogContent dividers>
|
||||
<Box m={0} py={0} display="flex" alignItems="center" flexDirection="column">
|
||||
<Typography
|
||||
color="secondary"
|
||||
variant="h6"
|
||||
fontWeight={400}
|
||||
textAlign="center"
|
||||
>
|
||||
{data?.status === 'uploading'
|
||||
? LL.WAIT_FIRMWARE()
|
||||
: data?.status === 'restarting'
|
||||
? LL.APPLICATION_RESTARTING()
|
||||
: data?.status === 'ready'
|
||||
? LL.RESTARTING_PRE()
|
||||
: LL.RESTARTING_POST()}
|
||||
…
|
||||
</Typography>
|
||||
<Typography mt={2} variant="h6" fontWeight={400} textAlign="center">
|
||||
{LL.PLEASE_WAIT()}
|
||||
</Typography>
|
||||
|
||||
{errorMessage ? (
|
||||
<MessageBox my={2} level="error" message={errorMessage} />
|
||||
) : (
|
||||
<Box py={2}>
|
||||
<CircularProgress size={32} />
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
);
|
||||
};
|
||||
|
||||
export default RestartMonitor;
|
||||
@@ -40,7 +40,7 @@ import { NTPSyncStatus, NetworkConnectionStatus } from 'types';
|
||||
import { useInterval } from 'utils';
|
||||
import { formatDateTime } from 'utils/time';
|
||||
|
||||
import RestartMonitor from './RestartMonitor';
|
||||
import SystemMonitor from './SystemMonitor';
|
||||
|
||||
const SystemStatus = () => {
|
||||
const { LL } = useI18nContext();
|
||||
@@ -349,7 +349,7 @@ const SystemStatus = () => {
|
||||
};
|
||||
|
||||
return (
|
||||
<SectionContent>{restarting ? <RestartMonitor /> : content()}</SectionContent>
|
||||
<SectionContent>{restarting ? <SystemMonitor /> : content()}</SectionContent>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
122
interface/src/app/status/SystemMonitor.tsx
Normal file
122
interface/src/app/status/SystemMonitor.tsx
Normal file
@@ -0,0 +1,122 @@
|
||||
import { useState } from 'react';
|
||||
|
||||
import CancelIcon from '@mui/icons-material/Cancel';
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
CircularProgress,
|
||||
Dialog,
|
||||
DialogContent,
|
||||
Typography
|
||||
} from '@mui/material';
|
||||
|
||||
import { callAction } from 'api/app';
|
||||
import { readSystemStatus } from 'api/system';
|
||||
|
||||
import { dialogStyle } from 'CustomTheme';
|
||||
import { useRequest } from 'alova/client';
|
||||
import MessageBox from 'components/MessageBox';
|
||||
import { useI18nContext } from 'i18n/i18n-react';
|
||||
import { SystemStatusCodes } from 'types';
|
||||
import { useInterval } from 'utils';
|
||||
|
||||
const SystemMonitor = () => {
|
||||
const [errorMessage, setErrorMessage] = useState<string>();
|
||||
|
||||
const { LL } = useI18nContext();
|
||||
|
||||
let count = 0;
|
||||
|
||||
const { send: setSystemStatus } = useRequest(
|
||||
(status: string) => callAction({ action: 'systemStatus', param: status }),
|
||||
{
|
||||
immediate: false
|
||||
}
|
||||
);
|
||||
|
||||
const { data, send } = useRequest(readSystemStatus, {
|
||||
force: true,
|
||||
async middleware(_, next) {
|
||||
if (count++ >= 1) {
|
||||
// skip first request (1 second) to allow AsyncWS to send its response
|
||||
await next();
|
||||
}
|
||||
}
|
||||
})
|
||||
.onSuccess((event) => {
|
||||
if (
|
||||
event.data.status === SystemStatusCodes.SYSTEM_STATUS_NORMAL ||
|
||||
event.data.status === undefined
|
||||
) {
|
||||
document.location.href = '/';
|
||||
} else if (
|
||||
event.data.status === SystemStatusCodes.SYSTEM_STATUS_ERROR_UPLOAD
|
||||
) {
|
||||
setErrorMessage('Please check system logs for possible causes');
|
||||
}
|
||||
})
|
||||
.onError((error) => {
|
||||
setErrorMessage(error.message);
|
||||
});
|
||||
|
||||
useInterval(() => {
|
||||
void send();
|
||||
}, 1000); // check every second
|
||||
|
||||
const onCancel = () => {
|
||||
setErrorMessage(undefined);
|
||||
setSystemStatus(SystemStatusCodes.SYSTEM_STATUS_NORMAL as unknown as string);
|
||||
document.location.href = '/';
|
||||
};
|
||||
|
||||
return (
|
||||
<Dialog fullWidth={true} sx={dialogStyle} open={true}>
|
||||
<DialogContent dividers>
|
||||
<Box m={0} py={0} display="flex" alignItems="center" flexDirection="column">
|
||||
<Typography
|
||||
color="secondary"
|
||||
variant="h6"
|
||||
fontWeight={400}
|
||||
textAlign="center"
|
||||
>
|
||||
{data?.status === SystemStatusCodes.SYSTEM_STATUS_UPLOADING
|
||||
? LL.WAIT_FIRMWARE()
|
||||
: data?.status === SystemStatusCodes.SYSTEM_STATUS_RESTARTING
|
||||
? LL.APPLICATION_RESTARTING()
|
||||
: data?.status === SystemStatusCodes.SYSTEM_STATUS_NORMAL
|
||||
? LL.RESTARTING_PRE()
|
||||
: data?.status === SystemStatusCodes.SYSTEM_STATUS_ERROR_UPLOAD
|
||||
? 'Upload Failed'
|
||||
: LL.RESTARTING_POST()}
|
||||
</Typography>
|
||||
|
||||
{errorMessage ? (
|
||||
<MessageBox my={2} level="error" message={errorMessage}>
|
||||
<Button
|
||||
size="small"
|
||||
sx={{ ml: 2 }}
|
||||
startIcon={<CancelIcon />}
|
||||
variant="contained"
|
||||
color="error"
|
||||
onClick={onCancel}
|
||||
>
|
||||
{LL.RESET(0)}
|
||||
</Button>
|
||||
</MessageBox>
|
||||
) : (
|
||||
<>
|
||||
<Typography mt={2} variant="h6" fontWeight={400} textAlign="center">
|
||||
{LL.PLEASE_WAIT()}…
|
||||
</Typography>
|
||||
<Box py={2}>
|
||||
<CircularProgress size={32} />
|
||||
</Box>
|
||||
</>
|
||||
)}
|
||||
</Box>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
);
|
||||
};
|
||||
|
||||
export default SystemMonitor;
|
||||
Reference in New Issue
Block a user