mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2025-12-07 08:19:52 +03:00
translate system menu
This commit is contained in:
@@ -31,6 +31,8 @@ import { ButtonRow, FormLoader, SectionContent } from '../../components';
|
||||
import { extractErrorMessage, formatDateTime, formatLocalDateTime, useRest } from '../../utils';
|
||||
import { AuthenticatedContext } from '../../contexts/authentication';
|
||||
|
||||
import { useI18nContext } from '../../i18n/i18n-react';
|
||||
|
||||
export const isNtpActive = ({ status }: NTPStatus) => status === NTPSyncStatus.NTP_ACTIVE;
|
||||
export const isNtpEnabled = ({ status }: NTPStatus) => status !== NTPSyncStatus.NTP_DISABLED;
|
||||
|
||||
@@ -68,6 +70,8 @@ const NTPStatusForm: FC = () => {
|
||||
const { enqueueSnackbar } = useSnackbar();
|
||||
const { me } = useContext(AuthenticatedContext);
|
||||
|
||||
const { LL } = useI18nContext();
|
||||
|
||||
const updateLocalTime = (event: React.ChangeEvent<HTMLInputElement>) => setLocalTime(event.target.value);
|
||||
|
||||
const openSetTime = () => {
|
||||
@@ -83,11 +87,11 @@ const NTPStatusForm: FC = () => {
|
||||
await NTPApi.updateTime({
|
||||
local_time: formatLocalDateTime(new Date(localTime))
|
||||
});
|
||||
enqueueSnackbar('Time set', { variant: 'success' });
|
||||
enqueueSnackbar(LL.TIME_SET(), { variant: 'success' });
|
||||
setSettingTime(false);
|
||||
loadData();
|
||||
} catch (error: unknown) {
|
||||
enqueueSnackbar(extractErrorMessage(error, 'Problem updating time'), { variant: 'error' });
|
||||
enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_UPDATING()), { variant: 'error' });
|
||||
} finally {
|
||||
setProcessing(false);
|
||||
}
|
||||
|
||||
@@ -14,6 +14,8 @@ import { extractErrorMessage } from '../../utils';
|
||||
|
||||
import * as EMSESP from '../../project/api';
|
||||
|
||||
import { useI18nContext } from '../../i18n/i18n-react';
|
||||
|
||||
interface UploadFileProps {
|
||||
uploadGeneralFile: (file: File, config?: FileUploadConfig) => AxiosPromise<void>;
|
||||
}
|
||||
@@ -23,6 +25,8 @@ const GeneralFileUpload: FC<UploadFileProps> = ({ uploadGeneralFile }) => {
|
||||
|
||||
const { enqueueSnackbar } = useSnackbar();
|
||||
|
||||
const { LL } = useI18nContext();
|
||||
|
||||
const saveFile = (json: any, endpoint: string) => {
|
||||
const a = document.createElement('a');
|
||||
const filename = 'emsesp_' + endpoint + '.json';
|
||||
@@ -35,19 +39,19 @@ const GeneralFileUpload: FC<UploadFileProps> = ({ uploadGeneralFile }) => {
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
document.body.removeChild(a);
|
||||
enqueueSnackbar('File downloaded', { variant: 'info' });
|
||||
enqueueSnackbar(LL.DOWNLOAD_SUCCESSFUL(), { variant: 'info' });
|
||||
};
|
||||
|
||||
const downloadSettings = async () => {
|
||||
try {
|
||||
const response = await EMSESP.getSettings();
|
||||
if (response.status !== 200) {
|
||||
enqueueSnackbar('Unable to get settings', { variant: 'error' });
|
||||
enqueueSnackbar(LL.PROBLEM_LOADING(), { variant: 'error' });
|
||||
} else {
|
||||
saveFile(response.data, 'settings');
|
||||
}
|
||||
} catch (error: unknown) {
|
||||
enqueueSnackbar(extractErrorMessage(error, 'Problem with downloading'), { variant: 'error' });
|
||||
enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_LOADING()), { variant: 'error' });
|
||||
}
|
||||
};
|
||||
|
||||
@@ -55,47 +59,43 @@ const GeneralFileUpload: FC<UploadFileProps> = ({ uploadGeneralFile }) => {
|
||||
try {
|
||||
const response = await EMSESP.getCustomizations();
|
||||
if (response.status !== 200) {
|
||||
enqueueSnackbar('Unable to get customizations', { variant: 'error' });
|
||||
enqueueSnackbar(LL.PROBLEM_LOADING(), { variant: 'error' });
|
||||
} else {
|
||||
saveFile(response.data, 'customizations');
|
||||
}
|
||||
} catch (error: unknown) {
|
||||
enqueueSnackbar(extractErrorMessage(error, 'Problem with downloading'), { variant: 'error' });
|
||||
enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_LOADING()), { variant: 'error' });
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Typography sx={{ pt: 2, pb: 2 }} variant="h6" color="primary">
|
||||
Upload
|
||||
{LL.UPLOAD()}
|
||||
</Typography>
|
||||
{!uploading && (
|
||||
<Box mb={2} color="warning.main">
|
||||
<Typography variant="body2">
|
||||
Upload a new firmware (.bin) file, settings or customizations (.json) file below
|
||||
</Typography>
|
||||
<Typography variant="body2">{LL.UPLOAD_TEXT()} </Typography>
|
||||
</Box>
|
||||
)}
|
||||
<SingleUpload onDrop={uploadFile} onCancel={cancelUpload} uploading={uploading} progress={uploadProgress} />
|
||||
|
||||
<Typography sx={{ pt: 2, pb: 2 }} variant="h6" color="primary">
|
||||
Download
|
||||
{LL.DOWNLOAD()}
|
||||
</Typography>
|
||||
{!uploading && (
|
||||
<>
|
||||
<Box color="warning.main">
|
||||
<Typography mb={1} variant="body2">
|
||||
Download the application settings. Be careful when sharing your settings as this file contains passwords
|
||||
and other sensitive system information
|
||||
{LL.DOWNLOAD_SETTINGS_TEXT()}
|
||||
</Typography>
|
||||
</Box>
|
||||
<Button startIcon={<DownloadIcon />} variant="outlined" color="primary" onClick={() => downloadSettings()}>
|
||||
settings
|
||||
{LL.SETTINGS()}
|
||||
</Button>
|
||||
|
||||
<Box color="warning.main">
|
||||
<Typography mt={2} mb={1} variant="body2">
|
||||
Download the entity customizations
|
||||
{LL.DOWNLOAD_CUSTOMIZATION_TEXT()}{' '}
|
||||
</Typography>
|
||||
</Box>
|
||||
<Button
|
||||
@@ -104,7 +104,7 @@ const GeneralFileUpload: FC<UploadFileProps> = ({ uploadGeneralFile }) => {
|
||||
color="primary"
|
||||
onClick={() => downloadCustomizations()}
|
||||
>
|
||||
customizations
|
||||
{LL.CUSTOMIZATION()}
|
||||
</Button>
|
||||
</>
|
||||
)}
|
||||
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
ValidatedPasswordField,
|
||||
ValidatedTextField
|
||||
} from '../../components';
|
||||
|
||||
import { OTASettings } from '../../types';
|
||||
import { numberValue, updateValue, useRest } from '../../utils';
|
||||
|
||||
@@ -19,12 +20,16 @@ import { ValidateFieldsError } from 'async-validator';
|
||||
import { validate } from '../../validators';
|
||||
import { OTA_SETTINGS_VALIDATOR } from '../../validators/system';
|
||||
|
||||
import { useI18nContext } from '../../i18n/i18n-react';
|
||||
|
||||
const OTASettingsForm: FC = () => {
|
||||
const { loadData, saving, data, setData, saveData, errorMessage } = useRest<OTASettings>({
|
||||
read: SystemApi.readOTASettings,
|
||||
update: SystemApi.updateOTASettings
|
||||
});
|
||||
|
||||
const { LL } = useI18nContext();
|
||||
|
||||
const updateFormValue = updateValue(setData);
|
||||
|
||||
const [fieldErrors, setFieldErrors] = useState<ValidateFieldsError>();
|
||||
@@ -48,7 +53,7 @@ const OTASettingsForm: FC = () => {
|
||||
<>
|
||||
<BlockFormControlLabel
|
||||
control={<Checkbox name="enabled" checked={data.enabled} onChange={updateFormValue} />}
|
||||
label="Enable OTA Updates"
|
||||
label={LL.ENABLE_OTA()}
|
||||
/>
|
||||
<ValidatedTextField
|
||||
fieldErrors={fieldErrors}
|
||||
@@ -64,7 +69,7 @@ const OTASettingsForm: FC = () => {
|
||||
<ValidatedPasswordField
|
||||
fieldErrors={fieldErrors}
|
||||
name="password"
|
||||
label="Password"
|
||||
label={LL.PASSWORD()}
|
||||
fullWidth
|
||||
variant="outlined"
|
||||
value={data.password}
|
||||
@@ -80,7 +85,7 @@ const OTASettingsForm: FC = () => {
|
||||
type="submit"
|
||||
onClick={validateAndSubmit}
|
||||
>
|
||||
Save
|
||||
{LL.SAVE()}
|
||||
</Button>
|
||||
</ButtonRow>
|
||||
</>
|
||||
@@ -88,7 +93,7 @@ const OTASettingsForm: FC = () => {
|
||||
};
|
||||
|
||||
return (
|
||||
<SectionContent title="OTA Settings" titleGutter>
|
||||
<SectionContent title={'OTA ' + LL.SETTINGS()} titleGutter>
|
||||
{content()}
|
||||
</SectionContent>
|
||||
);
|
||||
|
||||
@@ -4,6 +4,8 @@ import { FC, useRef, useState } from 'react';
|
||||
import * as SystemApi from '../../api/system';
|
||||
import { FormLoader } from '../../components';
|
||||
|
||||
import { useI18nContext } from '../../i18n/i18n-react';
|
||||
|
||||
const RESTART_TIMEOUT = 2 * 60 * 1000;
|
||||
const POLL_TIMEOUT = 2000;
|
||||
const POLL_INTERVAL = 5000;
|
||||
@@ -12,6 +14,8 @@ const RestartMonitor: FC = () => {
|
||||
const [failed, setFailed] = useState<boolean>(false);
|
||||
const [timeoutId, setTimeoutId] = useState<NodeJS.Timeout>();
|
||||
|
||||
const { LL } = useI18nContext();
|
||||
|
||||
const timeoutAt = useRef(new Date().getTime() + RESTART_TIMEOUT);
|
||||
const poll = useRef(async () => {
|
||||
try {
|
||||
@@ -32,12 +36,7 @@ const RestartMonitor: FC = () => {
|
||||
|
||||
useEffect(() => () => timeoutId && clearTimeout(timeoutId), [timeoutId]);
|
||||
|
||||
return (
|
||||
<FormLoader
|
||||
message="EMS-ESP is restarting, please wait…"
|
||||
errorMessage={failed ? 'Timed out waiting for device to restart.' : undefined}
|
||||
/>
|
||||
);
|
||||
return <FormLoader message={LL.APPLICATION_RESTARTING() + '...'} errorMessage={failed ? 'Timed out' : undefined} />;
|
||||
};
|
||||
|
||||
export default RestartMonitor;
|
||||
|
||||
@@ -12,8 +12,13 @@ import OTASettingsForm from './OTASettingsForm';
|
||||
|
||||
import SystemLog from './SystemLog';
|
||||
|
||||
import { useI18nContext } from '../../i18n/i18n-react';
|
||||
|
||||
const System: FC = () => {
|
||||
useLayoutTitle('System');
|
||||
|
||||
const { LL } = useI18nContext();
|
||||
|
||||
useLayoutTitle(LL.SYSTEM());
|
||||
|
||||
const { me } = useContext(AuthenticatedContext);
|
||||
const { features } = useContext(FeaturesContext);
|
||||
@@ -22,11 +27,11 @@ const System: FC = () => {
|
||||
return (
|
||||
<>
|
||||
<RouterTabs value={routerTab}>
|
||||
<Tab value="status" label="System Status" />
|
||||
<Tab value="log" label="System Log" />
|
||||
<Tab value="status" label={LL.SYSTEM() + ' ' + LL.STATUS()} />
|
||||
<Tab value="log" label={LL.SYSTEM() + ' ' + LL.LOG()} />
|
||||
|
||||
{features.ota && <Tab value="ota" label="OTA Settings" disabled={!me.admin} />}
|
||||
{features.upload_firmware && <Tab value="upload" label="Upload/Download" disabled={!me.admin} />}
|
||||
{features.ota && <Tab value="ota" label={"OTA " + LL.SETTINGS()} disabled={!me.admin} />}
|
||||
{features.upload_firmware && <Tab value="upload" label={LL.UPLOAD_DOWNLOAD()} disabled={!me.admin} />}
|
||||
</RouterTabs>
|
||||
<Routes>
|
||||
<Route path="status" element={<SystemStatusForm />} />
|
||||
|
||||
@@ -15,6 +15,9 @@ import DownloadIcon from '@mui/icons-material/GetApp';
|
||||
import { useSnackbar } from 'notistack';
|
||||
|
||||
import { EVENT_SOURCE_ROOT } from '../../api/endpoints';
|
||||
|
||||
import { useI18nContext } from '../../i18n/i18n-react';
|
||||
|
||||
export const LOG_EVENTSOURCE_URL = EVENT_SOURCE_ROOT + 'log';
|
||||
|
||||
const useWindowSize = () => {
|
||||
@@ -63,6 +66,8 @@ const levelLabel = (level: LogLevel) => {
|
||||
const SystemLog: FC = () => {
|
||||
useWindowSize();
|
||||
|
||||
const { LL } = useI18nContext();
|
||||
|
||||
const { loadData, data, setData } = useRest<LogSettings>({
|
||||
read: SystemApi.readLogSettings
|
||||
});
|
||||
@@ -104,10 +109,10 @@ const SystemLog: FC = () => {
|
||||
compact: data.compact
|
||||
});
|
||||
if (response.status !== 200) {
|
||||
enqueueSnackbar('Problem applying log settings', { variant: 'error' });
|
||||
enqueueSnackbar(LL.PROBLEM_UPDATING(), { variant: 'error' });
|
||||
}
|
||||
} catch (error: unknown) {
|
||||
enqueueSnackbar(extractErrorMessage(error, 'Problem applying log settings'), { variant: 'error' });
|
||||
enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_UPDATING()), { variant: 'error' });
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -159,9 +164,9 @@ const SystemLog: FC = () => {
|
||||
try {
|
||||
setLogEntries((await SystemApi.readLogEntries()).data);
|
||||
} catch (error: unknown) {
|
||||
setErrorMessage(extractErrorMessage(error, 'Failed to fetch log'));
|
||||
setErrorMessage(extractErrorMessage(error, LL.PROBLEM_LOADING()));
|
||||
}
|
||||
}, []);
|
||||
}, [LL]);
|
||||
|
||||
useEffect(() => {
|
||||
fetchLog();
|
||||
@@ -214,7 +219,7 @@ const SystemLog: FC = () => {
|
||||
</ValidatedTextField>
|
||||
</Grid>
|
||||
<Grid item xs={3}>
|
||||
<FormLabel>Buffer size</FormLabel>
|
||||
<FormLabel>{LL.BUFFER_SIZE()}</FormLabel>
|
||||
<Slider
|
||||
value={data.max_messages}
|
||||
valueLabelDisplay="auto"
|
||||
@@ -235,12 +240,12 @@ const SystemLog: FC = () => {
|
||||
<Grid item>
|
||||
<BlockFormControlLabel
|
||||
control={<Checkbox checked={data.compact} onChange={updateFormValue} name="compact" />}
|
||||
label="Compact"
|
||||
label={LL.COMPACT()}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item>
|
||||
<Button startIcon={<DownloadIcon />} variant="outlined" color="secondary" onClick={onDownload}>
|
||||
Export
|
||||
{LL.EXPORT()}
|
||||
</Button>
|
||||
</Grid>
|
||||
</Grid>
|
||||
@@ -273,7 +278,7 @@ const SystemLog: FC = () => {
|
||||
};
|
||||
|
||||
return (
|
||||
<SectionContent title="System Log" titleGutter id="log-window">
|
||||
<SectionContent title={LL.SYSTEM() + ' ' + LL.LOG()} titleGutter id="log-window">
|
||||
{content()}
|
||||
</SectionContent>
|
||||
);
|
||||
|
||||
@@ -39,6 +39,8 @@ import { AuthenticatedContext } from '../../contexts/authentication';
|
||||
|
||||
import axios from 'axios';
|
||||
|
||||
import { useI18nContext } from '../../i18n/i18n-react';
|
||||
|
||||
export const VERSIONCHECK_ENDPOINT = 'https://api.github.com/repos/emsesp/EMS-ESP32/releases/latest';
|
||||
export const VERSIONCHECK_DEV_ENDPOINT = 'https://api.github.com/repos/emsesp/EMS-ESP32/releases/tags/latest';
|
||||
export const uploadURL = window.location.origin + '/system/upload';
|
||||
@@ -48,6 +50,8 @@ function formatNumber(num: number) {
|
||||
}
|
||||
|
||||
const SystemStatusForm: FC = () => {
|
||||
const { LL } = useI18nContext();
|
||||
|
||||
const { loadData, data, errorMessage } = useRest<SystemStatus>({ read: SystemApi.readSystemStatus });
|
||||
|
||||
const { me } = useContext(AuthenticatedContext);
|
||||
@@ -80,9 +84,9 @@ const SystemStatusForm: FC = () => {
|
||||
setProcessing(true);
|
||||
try {
|
||||
await SystemApi.restart();
|
||||
enqueueSnackbar('EMS-ESP is restarting...', { variant: 'info' });
|
||||
enqueueSnackbar(LL.APPLICATION_RESTARTING(), { variant: 'info' });
|
||||
} catch (error: unknown) {
|
||||
enqueueSnackbar(extractErrorMessage(error, 'Problem restarting device'), { variant: 'error' });
|
||||
enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_LOADING()), { variant: 'error' });
|
||||
} finally {
|
||||
setConfirmRestart(false);
|
||||
setProcessing(false);
|
||||
@@ -92,7 +96,7 @@ const SystemStatusForm: FC = () => {
|
||||
const renderRestartDialog = () => (
|
||||
<Dialog open={confirmRestart} onClose={() => setConfirmRestart(false)}>
|
||||
<DialogTitle>Restart</DialogTitle>
|
||||
<DialogContent dividers>Are you sure you want to restart EMS-ESP?</DialogContent>
|
||||
<DialogContent dividers>{LL.RESTART_TEXT()}</DialogContent>
|
||||
<DialogActions>
|
||||
<Button
|
||||
startIcon={<CancelIcon />}
|
||||
@@ -119,16 +123,12 @@ const SystemStatusForm: FC = () => {
|
||||
const renderVersionDialog = () => {
|
||||
return (
|
||||
<Dialog open={showingVersion} onClose={() => setShowingVersion(false)}>
|
||||
<DialogTitle>Version Check</DialogTitle>
|
||||
<DialogTitle>{LL.VERSION_CHECK()}</DialogTitle>
|
||||
<DialogContent dividers>
|
||||
<MessageBox
|
||||
my={0}
|
||||
level="info"
|
||||
message={'You are currently running EMS-ESP version ' + data?.emsesp_version}
|
||||
/>
|
||||
<MessageBox my={0} level="info" message={LL.SYSTEM_VERSION_RUNNING() + ' ' + data?.emsesp_version} />
|
||||
{latestVersion && (
|
||||
<Box mt={2} mb={2}>
|
||||
The latest <u>official</u> version is <b>{latestVersion.version}</b> (
|
||||
{LL.THE_LATEST()} <u>official</u> version is <b>{latestVersion.version}</b> (
|
||||
<Link target="_blank" href={latestVersion.changelog} color="primary">
|
||||
{'release notes'}
|
||||
</Link>
|
||||
@@ -142,7 +142,7 @@ const SystemStatusForm: FC = () => {
|
||||
|
||||
{latestDevVersion && (
|
||||
<Box mt={2} mb={2}>
|
||||
The latest <u>development</u> version is <b>{latestDevVersion.version}</b>
|
||||
{LL.THE_LATEST()} <u>development</u> version is <b>{latestDevVersion.version}</b>
|
||||
(
|
||||
<Link target="_blank" href={latestDevVersion.changelog} color="primary">
|
||||
{'release notes'}
|
||||
@@ -157,17 +157,17 @@ const SystemStatusForm: FC = () => {
|
||||
|
||||
<Box color="warning.main" p={0} pl={0} pr={0} mt={4} mb={0}>
|
||||
<Typography variant="body2">
|
||||
Use
|
||||
{LL.USE()}
|
||||
<Link target="_blank" href={uploadURL} color="primary">
|
||||
{'UPLOAD'}
|
||||
</Link>
|
||||
to apply the new firmware
|
||||
{LL.SYSTEM_APPLY_FIRMWARE()}
|
||||
</Typography>
|
||||
</Box>
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button variant="outlined" onClick={() => setShowingVersion(false)} color="secondary">
|
||||
Close
|
||||
{LL.CLOSE()}
|
||||
</Button>
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
@@ -178,9 +178,9 @@ const SystemStatusForm: FC = () => {
|
||||
setProcessing(true);
|
||||
try {
|
||||
await SystemApi.factoryReset();
|
||||
enqueueSnackbar('Device has been factory reset and will now restart', { variant: 'info' });
|
||||
enqueueSnackbar(LL.SYSTEM_FACTORY_TEXT(), { variant: 'info' });
|
||||
} catch (error: unknown) {
|
||||
enqueueSnackbar(extractErrorMessage(error, 'Problem factory resetting the device'), { variant: 'error' });
|
||||
enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_UPDATING()), { variant: 'error' });
|
||||
} finally {
|
||||
setConfirmFactoryReset(false);
|
||||
setProcessing(false);
|
||||
@@ -189,8 +189,8 @@ const SystemStatusForm: FC = () => {
|
||||
|
||||
const renderFactoryResetDialog = () => (
|
||||
<Dialog open={confirmFactoryReset} onClose={() => setConfirmFactoryReset(false)}>
|
||||
<DialogTitle>Factory Reset</DialogTitle>
|
||||
<DialogContent dividers>Are you sure you want to reset the device to its factory defaults?</DialogContent>
|
||||
<DialogTitle>{LL.FACTORY_RESET()}</DialogTitle>
|
||||
<DialogContent dividers>{LL.SYSTEM_FACTORY_TEXT_DIALOG()}</DialogContent>
|
||||
<DialogActions>
|
||||
<Button
|
||||
startIcon={<CancelIcon />}
|
||||
@@ -198,7 +198,7 @@ const SystemStatusForm: FC = () => {
|
||||
onClick={() => setConfirmFactoryReset(false)}
|
||||
color="secondary"
|
||||
>
|
||||
Cancel
|
||||
{LL.CANCEL()}
|
||||
</Button>
|
||||
<Button
|
||||
startIcon={<SettingsBackupRestoreIcon />}
|
||||
@@ -208,7 +208,7 @@ const SystemStatusForm: FC = () => {
|
||||
autoFocus
|
||||
color="error"
|
||||
>
|
||||
Factory Reset
|
||||
{LL.FACTORY_RESET()}
|
||||
</Button>
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
@@ -231,7 +231,7 @@ const SystemStatusForm: FC = () => {
|
||||
<ListItemText primary="EMS-ESP Version" secondary={'v' + data.emsesp_version} />
|
||||
{latestVersion && (
|
||||
<Button color="primary" onClick={() => setShowingVersion(true)}>
|
||||
Version Check
|
||||
{LL.VERSION_CHECK()}
|
||||
</Button>
|
||||
)}
|
||||
</ListItem>
|
||||
@@ -335,7 +335,7 @@ const SystemStatusForm: FC = () => {
|
||||
<Box flexGrow={1} sx={{ '& button': { mt: 2 } }}>
|
||||
<ButtonRow>
|
||||
<Button startIcon={<RefreshIcon />} variant="outlined" color="secondary" onClick={loadData}>
|
||||
Refresh
|
||||
{LL.REFRESH()}
|
||||
</Button>
|
||||
</ButtonRow>
|
||||
</Box>
|
||||
@@ -348,7 +348,7 @@ const SystemStatusForm: FC = () => {
|
||||
color="primary"
|
||||
onClick={() => setConfirmRestart(true)}
|
||||
>
|
||||
Restart
|
||||
{LL.RESTART()}
|
||||
</Button>
|
||||
<Button
|
||||
startIcon={<SettingsBackupRestoreIcon />}
|
||||
@@ -356,7 +356,7 @@ const SystemStatusForm: FC = () => {
|
||||
onClick={() => setConfirmFactoryReset(true)}
|
||||
color="error"
|
||||
>
|
||||
Factory reset
|
||||
{LL.FACTORY_RESET()}
|
||||
</Button>
|
||||
</ButtonRow>
|
||||
</Box>
|
||||
@@ -370,7 +370,7 @@ const SystemStatusForm: FC = () => {
|
||||
};
|
||||
|
||||
return (
|
||||
<SectionContent title="System Status" titleGutter>
|
||||
<SectionContent title={LL.SYSTEM() + ' ' + LL.STATUS()} titleGutter>
|
||||
{content()}
|
||||
</SectionContent>
|
||||
);
|
||||
|
||||
@@ -7,9 +7,13 @@ import { FileUploadConfig } from '../../api/endpoints';
|
||||
import GeneralFileUpload from './GeneralFileUpload';
|
||||
import RestartMonitor from './RestartMonitor';
|
||||
|
||||
import { useI18nContext } from '../../i18n/i18n-react';
|
||||
|
||||
const UploadFileForm: FC = () => {
|
||||
const [restarting, setRestarting] = useState<boolean>();
|
||||
|
||||
const { LL } = useI18nContext();
|
||||
|
||||
const uploadFile = useRef(async (file: File, config?: FileUploadConfig) => {
|
||||
const response = await SystemApi.uploadFile(file, config);
|
||||
setRestarting(true);
|
||||
@@ -17,7 +21,7 @@ const UploadFileForm: FC = () => {
|
||||
});
|
||||
|
||||
return (
|
||||
<SectionContent title="Upload/Download" titleGutter>
|
||||
<SectionContent title={LL.UPLOAD_DOWNLOAD()} titleGutter>
|
||||
{restarting ? <RestartMonitor /> : <GeneralFileUpload uploadGeneralFile={uploadFile.current} />}
|
||||
</SectionContent>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user