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