Merge pull request #1742 from proddy/dev

move restart button to System menu
This commit is contained in:
Proddy
2024-05-05 13:02:03 +02:00
committed by GitHub
5 changed files with 298 additions and 141 deletions

View File

@@ -50,10 +50,12 @@
"typescript": "^5.4.5"
},
"devDependencies": {
"@babel/core": "^7.24.5",
"@eslint/js": "^9.2.0",
"@preact/compat": "^17.1.2",
"@preact/preset-vite": "^2.8.2",
"@trivago/prettier-plugin-sort-imports": "^4.3.0",
"@types/babel__core": "^7",
"concurrently": "^8.2.2",
"eslint": "^9.2.0",
"eslint-config-prettier": "^9.1.0",

View File

@@ -15,8 +15,7 @@ export const dialogStyle = {
borderColor: '#565656',
borderStyle: 'solid',
borderWidth: '1px'
},
backdropFilter: 'blur(1px)'
}
};
const theme = responsiveFontSizes(

View File

@@ -1,5 +1,4 @@
import { type FC, useState } from 'react';
import { toast } from 'react-toastify';
import AccessTimeIcon from '@mui/icons-material/AccessTime';
import CancelIcon from '@mui/icons-material/Cancel';
@@ -7,7 +6,6 @@ import DeviceHubIcon from '@mui/icons-material/DeviceHub';
import ImportExportIcon from '@mui/icons-material/ImportExport';
import LockIcon from '@mui/icons-material/Lock';
import MemoryIcon from '@mui/icons-material/Memory';
import PowerSettingsNewIcon from '@mui/icons-material/PowerSettingsNew';
import SettingsBackupRestoreIcon from '@mui/icons-material/SettingsBackupRestore';
import SettingsEthernetIcon from '@mui/icons-material/SettingsEthernet';
import SettingsInputAntennaIcon from '@mui/icons-material/SettingsInputAntenna';
@@ -19,6 +17,7 @@ import {
DialogActions,
DialogContent,
DialogTitle,
Divider,
List
} from '@mui/material';
@@ -26,118 +25,25 @@ import * as SystemApi from 'api/system';
import { dialogStyle } from 'CustomTheme';
import { useRequest } from 'alova';
import { ButtonRow, SectionContent, useLayoutTitle } from 'components';
import { SectionContent, useLayoutTitle } from 'components';
import ListMenuItem from 'components/layout/ListMenuItem';
import { useI18nContext } from 'i18n/i18n-react';
import RestartMonitor from './system/RestartMonitor';
const Settings: FC = () => {
const { LL } = useI18nContext();
useLayoutTitle(LL.SETTINGS(0));
const [confirmRestart, setConfirmRestart] = useState<boolean>(false);
const [confirmFactoryReset, setConfirmFactoryReset] = useState<boolean>(false);
const [processing, setProcessing] = useState<boolean>(false);
const [restarting, setRestarting] = useState<boolean>();
const { send: restartCommand } = useRequest(SystemApi.restart(), {
immediate: false
});
const { send: factoryResetCommand } = useRequest(SystemApi.factoryReset(), {
immediate: false
});
const { send: partitionCommand } = useRequest(SystemApi.partition(), {
immediate: false
});
const restart = async () => {
setProcessing(true);
await restartCommand()
.then(() => {
setRestarting(true);
})
.catch((error: Error) => {
toast.error(error.message);
})
.finally(() => {
setConfirmRestart(false);
setProcessing(false);
});
};
const factoryReset = async () => {
setProcessing(true);
await factoryResetCommand()
.then(() => {
setRestarting(true);
})
.catch((error: Error) => {
toast.error(error.message);
})
.finally(() => {
setConfirmFactoryReset(false);
setProcessing(false);
});
await factoryResetCommand();
setConfirmFactoryReset(false);
};
const partition = async () => {
setProcessing(true);
await partitionCommand()
.then(() => {
setRestarting(true);
})
.catch((error: Error) => {
toast.error(error.message);
})
.finally(() => {
setConfirmRestart(false);
setProcessing(false);
});
};
const renderRestartDialog = () => (
<Dialog
sx={dialogStyle}
open={confirmRestart}
onClose={() => setConfirmRestart(false)}
>
<DialogTitle>{LL.RESTART()}</DialogTitle>
<DialogContent dividers>{LL.RESTART_CONFIRM()}</DialogContent>
<DialogActions>
<Button
startIcon={<CancelIcon />}
variant="outlined"
onClick={() => setConfirmRestart(false)}
disabled={processing}
color="secondary"
>
{LL.CANCEL()}
</Button>
<Button
startIcon={<PowerSettingsNewIcon />}
variant="outlined"
onClick={restart}
disabled={processing}
color="primary"
>
{LL.RESTART()}
</Button>
<Button
startIcon={<PowerSettingsNewIcon />}
variant="outlined"
onClick={partition}
disabled={processing}
color="primary"
>
EMS-ESP Loader
</Button>
</DialogActions>
</Dialog>
);
const renderFactoryResetDialog = () => (
<Dialog
sx={dialogStyle}
@@ -151,7 +57,6 @@ const Settings: FC = () => {
startIcon={<CancelIcon />}
variant="outlined"
onClick={() => setConfirmFactoryReset(false)}
disabled={processing}
color="secondary"
>
{LL.CANCEL()}
@@ -160,7 +65,6 @@ const Settings: FC = () => {
startIcon={<SettingsBackupRestoreIcon />}
variant="outlined"
onClick={factoryReset}
disabled={processing}
color="error"
>
{LL.FACTORY_RESET()}
@@ -219,6 +123,8 @@ const Settings: FC = () => {
to="security"
/>
<Divider />
<ListMenuItem
icon={MemoryIcon}
bgcolor="#b1395f"
@@ -236,41 +142,22 @@ const Settings: FC = () => {
/>
</List>
{renderRestartDialog()}
{renderFactoryResetDialog()}
<Box mt={1} display="flex" flexWrap="wrap">
<Box flexGrow={1} sx={{ '& button': { mt: 2 } }}>
<ButtonRow>
<Button
startIcon={<PowerSettingsNewIcon />}
variant="outlined"
color="primary"
onClick={() => setConfirmRestart(true)}
>
{LL.RESTART()}
</Button>
</ButtonRow>
</Box>
<Box flexWrap="nowrap" whiteSpace="nowrap">
<ButtonRow>
<Button
startIcon={<SettingsBackupRestoreIcon />}
variant="outlined"
onClick={() => setConfirmFactoryReset(true)}
color="error"
>
{LL.FACTORY_RESET()}
</Button>
</ButtonRow>
</Box>
<Box mt={2} display="flex" flexWrap="wrap">
<Button
startIcon={<SettingsBackupRestoreIcon />}
variant="outlined"
onClick={() => setConfirmFactoryReset(true)}
color="error"
>
{LL.FACTORY_RESET()}
</Button>
</Box>
</>
);
return (
<SectionContent>{restarting ? <RestartMonitor /> : content()}</SectionContent>
);
return <SectionContent>{content()}</SectionContent>;
};
export default Settings;

View File

@@ -8,6 +8,7 @@ import DeviceHubIcon from '@mui/icons-material/DeviceHub';
import DirectionsBusIcon from '@mui/icons-material/DirectionsBus';
import MemoryIcon from '@mui/icons-material/Memory';
import PermScanWifiIcon from '@mui/icons-material/PermScanWifi';
import PowerSettingsNewIcon from '@mui/icons-material/PowerSettingsNew';
import RefreshIcon from '@mui/icons-material/Refresh';
import SettingsInputAntennaIcon from '@mui/icons-material/SettingsInputAntenna';
import TimerIcon from '@mui/icons-material/Timer';
@@ -39,6 +40,8 @@ import { useI18nContext } from 'i18n/i18n-react';
import { busConnectionStatus } from 'project/types';
import { NTPSyncStatus } from 'types';
import RestartMonitor from './RestartMonitor';
const SystemStatus: FC = () => {
const { LL } = useI18nContext();
@@ -46,7 +49,18 @@ const SystemStatus: FC = () => {
const { me } = useContext(AuthenticatedContext);
const [confirmRestart, setConfirmRestart] = useState<boolean>(false);
const [confirmScan, setConfirmScan] = useState<boolean>(false);
const [processing, setProcessing] = useState<boolean>(false);
const [restarting, setRestarting] = useState<boolean>();
const { send: restartCommand } = useRequest(SystemApi.restart(), {
immediate: false
});
const { send: partitionCommand } = useRequest(SystemApi.partition(), {
immediate: false
});
const {
data: data,
@@ -180,6 +194,76 @@ const SystemStatus: FC = () => {
</Dialog>
);
const restart = async () => {
setProcessing(true);
await restartCommand()
.then(() => {
setRestarting(true);
})
.catch((error: Error) => {
toast.error(error.message);
})
.finally(() => {
setConfirmRestart(false);
setProcessing(false);
});
};
const partition = async () => {
setProcessing(true);
await partitionCommand()
.then(() => {
setRestarting(true);
})
.catch((error: Error) => {
toast.error(error.message);
})
.finally(() => {
setConfirmRestart(false);
setProcessing(false);
});
};
const renderRestartDialog = () => (
<Dialog
sx={dialogStyle}
open={confirmRestart}
onClose={() => setConfirmRestart(false)}
>
<DialogTitle>{LL.RESTART()}</DialogTitle>
<DialogContent dividers>{LL.RESTART_CONFIRM()}</DialogContent>
<DialogActions>
<Button
startIcon={<CancelIcon />}
variant="outlined"
onClick={() => setConfirmRestart(false)}
disabled={processing}
color="secondary"
>
{LL.CANCEL()}
</Button>
<Button
startIcon={<PowerSettingsNewIcon />}
variant="outlined"
onClick={restart}
disabled={processing}
color="primary"
>
{LL.RESTART()}
</Button>
<Button
startIcon={<PowerSettingsNewIcon />}
variant="outlined"
onClick={partition}
disabled={processing}
color="primary"
>
EMS-ESP Loader
</Button>
</DialogActions>
</Dialog>
);
const content = () => {
if (!data) {
return <FormLoader onRetry={loadData} errorMessage={error?.message} />;
@@ -198,13 +282,28 @@ const SystemStatus: FC = () => {
</ListItem>
<Divider variant="inset" component="li" />
<ListMenuItem
disabled={!me.admin}
icon={TimerIcon}
bgcolor="#c5572c"
label={LL.UPTIME()}
text={formatDurationSec(data.uptime)}
/>
<ListItem>
<ListItemAvatar>
<Avatar sx={{ bgcolor: '#c5572c', color: 'white' }}>
<TimerIcon />
</Avatar>
</ListItemAvatar>
<ListItemText
primary={LL.UPTIME()}
secondary={formatDurationSec(data.uptime)}
/>
{me.admin && (
<Button
startIcon={<PowerSettingsNewIcon />}
variant="outlined"
color="primary"
onClick={() => setConfirmRestart(true)}
>
{LL.RESTART()}
</Button>
)}
</ListItem>
<Divider variant="inset" component="li" />
<ListItem>
@@ -288,6 +387,7 @@ const SystemStatus: FC = () => {
</List>
{renderScanDialog()}
{renderRestartDialog()}
<Box mt={2} display="flex" flexWrap="wrap">
<Button
@@ -303,7 +403,9 @@ const SystemStatus: FC = () => {
);
};
return <SectionContent>{content()}</SectionContent>;
return (
<SectionContent>{restarting ? <RestartMonitor /> : content()}</SectionContent>
);
};
export default SystemStatus;

View File

@@ -69,6 +69,29 @@ __metadata:
languageName: node
linkType: hard
"@babel/core@npm:^7.24.5":
version: 7.24.5
resolution: "@babel/core@npm:7.24.5"
dependencies:
"@ampproject/remapping": "npm:^2.2.0"
"@babel/code-frame": "npm:^7.24.2"
"@babel/generator": "npm:^7.24.5"
"@babel/helper-compilation-targets": "npm:^7.23.6"
"@babel/helper-module-transforms": "npm:^7.24.5"
"@babel/helpers": "npm:^7.24.5"
"@babel/parser": "npm:^7.24.5"
"@babel/template": "npm:^7.24.0"
"@babel/traverse": "npm:^7.24.5"
"@babel/types": "npm:^7.24.5"
convert-source-map: "npm:^2.0.0"
debug: "npm:^4.1.0"
gensync: "npm:^1.0.0-beta.2"
json5: "npm:^2.2.3"
semver: "npm:^6.3.1"
checksum: 10c0/e26ba810a77bc8e21579a12fc36c79a0a60554404dc9447f2d64eb1f26d181c48d3b97d39d9f158e9911ec7162a8280acfaf2b4b210e975f0dd4bd4dbb1ee159
languageName: node
linkType: hard
"@babel/generator@npm:7.17.7":
version: 7.17.7
resolution: "@babel/generator@npm:7.17.7"
@@ -92,6 +115,18 @@ __metadata:
languageName: node
linkType: hard
"@babel/generator@npm:^7.24.5":
version: 7.24.5
resolution: "@babel/generator@npm:7.24.5"
dependencies:
"@babel/types": "npm:^7.24.5"
"@jridgewell/gen-mapping": "npm:^0.3.5"
"@jridgewell/trace-mapping": "npm:^0.3.25"
jsesc: "npm:^2.5.1"
checksum: 10c0/0d64f880150e7dfb92ceff2b4ac865f36aa1e295120920246492ffd0146562dabf79ba8699af1c8833f8a7954818d4d146b7b02f808df4d6024fb99f98b2f78d
languageName: node
linkType: hard
"@babel/helper-annotate-as-pure@npm:^7.22.5":
version: 7.22.5
resolution: "@babel/helper-annotate-as-pure@npm:7.22.5"
@@ -140,7 +175,7 @@ __metadata:
languageName: node
linkType: hard
"@babel/helper-module-imports@npm:^7.16.7, @babel/helper-module-imports@npm:^7.22.15":
"@babel/helper-module-imports@npm:^7.16.7, @babel/helper-module-imports@npm:^7.22.15, @babel/helper-module-imports@npm:^7.24.3":
version: 7.24.3
resolution: "@babel/helper-module-imports@npm:7.24.3"
dependencies:
@@ -164,6 +199,21 @@ __metadata:
languageName: node
linkType: hard
"@babel/helper-module-transforms@npm:^7.24.5":
version: 7.24.5
resolution: "@babel/helper-module-transforms@npm:7.24.5"
dependencies:
"@babel/helper-environment-visitor": "npm:^7.22.20"
"@babel/helper-module-imports": "npm:^7.24.3"
"@babel/helper-simple-access": "npm:^7.24.5"
"@babel/helper-split-export-declaration": "npm:^7.24.5"
"@babel/helper-validator-identifier": "npm:^7.24.5"
peerDependencies:
"@babel/core": ^7.0.0
checksum: 10c0/6e77d72f62b7e87abaea800ea0bccd4d54cde26485750969f5f493c032eb63251eb50c3522cace557781565d51c1d0c4bcc866407d24becfb109c18fb92c978d
languageName: node
linkType: hard
"@babel/helper-plugin-utils@npm:^7.22.5, @babel/helper-plugin-utils@npm:^7.24.0":
version: 7.24.0
resolution: "@babel/helper-plugin-utils@npm:7.24.0"
@@ -180,6 +230,15 @@ __metadata:
languageName: node
linkType: hard
"@babel/helper-simple-access@npm:^7.24.5":
version: 7.24.5
resolution: "@babel/helper-simple-access@npm:7.24.5"
dependencies:
"@babel/types": "npm:^7.24.5"
checksum: 10c0/d96a0ab790a400f6c2dcbd9457b9ca74b9ba6d0f67ff9cd5bcc73792c8fbbd0847322a0dddbd8987dd98610ee1637c680938c7d83d3ffce7d06d7519d823d996
languageName: node
linkType: hard
"@babel/helper-split-export-declaration@npm:^7.22.6":
version: 7.22.6
resolution: "@babel/helper-split-export-declaration@npm:7.22.6"
@@ -189,7 +248,16 @@ __metadata:
languageName: node
linkType: hard
"@babel/helper-string-parser@npm:^7.23.4":
"@babel/helper-split-export-declaration@npm:^7.24.5":
version: 7.24.5
resolution: "@babel/helper-split-export-declaration@npm:7.24.5"
dependencies:
"@babel/types": "npm:^7.24.5"
checksum: 10c0/d7a812d67d031a348f3fb0e6263ce2dbe6038f81536ba7fb16db385383bcd6542b71833194303bf6d3d0e4f7b6b584c9c8fae8772122e2ce68fc9bdf07f4135d
languageName: node
linkType: hard
"@babel/helper-string-parser@npm:^7.23.4, @babel/helper-string-parser@npm:^7.24.1":
version: 7.24.1
resolution: "@babel/helper-string-parser@npm:7.24.1"
checksum: 10c0/2f9bfcf8d2f9f083785df0501dbab92770111ece2f90d120352fda6dd2a7d47db11b807d111e6f32aa1ba6d763fe2dc6603d153068d672a5d0ad33ca802632b2
@@ -203,6 +271,13 @@ __metadata:
languageName: node
linkType: hard
"@babel/helper-validator-identifier@npm:^7.24.5":
version: 7.24.5
resolution: "@babel/helper-validator-identifier@npm:7.24.5"
checksum: 10c0/05f957229d89ce95a137d04e27f7d0680d84ae48b6ad830e399db0779341f7d30290f863a93351b4b3bde2166737f73a286ea42856bb07c8ddaa95600d38645c
languageName: node
linkType: hard
"@babel/helper-validator-option@npm:^7.23.5":
version: 7.23.5
resolution: "@babel/helper-validator-option@npm:7.23.5"
@@ -221,6 +296,17 @@ __metadata:
languageName: node
linkType: hard
"@babel/helpers@npm:^7.24.5":
version: 7.24.5
resolution: "@babel/helpers@npm:7.24.5"
dependencies:
"@babel/template": "npm:^7.24.0"
"@babel/traverse": "npm:^7.24.5"
"@babel/types": "npm:^7.24.5"
checksum: 10c0/0630b0223c3a9a34027ddc05b3bac54d68d5957f84e92d2d4814b00448a76e12f9188f9c85cfce2011696d82a8ffcbd8189da097c0af0181d32eb27eca34185e
languageName: node
linkType: hard
"@babel/highlight@npm:^7.24.2":
version: 7.24.2
resolution: "@babel/highlight@npm:7.24.2"
@@ -233,6 +319,15 @@ __metadata:
languageName: node
linkType: hard
"@babel/parser@npm:^7.1.0, @babel/parser@npm:^7.20.7, @babel/parser@npm:^7.24.5":
version: 7.24.5
resolution: "@babel/parser@npm:7.24.5"
bin:
parser: ./bin/babel-parser.js
checksum: 10c0/8333a6ad5328bad34fa0e12bcee147c3345ea9a438c0909e7c68c6cfbea43c464834ffd7eabd1cbc1c62df0a558e22ffade9f5b29440833ba7b33d96a71f88c0
languageName: node
linkType: hard
"@babel/parser@npm:^7.20.5, @babel/parser@npm:^7.23.0, @babel/parser@npm:^7.24.0, @babel/parser@npm:^7.24.1, @babel/parser@npm:^7.24.4":
version: 7.24.4
resolution: "@babel/parser@npm:7.24.4"
@@ -335,6 +430,24 @@ __metadata:
languageName: node
linkType: hard
"@babel/traverse@npm:^7.24.5":
version: 7.24.5
resolution: "@babel/traverse@npm:7.24.5"
dependencies:
"@babel/code-frame": "npm:^7.24.2"
"@babel/generator": "npm:^7.24.5"
"@babel/helper-environment-visitor": "npm:^7.22.20"
"@babel/helper-function-name": "npm:^7.23.0"
"@babel/helper-hoist-variables": "npm:^7.22.5"
"@babel/helper-split-export-declaration": "npm:^7.24.5"
"@babel/parser": "npm:^7.24.5"
"@babel/types": "npm:^7.24.5"
debug: "npm:^4.3.1"
globals: "npm:^11.1.0"
checksum: 10c0/3f22534bc2b2ed9208e55ef48af3b32939032b23cb9dc4037447cb108640df70bbb0b9fea86e9c58648949fdc2cb14e89aa79ffa3c62a5dd43459a52fe8c01d1
languageName: node
linkType: hard
"@babel/types@npm:7.17.0":
version: 7.17.0
resolution: "@babel/types@npm:7.17.0"
@@ -345,6 +458,17 @@ __metadata:
languageName: node
linkType: hard
"@babel/types@npm:^7.0.0, @babel/types@npm:^7.20.7, @babel/types@npm:^7.24.5":
version: 7.24.5
resolution: "@babel/types@npm:7.24.5"
dependencies:
"@babel/helper-string-parser": "npm:^7.24.1"
"@babel/helper-validator-identifier": "npm:^7.24.5"
to-fast-properties: "npm:^2.0.0"
checksum: 10c0/e1284eb046c5e0451b80220d1200e2327e0a8544a2fe45bb62c952e5fdef7099c603d2336b17b6eac3cc046b7a69bfbce67fe56e1c0ea48cd37c65cb88638f2a
languageName: node
linkType: hard
"@babel/types@npm:^7.17.0, @babel/types@npm:^7.22.5, @babel/types@npm:^7.23.0, @babel/types@npm:^7.23.4, @babel/types@npm:^7.24.0, @babel/types@npm:^7.8.3":
version: 7.24.0
resolution: "@babel/types@npm:7.24.0"
@@ -1334,6 +1458,47 @@ __metadata:
languageName: node
linkType: hard
"@types/babel__core@npm:^7":
version: 7.20.5
resolution: "@types/babel__core@npm:7.20.5"
dependencies:
"@babel/parser": "npm:^7.20.7"
"@babel/types": "npm:^7.20.7"
"@types/babel__generator": "npm:*"
"@types/babel__template": "npm:*"
"@types/babel__traverse": "npm:*"
checksum: 10c0/bdee3bb69951e833a4b811b8ee9356b69a61ed5b7a23e1a081ec9249769117fa83aaaf023bb06562a038eb5845155ff663e2d5c75dd95c1d5ccc91db012868ff
languageName: node
linkType: hard
"@types/babel__generator@npm:*":
version: 7.6.8
resolution: "@types/babel__generator@npm:7.6.8"
dependencies:
"@babel/types": "npm:^7.0.0"
checksum: 10c0/f0ba105e7d2296bf367d6e055bb22996886c114261e2cb70bf9359556d0076c7a57239d019dee42bb063f565bade5ccb46009bce2044b2952d964bf9a454d6d2
languageName: node
linkType: hard
"@types/babel__template@npm:*":
version: 7.4.4
resolution: "@types/babel__template@npm:7.4.4"
dependencies:
"@babel/parser": "npm:^7.1.0"
"@babel/types": "npm:^7.0.0"
checksum: 10c0/cc84f6c6ab1eab1427e90dd2b76ccee65ce940b778a9a67be2c8c39e1994e6f5bbc8efa309f6cea8dc6754994524cd4d2896558df76d92e7a1f46ecffee7112b
languageName: node
linkType: hard
"@types/babel__traverse@npm:*":
version: 7.20.5
resolution: "@types/babel__traverse@npm:7.20.5"
dependencies:
"@babel/types": "npm:^7.20.7"
checksum: 10c0/033abcb2f4c084ad33e30c3efaad82161240f351e3c71b6154ed289946b33b363696c0fbd42502b68e4582a87413c418321f40eb1ea863e34fe525641345e05b
languageName: node
linkType: hard
"@types/estree@npm:1.0.5":
version: 1.0.5
resolution: "@types/estree@npm:1.0.5"
@@ -1705,6 +1870,7 @@ __metadata:
dependencies:
"@alova/adapter-xhr": "npm:^1.0.6"
"@alova/scene-react": "npm:^1.5.0"
"@babel/core": "npm:^7.24.5"
"@emotion/react": "npm:^11.11.4"
"@emotion/styled": "npm:^11.11.5"
"@eslint/js": "npm:^9.2.0"
@@ -1714,6 +1880,7 @@ __metadata:
"@preact/preset-vite": "npm:^2.8.2"
"@table-library/react-table-library": "npm:4.1.7"
"@trivago/prettier-plugin-sort-imports": "npm:^4.3.0"
"@types/babel__core": "npm:^7"
"@types/lodash-es": "npm:^4.17.12"
"@types/node": "npm:^20.12.8"
"@types/react": "npm:^18.3.1"