new linting, make sure code is type safe

This commit is contained in:
proddy
2024-04-20 20:46:01 +02:00
parent ae7cd23758
commit 9dc91f2d69
122 changed files with 1194 additions and 2412 deletions

View File

@@ -1,3 +1,5 @@
import type { FC } from 'react';
import AppsIcon from '@mui/icons-material/Apps';
import DeveloperBoardIcon from '@mui/icons-material/DeveloperBoard';
import DevicesIcon from '@mui/icons-material/Devices';
@@ -8,10 +10,9 @@ import SdCardAlertIcon from '@mui/icons-material/SdCardAlert';
import SdStorageIcon from '@mui/icons-material/SdStorage';
import { Avatar, Box, Button, Divider, List, ListItem, ListItemAvatar, ListItemText } from '@mui/material';
import { useRequest } from 'alova';
import type { FC } from 'react';
import * as SystemApi from 'api/system';
import { useRequest } from 'alova';
import { ButtonRow, FormLoader, SectionContent, useLayoutTitle } from 'components';
import { useI18nContext } from 'i18n/i18n-react';

View File

@@ -1,10 +1,10 @@
import { useRequest } from 'alova';
import { useRef, useState, useEffect } from 'react';
import { useEffect, useRef, useState } from 'react';
import type { FC } from 'react';
import * as SystemApi from 'api/system';
import { FormLoader } from 'components';
import { useRequest } from 'alova';
import { FormLoader } from 'components';
import { useI18nContext } from 'i18n/i18n-react';
const RESTART_TIMEOUT = 2 * 60 * 1000;

View File

@@ -1,15 +1,16 @@
import { type FC, useContext } from 'react';
import { Navigate, Route, Routes } from 'react-router-dom';
import { Tab } from '@mui/material';
import { useContext, type FC } from 'react';
import { Navigate, Routes, Route } from 'react-router-dom';
import SystemLog from './SystemLog';
import SystemStatus from './SystemStatus';
import { useRouterTab, RouterTabs, useLayoutTitle, RequireAdmin } from 'components';
import { RequireAdmin, RouterTabs, useLayoutTitle, useRouterTab } from 'components';
import { AuthenticatedContext } from 'contexts/authentication';
import { useI18nContext } from 'i18n/i18n-react';
import SystemActivity from 'project/SystemActivity';
import SystemLog from './SystemLog';
import SystemStatus from './SystemStatus';
const System: FC = () => {
const { LL } = useI18nContext();

View File

@@ -1,24 +1,22 @@
import { useEffect, useRef, useState } from 'react';
import type { FC } from 'react';
import { toast } from 'react-toastify';
import DownloadIcon from '@mui/icons-material/GetApp';
import WarningIcon from '@mui/icons-material/Warning';
import { Box, styled, Button, Checkbox, MenuItem, Grid, TextField } from '@mui/material';
import { useRequest } from 'alova';
import { useState, useEffect, useRef } from 'react';
import { toast } from 'react-toastify';
import type { FC } from 'react';
import { Box, Button, Checkbox, Grid, MenuItem, TextField, styled } from '@mui/material';
import type { LogSettings, LogEntry } from 'types';
import { addAccessTokenParameter } from 'api/authentication';
import { EVENT_SOURCE_ROOT } from 'api/endpoints';
import * as SystemApi from 'api/system';
import { fetchLogES } from 'api/system';
import { SectionContent, FormLoader, BlockFormControlLabel, BlockNavigation, useLayoutTitle } from 'components';
import { useSSE } from '@alova/scene-react';
import { useRequest } from 'alova';
import { BlockFormControlLabel, BlockNavigation, FormLoader, SectionContent, useLayoutTitle } from 'components';
import { useI18nContext } from 'i18n/i18n-react';
import type { LogEntry, LogSettings } from 'types';
import { LogLevel } from 'types';
import { updateValueDirty, useRest } from 'utils';
export const LOG_EVENTSOURCE_URL = EVENT_SOURCE_ROOT + 'log';
const LogEntryLine = styled('div')(() => ({
color: '#bbbbbb',
fontFamily: 'monospace',
@@ -58,13 +56,34 @@ const SystemLog: FC = () => {
update: SystemApi.updateLogSettings
});
// called on page load to reset pointer and fetch all log entries
useRequest(SystemApi.fetchLog());
const [logEntries, setLogEntries] = useState<LogEntry[]>([]);
const [lastIndex, setLastIndex] = useState<number>(0);
const updateFormValue = updateValueDirty(origData, dirtyFlags, setDirtyFlags, updateDataValue);
// eslint-disable-next-line @typescript-eslint/unbound-method
const { onMessage, onError } = useSSE(fetchLogES, {
immediate: true,
// withCredentials: true,
interceptByGlobalResponded: false
});
onMessage((message: { id: number; data: string }) => {
const rawData = message.data;
const logentry = JSON.parse(rawData) as LogEntry;
if (logentry.i > lastIndex) {
setLastIndex(logentry.i);
setLogEntries((log) => [...log, logentry]);
}
});
onError(() => {
toast.error('No connection to Log server');
});
// called on page load to reset pointer and fetch all log entries
useRequest(SystemApi.fetchLog());
const paddedLevelLabel = (level: LogLevel) => {
const label = levelLabel(level);
return data?.compact ? ' ' + label[0] : label.padStart(8, '\xa0');
@@ -97,8 +116,8 @@ const SystemLog: FC = () => {
await saveData();
};
// handle scrolling
const ref = useRef<HTMLDivElement>(null);
useEffect(() => {
if (logEntries.length) {
ref.current?.scrollIntoView({
@@ -108,29 +127,6 @@ const SystemLog: FC = () => {
}
}, [logEntries.length]);
useEffect(() => {
const es = new EventSource(addAccessTokenParameter(LOG_EVENTSOURCE_URL));
es.onmessage = (event: MessageEvent) => {
const rawData = event.data;
if (typeof rawData === 'string' || rawData instanceof String) {
const logentry = JSON.parse(rawData as string) as LogEntry;
if (logentry.i > lastIndex) {
setLastIndex(logentry.i);
setLogEntries((log) => [...log, logentry]);
}
}
};
es.onerror = () => {
es.close();
toast.error('No connection to Log server');
};
return () => {
es.close();
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
const content = () => {
if (!data) {
return <FormLoader onRetry={loadData} errorMessage={errorMessage} />;

View File

@@ -1,3 +1,6 @@
import { type FC, useContext, useState } from 'react';
import { toast } from 'react-toastify';
import AccessTimeIcon from '@mui/icons-material/AccessTime';
import BuildIcon from '@mui/icons-material/Build';
import CancelIcon from '@mui/icons-material/Cancel';
@@ -9,7 +12,6 @@ import PermScanWifiIcon from '@mui/icons-material/PermScanWifi';
import RefreshIcon from '@mui/icons-material/Refresh';
import SettingsInputAntennaIcon from '@mui/icons-material/SettingsInputAntenna';
import TimerIcon from '@mui/icons-material/Timer';
import {
Avatar,
Box,
@@ -26,17 +28,15 @@ import {
useTheme
} from '@mui/material';
import { useRequest } from 'alova';
import { useContext, type FC, useState } from 'react';
import { toast } from 'react-toastify';
import { dialogStyle } from 'CustomTheme';
import * as SystemApi from 'api/system';
import * as EMSESP from 'project/api';
import { dialogStyle } from 'CustomTheme';
import { useRequest } from 'alova';
import { FormLoader, SectionContent, useLayoutTitle } from 'components';
import ListMenuItem from 'components/layout/ListMenuItem';
import { AuthenticatedContext } from 'contexts/authentication';
import { useI18nContext } from 'i18n/i18n-react';
import * as EMSESP from 'project/api';
import { busConnectionStatus } from 'project/types';
import { NTPSyncStatus } from 'types';
@@ -141,8 +141,8 @@ const SystemStatus: FC = () => {
.then(() => {
toast.info(LL.SCANNING() + '...');
})
.catch((err) => {
toast.error(err.message);
.catch((error: Error) => {
toast.error(error.message);
});
setConfirmScan(false);
};

View File

@@ -1,15 +1,18 @@
import DownloadIcon from '@mui/icons-material/GetApp';
import { Typography, Button, Box, Link } from '@mui/material';
import { useRequest } from 'alova';
import { useState, type FC } from 'react';
import { type FC, useState } from 'react';
import { toast } from 'react-toastify';
import RestartMonitor from './RestartMonitor';
import DownloadIcon from '@mui/icons-material/GetApp';
import { Box, Button, Link, Typography } from '@mui/material';
import * as SystemApi from 'api/system';
import { FormLoader, SectionContent, SingleUpload, useLayoutTitle } from 'components';
import { useI18nContext } from 'i18n/i18n-react';
import * as EMSESP from 'project/api';
import { useRequest } from 'alova';
import { FormLoader, SectionContent, SingleUpload, useLayoutTitle } from 'components';
import { useI18nContext } from 'i18n/i18n-react';
import type { APIcall } from 'project/types';
import RestartMonitor from './RestartMonitor';
const UploadDownload: FC = () => {
const { LL } = useI18nContext();
@@ -28,7 +31,7 @@ const UploadDownload: FC = () => {
const { send: getSchedule, onSuccess: onSuccessGetSchedule } = useRequest(EMSESP.getSchedule(), {
immediate: false
});
const { send: getAPI, onSuccess: onGetAPI } = useRequest((data) => EMSESP.API(data), {
const { send: getAPI, onSuccess: onGetAPI } = useRequest((data: APIcall) => EMSESP.API(data), {
immediate: false
});
@@ -64,8 +67,9 @@ const UploadDownload: FC = () => {
force: true
});
onSuccessUpload(({ data }: any) => {
onSuccessUpload(({ data }) => {
if (data) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
setMd5(data.md5);
toast.success(LL.UPLOAD() + ' MD5 ' + LL.SUCCESSFUL());
} else {
@@ -74,18 +78,18 @@ const UploadDownload: FC = () => {
});
const startUpload = async (files: File[]) => {
await sendUpload(files[0]).catch((err) => {
if (err.message === 'The user aborted a request') {
await sendUpload(files[0]).catch((error: Error) => {
if (error.message === 'The user aborted a request') {
toast.warning(LL.UPLOAD() + ' ' + LL.ABORTED());
} else if (err.message === 'Network Error') {
} else if (error.message === 'Network Error') {
toast.warning('Invalid file extension or incompatible bin file');
} else {
toast.error(err.message);
toast.error(error.message);
}
});
};
const saveFile = (json: any, endpoint: string) => {
const saveFile = (json: unknown, endpoint: string) => {
const anchor = document.createElement('a');
anchor.href = URL.createObjectURL(
new Blob([JSON.stringify(json, null, 2)], {
@@ -111,30 +115,31 @@ const UploadDownload: FC = () => {
saveFile(event.data, 'schedule.json');
});
onGetAPI((event) => {
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
saveFile(event.data, event.sendArgs[0].device + '_' + event.sendArgs[0].entity + '.txt');
});
const downloadSettings = async () => {
await getSettings().catch((error) => {
await getSettings().catch((error: Error) => {
toast.error(error.message);
});
};
const downloadCustomizations = async () => {
await getCustomizations().catch((error) => {
await getCustomizations().catch((error: Error) => {
toast.error(error.message);
});
};
const downloadEntities = async () => {
await getEntities().catch((error) => {
await getEntities().catch((error: Error) => {
toast.error(error.message);
});
};
const downloadSchedule = async () => {
await getSchedule()
.catch((error) => {
.catch((error: Error) => {
toast.error(error.message);
})
.finally(() => {
@@ -143,7 +148,7 @@ const UploadDownload: FC = () => {
};
const callAPI = async (device: string, entity: string) => {
await getAPI({ device, entity, id: 0 }).catch((error) => {
await getAPI({ device, entity, id: 0 }).catch((error: Error) => {
toast.error(error.message);
});
};
@@ -173,7 +178,7 @@ const UploadDownload: FC = () => {
)&nbsp;(
<Link
target="_blank"
href={STABLE_URL + 'v' + latestVersion + '/' + getBinURL(latestVersion)}
href={STABLE_URL + 'v' + latestVersion + '/' + getBinURL(latestVersion as string)}
color="primary"
>
{LL.DOWNLOAD(1)}
@@ -190,7 +195,7 @@ const UploadDownload: FC = () => {
{LL.RELEASE_NOTES()}
</Link>
)&nbsp;(
<Link target="_blank" href={DEV_URL + getBinURL(latestDevVersion)} color="primary">
<Link target="_blank" href={DEV_URL + getBinURL(latestDevVersion as string)} color="primary">
{LL.DOWNLOAD(1)}
</Link>
)