mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2025-12-06 07:49:52 +03:00
initial lint cleanup
This commit is contained in:
@@ -1,10 +1,11 @@
|
||||
import { FC, useEffect, useState } from 'react';
|
||||
|
||||
import { useEffect, useState } from 'react';
|
||||
import { ToastContainer, Slide } from 'react-toastify';
|
||||
import type { FC } from 'react';
|
||||
|
||||
import 'react-toastify/dist/ReactToastify.min.css';
|
||||
|
||||
import CustomTheme from 'CustomTheme';
|
||||
import AppRouting from 'AppRouting';
|
||||
import CustomTheme from 'CustomTheme';
|
||||
|
||||
import { localStorageDetector } from 'typesafe-i18n/detectors';
|
||||
import TypesafeI18n from 'i18n/i18n-react';
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
import { FC, useContext, useEffect } from 'react';
|
||||
import { useContext, useEffect } from 'react';
|
||||
|
||||
import { Route, Routes, Navigate, useLocation } from 'react-router-dom';
|
||||
|
||||
import { toast } from 'react-toastify';
|
||||
import type { FC } from 'react';
|
||||
|
||||
import { useI18nContext } from 'i18n/i18n-react';
|
||||
|
||||
import { Authentication, AuthenticationContext } from 'contexts/authentication';
|
||||
import AuthenticatedRouting from 'AuthenticatedRouting';
|
||||
import SignIn from 'SignIn';
|
||||
import { RequireAuthenticated, RequireUnauthenticated } from 'components';
|
||||
|
||||
import SignIn from 'SignIn';
|
||||
import AuthenticatedRouting from 'AuthenticatedRouting';
|
||||
import { Authentication, AuthenticationContext } from 'contexts/authentication';
|
||||
import { useI18nContext } from 'i18n/i18n-react';
|
||||
|
||||
interface SecurityRedirectProps {
|
||||
message: string;
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
import { FC, useCallback, useEffect } from 'react';
|
||||
import { useCallback, useEffect } from 'react';
|
||||
import { Navigate, Routes, Route, useNavigate, useLocation } from 'react-router-dom';
|
||||
import { AxiosError } from 'axios';
|
||||
import Dashboard from './project/Dashboard';
|
||||
import Help from './project/Help';
|
||||
import Settings from './project/Settings';
|
||||
import type { AxiosError } from 'axios';
|
||||
import type { FC } from 'react';
|
||||
|
||||
import * as AuthenticationApi from 'api/authentication';
|
||||
import { AXIOS } from 'api/endpoints';
|
||||
import { Layout, RequireAdmin } from 'components';
|
||||
|
||||
import Dashboard from './project/Dashboard';
|
||||
import Settings from './project/Settings';
|
||||
import Help from './project/Help';
|
||||
|
||||
import NetworkConnection from 'framework/network/NetworkConnection';
|
||||
import AccessPoint from 'framework/ap/AccessPoint';
|
||||
import NetworkTime from 'framework/ntp/NetworkTime';
|
||||
import Mqtt from 'framework/mqtt/Mqtt';
|
||||
import System from 'framework/system/System';
|
||||
import NetworkConnection from 'framework/network/NetworkConnection';
|
||||
import NetworkTime from 'framework/ntp/NetworkTime';
|
||||
import Security from 'framework/security/Security';
|
||||
import System from 'framework/system/System';
|
||||
|
||||
const AuthenticatedRouting: FC = () => {
|
||||
const location = useLocation();
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
import { FC } from 'react';
|
||||
|
||||
import { CssBaseline } from '@mui/material';
|
||||
import { createTheme, responsiveFontSizes, ThemeProvider } from '@mui/material/styles';
|
||||
import { blueGrey, blue } from '@mui/material/colors';
|
||||
import { createTheme, responsiveFontSizes, ThemeProvider } from '@mui/material/styles';
|
||||
import type { FC } from 'react';
|
||||
|
||||
import { RequiredChildrenProps } from 'utils';
|
||||
import type { RequiredChildrenProps } from 'utils';
|
||||
|
||||
const theme = responsiveFontSizes(
|
||||
createTheme({
|
||||
|
||||
@@ -1,31 +1,30 @@
|
||||
import { FC, useContext, useState } from 'react';
|
||||
import { ValidateFieldsError } from 'async-validator';
|
||||
import { toast } from 'react-toastify';
|
||||
|
||||
import { Box, Fab, Paper, Typography, Button } from '@mui/material';
|
||||
import ForwardIcon from '@mui/icons-material/Forward';
|
||||
import { Box, Fab, Paper, Typography, Button } from '@mui/material';
|
||||
import { useContext, useState } from 'react';
|
||||
import { toast } from 'react-toastify';
|
||||
import type { ValidateFieldsError } from 'async-validator';
|
||||
|
||||
import type { Locales } from 'i18n/i18n-types';
|
||||
import type { FC } from 'react';
|
||||
import type { SignInRequest } from 'types';
|
||||
import * as AuthenticationApi from 'api/authentication';
|
||||
import { PROJECT_NAME } from 'api/env';
|
||||
|
||||
import { ValidatedTextField } from 'components';
|
||||
import { AuthenticationContext } from 'contexts/authentication';
|
||||
|
||||
import { extractErrorMessage, onEnterCallback, updateValue } from 'utils';
|
||||
import { SignInRequest } from 'types';
|
||||
import { ValidatedTextField } from 'components';
|
||||
import { SIGN_IN_REQUEST_VALIDATOR, validate } from 'validators';
|
||||
|
||||
import { I18nContext } from 'i18n/i18n-react';
|
||||
import type { Locales } from 'i18n/i18n-types';
|
||||
import { loadLocaleAsync } from 'i18n/i18n-util.async';
|
||||
|
||||
import { ReactComponent as NLflag } from 'i18n/NL.svg';
|
||||
import { ReactComponent as DEflag } from 'i18n/DE.svg';
|
||||
import { ReactComponent as GBflag } from 'i18n/GB.svg';
|
||||
import { ReactComponent as SVflag } from 'i18n/SV.svg';
|
||||
import { ReactComponent as PLflag } from 'i18n/PL.svg';
|
||||
import { ReactComponent as NLflag } from 'i18n/NL.svg';
|
||||
import { ReactComponent as NOflag } from 'i18n/NO.svg';
|
||||
import { ReactComponent as PLflag } from 'i18n/PL.svg';
|
||||
import { ReactComponent as SVflag } from 'i18n/SV.svg';
|
||||
import { ReactComponent as FRflag } from 'i18n/FR.svg';
|
||||
import { ReactComponent as TRflag } from 'i18n/TR.svg';
|
||||
import { I18nContext } from 'i18n/i18n-react';
|
||||
import { loadLocaleAsync } from 'i18n/i18n-util.async';
|
||||
import { extractErrorMessage, onEnterCallback, updateValue } from 'utils';
|
||||
import { SIGN_IN_REQUEST_VALIDATOR, validate } from 'validators';
|
||||
|
||||
const SignIn: FC = () => {
|
||||
const authenticationContext = useContext(AuthenticationContext);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { AxiosPromise } from 'axios';
|
||||
|
||||
import { APSettings, APStatus } from 'types';
|
||||
import { AXIOS } from './endpoints';
|
||||
import type { AxiosPromise } from 'axios';
|
||||
|
||||
import type { APSettings, APStatus } from 'types';
|
||||
|
||||
export function readAPStatus(): AxiosPromise<APStatus> {
|
||||
return AXIOS.get('/apStatus');
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
import { AxiosPromise } from 'axios';
|
||||
import * as H from 'history';
|
||||
import jwtDecode from 'jwt-decode';
|
||||
import { Path } from 'react-router-dom';
|
||||
|
||||
import { Me, SignInRequest, SignInResponse } from 'types';
|
||||
|
||||
import { ACCESS_TOKEN, AXIOS } from './endpoints';
|
||||
import type { AxiosPromise } from 'axios';
|
||||
import type * as H from 'history';
|
||||
import type { Path } from 'react-router-dom';
|
||||
|
||||
import type { Me, SignInRequest, SignInResponse } from 'types';
|
||||
|
||||
export const SIGN_IN_PATHNAME = 'loginPathname';
|
||||
export const SIGN_IN_SEARCH = 'loginSearch';
|
||||
@@ -45,7 +44,7 @@ export function fetchLoginRedirect(): Partial<Path> {
|
||||
}
|
||||
|
||||
export const clearAccessToken = () => localStorage.removeItem(ACCESS_TOKEN);
|
||||
export const decodeMeJWT = (accessToken: string): Me => jwtDecode(accessToken) as Me;
|
||||
export const decodeMeJWT = (accessToken: string): Me => jwtDecode(accessToken);
|
||||
|
||||
export function addAccessTokenParameter(url: string) {
|
||||
const accessToken = getStorage().getItem(ACCESS_TOKEN);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import axios, { AxiosPromise, CancelToken, AxiosProgressEvent } from 'axios';
|
||||
|
||||
import { decode } from '@msgpack/msgpack';
|
||||
import axios from 'axios';
|
||||
import type { AxiosPromise, CancelToken, AxiosProgressEvent } from 'axios';
|
||||
|
||||
export const WS_BASE_URL = '/ws/';
|
||||
export const API_BASE_URL = '/rest/';
|
||||
@@ -72,11 +72,7 @@ export const AXIOS_BIN = axios.create({
|
||||
return JSON.stringify(data);
|
||||
}
|
||||
],
|
||||
transformResponse: [
|
||||
(data) => {
|
||||
return decode(data);
|
||||
}
|
||||
]
|
||||
transformResponse: [(data) => decode(data)]
|
||||
});
|
||||
|
||||
export interface FileUploadConfig {
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import { AxiosPromise } from 'axios';
|
||||
|
||||
import { Features } from 'types';
|
||||
|
||||
import { AXIOS } from './endpoints';
|
||||
import type { AxiosPromise } from 'axios';
|
||||
|
||||
import type { Features } from 'types';
|
||||
|
||||
export function readFeatures(): AxiosPromise<Features> {
|
||||
return AXIOS.get('/features');
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { AxiosPromise } from 'axios';
|
||||
import { MqttSettings, MqttStatus } from 'types';
|
||||
|
||||
import { AXIOS } from './endpoints';
|
||||
import type { AxiosPromise } from 'axios';
|
||||
import type { MqttSettings, MqttStatus } from 'types';
|
||||
|
||||
export function readMqttStatus(): AxiosPromise<MqttStatus> {
|
||||
return AXIOS.get('/mqttStatus');
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import { AxiosPromise } from 'axios';
|
||||
|
||||
import { WiFiNetworkList, NetworkSettings, NetworkStatus } from 'types';
|
||||
|
||||
import { AXIOS } from './endpoints';
|
||||
import type { AxiosPromise } from 'axios';
|
||||
|
||||
import type { WiFiNetworkList, NetworkSettings, NetworkStatus } from 'types';
|
||||
|
||||
export function readNetworkStatus(): AxiosPromise<NetworkStatus> {
|
||||
return AXIOS.get('/networkStatus');
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { AxiosPromise } from 'axios';
|
||||
import { NTPSettings, NTPStatus, Time } from 'types';
|
||||
|
||||
import { AXIOS } from './endpoints';
|
||||
import type { AxiosPromise } from 'axios';
|
||||
import type { NTPSettings, NTPStatus, Time } from 'types';
|
||||
|
||||
export function readNTPStatus(): AxiosPromise<NTPStatus> {
|
||||
return AXIOS.get('/ntpStatus');
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import { AxiosPromise } from 'axios';
|
||||
|
||||
import { SecuritySettings, Token } from 'types';
|
||||
|
||||
import { AXIOS } from './endpoints';
|
||||
import type { AxiosPromise } from 'axios';
|
||||
|
||||
import type { SecuritySettings, Token } from 'types';
|
||||
|
||||
export function readSecuritySettings(): AxiosPromise<SecuritySettings> {
|
||||
return AXIOS.get('/securitySettings');
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { AxiosPromise } from 'axios';
|
||||
import { AXIOS, AXIOS_BIN, startUploadFile } from './endpoints';
|
||||
import type { FileUploadConfig } from './endpoints';
|
||||
import type { AxiosPromise } from 'axios';
|
||||
|
||||
import { OTASettings, SystemStatus, LogSettings, LogEntries } from 'types';
|
||||
|
||||
import { AXIOS, AXIOS_BIN, FileUploadConfig, startUploadFile } from './endpoints';
|
||||
import type { OTASettings, SystemStatus, LogSettings, LogEntries } from 'types';
|
||||
|
||||
export function readSystemStatus(timeout?: number): AxiosPromise<SystemStatus> {
|
||||
return AXIOS.get('/systemStatus', { timeout });
|
||||
|
||||
@@ -1,26 +1,25 @@
|
||||
import { FC } from 'react';
|
||||
import { Box, BoxProps } from '@mui/material';
|
||||
import { Box } from '@mui/material';
|
||||
import type { BoxProps } from '@mui/material';
|
||||
import type { FC } from 'react';
|
||||
|
||||
const ButtonRow: FC<BoxProps> = ({ children, ...rest }) => {
|
||||
return (
|
||||
<Box
|
||||
sx={{
|
||||
'& button, & a, & .MuiCard-root': {
|
||||
mt: 2,
|
||||
mx: 0.6,
|
||||
'&:last-child': {
|
||||
mr: 0
|
||||
},
|
||||
'&:first-of-type': {
|
||||
ml: 0
|
||||
}
|
||||
const ButtonRow: FC<BoxProps> = ({ children, ...rest }) => (
|
||||
<Box
|
||||
sx={{
|
||||
'& button, & a, & .MuiCard-root': {
|
||||
mt: 2,
|
||||
mx: 0.6,
|
||||
'&:last-child': {
|
||||
mr: 0
|
||||
},
|
||||
'&:first-of-type': {
|
||||
ml: 0
|
||||
}
|
||||
}}
|
||||
{...rest}
|
||||
>
|
||||
{children}
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
}
|
||||
}}
|
||||
{...rest}
|
||||
>
|
||||
{children}
|
||||
</Box>
|
||||
);
|
||||
|
||||
export default ButtonRow;
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
import { FC } from 'react';
|
||||
|
||||
import { Box, BoxProps, SvgIconProps, Theme, Typography, useTheme } from '@mui/material';
|
||||
|
||||
import CheckCircleOutlineOutlinedIcon from '@mui/icons-material/CheckCircleOutlineOutlined';
|
||||
import ErrorIcon from '@mui/icons-material/Error';
|
||||
import InfoOutlinedIcon from '@mui/icons-material/InfoOutlined';
|
||||
import ReportProblemOutlinedIcon from '@mui/icons-material/ReportProblemOutlined';
|
||||
import ErrorIcon from '@mui/icons-material/Error';
|
||||
import { Box, Typography, useTheme } from '@mui/material';
|
||||
import type { BoxProps, SvgIconProps, Theme } from '@mui/material';
|
||||
import type { FC } from 'react';
|
||||
|
||||
type MessageBoxLevel = 'warning' | 'success' | 'info' | 'error';
|
||||
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import { FC } from 'react';
|
||||
|
||||
import { Paper, Divider } from '@mui/material';
|
||||
import type { FC } from 'react';
|
||||
|
||||
import { RequiredChildrenProps } from 'utils';
|
||||
import type { RequiredChildrenProps } from 'utils';
|
||||
|
||||
interface SectionContentProps extends RequiredChildrenProps {
|
||||
title: string;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { FC } from 'react';
|
||||
import { FormControlLabel, FormControlLabelProps } from '@mui/material';
|
||||
import { FormControlLabel } from '@mui/material';
|
||||
import type { FormControlLabelProps } from '@mui/material';
|
||||
import type { FC } from 'react';
|
||||
|
||||
const BlockFormControlLabel: FC<FormControlLabelProps> = (props) => (
|
||||
<div>
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import { FC, useState } from 'react';
|
||||
|
||||
import { IconButton, InputAdornment } from '@mui/material';
|
||||
import VisibilityIcon from '@mui/icons-material/Visibility';
|
||||
import VisibilityOffIcon from '@mui/icons-material/VisibilityOff';
|
||||
import { IconButton, InputAdornment } from '@mui/material';
|
||||
import { useState } from 'react';
|
||||
|
||||
import ValidatedTextField, { ValidatedTextFieldProps } from './ValidatedTextField';
|
||||
import ValidatedTextField from './ValidatedTextField';
|
||||
import type { ValidatedTextFieldProps } from './ValidatedTextField';
|
||||
import type { FC } from 'react';
|
||||
|
||||
type ValidatedPasswordFieldProps = Omit<ValidatedTextFieldProps, 'type'>;
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { FC } from 'react';
|
||||
import { ValidateFieldsError } from 'async-validator';
|
||||
|
||||
import { FormHelperText, TextField, TextFieldProps } from '@mui/material';
|
||||
import { FormHelperText, TextField } from '@mui/material';
|
||||
import type { TextFieldProps } from '@mui/material';
|
||||
import type { ValidateFieldsError } from 'async-validator';
|
||||
import type { FC } from 'react';
|
||||
|
||||
interface ValidatedFieldProps {
|
||||
fieldErrors?: ValidateFieldsError;
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
import { FC, useState, useEffect } from 'react';
|
||||
import { useLocation } from 'react-router-dom';
|
||||
|
||||
import { Box, Toolbar } from '@mui/material';
|
||||
|
||||
import { PROJECT_NAME } from 'api/env';
|
||||
import { RequiredChildrenProps } from 'utils';
|
||||
|
||||
import LayoutDrawer from './LayoutDrawer';
|
||||
import { useState, useEffect } from 'react';
|
||||
import { useLocation } from 'react-router-dom';
|
||||
import LayoutAppBar from './LayoutAppBar';
|
||||
import LayoutDrawer from './LayoutDrawer';
|
||||
import { LayoutContext } from './context';
|
||||
import type { FC } from 'react';
|
||||
|
||||
import type { RequiredChildrenProps } from 'utils';
|
||||
import { PROJECT_NAME } from 'api/env';
|
||||
|
||||
export const DRAWER_WIDTH = 240;
|
||||
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
import { FC } from 'react';
|
||||
|
||||
import { AppBar, Box, IconButton, Toolbar, Typography } from '@mui/material';
|
||||
import MenuIcon from '@mui/icons-material/Menu';
|
||||
|
||||
import { AppBar, Box, IconButton, Toolbar, Typography } from '@mui/material';
|
||||
import LayoutAuthMenu from './LayoutAuthMenu';
|
||||
import type { FC } from 'react';
|
||||
|
||||
export const DRAWER_WIDTH = 240;
|
||||
|
||||
@@ -12,35 +10,33 @@ interface LayoutAppBarProps {
|
||||
onToggleDrawer: () => void;
|
||||
}
|
||||
|
||||
const LayoutAppBar: FC<LayoutAppBarProps> = ({ title, onToggleDrawer }) => {
|
||||
return (
|
||||
<AppBar
|
||||
position="fixed"
|
||||
sx={{
|
||||
width: { md: `calc(100% - ${DRAWER_WIDTH}px)` },
|
||||
ml: { md: `${DRAWER_WIDTH}px` },
|
||||
boxShadow: 'none',
|
||||
backgroundColor: '#2e586a'
|
||||
}}
|
||||
>
|
||||
<Toolbar>
|
||||
<IconButton
|
||||
color="inherit"
|
||||
aria-label="open drawer"
|
||||
edge="start"
|
||||
onClick={onToggleDrawer}
|
||||
sx={{ mr: 2, display: { md: 'none' } }}
|
||||
>
|
||||
<MenuIcon />
|
||||
</IconButton>
|
||||
<Typography variant="h6" noWrap component="div">
|
||||
{title}
|
||||
</Typography>
|
||||
<Box flexGrow={1} />
|
||||
<LayoutAuthMenu />
|
||||
</Toolbar>
|
||||
</AppBar>
|
||||
);
|
||||
};
|
||||
const LayoutAppBar: FC<LayoutAppBarProps> = ({ title, onToggleDrawer }) => (
|
||||
<AppBar
|
||||
position="fixed"
|
||||
sx={{
|
||||
width: { md: `calc(100% - ${DRAWER_WIDTH}px)` },
|
||||
ml: { md: `${DRAWER_WIDTH}px` },
|
||||
boxShadow: 'none',
|
||||
backgroundColor: '#2e586a'
|
||||
}}
|
||||
>
|
||||
<Toolbar>
|
||||
<IconButton
|
||||
color="inherit"
|
||||
aria-label="open drawer"
|
||||
edge="start"
|
||||
onClick={onToggleDrawer}
|
||||
sx={{ mr: 2, display: { md: 'none' } }}
|
||||
>
|
||||
<MenuIcon />
|
||||
</IconButton>
|
||||
<Typography variant="h6" noWrap component="div">
|
||||
{title}
|
||||
</Typography>
|
||||
<Box flexGrow={1} />
|
||||
<LayoutAuthMenu />
|
||||
</Toolbar>
|
||||
</AppBar>
|
||||
);
|
||||
|
||||
export default LayoutAppBar;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { FC, useState, useContext, ChangeEventHandler } from 'react';
|
||||
|
||||
import AccountCircleIcon from '@mui/icons-material/AccountCircle';
|
||||
import PersonIcon from '@mui/icons-material/Person';
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
@@ -9,28 +9,26 @@ import {
|
||||
Typography,
|
||||
Avatar,
|
||||
styled,
|
||||
TypographyProps,
|
||||
MenuItem,
|
||||
TextField
|
||||
} from '@mui/material';
|
||||
import { useState, useContext } from 'react';
|
||||
import type { TypographyProps } from '@mui/material';
|
||||
|
||||
import PersonIcon from '@mui/icons-material/Person';
|
||||
import AccountCircleIcon from '@mui/icons-material/AccountCircle';
|
||||
|
||||
import type { Locales } from 'i18n/i18n-types';
|
||||
import type { FC, ChangeEventHandler } from 'react';
|
||||
import { AuthenticatedContext } from 'contexts/authentication';
|
||||
|
||||
import { I18nContext } from 'i18n/i18n-react';
|
||||
import type { Locales } from 'i18n/i18n-types';
|
||||
import { loadLocaleAsync } from 'i18n/i18n-util.async';
|
||||
|
||||
import { ReactComponent as NLflag } from 'i18n/NL.svg';
|
||||
import { ReactComponent as DEflag } from 'i18n/DE.svg';
|
||||
import { ReactComponent as GBflag } from 'i18n/GB.svg';
|
||||
import { ReactComponent as SVflag } from 'i18n/SV.svg';
|
||||
import { ReactComponent as PLflag } from 'i18n/PL.svg';
|
||||
import { ReactComponent as NOflag } from 'i18n/NO.svg';
|
||||
import { ReactComponent as FRflag } from 'i18n/FR.svg';
|
||||
import { ReactComponent as GBflag } from 'i18n/GB.svg';
|
||||
import { ReactComponent as NLflag } from 'i18n/NL.svg';
|
||||
import { ReactComponent as NOflag } from 'i18n/NO.svg';
|
||||
import { ReactComponent as PLflag } from 'i18n/PL.svg';
|
||||
import { ReactComponent as SVflag } from 'i18n/SV.svg';
|
||||
import { ReactComponent as TRflag } from 'i18n/TR.svg';
|
||||
import { I18nContext } from 'i18n/i18n-react';
|
||||
import { loadLocaleAsync } from 'i18n/i18n-util.async';
|
||||
|
||||
const ItemTypography = styled(Typography)<TypographyProps>({
|
||||
maxWidth: '250px',
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
import { FC } from 'react';
|
||||
|
||||
import { Box, Divider, Drawer, Toolbar, Typography, styled } from '@mui/material';
|
||||
import { DRAWER_WIDTH } from './Layout';
|
||||
import LayoutMenu from './LayoutMenu';
|
||||
import type { FC } from 'react';
|
||||
|
||||
import { PROJECT_NAME } from 'api/env';
|
||||
|
||||
import LayoutMenu from './LayoutMenu';
|
||||
import { DRAWER_WIDTH } from './Layout';
|
||||
|
||||
const LayoutDrawerLogo = styled('img')(({ theme }) => ({
|
||||
[theme.breakpoints.down('sm')]: {
|
||||
height: 24,
|
||||
|
||||
@@ -1,17 +1,16 @@
|
||||
import { FC, useContext } from 'react';
|
||||
|
||||
import { Divider, List } from '@mui/material';
|
||||
|
||||
import SettingsInputAntennaIcon from '@mui/icons-material/SettingsInputAntenna';
|
||||
import AccessTimeIcon from '@mui/icons-material/AccessTime';
|
||||
import DeviceHubIcon from '@mui/icons-material/DeviceHub';
|
||||
import SettingsIcon from '@mui/icons-material/Settings';
|
||||
import LockIcon from '@mui/icons-material/Lock';
|
||||
import SettingsEthernetIcon from '@mui/icons-material/SettingsEthernet';
|
||||
|
||||
import TuneIcon from '@mui/icons-material/Tune';
|
||||
import DashboardIcon from '@mui/icons-material/Dashboard';
|
||||
import DeviceHubIcon from '@mui/icons-material/DeviceHub';
|
||||
import InfoIcon from '@mui/icons-material/Info';
|
||||
import LockIcon from '@mui/icons-material/Lock';
|
||||
import SettingsIcon from '@mui/icons-material/Settings';
|
||||
import SettingsEthernetIcon from '@mui/icons-material/SettingsEthernet';
|
||||
import SettingsInputAntennaIcon from '@mui/icons-material/SettingsInputAntenna';
|
||||
import TuneIcon from '@mui/icons-material/Tune';
|
||||
import { Divider, List } from '@mui/material';
|
||||
import { useContext } from 'react';
|
||||
import type { FC } from 'react';
|
||||
|
||||
import LayoutMenuItem from 'components/layout/LayoutMenuItem';
|
||||
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
import { FC } from 'react';
|
||||
import { ListItem, ListItemButton, ListItemIcon, ListItemText } from '@mui/material';
|
||||
import { grey } from '@mui/material/colors';
|
||||
import { Link, useLocation } from 'react-router-dom';
|
||||
|
||||
import { ListItem, ListItemButton, ListItemIcon, ListItemText, SvgIconProps } from '@mui/material';
|
||||
import type { SvgIconProps } from '@mui/material';
|
||||
import type { FC } from 'react';
|
||||
|
||||
import { routeMatches } from 'utils';
|
||||
|
||||
import { grey } from '@mui/material/colors';
|
||||
|
||||
interface LayoutMenuItemProps {
|
||||
icon: React.ComponentType<SvgIconProps>;
|
||||
label: string;
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { FC } from 'react';
|
||||
|
||||
import { Box, Paper, Typography } from '@mui/material';
|
||||
import WarningIcon from '@mui/icons-material/Warning';
|
||||
import { Box, Paper, Typography } from '@mui/material';
|
||||
import type { FC } from 'react';
|
||||
|
||||
interface ApplicationErrorProps {
|
||||
message?: string;
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { FC } from 'react';
|
||||
|
||||
import { Box, Button, CircularProgress, Typography } from '@mui/material';
|
||||
import RefreshIcon from '@mui/icons-material/Refresh';
|
||||
import { Box, Button, CircularProgress, Typography } from '@mui/material';
|
||||
import type { FC } from 'react';
|
||||
|
||||
import { MessageBox } from 'components';
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { FC } from 'react';
|
||||
|
||||
import { CircularProgress, Box, Typography, Theme } from '@mui/material';
|
||||
import { CircularProgress, Box, Typography } from '@mui/material';
|
||||
import type { Theme } from '@mui/material';
|
||||
import type { FC } from 'react';
|
||||
|
||||
import { useI18nContext } from 'i18n/i18n-react';
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { FC } from 'react';
|
||||
import type { Blocker } from '@remix-run/router';
|
||||
import { Button, Dialog, DialogActions, DialogContent, DialogTitle } from '@mui/material';
|
||||
import type { Blocker } from '@remix-run/router';
|
||||
import type { FC } from 'react';
|
||||
|
||||
import { useI18nContext } from 'i18n/i18n-react';
|
||||
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import { FC, useContext } from 'react';
|
||||
import { useContext } from 'react';
|
||||
import { Navigate } from 'react-router-dom';
|
||||
import type { FC } from 'react';
|
||||
|
||||
import type { RequiredChildrenProps } from 'utils';
|
||||
import { AuthenticatedContext } from 'contexts/authentication';
|
||||
import { RequiredChildrenProps } from 'utils';
|
||||
|
||||
const RequireAdmin: FC<RequiredChildrenProps> = ({ children }) => {
|
||||
const authenticatedContext = useContext(AuthenticatedContext);
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
import { FC, useContext, useEffect } from 'react';
|
||||
import { useContext, useEffect } from 'react';
|
||||
import { Navigate, useLocation } from 'react-router-dom';
|
||||
|
||||
import {
|
||||
AuthenticatedContext,
|
||||
AuthenticatedContextValue,
|
||||
AuthenticationContext
|
||||
} from 'contexts/authentication/context';
|
||||
import { storeLoginRedirect } from 'api/authentication';
|
||||
import type { AuthenticatedContextValue } from 'contexts/authentication/context';
|
||||
import type { FC } from 'react';
|
||||
|
||||
import { RequiredChildrenProps } from 'utils';
|
||||
import type { RequiredChildrenProps } from 'utils';
|
||||
import { storeLoginRedirect } from 'api/authentication';
|
||||
import { AuthenticatedContext, AuthenticationContext } from 'contexts/authentication/context';
|
||||
|
||||
const RequireAuthenticated: FC<RequiredChildrenProps> = ({ children }) => {
|
||||
const authenticationContext = useContext(AuthenticationContext);
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import { FC, useContext } from 'react';
|
||||
import { useContext } from 'react';
|
||||
import { Navigate } from 'react-router-dom';
|
||||
import type { FC } from 'react';
|
||||
|
||||
import type { RequiredChildrenProps } from 'utils';
|
||||
import * as AuthenticationApi from 'api/authentication';
|
||||
import { AuthenticationContext } from 'contexts/authentication';
|
||||
import { RequiredChildrenProps } from 'utils';
|
||||
|
||||
const RequireUnauthenticated: FC<RequiredChildrenProps> = ({ children }) => {
|
||||
const authenticationContext = useContext(AuthenticationContext);
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
import { FC } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
|
||||
import { Tabs, useMediaQuery, useTheme } from '@mui/material';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import type { FC } from 'react';
|
||||
|
||||
import { RequiredChildrenProps } from 'utils';
|
||||
import type { RequiredChildrenProps } from 'utils';
|
||||
|
||||
interface RouterTabsProps extends RequiredChildrenProps {
|
||||
value: string | false;
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { FC, Fragment } from 'react';
|
||||
import { useDropzone, DropzoneState } from 'react-dropzone';
|
||||
|
||||
import { AxiosProgressEvent } from 'axios';
|
||||
|
||||
import { Box, Button, LinearProgress, Theme, Typography, useTheme } from '@mui/material';
|
||||
|
||||
import CloudUploadIcon from '@mui/icons-material/CloudUpload';
|
||||
import CancelIcon from '@mui/icons-material/Cancel';
|
||||
import CloudUploadIcon from '@mui/icons-material/CloudUpload';
|
||||
import { Box, Button, LinearProgress, Typography, useTheme } from '@mui/material';
|
||||
import { Fragment } from 'react';
|
||||
import { useDropzone } from 'react-dropzone';
|
||||
import type { Theme } from '@mui/material';
|
||||
import type { AxiosProgressEvent } from 'axios';
|
||||
import type { FC } from 'react';
|
||||
import type { DropzoneState } from 'react-dropzone';
|
||||
|
||||
import { useI18nContext } from 'i18n/i18n-react';
|
||||
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import axios from 'axios';
|
||||
import { useCallback, useEffect, useState } from 'react';
|
||||
import axios, { AxiosPromise, CancelTokenSource, AxiosProgressEvent } from 'axios';
|
||||
import { toast } from 'react-toastify';
|
||||
|
||||
import { extractErrorMessage } from 'utils';
|
||||
import { FileUploadConfig } from 'api/endpoints';
|
||||
import type { FileUploadConfig } from 'api/endpoints';
|
||||
import type { AxiosPromise, CancelTokenSource, AxiosProgressEvent } from 'axios';
|
||||
|
||||
import { useI18nContext } from 'i18n/i18n-react';
|
||||
import { extractErrorMessage } from 'utils';
|
||||
|
||||
interface MediaUploadOptions {
|
||||
upload: (file: File, config?: FileUploadConfig) => AxiosPromise<void>;
|
||||
@@ -31,11 +32,12 @@ const useFileUpload = ({ upload }: MediaUploadOptions) => {
|
||||
resetUploadingStates();
|
||||
}, [uploadCancelToken]);
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
useEffect(
|
||||
() => () => {
|
||||
uploadCancelToken?.cancel();
|
||||
};
|
||||
}, [uploadCancelToken]);
|
||||
},
|
||||
[uploadCancelToken]
|
||||
);
|
||||
|
||||
const uploadFile = async (images: File[]) => {
|
||||
try {
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
import { FC, useCallback, useEffect, useState } from 'react';
|
||||
import { toast } from 'react-toastify';
|
||||
import { useCallback, useEffect, useState } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { toast } from 'react-toastify';
|
||||
import { AuthenticationContext } from './context';
|
||||
import type { FC } from 'react';
|
||||
|
||||
import { useI18nContext } from 'i18n/i18n-react';
|
||||
|
||||
import type { Me } from 'types';
|
||||
import type { RequiredChildrenProps } from 'utils';
|
||||
import * as AuthenticationApi from 'api/authentication';
|
||||
import { ACCESS_TOKEN } from 'api/endpoints';
|
||||
import { RequiredChildrenProps } from 'utils';
|
||||
import { LoadingSpinner } from 'components';
|
||||
import { Me } from 'types';
|
||||
import { AuthenticationContext } from './context';
|
||||
import { useI18nContext } from 'i18n/i18n-react';
|
||||
|
||||
const Authentication: FC<RequiredChildrenProps> = ({ children }) => {
|
||||
const { LL } = useI18nContext();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { createContext } from 'react';
|
||||
import { Me } from 'types';
|
||||
import type { Me } from 'types';
|
||||
|
||||
export interface AuthenticationContextValue {
|
||||
refresh: () => Promise<void>;
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
import { FC, useCallback, useEffect, useState } from 'react';
|
||||
|
||||
import * as FeaturesApi from 'api/features';
|
||||
|
||||
import { extractErrorMessage, RequiredChildrenProps } from 'utils';
|
||||
import { Features } from 'types';
|
||||
import { ApplicationError, LoadingSpinner } from 'components';
|
||||
import { useCallback, useEffect, useState } from 'react';
|
||||
|
||||
import { FeaturesContext } from '.';
|
||||
import type { FC } from 'react';
|
||||
|
||||
import type { Features } from 'types';
|
||||
import type { RequiredChildrenProps } from 'utils';
|
||||
import * as FeaturesApi from 'api/features';
|
||||
import { ApplicationError, LoadingSpinner } from 'components';
|
||||
import { extractErrorMessage } from 'utils';
|
||||
|
||||
const FeaturesLoader: FC<RequiredChildrenProps> = (props) => {
|
||||
const [errorMessage, setErrorMessage] = useState<string>();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { createContext } from 'react';
|
||||
|
||||
import { Features } from 'types';
|
||||
import type { Features } from 'types';
|
||||
|
||||
export interface FeaturesContextValue {
|
||||
features: Features;
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
import { FC, useState } from 'react';
|
||||
import { ValidateFieldsError } from 'async-validator';
|
||||
import { range } from 'lodash-es';
|
||||
|
||||
import { Button, Checkbox, MenuItem } from '@mui/material';
|
||||
import WarningIcon from '@mui/icons-material/Warning';
|
||||
import CancelIcon from '@mui/icons-material/Cancel';
|
||||
import WarningIcon from '@mui/icons-material/Warning';
|
||||
import { Button, Checkbox, MenuItem } from '@mui/material';
|
||||
import { range } from 'lodash-es';
|
||||
import { useState } from 'react';
|
||||
import type { ValidateFieldsError } from 'async-validator';
|
||||
import type { FC } from 'react';
|
||||
|
||||
import { createAPSettingsValidator, validate } from 'validators';
|
||||
import type { APSettings } from 'types';
|
||||
import * as APApi from 'api/ap';
|
||||
import {
|
||||
BlockFormControlLabel,
|
||||
ButtonRow,
|
||||
@@ -17,15 +18,14 @@ import {
|
||||
BlockNavigation
|
||||
} from 'components';
|
||||
|
||||
import { APProvisionMode, APSettings } from 'types';
|
||||
import { numberValue, updateValueDirty, useRest } from 'utils';
|
||||
import * as APApi from 'api/ap';
|
||||
|
||||
import { useI18nContext } from 'i18n/i18n-react';
|
||||
import { APProvisionMode } from 'types';
|
||||
import { numberValue, updateValueDirty, useRest } from 'utils';
|
||||
|
||||
export const isAPEnabled = ({ provision_mode }: APSettings) => {
|
||||
return provision_mode === APProvisionMode.AP_MODE_ALWAYS || provision_mode === APProvisionMode.AP_MODE_DISCONNECTED;
|
||||
};
|
||||
import { createAPSettingsValidator, validate } from 'validators';
|
||||
|
||||
export const isAPEnabled = ({ provision_mode }: APSettings) =>
|
||||
provision_mode === APProvisionMode.AP_MODE_ALWAYS || provision_mode === APProvisionMode.AP_MODE_DISCONNECTED;
|
||||
|
||||
const APSettingsForm: FC = () => {
|
||||
const { loadData, saving, data, setData, origData, dirtyFlags, setDirtyFlags, blocker, saveData, errorMessage } =
|
||||
|
||||
@@ -1,17 +1,18 @@
|
||||
import { FC } from 'react';
|
||||
|
||||
import { Avatar, Button, Divider, List, ListItem, ListItemAvatar, ListItemText, Theme, useTheme } from '@mui/material';
|
||||
import SettingsInputAntennaIcon from '@mui/icons-material/SettingsInputAntenna';
|
||||
import DeviceHubIcon from '@mui/icons-material/DeviceHub';
|
||||
import ComputerIcon from '@mui/icons-material/Computer';
|
||||
import DeviceHubIcon from '@mui/icons-material/DeviceHub';
|
||||
import RefreshIcon from '@mui/icons-material/Refresh';
|
||||
import SettingsInputAntennaIcon from '@mui/icons-material/SettingsInputAntenna';
|
||||
import { Avatar, Button, Divider, List, ListItem, ListItemAvatar, ListItemText, useTheme } from '@mui/material';
|
||||
import type { Theme } from '@mui/material';
|
||||
import type { FC } from 'react';
|
||||
|
||||
import type { APStatus } from 'types';
|
||||
import * as APApi from 'api/ap';
|
||||
import { APNetworkStatus, APStatus } from 'types';
|
||||
import { ButtonRow, FormLoader, SectionContent } from 'components';
|
||||
import { useRest } from 'utils';
|
||||
|
||||
import { useI18nContext } from 'i18n/i18n-react';
|
||||
import { APNetworkStatus } from 'types';
|
||||
import { useRest } from 'utils';
|
||||
|
||||
export const apStatusHighlight = ({ status }: APStatus, theme: Theme) => {
|
||||
switch (status) {
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { FC, useContext } from 'react';
|
||||
import { Tab } from '@mui/material';
|
||||
import { useContext } from 'react';
|
||||
import { Navigate, Routes, Route } from 'react-router-dom';
|
||||
|
||||
import { Tab } from '@mui/material';
|
||||
|
||||
import { AuthenticatedContext } from 'contexts/authentication';
|
||||
import APStatusForm from './APStatusForm';
|
||||
import APSettingsForm from './APSettingsForm';
|
||||
import APStatusForm from './APStatusForm';
|
||||
import type { FC } from 'react';
|
||||
import { RequireAdmin, RouterTabs, useLayoutTitle, useRouterTab } from 'components';
|
||||
import { AuthenticatedContext } from 'contexts/authentication';
|
||||
|
||||
import { useI18nContext } from 'i18n/i18n-react';
|
||||
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
import { FC, useContext } from 'react';
|
||||
import { Navigate, Route, Routes } from 'react-router-dom';
|
||||
|
||||
import { Tab } from '@mui/material';
|
||||
import { useContext } from 'react';
|
||||
import { Navigate, Route, Routes } from 'react-router-dom';
|
||||
import MqttSettingsForm from './MqttSettingsForm';
|
||||
import MqttStatusForm from './MqttStatusForm';
|
||||
import type { FC } from 'react';
|
||||
|
||||
import { RequireAdmin, RouterTabs, useLayoutTitle, useRouterTab } from 'components';
|
||||
import { AuthenticatedContext } from 'contexts/authentication';
|
||||
|
||||
import MqttStatusForm from './MqttStatusForm';
|
||||
import MqttSettingsForm from './MqttSettingsForm';
|
||||
|
||||
import { useI18nContext } from 'i18n/i18n-react';
|
||||
|
||||
const Mqtt: FC = () => {
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { FC, useState } from 'react';
|
||||
import { ValidateFieldsError } from 'async-validator';
|
||||
|
||||
import { Button, Checkbox, MenuItem, Grid, Typography, InputAdornment } from '@mui/material';
|
||||
|
||||
import WarningIcon from '@mui/icons-material/Warning';
|
||||
import CancelIcon from '@mui/icons-material/Cancel';
|
||||
import WarningIcon from '@mui/icons-material/Warning';
|
||||
import { Button, Checkbox, MenuItem, Grid, Typography, InputAdornment } from '@mui/material';
|
||||
import { useState } from 'react';
|
||||
import type { ValidateFieldsError } from 'async-validator';
|
||||
import type { FC } from 'react';
|
||||
|
||||
import { createMqttSettingsValidator, validate } from 'validators';
|
||||
import type { MqttSettings } from 'types';
|
||||
import * as MqttApi from 'api/mqtt';
|
||||
import {
|
||||
BlockFormControlLabel,
|
||||
ButtonRow,
|
||||
@@ -16,11 +16,10 @@ import {
|
||||
ValidatedTextField,
|
||||
BlockNavigation
|
||||
} from 'components';
|
||||
import { MqttSettings } from 'types';
|
||||
import { numberValue, updateValueDirty, useRest } from 'utils';
|
||||
import * as MqttApi from 'api/mqtt';
|
||||
|
||||
import { useI18nContext } from 'i18n/i18n-react';
|
||||
import { numberValue, updateValueDirty, useRest } from 'utils';
|
||||
|
||||
import { createMqttSettingsValidator, validate } from 'validators';
|
||||
|
||||
const MqttSettingsForm: FC = () => {
|
||||
const { loadData, saving, data, setData, origData, dirtyFlags, setDirtyFlags, blocker, saveData, errorMessage } =
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
import { FC } from 'react';
|
||||
import { Avatar, Button, Divider, List, ListItem, ListItemAvatar, ListItemText, Theme, useTheme } from '@mui/material';
|
||||
|
||||
import AutoAwesomeMotionIcon from '@mui/icons-material/AutoAwesomeMotion';
|
||||
import DeviceHubIcon from '@mui/icons-material/DeviceHub';
|
||||
import RefreshIcon from '@mui/icons-material/Refresh';
|
||||
import ReportIcon from '@mui/icons-material/Report';
|
||||
import SpeakerNotesOffIcon from '@mui/icons-material/SpeakerNotesOff';
|
||||
import AutoAwesomeMotionIcon from '@mui/icons-material/AutoAwesomeMotion';
|
||||
import { Avatar, Button, Divider, List, ListItem, ListItemAvatar, ListItemText, useTheme } from '@mui/material';
|
||||
import type { Theme } from '@mui/material';
|
||||
import type { FC } from 'react';
|
||||
|
||||
import { ButtonRow, FormLoader, SectionContent } from 'components';
|
||||
import { MqttStatus, MqttDisconnectReason } from 'types';
|
||||
import type { MqttStatus } from 'types';
|
||||
import * as MqttApi from 'api/mqtt';
|
||||
import { useRest } from 'utils';
|
||||
|
||||
import { ButtonRow, FormLoader, SectionContent } from 'components';
|
||||
import { useI18nContext } from 'i18n/i18n-react';
|
||||
import { MqttDisconnectReason } from 'types';
|
||||
import { useRest } from 'utils';
|
||||
|
||||
export const mqttStatusHighlight = ({ enabled, connected }: MqttStatus, theme: Theme) => {
|
||||
if (!enabled) {
|
||||
@@ -83,50 +83,48 @@ const MqttStatusForm: FC = () => {
|
||||
return <FormLoader onRetry={loadData} errorMessage={errorMessage} />;
|
||||
}
|
||||
|
||||
const renderConnectionStatus = () => {
|
||||
return (
|
||||
<>
|
||||
{!data.connected && (
|
||||
<>
|
||||
<ListItem>
|
||||
<ListItemAvatar>
|
||||
<Avatar>
|
||||
<ReportIcon />
|
||||
</Avatar>
|
||||
</ListItemAvatar>
|
||||
<ListItemText primary={LL.DISCONNECT_REASON()} secondary={disconnectReason(data)} />
|
||||
</ListItem>
|
||||
<Divider variant="inset" component="li" />
|
||||
</>
|
||||
)}
|
||||
<ListItem>
|
||||
<ListItemAvatar>
|
||||
<Avatar>#</Avatar>
|
||||
</ListItemAvatar>
|
||||
<ListItemText primary={LL.ID_OF(LL.CLIENT())} secondary={data.client_id} />
|
||||
</ListItem>
|
||||
<Divider variant="inset" component="li" />
|
||||
<ListItem>
|
||||
<ListItemAvatar>
|
||||
<Avatar sx={{ bgcolor: mqttQueueHighlight(data, theme) }}>
|
||||
<AutoAwesomeMotionIcon />
|
||||
</Avatar>
|
||||
</ListItemAvatar>
|
||||
<ListItemText primary={LL.MQTT_QUEUE()} secondary={data.mqtt_queued} />
|
||||
</ListItem>
|
||||
<Divider variant="inset" component="li" />
|
||||
<ListItem>
|
||||
<ListItemAvatar>
|
||||
<Avatar sx={{ bgcolor: mqttPublishHighlight(data, theme) }}>
|
||||
<SpeakerNotesOffIcon />
|
||||
</Avatar>
|
||||
</ListItemAvatar>
|
||||
<ListItemText primary={LL.ERRORS_OF('MQTT')} secondary={data.mqtt_fails} />
|
||||
</ListItem>
|
||||
<Divider variant="inset" component="li" />
|
||||
</>
|
||||
);
|
||||
};
|
||||
const renderConnectionStatus = () => (
|
||||
<>
|
||||
{!data.connected && (
|
||||
<>
|
||||
<ListItem>
|
||||
<ListItemAvatar>
|
||||
<Avatar>
|
||||
<ReportIcon />
|
||||
</Avatar>
|
||||
</ListItemAvatar>
|
||||
<ListItemText primary={LL.DISCONNECT_REASON()} secondary={disconnectReason(data)} />
|
||||
</ListItem>
|
||||
<Divider variant="inset" component="li" />
|
||||
</>
|
||||
)}
|
||||
<ListItem>
|
||||
<ListItemAvatar>
|
||||
<Avatar>#</Avatar>
|
||||
</ListItemAvatar>
|
||||
<ListItemText primary={LL.ID_OF(LL.CLIENT())} secondary={data.client_id} />
|
||||
</ListItem>
|
||||
<Divider variant="inset" component="li" />
|
||||
<ListItem>
|
||||
<ListItemAvatar>
|
||||
<Avatar sx={{ bgcolor: mqttQueueHighlight(data, theme) }}>
|
||||
<AutoAwesomeMotionIcon />
|
||||
</Avatar>
|
||||
</ListItemAvatar>
|
||||
<ListItemText primary={LL.MQTT_QUEUE()} secondary={data.mqtt_queued} />
|
||||
</ListItem>
|
||||
<Divider variant="inset" component="li" />
|
||||
<ListItem>
|
||||
<ListItemAvatar>
|
||||
<Avatar sx={{ bgcolor: mqttPublishHighlight(data, theme) }}>
|
||||
<SpeakerNotesOffIcon />
|
||||
</Avatar>
|
||||
</ListItemAvatar>
|
||||
<ListItemText primary={LL.ERRORS_OF('MQTT')} secondary={data.mqtt_fails} />
|
||||
</ListItem>
|
||||
<Divider variant="inset" component="li" />
|
||||
</>
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
|
||||
@@ -1,16 +1,15 @@
|
||||
import { FC, useCallback, useContext, useState } from 'react';
|
||||
import { Navigate, Routes, Route, useNavigate } from 'react-router-dom';
|
||||
|
||||
import { Tab } from '@mui/material';
|
||||
|
||||
import { RequireAdmin, RouterTabs, useLayoutTitle, useRouterTab } from 'components';
|
||||
import { WiFiNetwork } from 'types';
|
||||
import { AuthenticatedContext } from 'contexts/authentication';
|
||||
import { WiFiConnectionContext } from './WiFiConnectionContext';
|
||||
import NetworkStatusForm from './NetworkStatusForm';
|
||||
import WiFiNetworkScanner from './WiFiNetworkScanner';
|
||||
import { useCallback, useContext, useState } from 'react';
|
||||
import { Navigate, Routes, Route, useNavigate } from 'react-router-dom';
|
||||
import NetworkSettingsForm from './NetworkSettingsForm';
|
||||
import NetworkStatusForm from './NetworkStatusForm';
|
||||
import { WiFiConnectionContext } from './WiFiConnectionContext';
|
||||
import WiFiNetworkScanner from './WiFiNetworkScanner';
|
||||
import type { FC } from 'react';
|
||||
|
||||
import type { WiFiNetwork } from 'types';
|
||||
import { RequireAdmin, RouterTabs, useLayoutTitle, useRouterTab } from 'components';
|
||||
import { AuthenticatedContext } from 'contexts/authentication';
|
||||
import { useI18nContext } from 'i18n/i18n-react';
|
||||
|
||||
const NetworkConnection: FC = () => {
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import { FC, useContext, useEffect, useState } from 'react';
|
||||
import { toast } from 'react-toastify';
|
||||
|
||||
import CancelIcon from '@mui/icons-material/Cancel';
|
||||
import DeleteIcon from '@mui/icons-material/Delete';
|
||||
import LockIcon from '@mui/icons-material/Lock';
|
||||
import LockOpenIcon from '@mui/icons-material/LockOpen';
|
||||
import PowerSettingsNewIcon from '@mui/icons-material/PowerSettingsNew';
|
||||
import WarningIcon from '@mui/icons-material/Warning';
|
||||
import {
|
||||
Avatar,
|
||||
Button,
|
||||
@@ -14,14 +17,14 @@ import {
|
||||
Typography,
|
||||
InputAdornment
|
||||
} from '@mui/material';
|
||||
import { useContext, useEffect, useState } from 'react';
|
||||
import { toast } from 'react-toastify';
|
||||
import type { FC} from 'react';
|
||||
|
||||
import LockOpenIcon from '@mui/icons-material/LockOpen';
|
||||
import DeleteIcon from '@mui/icons-material/Delete';
|
||||
import WarningIcon from '@mui/icons-material/Warning';
|
||||
import LockIcon from '@mui/icons-material/Lock';
|
||||
import PowerSettingsNewIcon from '@mui/icons-material/PowerSettingsNew';
|
||||
import CancelIcon from '@mui/icons-material/Cancel';
|
||||
|
||||
|
||||
import type { NetworkSettings } from 'types';
|
||||
import * as NetworkApi from 'api/network';
|
||||
import {
|
||||
BlockFormControlLabel,
|
||||
ButtonRow,
|
||||
@@ -32,18 +35,16 @@ import {
|
||||
MessageBox,
|
||||
BlockNavigation
|
||||
} from 'components';
|
||||
import { NetworkSettings } from 'types';
|
||||
import * as NetworkApi from 'api/network';
|
||||
import { numberValue, updateValueDirty, useRest } from 'utils';
|
||||
import { useI18nContext } from 'i18n/i18n-react';
|
||||
import * as EMSESP from 'project/api';
|
||||
import { numberValue, updateValueDirty, useRest } from 'utils';
|
||||
|
||||
import { WiFiConnectionContext } from './WiFiConnectionContext';
|
||||
import { isNetworkOpen, networkSecurityMode } from './WiFiNetworkSelector';
|
||||
import { ValidateFieldsError } from 'async-validator';
|
||||
import type { ValidateFieldsError } from 'async-validator';
|
||||
import { validate } from 'validators';
|
||||
import { createNetworkSettingsValidator } from 'validators/network';
|
||||
|
||||
import { useI18nContext } from 'i18n/i18n-react';
|
||||
import RestartMonitor from '../system/RestartMonitor';
|
||||
|
||||
const WiFiSettingsForm: FC = () => {
|
||||
|
||||
@@ -1,20 +1,21 @@
|
||||
import { FC } from 'react';
|
||||
import { Avatar, Button, Divider, List, ListItem, ListItemAvatar, ListItemText, Theme, useTheme } from '@mui/material';
|
||||
|
||||
import SettingsInputComponentIcon from '@mui/icons-material/SettingsInputComponent';
|
||||
import SettingsInputAntennaIcon from '@mui/icons-material/SettingsInputAntenna';
|
||||
import DeviceHubIcon from '@mui/icons-material/DeviceHub';
|
||||
import WifiIcon from '@mui/icons-material/Wifi';
|
||||
import DnsIcon from '@mui/icons-material/Dns';
|
||||
import RefreshIcon from '@mui/icons-material/Refresh';
|
||||
import RouterIcon from '@mui/icons-material/Router';
|
||||
import SettingsInputAntennaIcon from '@mui/icons-material/SettingsInputAntenna';
|
||||
import SettingsInputComponentIcon from '@mui/icons-material/SettingsInputComponent';
|
||||
import WifiIcon from '@mui/icons-material/Wifi';
|
||||
import { Avatar, Button, Divider, List, ListItem, ListItemAvatar, ListItemText, useTheme } from '@mui/material';
|
||||
import type { Theme } from '@mui/material';
|
||||
import type { FC } from 'react';
|
||||
|
||||
import { ButtonRow, FormLoader, SectionContent } from 'components';
|
||||
import { NetworkConnectionStatus, NetworkStatus } from 'types';
|
||||
import type { NetworkStatus } from 'types';
|
||||
import * as NetworkApi from 'api/network';
|
||||
import { useRest } from 'utils';
|
||||
import { ButtonRow, FormLoader, SectionContent } from 'components';
|
||||
|
||||
import { useI18nContext } from 'i18n/i18n-react';
|
||||
import { NetworkConnectionStatus } from 'types';
|
||||
import { useRest } from 'utils';
|
||||
|
||||
const isConnected = ({ status }: NetworkStatus) =>
|
||||
status === NetworkConnectionStatus.WIFI_STATUS_CONNECTED ||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { createContext } from 'react';
|
||||
import { WiFiNetwork } from 'types';
|
||||
import type { WiFiNetwork } from 'types';
|
||||
|
||||
export interface WiFiConnectionContextValue {
|
||||
selectedNetwork?: WiFiNetwork;
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
import { useEffect, FC, useState, useCallback, useRef } from 'react';
|
||||
import PermScanWifiIcon from '@mui/icons-material/PermScanWifi';
|
||||
import { Button } from '@mui/material';
|
||||
import { useEffect, useState, useCallback, useRef } from 'react';
|
||||
import { toast } from 'react-toastify';
|
||||
|
||||
import { Button } from '@mui/material';
|
||||
import PermScanWifiIcon from '@mui/icons-material/PermScanWifi';
|
||||
|
||||
import * as NetworkApi from 'api/network';
|
||||
import { WiFiNetwork, WiFiNetworkList } from 'types';
|
||||
import { ButtonRow, FormLoader, SectionContent } from 'components';
|
||||
|
||||
import WiFiNetworkSelector from './WiFiNetworkSelector';
|
||||
import type { FC } from 'react';
|
||||
import type { WiFiNetwork, WiFiNetworkList } from 'types';
|
||||
import * as NetworkApi from 'api/network';
|
||||
import { ButtonRow, FormLoader, SectionContent } from 'components';
|
||||
|
||||
import { useI18nContext } from 'i18n/i18n-react';
|
||||
|
||||
|
||||
@@ -1,18 +1,16 @@
|
||||
import { FC, useContext } from 'react';
|
||||
|
||||
import { Avatar, Badge, List, ListItem, ListItemAvatar, ListItemIcon, ListItemText } from '@mui/material';
|
||||
|
||||
import LockOpenIcon from '@mui/icons-material/LockOpen';
|
||||
import LockIcon from '@mui/icons-material/Lock';
|
||||
import LockOpenIcon from '@mui/icons-material/LockOpen';
|
||||
import WifiIcon from '@mui/icons-material/Wifi';
|
||||
|
||||
import { MessageBox } from 'components';
|
||||
|
||||
import { WiFiEncryptionType, WiFiNetwork, WiFiNetworkList } from 'types';
|
||||
import { Avatar, Badge, List, ListItem, ListItemAvatar, ListItemIcon, ListItemText } from '@mui/material';
|
||||
import { useContext } from 'react';
|
||||
|
||||
import { WiFiConnectionContext } from './WiFiConnectionContext';
|
||||
import type { FC } from 'react';
|
||||
import type { WiFiNetwork, WiFiNetworkList } from 'types';
|
||||
import { MessageBox } from 'components';
|
||||
|
||||
import { useI18nContext } from 'i18n/i18n-react';
|
||||
import { WiFiEncryptionType } from 'types';
|
||||
|
||||
interface WiFiNetworkSelectorProps {
|
||||
networkList: WiFiNetworkList;
|
||||
@@ -45,24 +43,22 @@ const WiFiNetworkSelector: FC<WiFiNetworkSelectorProps> = ({ networkList }) => {
|
||||
|
||||
const wifiConnectionContext = useContext(WiFiConnectionContext);
|
||||
|
||||
const renderNetwork = (network: WiFiNetwork) => {
|
||||
return (
|
||||
<ListItem key={network.bssid} onClick={() => wifiConnectionContext.selectNetwork(network)}>
|
||||
<ListItemAvatar>
|
||||
<Avatar>{isNetworkOpen(network) ? <LockOpenIcon /> : <LockIcon />}</Avatar>
|
||||
</ListItemAvatar>
|
||||
<ListItemText
|
||||
primary={network.ssid}
|
||||
secondary={'Security: ' + networkSecurityMode(network) + ', Ch: ' + network.channel}
|
||||
/>
|
||||
<ListItemIcon>
|
||||
<Badge badgeContent={network.rssi + 'db'}>
|
||||
<WifiIcon />
|
||||
</Badge>
|
||||
</ListItemIcon>
|
||||
</ListItem>
|
||||
);
|
||||
};
|
||||
const renderNetwork = (network: WiFiNetwork) => (
|
||||
<ListItem key={network.bssid} onClick={() => wifiConnectionContext.selectNetwork(network)}>
|
||||
<ListItemAvatar>
|
||||
<Avatar>{isNetworkOpen(network) ? <LockOpenIcon /> : <LockIcon />}</Avatar>
|
||||
</ListItemAvatar>
|
||||
<ListItemText
|
||||
primary={network.ssid}
|
||||
secondary={'Security: ' + networkSecurityMode(network) + ', Ch: ' + network.channel}
|
||||
/>
|
||||
<ListItemIcon>
|
||||
<Badge badgeContent={network.rssi + 'db'}>
|
||||
<WifiIcon />
|
||||
</Badge>
|
||||
</ListItemIcon>
|
||||
</ListItem>
|
||||
);
|
||||
|
||||
if (networkList.networks.length === 0) {
|
||||
return <MessageBox mt={2} mb={1} message={LL.NETWORK_NO_WIFI()} level="info" />;
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
import { FC, useState } from 'react';
|
||||
import { ValidateFieldsError } from 'async-validator';
|
||||
|
||||
import { Button, Checkbox, MenuItem } from '@mui/material';
|
||||
import WarningIcon from '@mui/icons-material/Warning';
|
||||
import CancelIcon from '@mui/icons-material/Cancel';
|
||||
import WarningIcon from '@mui/icons-material/Warning';
|
||||
import { Button, Checkbox, MenuItem } from '@mui/material';
|
||||
import { useState } from 'react';
|
||||
import { selectedTimeZone, timeZoneSelectItems, TIME_ZONES } from './TZ';
|
||||
import type { ValidateFieldsError } from 'async-validator';
|
||||
import type { FC } from 'react';
|
||||
|
||||
import { validate } from 'validators';
|
||||
import type { NTPSettings } from 'types';
|
||||
import * as NTPApi from 'api/ntp';
|
||||
import {
|
||||
BlockFormControlLabel,
|
||||
ButtonRow,
|
||||
@@ -14,13 +16,10 @@ import {
|
||||
ValidatedTextField,
|
||||
BlockNavigation
|
||||
} from 'components';
|
||||
import { NTPSettings } from 'types';
|
||||
import { updateValueDirty, useRest } from 'utils';
|
||||
import * as NTPApi from 'api/ntp';
|
||||
import { selectedTimeZone, timeZoneSelectItems, TIME_ZONES } from './TZ';
|
||||
import { NTP_SETTINGS_VALIDATOR } from 'validators/ntp';
|
||||
|
||||
import { useI18nContext } from 'i18n/i18n-react';
|
||||
import { updateValueDirty, useRest } from 'utils';
|
||||
import { validate } from 'validators';
|
||||
import { NTP_SETTINGS_VALIDATOR } from 'validators/ntp';
|
||||
|
||||
const NTPSettingsForm: FC = () => {
|
||||
const { loadData, saving, data, setData, origData, dirtyFlags, setDirtyFlags, blocker, saveData, errorMessage } =
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import { FC, useContext, useState } from 'react';
|
||||
import { toast } from 'react-toastify';
|
||||
|
||||
import AccessTimeIcon from '@mui/icons-material/AccessTime';
|
||||
import CancelIcon from '@mui/icons-material/Cancel';
|
||||
import DnsIcon from '@mui/icons-material/Dns';
|
||||
import RefreshIcon from '@mui/icons-material/Refresh';
|
||||
import SwapVerticalCircleIcon from '@mui/icons-material/SwapVerticalCircle';
|
||||
import UpdateIcon from '@mui/icons-material/Update';
|
||||
import {
|
||||
Avatar,
|
||||
Box,
|
||||
@@ -15,24 +18,22 @@ import {
|
||||
ListItemAvatar,
|
||||
ListItemText,
|
||||
TextField,
|
||||
Theme,
|
||||
useTheme,
|
||||
Typography
|
||||
} from '@mui/material';
|
||||
import RefreshIcon from '@mui/icons-material/Refresh';
|
||||
import AccessTimeIcon from '@mui/icons-material/AccessTime';
|
||||
import SwapVerticalCircleIcon from '@mui/icons-material/SwapVerticalCircle';
|
||||
import UpdateIcon from '@mui/icons-material/Update';
|
||||
import DnsIcon from '@mui/icons-material/Dns';
|
||||
import CancelIcon from '@mui/icons-material/Cancel';
|
||||
import { useContext, useState } from 'react';
|
||||
import { toast } from 'react-toastify';
|
||||
import type { Theme } from '@mui/material';
|
||||
import type { FC } from 'react';
|
||||
|
||||
import type { NTPStatus } from 'types';
|
||||
import * as NTPApi from 'api/ntp';
|
||||
import { NTPStatus, NTPSyncStatus } from 'types';
|
||||
import { ButtonRow, FormLoader, SectionContent } from 'components';
|
||||
import { extractErrorMessage, formatDateTime, formatLocalDateTime, useRest } from 'utils';
|
||||
import { AuthenticatedContext } from 'contexts/authentication';
|
||||
|
||||
import { useI18nContext } from 'i18n/i18n-react';
|
||||
import { NTPSyncStatus } from 'types';
|
||||
import { extractErrorMessage, formatDateTime, formatLocalDateTime, useRest } from 'utils';
|
||||
|
||||
export const isNtpActive = ({ status }: NTPStatus) => status === NTPSyncStatus.NTP_ACTIVE;
|
||||
export const isNtpEnabled = ({ status }: NTPStatus) => status !== NTPSyncStatus.NTP_DISABLED;
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
import { FC, useContext } from 'react';
|
||||
import { Navigate, Route, Routes } from 'react-router-dom';
|
||||
|
||||
import { Tab } from '@mui/material';
|
||||
import { useContext } from 'react';
|
||||
import { Navigate, Route, Routes } from 'react-router-dom';
|
||||
import NTPSettingsForm from './NTPSettingsForm';
|
||||
import NTPStatusForm from './NTPStatusForm';
|
||||
import type { FC } from 'react';
|
||||
|
||||
import { RequireAdmin, RouterTabs, useLayoutTitle, useRouterTab } from 'components';
|
||||
import { AuthenticatedContext } from 'contexts/authentication';
|
||||
|
||||
import NTPStatusForm from './NTPStatusForm';
|
||||
import NTPSettingsForm from './NTPSettingsForm';
|
||||
|
||||
import { useI18nContext } from 'i18n/i18n-react';
|
||||
|
||||
const NetworkTime: FC = () => {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { FC, useCallback, useState, useEffect } from 'react';
|
||||
import CloseIcon from '@mui/icons-material/Close';
|
||||
import {
|
||||
Dialog,
|
||||
DialogTitle,
|
||||
@@ -10,16 +10,16 @@ import {
|
||||
TextField,
|
||||
Button
|
||||
} from '@mui/material';
|
||||
import { useCallback, useState, useEffect } from 'react';
|
||||
|
||||
import CloseIcon from '@mui/icons-material/Close';
|
||||
|
||||
import { extractErrorMessage } from 'utils';
|
||||
import { toast } from 'react-toastify';
|
||||
import { MessageBox } from 'components';
|
||||
import type { FC } from 'react';
|
||||
import type { Token } from 'types';
|
||||
import * as SecurityApi from 'api/security';
|
||||
import { Token } from 'types';
|
||||
import { MessageBox } from 'components';
|
||||
|
||||
import { useI18nContext } from 'i18n/i18n-react';
|
||||
import { extractErrorMessage } from 'utils';
|
||||
|
||||
interface GenerateTokenProps {
|
||||
username?: string;
|
||||
|
||||
@@ -1,28 +1,26 @@
|
||||
import { FC, useContext, useState } from 'react';
|
||||
|
||||
import { Button, IconButton, Box } from '@mui/material';
|
||||
import SaveIcon from '@mui/icons-material/Save';
|
||||
import DeleteIcon from '@mui/icons-material/Delete';
|
||||
import PersonAddIcon from '@mui/icons-material/PersonAdd';
|
||||
import EditIcon from '@mui/icons-material/Edit';
|
||||
import CheckIcon from '@mui/icons-material/Check';
|
||||
import CloseIcon from '@mui/icons-material/Close';
|
||||
import DeleteIcon from '@mui/icons-material/Delete';
|
||||
import EditIcon from '@mui/icons-material/Edit';
|
||||
import PersonAddIcon from '@mui/icons-material/PersonAdd';
|
||||
import SaveIcon from '@mui/icons-material/Save';
|
||||
import VpnKeyIcon from '@mui/icons-material/VpnKey';
|
||||
import { Button, IconButton, Box } from '@mui/material';
|
||||
|
||||
import { useTheme } from '@table-library/react-table-library/theme';
|
||||
import { Table, Header, HeaderRow, HeaderCell, Body, Row, Cell } from '@table-library/react-table-library/table';
|
||||
|
||||
import * as SecurityApi from 'api/security';
|
||||
import { SecuritySettings, User } from 'types';
|
||||
import { ButtonRow, FormLoader, MessageBox, SectionContent } from 'components';
|
||||
import { createUserValidator } from 'validators';
|
||||
import { useRest } from 'utils';
|
||||
import { AuthenticatedContext } from 'contexts/authentication';
|
||||
|
||||
import { useI18nContext } from 'i18n/i18n-react';
|
||||
import { useTheme } from '@table-library/react-table-library/theme';
|
||||
import { useContext, useState } from 'react';
|
||||
|
||||
import GenerateToken from './GenerateToken';
|
||||
import UserForm from './UserForm';
|
||||
import type { FC } from 'react';
|
||||
import type { SecuritySettings, User } from 'types';
|
||||
import * as SecurityApi from 'api/security';
|
||||
import { ButtonRow, FormLoader, MessageBox, SectionContent } from 'components';
|
||||
import { AuthenticatedContext } from 'contexts/authentication';
|
||||
import { useI18nContext } from 'i18n/i18n-react';
|
||||
import { useRest } from 'utils';
|
||||
import { createUserValidator } from 'validators';
|
||||
|
||||
const ManageUsersForm: FC = () => {
|
||||
const { loadData, saving, data, setData, saveData, errorMessage } = useRest<SecuritySettings>({
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
import { FC } from 'react';
|
||||
import { Navigate, Routes, Route } from 'react-router-dom';
|
||||
|
||||
import { Tab } from '@mui/material';
|
||||
import { Navigate, Routes, Route } from 'react-router-dom';
|
||||
import ManageUsersForm from './ManageUsersForm';
|
||||
import SecuritySettingsForm from './SecuritySettingsForm';
|
||||
import type { FC } from 'react';
|
||||
|
||||
import { RouterTabs, useRouterTab, useLayoutTitle } from 'components';
|
||||
|
||||
import SecuritySettingsForm from './SecuritySettingsForm';
|
||||
import ManageUsersForm from './ManageUsersForm';
|
||||
|
||||
import { useI18nContext } from 'i18n/i18n-react';
|
||||
|
||||
const Security: FC = () => {
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
import { FC, useContext, useState } from 'react';
|
||||
import { ValidateFieldsError } from 'async-validator';
|
||||
|
||||
import { Button } from '@mui/material';
|
||||
import WarningIcon from '@mui/icons-material/Warning';
|
||||
import CancelIcon from '@mui/icons-material/Cancel';
|
||||
import WarningIcon from '@mui/icons-material/Warning';
|
||||
import { Button } from '@mui/material';
|
||||
import { useContext, useState } from 'react';
|
||||
import type { ValidateFieldsError } from 'async-validator';
|
||||
import type { FC } from 'react';
|
||||
|
||||
import type { SecuritySettings } from 'types';
|
||||
import * as SecurityApi from 'api/security';
|
||||
import { SecuritySettings } from 'types';
|
||||
import { ButtonRow, FormLoader, MessageBox, SectionContent, ValidatedPasswordField, BlockNavigation } from 'components';
|
||||
import { SECURITY_SETTINGS_VALIDATOR, validate } from 'validators';
|
||||
import { updateValueDirty, useRest } from 'utils';
|
||||
import { AuthenticatedContext } from 'contexts/authentication';
|
||||
|
||||
import { useI18nContext } from 'i18n/i18n-react';
|
||||
import { updateValueDirty, useRest } from 'utils';
|
||||
import { SECURITY_SETTINGS_VALIDATOR, validate } from 'validators';
|
||||
|
||||
const SecuritySettingsForm: FC = () => {
|
||||
const { LL } = useI18nContext();
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
import { FC, useState, useEffect } from 'react';
|
||||
import Schema, { ValidateFieldsError } from 'async-validator';
|
||||
|
||||
import CancelIcon from '@mui/icons-material/Cancel';
|
||||
import PersonAddIcon from '@mui/icons-material/PersonAdd';
|
||||
import SaveIcon from '@mui/icons-material/Save';
|
||||
|
||||
import { Button, Checkbox, Dialog, DialogActions, DialogContent, DialogTitle } from '@mui/material';
|
||||
import { useState, useEffect } from 'react';
|
||||
import type Schema from 'async-validator';
|
||||
import type { ValidateFieldsError } from 'async-validator';
|
||||
import type { FC } from 'react';
|
||||
|
||||
import type { User } from 'types';
|
||||
import { BlockFormControlLabel, ValidatedPasswordField, ValidatedTextField } from 'components';
|
||||
import { User } from 'types';
|
||||
import { useI18nContext } from 'i18n/i18n-react';
|
||||
import { updateValue } from 'utils';
|
||||
import { validate } from 'validators';
|
||||
|
||||
import { useI18nContext } from 'i18n/i18n-react';
|
||||
|
||||
interface UserFormProps {
|
||||
creating: boolean;
|
||||
validator: Schema;
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import { FC, useState } from 'react';
|
||||
|
||||
import { Button, Checkbox } from '@mui/material';
|
||||
import WarningIcon from '@mui/icons-material/Warning';
|
||||
import CancelIcon from '@mui/icons-material/Cancel';
|
||||
import WarningIcon from '@mui/icons-material/Warning';
|
||||
import { Button, Checkbox } from '@mui/material';
|
||||
import { useState } from 'react';
|
||||
import type { ValidateFieldsError } from 'async-validator';
|
||||
import type { FC } from 'react';
|
||||
|
||||
import type { OTASettings } from 'types';
|
||||
import * as SystemApi from 'api/system';
|
||||
import {
|
||||
BlockFormControlLabel,
|
||||
@@ -15,15 +17,12 @@ import {
|
||||
BlockNavigation
|
||||
} from 'components';
|
||||
|
||||
import { OTASettings } from 'types';
|
||||
import { useI18nContext } from 'i18n/i18n-react';
|
||||
import { numberValue, updateValueDirty, useRest } from 'utils';
|
||||
|
||||
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, origData, dirtyFlags, setDirtyFlags, blocker, saveData, errorMessage } =
|
||||
useRest<OTASettings>({
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { FC, useRef, useState, useEffect } from 'react';
|
||||
import { useRef, useState, useEffect } from 'react';
|
||||
import type { FC } from 'react';
|
||||
|
||||
import * as SystemApi from 'api/system';
|
||||
import { FormLoader } from 'components';
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
import { FC, useContext } from 'react';
|
||||
import { Navigate, Routes, Route } from 'react-router-dom';
|
||||
|
||||
import { Tab } from '@mui/material';
|
||||
import { useContext } from 'react';
|
||||
import { Navigate, Routes, Route } from 'react-router-dom';
|
||||
import OTASettingsForm from './OTASettingsForm';
|
||||
import SystemLog from './SystemLog';
|
||||
import SystemStatusForm from './SystemStatusForm';
|
||||
import UploadFileForm from './UploadFileForm';
|
||||
import type { FC } from 'react';
|
||||
|
||||
import { useRouterTab, RouterTabs, useLayoutTitle, RequireAdmin } from 'components';
|
||||
import { AuthenticatedContext } from 'contexts/authentication';
|
||||
import UploadFileForm from './UploadFileForm';
|
||||
import SystemStatusForm from './SystemStatusForm';
|
||||
import OTASettingsForm from './OTASettingsForm';
|
||||
|
||||
import SystemLog from './SystemLog';
|
||||
|
||||
import { useI18nContext } from 'i18n/i18n-react';
|
||||
|
||||
|
||||
@@ -1,22 +1,19 @@
|
||||
import { FC, useState, useEffect, useCallback, useLayoutEffect } from 'react';
|
||||
|
||||
import DownloadIcon from '@mui/icons-material/GetApp';
|
||||
import { Box, styled, Button, Checkbox, MenuItem, Grid, Slider, FormLabel } from '@mui/material';
|
||||
import { useState, useEffect, useCallback, useLayoutEffect } from 'react';
|
||||
import { toast } from 'react-toastify';
|
||||
import type { FC } from 'react';
|
||||
|
||||
import * as SystemApi from 'api/system';
|
||||
import type { LogSettings, LogEntry, LogEntries } from 'types';
|
||||
import { addAccessTokenParameter } from 'api/authentication';
|
||||
import { EVENT_SOURCE_ROOT } from 'api/endpoints';
|
||||
import * as SystemApi from 'api/system';
|
||||
|
||||
import { SectionContent, FormLoader, BlockFormControlLabel, ValidatedTextField } from 'components';
|
||||
|
||||
import { LogSettings, LogEntry, LogEntries, LogLevel } from 'types';
|
||||
import { updateValue, useRest, extractErrorMessage } from 'utils';
|
||||
|
||||
import DownloadIcon from '@mui/icons-material/GetApp';
|
||||
|
||||
import { toast } from 'react-toastify';
|
||||
|
||||
import { EVENT_SOURCE_ROOT } from 'api/endpoints';
|
||||
|
||||
import { useI18nContext } from 'i18n/i18n-react';
|
||||
import { LogLevel } from 'types';
|
||||
import { updateValue, useRest, extractErrorMessage } from 'utils';
|
||||
|
||||
export const LOG_EVENTSOURCE_URL = EVENT_SOURCE_ROOT + 'log';
|
||||
|
||||
|
||||
@@ -1,5 +1,16 @@
|
||||
import { FC, useContext, useState, useEffect } from 'react';
|
||||
import { toast } from 'react-toastify';
|
||||
import AppsIcon from '@mui/icons-material/Apps';
|
||||
import RefreshIcon from '@mui/icons-material/Refresh';
|
||||
import PowerSettingsNewIcon from '@mui/icons-material/PowerSettingsNew';
|
||||
import SettingsBackupRestoreIcon from '@mui/icons-material/SettingsBackupRestore';
|
||||
import BuildIcon from '@mui/icons-material/Build';
|
||||
import TimerIcon from '@mui/icons-material/Timer';
|
||||
import CancelIcon from '@mui/icons-material/Cancel';
|
||||
import DevicesIcon from '@mui/icons-material/Devices';
|
||||
import FolderIcon from '@mui/icons-material/Folder';
|
||||
import MemoryIcon from '@mui/icons-material/Memory';
|
||||
import SdCardAlertIcon from '@mui/icons-material/SdCardAlert';
|
||||
import SdStorageIcon from '@mui/icons-material/SdStorage';
|
||||
import ShowChartIcon from '@mui/icons-material/ShowChart';
|
||||
import {
|
||||
Avatar,
|
||||
Box,
|
||||
@@ -17,31 +28,18 @@ import {
|
||||
Typography
|
||||
} from '@mui/material';
|
||||
|
||||
import DevicesIcon from '@mui/icons-material/Devices';
|
||||
import ShowChartIcon from '@mui/icons-material/ShowChart';
|
||||
import MemoryIcon from '@mui/icons-material/Memory';
|
||||
import AppsIcon from '@mui/icons-material/Apps';
|
||||
import SdStorageIcon from '@mui/icons-material/SdStorage';
|
||||
import SdCardAlertIcon from '@mui/icons-material/SdCardAlert';
|
||||
import FolderIcon from '@mui/icons-material/Folder';
|
||||
import RefreshIcon from '@mui/icons-material/Refresh';
|
||||
import PowerSettingsNewIcon from '@mui/icons-material/PowerSettingsNew';
|
||||
import SettingsBackupRestoreIcon from '@mui/icons-material/SettingsBackupRestore';
|
||||
import BuildIcon from '@mui/icons-material/Build';
|
||||
import TimerIcon from '@mui/icons-material/Timer';
|
||||
import CancelIcon from '@mui/icons-material/Cancel';
|
||||
|
||||
import { ButtonRow, FormLoader, SectionContent, MessageBox } from 'components';
|
||||
import { SystemStatus, Version } from 'types';
|
||||
import * as SystemApi from 'api/system';
|
||||
import { extractErrorMessage, useRest } from 'utils';
|
||||
|
||||
import { AuthenticatedContext } from 'contexts/authentication';
|
||||
|
||||
import axios from 'axios';
|
||||
import { useContext, useState, useEffect } from 'react';
|
||||
import { toast } from 'react-toastify';
|
||||
import RestartMonitor from './RestartMonitor';
|
||||
import type { FC } from 'react';
|
||||
|
||||
import { useI18nContext } from 'i18n/i18n-react';
|
||||
import type { SystemStatus, Version } from 'types';
|
||||
import * as SystemApi from 'api/system';
|
||||
import { ButtonRow, FormLoader, SectionContent, MessageBox } from 'components';
|
||||
import { AuthenticatedContext } from 'contexts/authentication';
|
||||
import { extractErrorMessage, useRest } from 'utils';
|
||||
|
||||
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';
|
||||
@@ -148,61 +146,59 @@ const SystemStatusForm: FC = () => {
|
||||
</Dialog>
|
||||
);
|
||||
|
||||
const renderVersionDialog = () => {
|
||||
return (
|
||||
<Dialog open={showingVersion} onClose={() => setShowingVersion(false)}>
|
||||
<DialogTitle>{LL.VERSION_CHECK(1)}</DialogTitle>
|
||||
<DialogContent dividers>
|
||||
<MessageBox my={0} level="info" message={LL.SYSTEM_VERSION_RUNNING() + ' ' + data?.emsesp_version} />
|
||||
{latestVersion && (
|
||||
<Box mt={2} mb={2}>
|
||||
{LL.THE_LATEST()} <u>{LL.OFFICIAL()}</u> {LL.VERSION_IS()} <b>{latestVersion.version}</b>
|
||||
(
|
||||
<Link target="_blank" href={latestVersion.changelog} color="primary">
|
||||
{LL.RELEASE_NOTES()}
|
||||
</Link>
|
||||
) (
|
||||
<Link target="_blank" href={latestVersion.url} color="primary">
|
||||
{LL.DOWNLOAD(1)}
|
||||
</Link>
|
||||
)
|
||||
</Box>
|
||||
)}
|
||||
|
||||
{latestDevVersion && (
|
||||
<Box mt={2} mb={2}>
|
||||
{LL.THE_LATEST()} <u>{LL.DEVELOPMENT()}</u> {LL.VERSION_IS()}
|
||||
<b>{latestDevVersion.version}</b>
|
||||
(
|
||||
<Link target="_blank" href={latestDevVersion.changelog} color="primary">
|
||||
{LL.RELEASE_NOTES()}
|
||||
</Link>
|
||||
) (
|
||||
<Link target="_blank" href={latestDevVersion.url} color="primary">
|
||||
{LL.DOWNLOAD(1)}
|
||||
</Link>
|
||||
)
|
||||
</Box>
|
||||
)}
|
||||
|
||||
<Box color="warning.main" p={0} pl={0} pr={0} mt={4} mb={0}>
|
||||
<Typography variant="body2">
|
||||
{LL.USE()}
|
||||
<Link href={uploadURL} color="primary">
|
||||
{LL.UPLOAD()}
|
||||
</Link>
|
||||
{LL.SYSTEM_APPLY_FIRMWARE()}
|
||||
</Typography>
|
||||
const renderVersionDialog = () => (
|
||||
<Dialog open={showingVersion} onClose={() => setShowingVersion(false)}>
|
||||
<DialogTitle>{LL.VERSION_CHECK(1)}</DialogTitle>
|
||||
<DialogContent dividers>
|
||||
<MessageBox my={0} level="info" message={LL.SYSTEM_VERSION_RUNNING() + ' ' + data?.emsesp_version} />
|
||||
{latestVersion && (
|
||||
<Box mt={2} mb={2}>
|
||||
{LL.THE_LATEST()} <u>{LL.OFFICIAL()}</u> {LL.VERSION_IS()} <b>{latestVersion.version}</b>
|
||||
(
|
||||
<Link target="_blank" href={latestVersion.changelog} color="primary">
|
||||
{LL.RELEASE_NOTES()}
|
||||
</Link>
|
||||
) (
|
||||
<Link target="_blank" href={latestVersion.url} color="primary">
|
||||
{LL.DOWNLOAD(1)}
|
||||
</Link>
|
||||
)
|
||||
</Box>
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button variant="outlined" onClick={() => setShowingVersion(false)} color="secondary">
|
||||
{LL.CLOSE()}
|
||||
</Button>
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
);
|
||||
};
|
||||
)}
|
||||
|
||||
{latestDevVersion && (
|
||||
<Box mt={2} mb={2}>
|
||||
{LL.THE_LATEST()} <u>{LL.DEVELOPMENT()}</u> {LL.VERSION_IS()}
|
||||
<b>{latestDevVersion.version}</b>
|
||||
(
|
||||
<Link target="_blank" href={latestDevVersion.changelog} color="primary">
|
||||
{LL.RELEASE_NOTES()}
|
||||
</Link>
|
||||
) (
|
||||
<Link target="_blank" href={latestDevVersion.url} color="primary">
|
||||
{LL.DOWNLOAD(1)}
|
||||
</Link>
|
||||
)
|
||||
</Box>
|
||||
)}
|
||||
|
||||
<Box color="warning.main" p={0} pl={0} pr={0} mt={4} mb={0}>
|
||||
<Typography variant="body2">
|
||||
{LL.USE()}
|
||||
<Link href={uploadURL} color="primary">
|
||||
{LL.UPLOAD()}
|
||||
</Link>
|
||||
{LL.SYSTEM_APPLY_FIRMWARE()}
|
||||
</Typography>
|
||||
</Box>
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button variant="outlined" onClick={() => setShowingVersion(false)} color="secondary">
|
||||
{LL.CLOSE()}
|
||||
</Button>
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
);
|
||||
|
||||
const factoryReset = async () => {
|
||||
setProcessing(true);
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { FC, useRef, useState } from 'react';
|
||||
import { useRef, useState } from 'react';
|
||||
import GeneralFileUpload from './GeneralFileUpload';
|
||||
import RestartMonitor from './RestartMonitor';
|
||||
import type { FileUploadConfig } from 'api/endpoints';
|
||||
import type { FC } from 'react';
|
||||
|
||||
import * as SystemApi from 'api/system';
|
||||
import { SectionContent } from 'components';
|
||||
import { FileUploadConfig } from 'api/endpoints';
|
||||
|
||||
import GeneralFileUpload from './GeneralFileUpload';
|
||||
import RestartMonitor from './RestartMonitor';
|
||||
|
||||
import { useI18nContext } from 'i18n/i18n-react';
|
||||
|
||||
|
||||
@@ -1,15 +1,13 @@
|
||||
import { FC } from 'react';
|
||||
import { Navigate, Route, Routes } from 'react-router-dom';
|
||||
|
||||
import { Tab } from '@mui/material';
|
||||
import { Navigate, Route, Routes } from 'react-router-dom';
|
||||
import DashboardData from './DashboardData';
|
||||
import DashboardStatus from './DashboardStatus';
|
||||
import type { FC } from 'react';
|
||||
|
||||
import { RouterTabs, useRouterTab, useLayoutTitle } from 'components';
|
||||
|
||||
import { useI18nContext } from 'i18n/i18n-react';
|
||||
|
||||
import DashboardStatus from './DashboardStatus';
|
||||
import DashboardData from './DashboardData';
|
||||
|
||||
const Dashboard: FC = () => {
|
||||
const { routerTab } = useRouterTab();
|
||||
|
||||
|
||||
@@ -1,42 +1,38 @@
|
||||
import { FC, useState, useContext, useEffect } from 'react';
|
||||
import { toast } from 'react-toastify';
|
||||
import CancelIcon from '@mui/icons-material/Cancel';
|
||||
import DeviceHubIcon from '@mui/icons-material/DeviceHub';
|
||||
import DirectionsBusIcon from '@mui/icons-material/DirectionsBus';
|
||||
import PermScanWifiIcon from '@mui/icons-material/PermScanWifi';
|
||||
import RefreshIcon from '@mui/icons-material/Refresh';
|
||||
import {
|
||||
Avatar,
|
||||
Button,
|
||||
List,
|
||||
ListItem,
|
||||
ListItemAvatar,
|
||||
ListItemText,
|
||||
Box,
|
||||
Button,
|
||||
Dialog,
|
||||
DialogActions,
|
||||
DialogContent,
|
||||
DialogTitle,
|
||||
Theme,
|
||||
List,
|
||||
ListItem,
|
||||
ListItemAvatar,
|
||||
ListItemText,
|
||||
useTheme
|
||||
} from '@mui/material';
|
||||
|
||||
import { Body, Cell, Header, HeaderCell, HeaderRow, Row, Table } from '@table-library/react-table-library/table';
|
||||
import { useTheme as tableTheme } from '@table-library/react-table-library/theme';
|
||||
import { Table, Header, HeaderRow, HeaderCell, Body, Row, Cell } from '@table-library/react-table-library/table';
|
||||
|
||||
import DeviceHubIcon from '@mui/icons-material/DeviceHub';
|
||||
import RefreshIcon from '@mui/icons-material/Refresh';
|
||||
import PermScanWifiIcon from '@mui/icons-material/PermScanWifi';
|
||||
import CancelIcon from '@mui/icons-material/Cancel';
|
||||
import DirectionsBusIcon from '@mui/icons-material/DirectionsBus';
|
||||
|
||||
import { AuthenticatedContext } from 'contexts/authentication';
|
||||
|
||||
import { ButtonRow, FormLoader, SectionContent } from 'components';
|
||||
|
||||
import { Status, busConnectionStatus, Stat } from './types';
|
||||
|
||||
import { extractErrorMessage, useRest } from 'utils';
|
||||
import { useContext, useEffect, useState } from 'react';
|
||||
import { toast } from 'react-toastify';
|
||||
|
||||
import * as EMSESP from './api';
|
||||
import { busConnectionStatus } from './types';
|
||||
import type { Stat, Status } from './types';
|
||||
import type { Theme } from '@mui/material';
|
||||
|
||||
import type { Translation } from 'i18n/i18n-types';
|
||||
import type { FC } from 'react';
|
||||
import { ButtonRow, FormLoader, SectionContent } from 'components';
|
||||
import { AuthenticatedContext } from 'contexts/authentication';
|
||||
import { useI18nContext } from 'i18n/i18n-react';
|
||||
import { extractErrorMessage, useRest } from 'utils';
|
||||
|
||||
export const isConnected = ({ status }: Status) => status !== busConnectionStatus.BUS_STATUS_OFFLINE;
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { FC } from 'react';
|
||||
|
||||
import { AiOutlineControl, AiOutlineGateway, AiOutlineAlert, AiOutlineChrome } from 'react-icons/ai';
|
||||
import { CgSmartHomeBoiler } from 'react-icons/cg';
|
||||
|
||||
import { FaSolarPanel } from 'react-icons/fa';
|
||||
import { MdThermostatAuto, MdOutlineSensors, MdOutlineExtension } from 'react-icons/md';
|
||||
import { GiHeatHaze } from 'react-icons/gi';
|
||||
import { MdThermostatAuto, MdOutlineSensors, MdOutlineExtension } from 'react-icons/md';
|
||||
import { TiFlowSwitch } from 'react-icons/ti';
|
||||
import { VscVmConnect } from 'react-icons/vsc';
|
||||
import { AiOutlineControl, AiOutlineGateway, AiOutlineAlert, AiOutlineChrome } from 'react-icons/ai';
|
||||
import type { FC } from 'react';
|
||||
|
||||
interface DeviceIconProps {
|
||||
type_id: number;
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
import { FC } from 'react';
|
||||
import { Navigate, Route, Routes } from 'react-router-dom';
|
||||
|
||||
import { Tab } from '@mui/material';
|
||||
import { Navigate, Route, Routes } from 'react-router-dom';
|
||||
import HelpInformation from './HelpInformation';
|
||||
import type { FC } from 'react';
|
||||
|
||||
import { RouterTabs, useRouterTab, useLayoutTitle } from 'components';
|
||||
|
||||
import { useI18nContext } from 'i18n/i18n-react';
|
||||
|
||||
import HelpInformation from './HelpInformation';
|
||||
|
||||
const Help: FC = () => {
|
||||
const { LL } = useI18nContext();
|
||||
const { routerTab } = useRouterTab();
|
||||
|
||||
@@ -1,22 +1,17 @@
|
||||
import { FC } from 'react';
|
||||
|
||||
import CommentIcon from '@mui/icons-material/CommentTwoTone';
|
||||
import EastIcon from '@mui/icons-material/East';
|
||||
import DownloadIcon from '@mui/icons-material/GetApp';
|
||||
import GitHubIcon from '@mui/icons-material/GitHub';
|
||||
import MenuBookIcon from '@mui/icons-material/MenuBookTwoTone';
|
||||
import { Typography, Button, Box, List, ListItem, ListItemText, Link, ListItemAvatar } from '@mui/material';
|
||||
import { toast } from 'react-toastify';
|
||||
import * as EMSESP from './api';
|
||||
import type { FC } from 'react';
|
||||
|
||||
import { SectionContent } from 'components';
|
||||
|
||||
import { toast } from 'react-toastify';
|
||||
|
||||
import CommentIcon from '@mui/icons-material/CommentTwoTone';
|
||||
import MenuBookIcon from '@mui/icons-material/MenuBookTwoTone';
|
||||
import GitHubIcon from '@mui/icons-material/GitHub';
|
||||
import DownloadIcon from '@mui/icons-material/GetApp';
|
||||
import EastIcon from '@mui/icons-material/East';
|
||||
|
||||
import { extractErrorMessage } from 'utils';
|
||||
|
||||
import { useI18nContext } from 'i18n/i18n-react';
|
||||
|
||||
import * as EMSESP from './api';
|
||||
import { extractErrorMessage } from 'utils';
|
||||
|
||||
const HelpInformation: FC = () => {
|
||||
const { LL } = useI18nContext();
|
||||
|
||||
@@ -1,20 +1,18 @@
|
||||
import { FC } from 'react';
|
||||
import { SvgIconProps } from '@mui/material';
|
||||
|
||||
import EditOutlinedIcon from '@mui/icons-material/EditOutlined';
|
||||
import CommentsDisabledOutlinedIcon from '@mui/icons-material/CommentsDisabledOutlined';
|
||||
import DeleteForeverIcon from '@mui/icons-material/DeleteForever';
|
||||
import DeleteOutlineIcon from '@mui/icons-material/DeleteOutline';
|
||||
import EditOffOutlinedIcon from '@mui/icons-material/EditOffOutlined';
|
||||
import EditOutlinedIcon from '@mui/icons-material/EditOutlined';
|
||||
|
||||
import InsertCommentOutlinedIcon from '@mui/icons-material/InsertCommentOutlined';
|
||||
import StarIcon from '@mui/icons-material/Star';
|
||||
import StarOutlineIcon from '@mui/icons-material/StarOutline';
|
||||
|
||||
import VisibilityOffOutlinedIcon from '@mui/icons-material/VisibilityOffOutlined';
|
||||
import VisibilityOutlinedIcon from '@mui/icons-material/VisibilityOutlined';
|
||||
|
||||
import CommentsDisabledOutlinedIcon from '@mui/icons-material/CommentsDisabledOutlined';
|
||||
import InsertCommentOutlinedIcon from '@mui/icons-material/InsertCommentOutlined';
|
||||
|
||||
import DeleteOutlineIcon from '@mui/icons-material/DeleteOutline';
|
||||
import DeleteForeverIcon from '@mui/icons-material/DeleteForever';
|
||||
import type { SvgIconProps } from '@mui/material';
|
||||
import type { FC } from 'react';
|
||||
|
||||
type OptionType = 'deleted' | 'readonly' | 'web_exclude' | 'api_mqtt_exclude' | 'favorite';
|
||||
|
||||
|
||||
@@ -1,17 +1,16 @@
|
||||
import { FC, useState } from 'react';
|
||||
import { ValidateFieldsError } from 'async-validator';
|
||||
|
||||
import { toast } from 'react-toastify';
|
||||
|
||||
import { Box, Button, Checkbox, MenuItem, Grid, Typography, Divider, InputAdornment } from '@mui/material';
|
||||
|
||||
import WarningIcon from '@mui/icons-material/Warning';
|
||||
import CancelIcon from '@mui/icons-material/Cancel';
|
||||
import PowerSettingsNewIcon from '@mui/icons-material/PowerSettingsNew';
|
||||
import WarningIcon from '@mui/icons-material/Warning';
|
||||
import { Box, Button, Checkbox, MenuItem, Grid, Typography, Divider, InputAdornment } from '@mui/material';
|
||||
import { useState } from 'react';
|
||||
import { toast } from 'react-toastify';
|
||||
|
||||
import { validate } from 'validators';
|
||||
import * as EMSESP from './api';
|
||||
import { BOARD_PROFILES } from './types';
|
||||
import { createSettingsValidator } from './validators';
|
||||
|
||||
import type { Settings } from './types';
|
||||
import type { ValidateFieldsError } from 'async-validator';
|
||||
import type { FC } from 'react';
|
||||
import {
|
||||
SectionContent,
|
||||
FormLoader,
|
||||
@@ -21,13 +20,11 @@ import {
|
||||
MessageBox,
|
||||
BlockNavigation
|
||||
} from 'components';
|
||||
import { numberValue, extractErrorMessage, updateValueDirty, useRest } from 'utils';
|
||||
|
||||
import * as EMSESP from './api';
|
||||
import { Settings, BOARD_PROFILES } from './types';
|
||||
|
||||
import { useI18nContext } from 'i18n/i18n-react';
|
||||
import RestartMonitor from 'framework/system/RestartMonitor';
|
||||
import { useI18nContext } from 'i18n/i18n-react';
|
||||
import { numberValue, extractErrorMessage, updateValueDirty, useRest } from 'utils';
|
||||
import { validate } from 'validators';
|
||||
|
||||
export function boardProfileSelectItems() {
|
||||
return Object.keys(BOARD_PROFILES).map((code) => (
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
import { FC, useState, useEffect, useCallback } from 'react';
|
||||
|
||||
import { unstable_useBlocker as useBlocker } from 'react-router-dom';
|
||||
import CancelIcon from '@mui/icons-material/Cancel';
|
||||
import DoneIcon from '@mui/icons-material/Done';
|
||||
|
||||
import FilterListIcon from '@mui/icons-material/FilterList';
|
||||
import PowerSettingsNewIcon from '@mui/icons-material/PowerSettingsNew';
|
||||
import SearchIcon from '@mui/icons-material/Search';
|
||||
import SettingsBackupRestoreIcon from '@mui/icons-material/SettingsBackupRestore';
|
||||
import WarningIcon from '@mui/icons-material/Warning';
|
||||
import {
|
||||
Button,
|
||||
Typography,
|
||||
@@ -18,34 +22,24 @@ import {
|
||||
TextField,
|
||||
Link
|
||||
} from '@mui/material';
|
||||
|
||||
import { useTheme } from '@table-library/react-table-library/theme';
|
||||
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 { useState, useEffect, useCallback } from 'react';
|
||||
import { unstable_useBlocker as useBlocker } from 'react-router-dom';
|
||||
import { toast } from 'react-toastify';
|
||||
|
||||
import WarningIcon from '@mui/icons-material/Warning';
|
||||
import CancelIcon from '@mui/icons-material/Cancel';
|
||||
import DoneIcon from '@mui/icons-material/Done';
|
||||
|
||||
import SettingsBackupRestoreIcon from '@mui/icons-material/SettingsBackupRestore';
|
||||
import SearchIcon from '@mui/icons-material/Search';
|
||||
import FilterListIcon from '@mui/icons-material/FilterList';
|
||||
import PowerSettingsNewIcon from '@mui/icons-material/PowerSettingsNew';
|
||||
|
||||
import OptionIcon from './OptionIcon';
|
||||
|
||||
import { ButtonRow, FormLoader, ValidatedTextField, SectionContent, MessageBox, BlockNavigation } from 'components';
|
||||
|
||||
import * as EMSESP from './api';
|
||||
|
||||
import { extractErrorMessage, updateValue } from 'utils';
|
||||
|
||||
import { DeviceShort, Devices, DeviceEntity, DeviceEntityMask } from './types';
|
||||
|
||||
import { useI18nContext } from 'i18n/i18n-react';
|
||||
import { DeviceEntityMask } from './types';
|
||||
import type { DeviceShort, Devices, DeviceEntity } from './types';
|
||||
import type { FC } from 'react';
|
||||
import { ButtonRow, FormLoader, ValidatedTextField, SectionContent, MessageBox, BlockNavigation } from 'components';
|
||||
|
||||
import RestartMonitor from 'framework/system/RestartMonitor';
|
||||
import { useI18nContext } from 'i18n/i18n-react';
|
||||
import { extractErrorMessage, updateValue } from 'utils';
|
||||
|
||||
export const APIURL = window.location.origin + '/api/';
|
||||
|
||||
@@ -584,61 +578,59 @@ const SettingsCustomization: FC = () => {
|
||||
</Dialog>
|
||||
);
|
||||
|
||||
const renderContent = () => {
|
||||
return (
|
||||
<>
|
||||
<Typography sx={{ pt: 2, pb: 2 }} variant="h6" color="primary">
|
||||
{LL.DEVICE_ENTITIES()}
|
||||
</Typography>
|
||||
{renderDeviceList()}
|
||||
{renderDeviceData()}
|
||||
{restartNeeded && (
|
||||
<MessageBox my={2} level="warning" message={LL.RESTART_TEXT()}>
|
||||
<Button startIcon={<PowerSettingsNewIcon />} variant="contained" color="error" onClick={restart}>
|
||||
{LL.RESTART()}
|
||||
</Button>
|
||||
</MessageBox>
|
||||
)}
|
||||
{!restartNeeded && (
|
||||
<Box display="flex" flexWrap="wrap">
|
||||
<Box flexGrow={1}>
|
||||
{numChanges !== 0 && (
|
||||
<ButtonRow>
|
||||
<Button
|
||||
startIcon={<CancelIcon />}
|
||||
variant="outlined"
|
||||
color="secondary"
|
||||
onClick={() => devices && fetchDeviceEntities(devices.devices[selectedDevice].i)}
|
||||
>
|
||||
{LL.CANCEL()}
|
||||
</Button>
|
||||
<Button
|
||||
startIcon={<WarningIcon color="warning" />}
|
||||
variant="contained"
|
||||
color="info"
|
||||
onClick={() => saveCustomization()}
|
||||
>
|
||||
{LL.APPLY_CHANGES(numChanges)}
|
||||
</Button>
|
||||
</ButtonRow>
|
||||
)}
|
||||
</Box>
|
||||
<ButtonRow>
|
||||
<Button
|
||||
startIcon={<SettingsBackupRestoreIcon />}
|
||||
variant="outlined"
|
||||
color="error"
|
||||
onClick={() => setConfirmReset(true)}
|
||||
>
|
||||
{LL.RESET(0)}
|
||||
</Button>
|
||||
</ButtonRow>
|
||||
const renderContent = () => (
|
||||
<>
|
||||
<Typography sx={{ pt: 2, pb: 2 }} variant="h6" color="primary">
|
||||
{LL.DEVICE_ENTITIES()}
|
||||
</Typography>
|
||||
{renderDeviceList()}
|
||||
{renderDeviceData()}
|
||||
{restartNeeded && (
|
||||
<MessageBox my={2} level="warning" message={LL.RESTART_TEXT()}>
|
||||
<Button startIcon={<PowerSettingsNewIcon />} variant="contained" color="error" onClick={restart}>
|
||||
{LL.RESTART()}
|
||||
</Button>
|
||||
</MessageBox>
|
||||
)}
|
||||
{!restartNeeded && (
|
||||
<Box display="flex" flexWrap="wrap">
|
||||
<Box flexGrow={1}>
|
||||
{numChanges !== 0 && (
|
||||
<ButtonRow>
|
||||
<Button
|
||||
startIcon={<CancelIcon />}
|
||||
variant="outlined"
|
||||
color="secondary"
|
||||
onClick={() => devices && fetchDeviceEntities(devices.devices[selectedDevice].i)}
|
||||
>
|
||||
{LL.CANCEL()}
|
||||
</Button>
|
||||
<Button
|
||||
startIcon={<WarningIcon color="warning" />}
|
||||
variant="contained"
|
||||
color="info"
|
||||
onClick={() => saveCustomization()}
|
||||
>
|
||||
{LL.APPLY_CHANGES(numChanges)}
|
||||
</Button>
|
||||
</ButtonRow>
|
||||
)}
|
||||
</Box>
|
||||
)}
|
||||
{renderResetDialog()}
|
||||
</>
|
||||
);
|
||||
};
|
||||
<ButtonRow>
|
||||
<Button
|
||||
startIcon={<SettingsBackupRestoreIcon />}
|
||||
variant="outlined"
|
||||
color="error"
|
||||
onClick={() => setConfirmReset(true)}
|
||||
>
|
||||
{LL.RESET(0)}
|
||||
</Button>
|
||||
</ButtonRow>
|
||||
</Box>
|
||||
)}
|
||||
{renderResetDialog()}
|
||||
</>
|
||||
);
|
||||
|
||||
const renderEditDialog = () => {
|
||||
if (deviceEntity) {
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
import { AxiosPromise } from 'axios';
|
||||
import { AXIOS, AXIOS_API, AXIOS_BIN } from 'api/endpoints';
|
||||
|
||||
import {
|
||||
import type {
|
||||
BoardProfile,
|
||||
BoardProfileName,
|
||||
APIcall,
|
||||
@@ -20,6 +17,8 @@ import {
|
||||
Schedule,
|
||||
Entities
|
||||
} from './types';
|
||||
import type { AxiosPromise } from 'axios';
|
||||
import { AXIOS, AXIOS_API, AXIOS_BIN } from 'api/endpoints';
|
||||
|
||||
export function restart(): AxiosPromise<void> {
|
||||
return AXIOS.post('/restart');
|
||||
|
||||
@@ -8,10 +8,7 @@ const LOCALE_FORMAT = new Intl.DateTimeFormat([...window.navigator.languages], {
|
||||
hour12: false
|
||||
});
|
||||
|
||||
export const formatDateTime = (dateTime: string) => {
|
||||
return LOCALE_FORMAT.format(new Date(dateTime.substring(0, 19)));
|
||||
};
|
||||
export const formatDateTime = (dateTime: string) => LOCALE_FORMAT.format(new Date(dateTime.substring(0, 19)));
|
||||
|
||||
export const formatLocalDateTime = (date: Date) => {
|
||||
return new Date(date.getTime() - date.getTimezoneOffset() * 60000).toISOString().slice(0, -1).substring(0, 19);
|
||||
};
|
||||
export const formatLocalDateTime = (date: Date) =>
|
||||
new Date(date.getTime() - date.getTimezoneOffset() * 60000).toISOString().slice(0, -1).substring(0, 19);
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
import { useCallback, useEffect, useState } from 'react';
|
||||
import { unstable_useBlocker as useBlocker } from 'react-router-dom';
|
||||
import { toast } from 'react-toastify';
|
||||
|
||||
import { AxiosPromise } from 'axios';
|
||||
|
||||
import { extractErrorMessage } from '.';
|
||||
import type { AxiosPromise } from 'axios';
|
||||
|
||||
import { useI18nContext } from 'i18n/i18n-react';
|
||||
|
||||
import { unstable_useBlocker as useBlocker } from 'react-router-dom';
|
||||
|
||||
export interface RestRequestOptions<D> {
|
||||
read: () => AxiosPromise<D>;
|
||||
update?: (value: D) => AxiosPromise<D>;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { debounce } from 'lodash-es';
|
||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||
import Sockette from 'sockette';
|
||||
import { debounce } from 'lodash-es';
|
||||
|
||||
import { addAccessTokenParameter } from 'api/authentication';
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import Schema from 'async-validator';
|
||||
import { isAPEnabled } from 'framework/ap/APSettingsForm';
|
||||
import { APSettings } from 'types';
|
||||
import { IP_ADDRESS_VALIDATOR } from './shared';
|
||||
import type { APSettings } from 'types';
|
||||
import { isAPEnabled } from 'framework/ap/APSettingsForm';
|
||||
|
||||
export const createAPSettingsValidator = (apSettings: APSettings) =>
|
||||
new Schema({
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import Schema from 'async-validator';
|
||||
import { MqttSettings } from 'types';
|
||||
import { IP_OR_HOSTNAME_VALIDATOR } from './shared';
|
||||
import type { MqttSettings } from 'types';
|
||||
|
||||
export const createMqttSettingsValidator = (mqttSettings: MqttSettings) =>
|
||||
new Schema({
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import Schema from 'async-validator';
|
||||
import { NetworkSettings } from 'types';
|
||||
import { HOSTNAME_VALIDATOR, IP_ADDRESS_VALIDATOR } from './shared';
|
||||
import type { NetworkSettings } from 'types';
|
||||
|
||||
export const createNetworkSettingsValidator = (networkSettings: NetworkSettings) =>
|
||||
new Schema({
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import Schema, { InternalRuleItem } from 'async-validator';
|
||||
import { User } from 'types';
|
||||
import Schema from 'async-validator';
|
||||
import type { InternalRuleItem } from 'async-validator';
|
||||
import type { User } from 'types';
|
||||
|
||||
export const SECURITY_SETTINGS_VALIDATOR = new Schema({
|
||||
jwt_secret: [
|
||||
|
||||
Reference in New Issue
Block a user