mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2025-12-09 17:29:50 +03:00
replace React bunder based on webpack with Vite #952
This commit is contained in:
@@ -1,8 +0,0 @@
|
||||
# This enables lint extensions
|
||||
EXTEND_ESLINT=true
|
||||
|
||||
# This is the name of your project. It appears on the sign-in page and in the menu bar.
|
||||
REACT_APP_PROJECT_NAME=EMS-ESP
|
||||
|
||||
# This is the url path your project will be exposed under.
|
||||
REACT_APP_PROJECT_PATH=ems-esp
|
||||
@@ -1,3 +0,0 @@
|
||||
GENERATE_SOURCEMAP=false
|
||||
|
||||
REACT_APP_HOSTED=true
|
||||
@@ -1 +0,0 @@
|
||||
GENERATE_SOURCEMAP=false
|
||||
5
interface/.eslintignore
Normal file
5
interface/.eslintignore
Normal file
@@ -0,0 +1,5 @@
|
||||
node_modules/
|
||||
build/
|
||||
.prettierrc
|
||||
.eslintrc.js
|
||||
env.d.ts
|
||||
48
interface/.eslintrc.js
Normal file
48
interface/.eslintrc.js
Normal file
@@ -0,0 +1,48 @@
|
||||
module.exports = {
|
||||
plugins: ['react-refresh'],
|
||||
extends: [
|
||||
// By extending from a plugin config, we can get recommended rules without having to add them manually.
|
||||
'eslint:recommended',
|
||||
'plugin:react/recommended',
|
||||
'plugin:import/recommended',
|
||||
'plugin:import/typescript',
|
||||
'plugin:jsx-a11y/recommended',
|
||||
'plugin:@typescript-eslint/recommended',
|
||||
// 'plugin:react-refresh/recommended',
|
||||
// This disables the formatting rules in ESLint that Prettier is going to be responsible for handling.
|
||||
// Make sure it's always the last config, so it gets the chance to override other configs.
|
||||
'eslint-config-prettier'
|
||||
],
|
||||
settings: {
|
||||
react: {
|
||||
// Tells eslint-plugin-react to automatically detect the version of React to use.
|
||||
version: 'detect'
|
||||
},
|
||||
// Tells eslint how to resolve imports
|
||||
'import/resolver': {
|
||||
node: {
|
||||
paths: ['src'],
|
||||
extensions: ['.js', '.jsx', '.ts', '.tsx']
|
||||
},
|
||||
typescript: {
|
||||
alwaysTryTypes: true // always try to resolve types under `<root>@types` directory even it doesn't contain any source code, like `@types/unist`
|
||||
}
|
||||
}
|
||||
},
|
||||
parserOptions: {
|
||||
project: ['tsconfig.json'],
|
||||
createDefaultProgram: true
|
||||
},
|
||||
rules: {
|
||||
// Add your own rules here to override ones from the extended configs.
|
||||
'react/react-in-jsx-scope': 'off',
|
||||
'@typescript-eslint/no-explicit-any': 'off',
|
||||
'jsx-a11y/no-autofocus': 'off',
|
||||
'react-refresh/only-export-components': 'off',
|
||||
'no-console': 'warn',
|
||||
'react/prop-types': 'off',
|
||||
'react/self-closing-comp': 'warn',
|
||||
'@typescript-eslint/consistent-type-definitions': ['off', 'type'],
|
||||
'@typescript-eslint/explicit-function-return-type': 'off'
|
||||
}
|
||||
};
|
||||
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"singleQuote": true,
|
||||
"semi": true,
|
||||
"trailingComma": "none",
|
||||
"printWidth": 120
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"adapter": "react",
|
||||
"baseLocale": "pl",
|
||||
"$schema": "https://unpkg.com/typesafe-i18n@5.24.0/schema/typesafe-i18n.json"
|
||||
}
|
||||
"adapter": "react",
|
||||
"baseLocale": "pl",
|
||||
"$schema": "https://unpkg.com/typesafe-i18n@5.24.0/schema/typesafe-i18n.json"
|
||||
}
|
||||
|
||||
31
interface/.vscode
Normal file
31
interface/.vscode
Normal file
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"emmet.excludeLanguages": [],
|
||||
"emmet.includeLanguages": {
|
||||
"markdown": "html",
|
||||
"javascript": "javascriptreact",
|
||||
"typescript": "typescriptreact"
|
||||
},
|
||||
"emmet.showSuggestionsAsSnippets": true,
|
||||
"emmet.triggerExpansionOnTab": true,
|
||||
"files.exclude": {
|
||||
"**/*.js.map": {
|
||||
"when": "$(basename)"
|
||||
},
|
||||
"**/node_modules": true
|
||||
},
|
||||
"html.autoClosingTags": true,
|
||||
"javascript.autoClosingTags": true,
|
||||
"javascript.suggest.completeFunctionCalls": true,
|
||||
"typescript.suggest.completeFunctionCalls": true,
|
||||
"javascript.inlayHints.functionLikeReturnTypes.enabled": true,
|
||||
"typescript.inlayHints.functionLikeReturnTypes.enabled": true,
|
||||
"javascript.inlayHints.parameterNames.enabled": "all",
|
||||
"typescript.inlayHints.parameterNames.enabled": "all",
|
||||
"javascript.suggest.autoImports": true,
|
||||
"search.exclude": {
|
||||
"**/coverage": true,
|
||||
"**/node_modules": true
|
||||
},
|
||||
"typescript.autoClosingTags": true,
|
||||
"typescript.suggest.autoImports": true
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
const { WebpackManifestPlugin } = require('webpack-manifest-plugin');
|
||||
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
|
||||
const ProgmemGenerator = require('./progmem-generator.js');
|
||||
const TerserPlugin = require('terser-webpack-plugin');
|
||||
|
||||
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
|
||||
|
||||
module.exports = function override(config, env) {
|
||||
const hosted = process.env.REACT_APP_HOSTED;
|
||||
|
||||
if (env === 'production' && !hosted) {
|
||||
// rename the output file, we need it's path to be short, for embedded FS
|
||||
config.output.filename = 'js/[id].[chunkhash:4].js';
|
||||
config.output.chunkFilename = 'js/[id].[chunkhash:4].js';
|
||||
|
||||
// take out the manifest plugin
|
||||
config.plugins = config.plugins.filter((plugin) => !(plugin instanceof WebpackManifestPlugin));
|
||||
|
||||
// shorten css filenames
|
||||
const miniCssExtractPlugin = config.plugins.find((plugin) => plugin instanceof MiniCssExtractPlugin);
|
||||
miniCssExtractPlugin.options.filename = 'css/[id].[contenthash:4].css';
|
||||
miniCssExtractPlugin.options.chunkFilename = 'css/[id].[contenthash:4].c.css';
|
||||
|
||||
// don't emit license file
|
||||
const terserPlugin = config.optimization.minimizer.find((plugin) => plugin instanceof TerserPlugin);
|
||||
terserPlugin.options.extractComments = false;
|
||||
|
||||
// create size map
|
||||
// config.plugins.push(new BundleAnalyzerPlugin());
|
||||
|
||||
// build progmem data files
|
||||
config.plugins.push(new ProgmemGenerator({ outputPath: '../lib/framework/WWWData.h', bytesPerLine: 20 }));
|
||||
|
||||
|
||||
|
||||
}
|
||||
return config;
|
||||
};
|
||||
14
interface/index.html
Normal file
14
interface/index.html
Normal file
@@ -0,0 +1,14 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=0, maximum-scale=1, minimum-scale=1" />
|
||||
<link rel="stylesheet" href="/css/roboto.css" />
|
||||
<link rel="manifest" href="/app/manifest.json" />
|
||||
<title>EMS-ESP</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<script type="module" src="/src/index.tsx"></script>
|
||||
</body>
|
||||
</html>
|
||||
14262
interface/package-lock.json
generated
14262
interface/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -1,8 +1,18 @@
|
||||
{
|
||||
"name": "EMS-ESP",
|
||||
"version": "3.5.0",
|
||||
"version": "3.6.0",
|
||||
"private": true,
|
||||
"proxy": "http://localhost:3080",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "tsc && vite build",
|
||||
"preview": "vite preview",
|
||||
"preview_standalone": "npm-run-all -p preview typesafe-i18n mock-api",
|
||||
"mock-api": "nodemon --watch ../mock-api ../mock-api/server.js",
|
||||
"standalone": "npm-run-all -p dev typesafe-i18n mock-api",
|
||||
"typesafe-i18n": "typesafe-i18n",
|
||||
"format": "prettier --write '**/*.{ts,tsx,js,css,json,md}'",
|
||||
"lint": "eslint . --ext .ts,.tsx"
|
||||
},
|
||||
"dependencies": {
|
||||
"@emotion/react": "^11.10.5",
|
||||
"@emotion/styled": "^11.10.5",
|
||||
@@ -10,96 +20,47 @@
|
||||
"@mui/icons-material": "^5.11.0",
|
||||
"@mui/material": "^5.11.8",
|
||||
"@table-library/react-table-library": "4.0.24",
|
||||
"@types/lodash-es": "^4.17.6",
|
||||
"@types/node": "^18.13.0",
|
||||
"@types/react": "^18.0.27",
|
||||
"@types/react-dom": "^18.0.10",
|
||||
"@types/react-router-dom": "^5.3.3",
|
||||
"@types/lodash-es": "^4.17.6",
|
||||
"async-validator": "^4.2.5",
|
||||
"axios": "^1.3.2",
|
||||
"jwt-decode": "^3.1.2",
|
||||
"lodash-es": "^4.17.21",
|
||||
"notistack": "^2.0.8",
|
||||
"react": "^18.2.0",
|
||||
"react-app-rewired": "^2.2.1",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-dropzone": "^14.2.3",
|
||||
"react-icons": "^4.7.1",
|
||||
"react-router-dom": "^6.8.1",
|
||||
"react-scripts": "^5.0.1",
|
||||
"sockette": "^2.0.6",
|
||||
"typesafe-i18n": "^5.24.0",
|
||||
"typescript": "^4.9.5"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "react-app-rewired start",
|
||||
"build": "react-app-rewired build",
|
||||
"test": "react-app-rewired test",
|
||||
"eject": "react-scripts eject",
|
||||
"format": "prettier --write '**/*.{ts,tsx,js,css,json,md}'",
|
||||
"build-hosted": "env-cmd -f .env.hosted npm run build",
|
||||
"build-localhost": "PUBLIC_URL=/ react-app-rewired build",
|
||||
"mock-api": "nodemon --watch ../mock-api ../mock-api/server.js",
|
||||
"standalone": "npm-run-all -p start typesafe-i18n mock-api",
|
||||
"lint": "eslint . --ext .ts,.tsx",
|
||||
"typesafe-i18n": "typesafe-i18n"
|
||||
},
|
||||
"eslintConfig": {
|
||||
"extends": [
|
||||
"react-app",
|
||||
"react-app/jest"
|
||||
],
|
||||
"rules": {
|
||||
"eol-last": 1,
|
||||
"react/jsx-closing-bracket-location": 1,
|
||||
"react/jsx-closing-tag-location": 1,
|
||||
"react/jsx-wrap-multilines": 1,
|
||||
"react/jsx-curly-newline": 1,
|
||||
"no-multiple-empty-lines": [
|
||||
1,
|
||||
{
|
||||
"max": 1
|
||||
}
|
||||
],
|
||||
"no-trailing-spaces": 1,
|
||||
"semi": 1,
|
||||
"no-extra-semi": 1,
|
||||
"react/jsx-max-props-per-line": [
|
||||
1,
|
||||
{
|
||||
"when": "multiline"
|
||||
}
|
||||
],
|
||||
"react/jsx-first-prop-new-line": [
|
||||
1,
|
||||
"multiline"
|
||||
],
|
||||
"@typescript-eslint/no-shadow": 1,
|
||||
"max-len": [
|
||||
1,
|
||||
{
|
||||
"code": 220
|
||||
}
|
||||
],
|
||||
"arrow-parens": 1
|
||||
}
|
||||
},
|
||||
"browserslist": {
|
||||
"production": [
|
||||
">0.2%",
|
||||
"not dead",
|
||||
"not op_mini all"
|
||||
],
|
||||
"development": [
|
||||
"last 1 chrome version",
|
||||
"last 1 firefox version",
|
||||
"last 1 safari version"
|
||||
]
|
||||
},
|
||||
"devDependencies": {
|
||||
"http-proxy-middleware": "^2.0.6",
|
||||
"@typescript-eslint/eslint-plugin": "^5.51.0",
|
||||
"@typescript-eslint/parser": "^5.51.0",
|
||||
"@vitejs/plugin-react-swc": "^3.1.0",
|
||||
"babel-plugin-styled-components": "^2.0.7",
|
||||
"babel-plugin-transform-react-remove-prop-types": "^0.4.24",
|
||||
"eslint": "^8.33.0",
|
||||
"eslint-config-prettier": "^8.6.0",
|
||||
"eslint-import-resolver-typescript": "^3.5.3",
|
||||
"eslint-plugin-import": "^2.27.5",
|
||||
"eslint-plugin-jsx-a11y": "^6.7.1",
|
||||
"eslint-plugin-react": "^7.32.2",
|
||||
"eslint-plugin-react-refresh": "^0.3.3",
|
||||
"nodemon": "^2.0.20",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"webpack-bundle-analyzer": "^4.7.0"
|
||||
"prettier": "^2.8.4",
|
||||
"rollup-plugin-visualizer": "^5.9.0",
|
||||
"vite": "^4.1.1",
|
||||
"vite-plugin-svgr": "^2.4.0",
|
||||
"vite-tsconfig-paths": "^4.0.5",
|
||||
"@types/styled-components": "^5.1.26",
|
||||
"@swc/plugin-styled-components": "^1.5.41",
|
||||
"styled-components": "^5.3.6"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ var zlib = require('zlib');
|
||||
var mime = require('mime-types');
|
||||
|
||||
const ARDUINO_INCLUDES = '#include <Arduino.h>\n\n';
|
||||
const INDENT = ' ';
|
||||
|
||||
function getFilesSync(dir, files = []) {
|
||||
readdirSync(dir, { withFileTypes: true }).forEach((entry) => {
|
||||
@@ -28,17 +29,16 @@ function cleanAndOpen(path) {
|
||||
return createWriteStream(path, { flags: 'w+' });
|
||||
}
|
||||
|
||||
class ProgmemGenerator {
|
||||
constructor(options = {}) {
|
||||
const { outputPath, bytesPerLine = 20, indent = ' ', includes = ARDUINO_INCLUDES } = options;
|
||||
this.options = { outputPath, bytesPerLine, indent, includes };
|
||||
}
|
||||
|
||||
apply(compiler) {
|
||||
compiler.hooks.emit.tapAsync({ name: 'ProgmemGenerator' }, (compilation, callback) => {
|
||||
const { outputPath, bytesPerLine, indent, includes } = this.options;
|
||||
export default function ProgmemGenerator({ outputPath = './WWWData.h', bytesPerLine = 20 }) {
|
||||
return {
|
||||
name: 'ProgmemGenerator',
|
||||
writeBundle: () => {
|
||||
console.log('Generating ' + outputPath);
|
||||
const includes = ARDUINO_INCLUDES;
|
||||
const indent = INDENT;
|
||||
const fileInfo = [];
|
||||
const writeStream = cleanAndOpen(resolve(compilation.options.context, outputPath));
|
||||
const writeStream = cleanAndOpen(resolve(outputPath));
|
||||
|
||||
try {
|
||||
const writeIncludes = () => {
|
||||
writeStream.write(includes);
|
||||
@@ -73,17 +73,18 @@ class ProgmemGenerator {
|
||||
|
||||
const writeFiles = () => {
|
||||
// process static files
|
||||
const buildPath = compilation.options.output.path;
|
||||
const buildPath = resolve('build');
|
||||
for (const filePath of getFilesSync(buildPath)) {
|
||||
const readStream = readFileSync(filePath);
|
||||
const relativeFilePath = relative(buildPath, filePath);
|
||||
writeFile(relativeFilePath, readStream);
|
||||
}
|
||||
|
||||
// process assets
|
||||
const { assets } = compilation;
|
||||
Object.keys(assets).forEach((relativeFilePath) => {
|
||||
writeFile(relativeFilePath, coherseToBuffer(assets[relativeFilePath].source()));
|
||||
});
|
||||
// const { assets } = compilation;
|
||||
// Object.keys(assets).forEach((relativeFilePath) => {
|
||||
// writeFile(relativeFilePath, coherseToBuffer(assets[relativeFilePath].source()));
|
||||
// });
|
||||
};
|
||||
|
||||
const generateWWWClass = () => {
|
||||
@@ -110,13 +111,11 @@ ${indent.repeat(2)}}
|
||||
writeWWWClass();
|
||||
|
||||
writeStream.on('finish', () => {
|
||||
callback();
|
||||
// callback();
|
||||
});
|
||||
} finally {
|
||||
writeStream.end();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = ProgmemGenerator;
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta
|
||||
name="viewport"
|
||||
content="width=device-width, initial-scale=1, user-scalable=0, maximum-scale=1, minimum-scale=1"
|
||||
/>
|
||||
<link rel="stylesheet" href="%PUBLIC_URL%/css/roboto.css" />
|
||||
<link rel="manifest" href="%PUBLIC_URL%/app/manifest.json" />
|
||||
<title>EMS-ESP</title>
|
||||
</head>
|
||||
<body>
|
||||
<noscript> You need to enable JavaScript to run this app. </noscript>
|
||||
<div id="root"></div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -4,13 +4,13 @@ import { SnackbarProvider } from 'notistack';
|
||||
import { IconButton } from '@mui/material';
|
||||
import CloseIcon from '@mui/icons-material/Close';
|
||||
|
||||
import CustomTheme from './CustomTheme';
|
||||
import AppRouting from './AppRouting';
|
||||
import CustomTheme from 'CustomTheme';
|
||||
import AppRouting from 'AppRouting';
|
||||
|
||||
import { localStorageDetector } from 'typesafe-i18n/detectors';
|
||||
import TypesafeI18n from './i18n/i18n-react';
|
||||
import { detectLocale } from './i18n/i18n-util';
|
||||
import { loadLocaleAsync } from './i18n/i18n-util.async';
|
||||
import TypesafeI18n from 'i18n/i18n-react';
|
||||
import { detectLocale } from 'i18n/i18n-util';
|
||||
import { loadLocaleAsync } from 'i18n/i18n-util.async';
|
||||
|
||||
const detectedLocale = detectLocale(localStorageDetector);
|
||||
|
||||
|
||||
@@ -4,13 +4,13 @@ import { Route, Routes, Navigate, useLocation } from 'react-router-dom';
|
||||
|
||||
import { useSnackbar, VariantType } from 'notistack';
|
||||
|
||||
import { useI18nContext } from './i18n/i18n-react';
|
||||
import { useI18nContext } from 'i18n/i18n-react';
|
||||
|
||||
import { Authentication, AuthenticationContext } from './contexts/authentication';
|
||||
import { RequireAuthenticated, RequireUnauthenticated } from './components';
|
||||
import { Authentication, AuthenticationContext } from 'contexts/authentication';
|
||||
import { RequireAuthenticated, RequireUnauthenticated } from 'components';
|
||||
|
||||
import SignIn from './SignIn';
|
||||
import AuthenticatedRouting from './AuthenticatedRouting';
|
||||
import SignIn from 'SignIn';
|
||||
import AuthenticatedRouting from 'AuthenticatedRouting';
|
||||
|
||||
interface SecurityRedirectProps {
|
||||
message: string;
|
||||
@@ -28,7 +28,6 @@ const RootRedirect: FC<SecurityRedirectProps> = ({ message, variant, signOut })
|
||||
return <Navigate to="/" />;
|
||||
};
|
||||
|
||||
// TODO still need this?
|
||||
export const RemoveTrailingSlashes = () => {
|
||||
const location = useLocation();
|
||||
return (
|
||||
|
||||
@@ -2,19 +2,19 @@ import { FC, useCallback, useEffect } from 'react';
|
||||
import { Navigate, Routes, Route, useNavigate, useLocation } from 'react-router-dom';
|
||||
import { AxiosError } from 'axios';
|
||||
|
||||
import * as AuthenticationApi from './api/authentication';
|
||||
import { PROJECT_PATH } from './api/env';
|
||||
import { AXIOS } from './api/endpoints';
|
||||
import { Layout, RequireAdmin } from './components';
|
||||
import * as AuthenticationApi from 'api/authentication';
|
||||
import { PROJECT_PATH } from 'api/env';
|
||||
import { AXIOS } from 'api/endpoints';
|
||||
import { Layout, RequireAdmin } from 'components';
|
||||
|
||||
import ProjectRouting from './project/ProjectRouting';
|
||||
import ProjectRouting from 'project/ProjectRouting';
|
||||
|
||||
import NetworkConnection from './framework/network/NetworkConnection';
|
||||
import AccessPoint from './framework/ap/AccessPoint';
|
||||
import NetworkTime from './framework/ntp/NetworkTime';
|
||||
import Mqtt from './framework/mqtt/Mqtt';
|
||||
import System from './framework/system/System';
|
||||
import Security from './framework/security/Security';
|
||||
import NetworkConnection from 'framework/network/NetworkConnection';
|
||||
import AccessPoint from 'framework/ap/AccessPoint';
|
||||
import NetworkTime from 'framework/ntp/NetworkTime';
|
||||
import Mqtt from 'framework/mqtt/Mqtt';
|
||||
import System from 'framework/system/System';
|
||||
import Security from 'framework/security/Security';
|
||||
|
||||
const AuthenticatedRouting: FC = () => {
|
||||
const location = useLocation();
|
||||
|
||||
@@ -4,7 +4,7 @@ import { CssBaseline } from '@mui/material';
|
||||
import { createTheme, responsiveFontSizes, ThemeProvider } from '@mui/material/styles';
|
||||
import { blueGrey, blue } from '@mui/material/colors';
|
||||
|
||||
import { RequiredChildrenProps } from './utils';
|
||||
import { RequiredChildrenProps } from 'utils';
|
||||
|
||||
const theme = responsiveFontSizes(
|
||||
createTheme({
|
||||
|
||||
@@ -5,26 +5,26 @@ import { useSnackbar } from 'notistack';
|
||||
import { Box, Fab, Paper, Typography, Button } from '@mui/material';
|
||||
import ForwardIcon from '@mui/icons-material/Forward';
|
||||
|
||||
import * as AuthenticationApi from './api/authentication';
|
||||
import { PROJECT_NAME } from './api/env';
|
||||
import { AuthenticationContext } from './contexts/authentication';
|
||||
import * as AuthenticationApi from 'api/authentication';
|
||||
import { PROJECT_NAME } from 'api/env';
|
||||
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 { 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 { I18nContext } from 'i18n/i18n-react';
|
||||
import type { Locales } from 'i18n/i18n-types';
|
||||
import { loadLocaleAsync } from 'i18n/i18n-util.async';
|
||||
|
||||
import { ReactComponent as NLflag } from './i18n/NL.svg';
|
||||
import { ReactComponent as DEflag } from './i18n/DE.svg';
|
||||
import { ReactComponent as GBflag } from './i18n/GB.svg';
|
||||
import { ReactComponent as SVflag } from './i18n/SV.svg';
|
||||
import { ReactComponent as PLflag } from './i18n/PL.svg';
|
||||
import { ReactComponent as NOflag } from './i18n/NO.svg';
|
||||
import { ReactComponent as FRflag } from './i18n/FR.svg';
|
||||
import { ReactComponent as NLflag } from 'i18n/NL.svg';
|
||||
import { ReactComponent as DEflag } from 'i18n/DE.svg';
|
||||
import { ReactComponent as GBflag } from 'i18n/GB.svg';
|
||||
import { ReactComponent as SVflag } from 'i18n/SV.svg';
|
||||
import { ReactComponent as PLflag } from 'i18n/PL.svg';
|
||||
import { ReactComponent as NOflag } from 'i18n/NO.svg';
|
||||
import { ReactComponent as FRflag } from 'i18n/FR.svg';
|
||||
|
||||
const SignIn: FC = () => {
|
||||
const authenticationContext = useContext(AuthenticationContext);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { AxiosPromise } from 'axios';
|
||||
|
||||
import { APSettings, APStatus } from '../types';
|
||||
import { APSettings, APStatus } from 'types';
|
||||
import { AXIOS } from './endpoints';
|
||||
|
||||
export function readAPStatus(): AxiosPromise<APStatus> {
|
||||
|
||||
@@ -3,7 +3,7 @@ import * as H from 'history';
|
||||
import jwtDecode from 'jwt-decode';
|
||||
import { Path } from 'react-router-dom';
|
||||
|
||||
import { Me, SignInRequest, SignInResponse } from '../types';
|
||||
import { Me, SignInRequest, SignInResponse } from 'types';
|
||||
|
||||
import { ACCESS_TOKEN, AXIOS } from './endpoints';
|
||||
import { PROJECT_PATH } from './env';
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
export const PROJECT_NAME = process.env.REACT_APP_PROJECT_NAME || 'EMS-ESP';
|
||||
export const PROJECT_PATH = process.env.REACT_APP_PROJECT_PATH || 'project';
|
||||
export const PROJECT_NAME = 'EMS-ESP';
|
||||
export const PROJECT_PATH = 'project';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { AxiosPromise } from 'axios';
|
||||
|
||||
import { Features } from '../types';
|
||||
import { Features } from 'types';
|
||||
|
||||
import { AXIOS } from './endpoints';
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { AxiosPromise } from 'axios';
|
||||
import { MqttSettings, MqttStatus } from '../types';
|
||||
import { MqttSettings, MqttStatus } from 'types';
|
||||
|
||||
import { AXIOS } from './endpoints';
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { AxiosPromise } from 'axios';
|
||||
|
||||
import { WiFiNetworkList, NetworkSettings, NetworkStatus } from '../types';
|
||||
import { WiFiNetworkList, NetworkSettings, NetworkStatus } from 'types';
|
||||
|
||||
import { AXIOS } from './endpoints';
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { AxiosPromise } from 'axios';
|
||||
import { NTPSettings, NTPStatus, Time } from '../types';
|
||||
import { NTPSettings, NTPStatus, Time } from 'types';
|
||||
|
||||
import { AXIOS } from './endpoints';
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { AxiosPromise } from 'axios';
|
||||
|
||||
import { SecuritySettings, Token } from '../types';
|
||||
import { SecuritySettings, Token } from 'types';
|
||||
|
||||
import { AXIOS } from './endpoints';
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { AxiosPromise } from 'axios';
|
||||
|
||||
import { OTASettings, SystemStatus, LogSettings, LogEntries } from '../types';
|
||||
import { OTASettings, SystemStatus, LogSettings, LogEntries } from 'types';
|
||||
|
||||
import { AXIOS, AXIOS_BIN, FileUploadConfig, startUploadFile } from './endpoints';
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ import { FC } from 'react';
|
||||
|
||||
import { Paper, Divider } from '@mui/material';
|
||||
|
||||
import { RequiredChildrenProps } from '../utils';
|
||||
import { RequiredChildrenProps } from 'utils';
|
||||
|
||||
interface SectionContentProps extends RequiredChildrenProps {
|
||||
title: string;
|
||||
|
||||
@@ -3,8 +3,8 @@ import { useLocation } from 'react-router-dom';
|
||||
|
||||
import { Box, Toolbar } from '@mui/material';
|
||||
|
||||
import { PROJECT_NAME } from '../../api/env';
|
||||
import { RequiredChildrenProps } from '../../utils';
|
||||
import { PROJECT_NAME } from 'api/env';
|
||||
import { RequiredChildrenProps } from 'utils';
|
||||
|
||||
import LayoutDrawer from './LayoutDrawer';
|
||||
import LayoutAppBar from './LayoutAppBar';
|
||||
|
||||
@@ -17,19 +17,19 @@ import {
|
||||
import PersonIcon from '@mui/icons-material/Person';
|
||||
import AccountCircleIcon from '@mui/icons-material/AccountCircle';
|
||||
|
||||
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 { I18nContext } from 'i18n/i18n-react';
|
||||
import type { Locales } from 'i18n/i18n-types';
|
||||
import { loadLocaleAsync } from 'i18n/i18n-util.async';
|
||||
|
||||
import { ReactComponent as NLflag } from '../../i18n/NL.svg';
|
||||
import { ReactComponent as DEflag } from '../../i18n/DE.svg';
|
||||
import { ReactComponent as GBflag } from '../../i18n/GB.svg';
|
||||
import { ReactComponent as SVflag } from '../../i18n/SV.svg';
|
||||
import { ReactComponent as PLflag } from '../../i18n/PL.svg';
|
||||
import { ReactComponent as NOflag } from '../../i18n/NO.svg';
|
||||
import { ReactComponent as FRflag } from '../../i18n/FR.svg';
|
||||
import { ReactComponent as NLflag } from 'i18n/NL.svg';
|
||||
import { ReactComponent as DEflag } from 'i18n/DE.svg';
|
||||
import { ReactComponent as GBflag } from 'i18n/GB.svg';
|
||||
import { ReactComponent as SVflag } from 'i18n/SV.svg';
|
||||
import { ReactComponent as PLflag } from 'i18n/PL.svg';
|
||||
import { ReactComponent as NOflag } from 'i18n/NO.svg';
|
||||
import { ReactComponent as FRflag } from 'i18n/FR.svg';
|
||||
|
||||
const ItemTypography = styled(Typography)<TypographyProps>({
|
||||
maxWidth: '250px',
|
||||
|
||||
@@ -2,7 +2,7 @@ import { FC } from 'react';
|
||||
|
||||
import { Box, Divider, Drawer, Toolbar, Typography, styled } from '@mui/material';
|
||||
|
||||
import { PROJECT_NAME } from '../../api/env';
|
||||
import { PROJECT_NAME } from 'api/env';
|
||||
|
||||
import LayoutMenu from './LayoutMenu';
|
||||
import { DRAWER_WIDTH } from './Layout';
|
||||
|
||||
@@ -9,12 +9,12 @@ import SettingsIcon from '@mui/icons-material/Settings';
|
||||
import LockIcon from '@mui/icons-material/Lock';
|
||||
import SettingsEthernetIcon from '@mui/icons-material/SettingsEthernet';
|
||||
|
||||
import ProjectMenu from '../../project/ProjectMenu';
|
||||
import ProjectMenu from 'project/ProjectMenu';
|
||||
|
||||
import LayoutMenuItem from './LayoutMenuItem';
|
||||
import { AuthenticatedContext } from '../../contexts/authentication';
|
||||
import { AuthenticatedContext } from 'contexts/authentication';
|
||||
|
||||
import { useI18nContext } from '../../i18n/i18n-react';
|
||||
import { useI18nContext } from 'i18n/i18n-react';
|
||||
|
||||
const LayoutMenu: FC = () => {
|
||||
const authenticatedContext = useContext(AuthenticatedContext);
|
||||
|
||||
@@ -5,7 +5,7 @@ import { ListItem, ListItemButton, ListItemIcon, ListItemText, SvgIconProps } fr
|
||||
|
||||
import { grey } from '@mui/material/colors';
|
||||
|
||||
import { routeMatches } from '../../utils';
|
||||
import { routeMatches } from 'utils';
|
||||
|
||||
interface LayoutMenuItemProps {
|
||||
icon: React.ComponentType<SvgIconProps>;
|
||||
|
||||
@@ -3,9 +3,9 @@ import { FC } from 'react';
|
||||
import { Box, Button, CircularProgress, Typography } from '@mui/material';
|
||||
import RefreshIcon from '@mui/icons-material/Refresh';
|
||||
|
||||
import { MessageBox } from '..';
|
||||
import { MessageBox } from 'components';
|
||||
|
||||
import { useI18nContext } from '../../i18n/i18n-react';
|
||||
import { useI18nContext } from 'i18n/i18n-react';
|
||||
|
||||
interface FormLoaderProps {
|
||||
message?: string;
|
||||
|
||||
@@ -2,7 +2,7 @@ import { FC } from 'react';
|
||||
|
||||
import { CircularProgress, Box, Typography, Theme } from '@mui/material';
|
||||
|
||||
import { useI18nContext } from '../../i18n/i18n-react';
|
||||
import { useI18nContext } from 'i18n/i18n-react';
|
||||
|
||||
interface LoadingSpinnerProps {
|
||||
height?: number | string;
|
||||
|
||||
@@ -2,7 +2,7 @@ import { FC } from 'react';
|
||||
import type { Blocker } from '@remix-run/router';
|
||||
import { Button, Dialog, DialogActions, DialogContent, DialogTitle } from '@mui/material';
|
||||
|
||||
import { useI18nContext } from '../../i18n/i18n-react';
|
||||
import { useI18nContext } from 'i18n/i18n-react';
|
||||
|
||||
interface BlockNavigationProps {
|
||||
blocker: Blocker;
|
||||
@@ -19,7 +19,7 @@ const BlockNavigation: FC<BlockNavigationProps> = ({ blocker }) => {
|
||||
<Button variant="outlined" onClick={() => blocker.reset?.()} color="secondary">
|
||||
{LL.STAY()}
|
||||
</Button>
|
||||
<Button variant="contained" onClick={() => blocker.proceed?.()} color="primary" autoFocus>
|
||||
<Button variant="contained" onClick={() => blocker.proceed?.()} color="primary">
|
||||
{LL.LEAVE()}
|
||||
</Button>
|
||||
</DialogActions>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { FC, useContext } from 'react';
|
||||
import { Navigate } from 'react-router-dom';
|
||||
|
||||
import { AuthenticatedContext } from '../../contexts/authentication';
|
||||
import { RequiredChildrenProps } from '../../utils';
|
||||
import { AuthenticatedContext } from 'contexts/authentication';
|
||||
import { RequiredChildrenProps } from 'utils';
|
||||
|
||||
const RequireAdmin: FC<RequiredChildrenProps> = ({ children }) => {
|
||||
const authenticatedContext = useContext(AuthenticatedContext);
|
||||
|
||||
@@ -5,10 +5,10 @@ import {
|
||||
AuthenticatedContext,
|
||||
AuthenticatedContextValue,
|
||||
AuthenticationContext
|
||||
} from '../../contexts/authentication/context';
|
||||
import { storeLoginRedirect } from '../../api/authentication';
|
||||
} from 'contexts/authentication/context';
|
||||
import { storeLoginRedirect } from 'api/authentication';
|
||||
|
||||
import { RequiredChildrenProps } from '../../utils';
|
||||
import { RequiredChildrenProps } from 'utils';
|
||||
|
||||
const RequireAuthenticated: FC<RequiredChildrenProps> = ({ children }) => {
|
||||
const authenticationContext = useContext(AuthenticationContext);
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { FC, useContext } from 'react';
|
||||
import { Navigate } from 'react-router-dom';
|
||||
|
||||
import * as AuthenticationApi from '../../api/authentication';
|
||||
import { AuthenticationContext } from '../../contexts/authentication';
|
||||
import { RequiredChildrenProps } from '../../utils';
|
||||
import * as AuthenticationApi from 'api/authentication';
|
||||
import { AuthenticationContext } from 'contexts/authentication';
|
||||
import { RequiredChildrenProps } from 'utils';
|
||||
|
||||
const RequireUnauthenticated: FC<RequiredChildrenProps> = ({ children }) => {
|
||||
const authenticationContext = useContext(AuthenticationContext);
|
||||
|
||||
@@ -3,7 +3,7 @@ import { useNavigate } from 'react-router-dom';
|
||||
|
||||
import { Tabs, useMediaQuery, useTheme } from '@mui/material';
|
||||
|
||||
import { RequiredChildrenProps } from '../../utils';
|
||||
import { RequiredChildrenProps } from 'utils';
|
||||
|
||||
interface RouterTabsProps extends RequiredChildrenProps {
|
||||
value: string | false;
|
||||
@@ -15,6 +15,7 @@ const RouterTabs: FC<RouterTabsProps> = ({ value, children }) => {
|
||||
const theme = useTheme();
|
||||
const smallDown = useMediaQuery(theme.breakpoints.down('sm'));
|
||||
|
||||
// TODO fix this
|
||||
const handleTabChange = (event: React.ChangeEvent<{}>, path: string) => {
|
||||
navigate(path);
|
||||
};
|
||||
|
||||
@@ -8,7 +8,7 @@ import { Box, Button, LinearProgress, Theme, Typography, useTheme } from '@mui/m
|
||||
import CloudUploadIcon from '@mui/icons-material/CloudUpload';
|
||||
import CancelIcon from '@mui/icons-material/Cancel';
|
||||
|
||||
import { useI18nContext } from '../../i18n/i18n-react';
|
||||
import { useI18nContext } from 'i18n/i18n-react';
|
||||
|
||||
const getBorderColor = (theme: Theme, props: DropzoneState) => {
|
||||
if (props.isDragAccept) {
|
||||
|
||||
@@ -2,10 +2,10 @@ import { useCallback, useEffect, useState } from 'react';
|
||||
import axios, { AxiosPromise, CancelTokenSource, AxiosProgressEvent } from 'axios';
|
||||
import { useSnackbar } from 'notistack';
|
||||
|
||||
import { extractErrorMessage } from '../../utils';
|
||||
import { FileUploadConfig } from '../../api/endpoints';
|
||||
import { extractErrorMessage } from 'utils';
|
||||
import { FileUploadConfig } from 'api/endpoints';
|
||||
|
||||
import { useI18nContext } from '../../i18n/i18n-react';
|
||||
import { useI18nContext } from 'i18n/i18n-react';
|
||||
|
||||
interface MediaUploadOptions {
|
||||
upload: (file: File, config?: FileUploadConfig) => AxiosPromise<void>;
|
||||
|
||||
@@ -2,13 +2,13 @@ import { FC, useCallback, useEffect, useState } from 'react';
|
||||
import { useSnackbar } from 'notistack';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
|
||||
import { useI18nContext } from '../../i18n/i18n-react';
|
||||
import { useI18nContext } from 'i18n/i18n-react';
|
||||
|
||||
import * as AuthenticationApi from '../../api/authentication';
|
||||
import { ACCESS_TOKEN } from '../../api/endpoints';
|
||||
import { RequiredChildrenProps } from '../../utils';
|
||||
import { LoadingSpinner } from '../../components';
|
||||
import { Me } from '../../types';
|
||||
import * as AuthenticationApi from 'api/authentication';
|
||||
import { ACCESS_TOKEN } from 'api/endpoints';
|
||||
import { RequiredChildrenProps } from 'utils';
|
||||
import { LoadingSpinner } from 'components';
|
||||
import { Me } from 'types';
|
||||
import { AuthenticationContext } from './context';
|
||||
|
||||
const Authentication: FC<RequiredChildrenProps> = ({ children }) => {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { createContext } from 'react';
|
||||
import { Me } from '../../types';
|
||||
import { Me } from 'types';
|
||||
|
||||
export interface AuthenticationContextValue {
|
||||
refresh: () => Promise<void>;
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { FC, useCallback, useEffect, useState } from 'react';
|
||||
|
||||
import * as FeaturesApi from '../../api/features';
|
||||
import * as FeaturesApi from 'api/features';
|
||||
|
||||
import { extractErrorMessage, RequiredChildrenProps } from '../../utils';
|
||||
import { Features } from '../../types';
|
||||
import { ApplicationError, LoadingSpinner } from '../../components';
|
||||
import { extractErrorMessage, RequiredChildrenProps } from 'utils';
|
||||
import { Features } from 'types';
|
||||
import { ApplicationError, LoadingSpinner } from 'components';
|
||||
|
||||
import { FeaturesContext } from '.';
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { createContext } from 'react';
|
||||
|
||||
import { Features } from '../../types';
|
||||
import { Features } from 'types';
|
||||
|
||||
export interface FeaturesContextValue {
|
||||
features: Features;
|
||||
|
||||
@@ -6,7 +6,7 @@ import { Button, Checkbox, MenuItem } from '@mui/material';
|
||||
import WarningIcon from '@mui/icons-material/Warning';
|
||||
import CancelIcon from '@mui/icons-material/Cancel';
|
||||
|
||||
import { createAPSettingsValidator, validate } from '../../validators';
|
||||
import { createAPSettingsValidator, validate } from 'validators';
|
||||
import {
|
||||
BlockFormControlLabel,
|
||||
ButtonRow,
|
||||
@@ -15,13 +15,13 @@ import {
|
||||
ValidatedPasswordField,
|
||||
ValidatedTextField,
|
||||
BlockNavigation
|
||||
} from '../../components';
|
||||
} from 'components';
|
||||
|
||||
import { APProvisionMode, APSettings } from '../../types';
|
||||
import { numberValue, updateValueDirty, useRest } from '../../utils';
|
||||
import * as APApi from '../../api/ap';
|
||||
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';
|
||||
|
||||
export const isAPEnabled = ({ provision_mode }: APSettings) => {
|
||||
return provision_mode === APProvisionMode.AP_MODE_ALWAYS || provision_mode === APProvisionMode.AP_MODE_DISCONNECTED;
|
||||
|
||||
@@ -6,12 +6,12 @@ import DeviceHubIcon from '@mui/icons-material/DeviceHub';
|
||||
import ComputerIcon from '@mui/icons-material/Computer';
|
||||
import RefreshIcon from '@mui/icons-material/Refresh';
|
||||
|
||||
import * as APApi from '../../api/ap';
|
||||
import { APNetworkStatus, APStatus } from '../../types';
|
||||
import { ButtonRow, FormLoader, SectionContent } from '../../components';
|
||||
import { useRest } from '../../utils';
|
||||
import * as APApi from 'api/ap';
|
||||
import { APNetworkStatus, APStatus } from 'types';
|
||||
import { ButtonRow, FormLoader, SectionContent } from 'components';
|
||||
import { useRest } from 'utils';
|
||||
|
||||
import { useI18nContext } from '../../i18n/i18n-react';
|
||||
import { useI18nContext } from 'i18n/i18n-react';
|
||||
|
||||
export const apStatusHighlight = ({ status }: APStatus, theme: Theme) => {
|
||||
switch (status) {
|
||||
|
||||
@@ -3,12 +3,12 @@ import { Navigate, Routes, Route } from 'react-router-dom';
|
||||
|
||||
import { Tab } from '@mui/material';
|
||||
|
||||
import { AuthenticatedContext } from '../../contexts/authentication';
|
||||
import { AuthenticatedContext } from 'contexts/authentication';
|
||||
import APStatusForm from './APStatusForm';
|
||||
import APSettingsForm from './APSettingsForm';
|
||||
import { RequireAdmin, RouterTabs, useLayoutTitle, useRouterTab } from '../../components';
|
||||
import { RequireAdmin, RouterTabs, useLayoutTitle, useRouterTab } from 'components';
|
||||
|
||||
import { useI18nContext } from '../../i18n/i18n-react';
|
||||
import { useI18nContext } from 'i18n/i18n-react';
|
||||
|
||||
const AccessPoint: FC = () => {
|
||||
const { LL } = useI18nContext();
|
||||
|
||||
@@ -3,13 +3,13 @@ import { Navigate, Route, Routes } from 'react-router-dom';
|
||||
|
||||
import { Tab } from '@mui/material';
|
||||
|
||||
import { RequireAdmin, RouterTabs, useLayoutTitle, useRouterTab } from '../../components';
|
||||
import { AuthenticatedContext } from '../../contexts/authentication';
|
||||
import { RequireAdmin, RouterTabs, useLayoutTitle, useRouterTab } from 'components';
|
||||
import { AuthenticatedContext } from 'contexts/authentication';
|
||||
|
||||
import MqttStatusForm from './MqttStatusForm';
|
||||
import MqttSettingsForm from './MqttSettingsForm';
|
||||
|
||||
import { useI18nContext } from '../../i18n/i18n-react';
|
||||
import { useI18nContext } from 'i18n/i18n-react';
|
||||
|
||||
const Mqtt: FC = () => {
|
||||
const { LL } = useI18nContext();
|
||||
|
||||
@@ -6,7 +6,7 @@ import { Button, Checkbox, MenuItem, Grid, Typography, InputAdornment } from '@m
|
||||
import WarningIcon from '@mui/icons-material/Warning';
|
||||
import CancelIcon from '@mui/icons-material/Cancel';
|
||||
|
||||
import { createMqttSettingsValidator, validate } from '../../validators';
|
||||
import { createMqttSettingsValidator, validate } from 'validators';
|
||||
import {
|
||||
BlockFormControlLabel,
|
||||
ButtonRow,
|
||||
@@ -15,12 +15,12 @@ import {
|
||||
ValidatedPasswordField,
|
||||
ValidatedTextField,
|
||||
BlockNavigation
|
||||
} from '../../components';
|
||||
import { MqttSettings } from '../../types';
|
||||
import { numberValue, updateValueDirty, useRest } from '../../utils';
|
||||
import * as MqttApi from '../../api/mqtt';
|
||||
} 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';
|
||||
|
||||
const MqttSettingsForm: FC = () => {
|
||||
const { loadData, saving, data, setData, origData, dirtyFlags, setDirtyFlags, blocker, saveData, errorMessage } =
|
||||
|
||||
@@ -7,12 +7,12 @@ import ReportIcon from '@mui/icons-material/Report';
|
||||
import SpeakerNotesOffIcon from '@mui/icons-material/SpeakerNotesOff';
|
||||
import AutoAwesomeMotionIcon from '@mui/icons-material/AutoAwesomeMotion';
|
||||
|
||||
import { ButtonRow, FormLoader, SectionContent } from '../../components';
|
||||
import { MqttStatus, MqttDisconnectReason } from '../../types';
|
||||
import * as MqttApi from '../../api/mqtt';
|
||||
import { useRest } from '../../utils';
|
||||
import { ButtonRow, FormLoader, SectionContent } from 'components';
|
||||
import { MqttStatus, MqttDisconnectReason } from 'types';
|
||||
import * as MqttApi from 'api/mqtt';
|
||||
import { useRest } from 'utils';
|
||||
|
||||
import { useI18nContext } from '../../i18n/i18n-react';
|
||||
import { useI18nContext } from 'i18n/i18n-react';
|
||||
|
||||
export const mqttStatusHighlight = ({ enabled, connected }: MqttStatus, theme: Theme) => {
|
||||
if (!enabled) {
|
||||
|
||||
@@ -3,15 +3,15 @@ import { Navigate, Routes, Route, useNavigate } from 'react-router-dom';
|
||||
|
||||
import { Tab } from '@mui/material';
|
||||
|
||||
import { RequireAdmin, RouterTabs, useLayoutTitle, useRouterTab } from '../../components';
|
||||
import { WiFiNetwork } from '../../types';
|
||||
import { AuthenticatedContext } from '../../contexts/authentication';
|
||||
import { RequireAdmin, RouterTabs, useLayoutTitle, useRouterTab } from 'components';
|
||||
import { WiFiNetwork } from 'types';
|
||||
import { AuthenticatedContext } from 'contexts/authentication';
|
||||
import { WiFiConnectionContext } from './WiFiConnectionContext';
|
||||
import NetworkStatusForm from './NetworkStatusForm';
|
||||
import WiFiNetworkScanner from './WiFiNetworkScanner';
|
||||
import NetworkSettingsForm from './NetworkSettingsForm';
|
||||
|
||||
import { useI18nContext } from '../../i18n/i18n-react';
|
||||
import { useI18nContext } from 'i18n/i18n-react';
|
||||
|
||||
const NetworkConnection: FC = () => {
|
||||
const { LL } = useI18nContext();
|
||||
|
||||
@@ -31,19 +31,19 @@ import {
|
||||
ValidatedTextField,
|
||||
MessageBox,
|
||||
BlockNavigation
|
||||
} from '../../components';
|
||||
import { NetworkSettings } from '../../types';
|
||||
import * as NetworkApi from '../../api/network';
|
||||
import { numberValue, updateValueDirty, useRest } from '../../utils';
|
||||
import * as EMSESP from '../../project/api';
|
||||
} from 'components';
|
||||
import { NetworkSettings } from 'types';
|
||||
import * as NetworkApi from 'api/network';
|
||||
import { numberValue, updateValueDirty, useRest } from 'utils';
|
||||
import * as EMSESP from 'project/api';
|
||||
|
||||
import { WiFiConnectionContext } from './WiFiConnectionContext';
|
||||
import { isNetworkOpen, networkSecurityMode } from './WiFiNetworkSelector';
|
||||
import { ValidateFieldsError } from 'async-validator';
|
||||
import { validate } from '../../validators';
|
||||
import { createNetworkSettingsValidator } from '../../validators/network';
|
||||
import { validate } from 'validators';
|
||||
import { createNetworkSettingsValidator } from 'validators/network';
|
||||
|
||||
import { useI18nContext } from '../../i18n/i18n-react';
|
||||
import { useI18nContext } from 'i18n/i18n-react';
|
||||
import RestartMonitor from '../system/RestartMonitor';
|
||||
|
||||
const WiFiSettingsForm: FC = () => {
|
||||
|
||||
@@ -9,12 +9,12 @@ import DnsIcon from '@mui/icons-material/Dns';
|
||||
import RefreshIcon from '@mui/icons-material/Refresh';
|
||||
import RouterIcon from '@mui/icons-material/Router';
|
||||
|
||||
import { ButtonRow, FormLoader, SectionContent } from '../../components';
|
||||
import { NetworkConnectionStatus, NetworkStatus } from '../../types';
|
||||
import * as NetworkApi from '../../api/network';
|
||||
import { useRest } from '../../utils';
|
||||
import { ButtonRow, FormLoader, SectionContent } from 'components';
|
||||
import { NetworkConnectionStatus, NetworkStatus } from 'types';
|
||||
import * as NetworkApi from 'api/network';
|
||||
import { useRest } from 'utils';
|
||||
|
||||
import { useI18nContext } from '../../i18n/i18n-react';
|
||||
import { useI18nContext } from 'i18n/i18n-react';
|
||||
|
||||
const isConnected = ({ status }: NetworkStatus) =>
|
||||
status === NetworkConnectionStatus.WIFI_STATUS_CONNECTED ||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { createContext } from 'react';
|
||||
import { WiFiNetwork } from '../../types';
|
||||
import { WiFiNetwork } from 'types';
|
||||
|
||||
export interface WiFiConnectionContextValue {
|
||||
selectedNetwork?: WiFiNetwork;
|
||||
|
||||
@@ -4,13 +4,13 @@ import { useSnackbar } from 'notistack';
|
||||
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 * as NetworkApi from 'api/network';
|
||||
import { WiFiNetwork, WiFiNetworkList } from 'types';
|
||||
import { ButtonRow, FormLoader, SectionContent } from 'components';
|
||||
|
||||
import WiFiNetworkSelector from './WiFiNetworkSelector';
|
||||
|
||||
import { useI18nContext } from '../../i18n/i18n-react';
|
||||
import { useI18nContext } from 'i18n/i18n-react';
|
||||
|
||||
const NUM_POLLS = 10;
|
||||
const POLLING_FREQUENCY = 500;
|
||||
|
||||
@@ -6,13 +6,13 @@ import LockOpenIcon from '@mui/icons-material/LockOpen';
|
||||
import LockIcon from '@mui/icons-material/Lock';
|
||||
import WifiIcon from '@mui/icons-material/Wifi';
|
||||
|
||||
import { MessageBox } from '../../components';
|
||||
import { MessageBox } from 'components';
|
||||
|
||||
import { WiFiEncryptionType, WiFiNetwork, WiFiNetworkList } from '../../types';
|
||||
import { WiFiEncryptionType, WiFiNetwork, WiFiNetworkList } from 'types';
|
||||
|
||||
import { WiFiConnectionContext } from './WiFiConnectionContext';
|
||||
|
||||
import { useI18nContext } from '../../i18n/i18n-react';
|
||||
import { useI18nContext } from 'i18n/i18n-react';
|
||||
|
||||
interface WiFiNetworkSelectorProps {
|
||||
networkList: WiFiNetworkList;
|
||||
|
||||
@@ -5,7 +5,7 @@ import { Button, Checkbox, MenuItem } from '@mui/material';
|
||||
import WarningIcon from '@mui/icons-material/Warning';
|
||||
import CancelIcon from '@mui/icons-material/Cancel';
|
||||
|
||||
import { validate } from '../../validators';
|
||||
import { validate } from 'validators';
|
||||
import {
|
||||
BlockFormControlLabel,
|
||||
ButtonRow,
|
||||
@@ -13,14 +13,14 @@ import {
|
||||
SectionContent,
|
||||
ValidatedTextField,
|
||||
BlockNavigation
|
||||
} from '../../components';
|
||||
import { NTPSettings } from '../../types';
|
||||
import { updateValueDirty, useRest } from '../../utils';
|
||||
import * as NTPApi from '../../api/ntp';
|
||||
} 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 { NTP_SETTINGS_VALIDATOR } from 'validators/ntp';
|
||||
|
||||
import { useI18nContext } from '../../i18n/i18n-react';
|
||||
import { useI18nContext } from 'i18n/i18n-react';
|
||||
|
||||
const NTPSettingsForm: FC = () => {
|
||||
const { loadData, saving, data, setData, origData, dirtyFlags, setDirtyFlags, blocker, saveData, errorMessage } =
|
||||
|
||||
@@ -26,13 +26,13 @@ import UpdateIcon from '@mui/icons-material/Update';
|
||||
import DnsIcon from '@mui/icons-material/Dns';
|
||||
import CancelIcon from '@mui/icons-material/Cancel';
|
||||
|
||||
import * as NTPApi from '../../api/ntp';
|
||||
import { NTPStatus, NTPSyncStatus } from '../../types';
|
||||
import { ButtonRow, FormLoader, SectionContent } from '../../components';
|
||||
import { extractErrorMessage, formatDateTime, formatLocalDateTime, useRest } from '../../utils';
|
||||
import { AuthenticatedContext } from '../../contexts/authentication';
|
||||
import * as NTPApi from 'api/ntp';
|
||||
import { NTPStatus, NTPSyncStatus } from 'types';
|
||||
import { ButtonRow, FormLoader, SectionContent } from 'components';
|
||||
import { extractErrorMessage, formatDateTime, formatLocalDateTime, useRest } from 'utils';
|
||||
import { AuthenticatedContext } from 'contexts/authentication';
|
||||
|
||||
import { useI18nContext } from '../../i18n/i18n-react';
|
||||
import { useI18nContext } from 'i18n/i18n-react';
|
||||
|
||||
export const isNtpActive = ({ status }: NTPStatus) => status === NTPSyncStatus.NTP_ACTIVE;
|
||||
export const isNtpEnabled = ({ status }: NTPStatus) => status !== NTPSyncStatus.NTP_DISABLED;
|
||||
@@ -127,7 +127,6 @@ const NTPStatusForm: FC = () => {
|
||||
onClick={configureTime}
|
||||
disabled={processing}
|
||||
color="primary"
|
||||
autoFocus
|
||||
>
|
||||
{LL.UPDATE()}
|
||||
</Button>
|
||||
|
||||
@@ -3,13 +3,13 @@ import { Navigate, Route, Routes } from 'react-router-dom';
|
||||
|
||||
import { Tab } from '@mui/material';
|
||||
|
||||
import { RequireAdmin, RouterTabs, useLayoutTitle, useRouterTab } from '../../components';
|
||||
import { AuthenticatedContext } from '../../contexts/authentication';
|
||||
import { RequireAdmin, RouterTabs, useLayoutTitle, useRouterTab } from 'components';
|
||||
import { AuthenticatedContext } from 'contexts/authentication';
|
||||
|
||||
import NTPStatusForm from './NTPStatusForm';
|
||||
import NTPSettingsForm from './NTPSettingsForm';
|
||||
|
||||
import { useI18nContext } from '../../i18n/i18n-react';
|
||||
import { useI18nContext } from 'i18n/i18n-react';
|
||||
|
||||
const NetworkTime: FC = () => {
|
||||
const { LL } = useI18nContext();
|
||||
|
||||
@@ -13,13 +13,13 @@ import {
|
||||
|
||||
import CloseIcon from '@mui/icons-material/Close';
|
||||
|
||||
import { extractErrorMessage } from '../../utils';
|
||||
import { extractErrorMessage } from 'utils';
|
||||
import { useSnackbar } from 'notistack';
|
||||
import { MessageBox } from '../../components';
|
||||
import * as SecurityApi from '../../api/security';
|
||||
import { Token } from '../../types';
|
||||
import { MessageBox } from 'components';
|
||||
import * as SecurityApi from 'api/security';
|
||||
import { Token } from 'types';
|
||||
|
||||
import { useI18nContext } from '../../i18n/i18n-react';
|
||||
import { useI18nContext } from 'i18n/i18n-react';
|
||||
|
||||
interface GenerateTokenProps {
|
||||
username?: string;
|
||||
|
||||
@@ -9,18 +9,17 @@ import CheckIcon from '@mui/icons-material/Check';
|
||||
import CloseIcon from '@mui/icons-material/Close';
|
||||
import VpnKeyIcon from '@mui/icons-material/VpnKey';
|
||||
|
||||
import { Table } from '@table-library/react-table-library/table';
|
||||
import { useTheme } from '@table-library/react-table-library/theme';
|
||||
import { 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 * as SecurityApi from '../../api/security';
|
||||
import { SecuritySettings, User } from '../../types';
|
||||
import { ButtonRow, FormLoader, MessageBox, SectionContent } from '../../components';
|
||||
import { createUserValidator } from '../../validators';
|
||||
import { useRest } from '../../utils';
|
||||
import { AuthenticatedContext } from '../../contexts/authentication';
|
||||
import * as SecurityApi from 'api/security';
|
||||
import { SecuritySettings, User } from 'types';
|
||||
import { ButtonRow, FormLoader, MessageBox, SectionContent } from 'components';
|
||||
import { createUserValidator } from 'validators';
|
||||
import { useRest } from 'utils';
|
||||
import { AuthenticatedContext } from 'contexts/authentication';
|
||||
|
||||
import { useI18nContext } from '../../i18n/i18n-react';
|
||||
import { useI18nContext } from 'i18n/i18n-react';
|
||||
|
||||
import GenerateToken from './GenerateToken';
|
||||
import UserForm from './UserForm';
|
||||
|
||||
@@ -3,12 +3,12 @@ import { Navigate, Routes, Route } from 'react-router-dom';
|
||||
|
||||
import { Tab } from '@mui/material';
|
||||
|
||||
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 { LL } = useI18nContext();
|
||||
|
||||
@@ -5,21 +5,14 @@ import { Button } from '@mui/material';
|
||||
import WarningIcon from '@mui/icons-material/Warning';
|
||||
import CancelIcon from '@mui/icons-material/Cancel';
|
||||
|
||||
import * as SecurityApi from '../../api/security';
|
||||
import { SecuritySettings } from '../../types';
|
||||
import {
|
||||
ButtonRow,
|
||||
FormLoader,
|
||||
MessageBox,
|
||||
SectionContent,
|
||||
ValidatedPasswordField,
|
||||
BlockNavigation
|
||||
} from '../../components';
|
||||
import { SECURITY_SETTINGS_VALIDATOR, validate } from '../../validators';
|
||||
import { updateValueDirty, useRest } from '../../utils';
|
||||
import { AuthenticatedContext } from '../../contexts/authentication';
|
||||
import * as SecurityApi from 'api/security';
|
||||
import { SecuritySettings } from 'types';
|
||||
import { ButtonRow, FormLoader, MessageBox, SectionContent, ValidatedPasswordField, BlockNavigation } from 'components';
|
||||
import { SECURITY_SETTINGS_VALIDATOR, validate } from 'validators';
|
||||
import { updateValueDirty, useRest } from 'utils';
|
||||
import { AuthenticatedContext } from 'contexts/authentication';
|
||||
|
||||
import { useI18nContext } from '../../i18n/i18n-react';
|
||||
import { useI18nContext } from 'i18n/i18n-react';
|
||||
|
||||
const SecuritySettingsForm: FC = () => {
|
||||
const { LL } = useI18nContext();
|
||||
|
||||
@@ -7,12 +7,12 @@ import SaveIcon from '@mui/icons-material/Save';
|
||||
|
||||
import { Button, Checkbox, Dialog, DialogActions, DialogContent, DialogTitle } from '@mui/material';
|
||||
|
||||
import { BlockFormControlLabel, ValidatedPasswordField, ValidatedTextField } from '../../components';
|
||||
import { User } from '../../types';
|
||||
import { updateValue } from '../../utils';
|
||||
import { validate } from '../../validators';
|
||||
import { BlockFormControlLabel, ValidatedPasswordField, ValidatedTextField } from 'components';
|
||||
import { User } from 'types';
|
||||
import { updateValue } from 'utils';
|
||||
import { validate } from 'validators';
|
||||
|
||||
import { useI18nContext } from '../../i18n/i18n-react';
|
||||
import { useI18nContext } from 'i18n/i18n-react';
|
||||
|
||||
interface UserFormProps {
|
||||
creating: boolean;
|
||||
@@ -93,7 +93,6 @@ const UserForm: FC<UserFormProps> = ({ creating, validator, user, setUser, onDon
|
||||
variant="outlined"
|
||||
onClick={validateAndDone}
|
||||
color="primary"
|
||||
autoFocus
|
||||
>
|
||||
{creating ? LL.ADD(0) : LL.UPDATE()}
|
||||
</Button>
|
||||
|
||||
@@ -3,19 +3,19 @@ import { AxiosPromise } from 'axios';
|
||||
|
||||
import { Typography, Button, Box } from '@mui/material';
|
||||
|
||||
import { FileUploadConfig } from '../../api/endpoints';
|
||||
import { FileUploadConfig } from 'api/endpoints';
|
||||
|
||||
import { SingleUpload, useFileUpload } from '../../components';
|
||||
import { SingleUpload, useFileUpload } from 'components';
|
||||
|
||||
import DownloadIcon from '@mui/icons-material/GetApp';
|
||||
|
||||
import { useSnackbar } from 'notistack';
|
||||
|
||||
import { extractErrorMessage } from '../../utils';
|
||||
import { extractErrorMessage } from 'utils';
|
||||
|
||||
import * as EMSESP from '../../project/api';
|
||||
import * as EMSESP from 'project/api';
|
||||
|
||||
import { useI18nContext } from '../../i18n/i18n-react';
|
||||
import { useI18nContext } from 'i18n/i18n-react';
|
||||
|
||||
interface UploadFileProps {
|
||||
uploadGeneralFile: (file: File, config?: FileUploadConfig) => AxiosPromise<void>;
|
||||
|
||||
@@ -4,7 +4,7 @@ import { Button, Checkbox } from '@mui/material';
|
||||
import WarningIcon from '@mui/icons-material/Warning';
|
||||
import CancelIcon from '@mui/icons-material/Cancel';
|
||||
|
||||
import * as SystemApi from '../../api/system';
|
||||
import * as SystemApi from 'api/system';
|
||||
import {
|
||||
BlockFormControlLabel,
|
||||
ButtonRow,
|
||||
@@ -13,16 +13,16 @@ import {
|
||||
ValidatedPasswordField,
|
||||
ValidatedTextField,
|
||||
BlockNavigation
|
||||
} from '../../components';
|
||||
} from 'components';
|
||||
|
||||
import { OTASettings } from '../../types';
|
||||
import { numberValue, updateValueDirty, useRest } from '../../utils';
|
||||
import { OTASettings } from 'types';
|
||||
import { numberValue, updateValueDirty, useRest } from 'utils';
|
||||
|
||||
import { ValidateFieldsError } from 'async-validator';
|
||||
import { validate } from '../../validators';
|
||||
import { OTA_SETTINGS_VALIDATOR } from '../../validators/system';
|
||||
import { validate } from 'validators';
|
||||
import { OTA_SETTINGS_VALIDATOR } from 'validators/system';
|
||||
|
||||
import { useI18nContext } from '../../i18n/i18n-react';
|
||||
import { useI18nContext } from 'i18n/i18n-react';
|
||||
|
||||
const OTASettingsForm: FC = () => {
|
||||
const { loadData, saving, data, setData, origData, dirtyFlags, setDirtyFlags, blocker, saveData, errorMessage } =
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
import { useEffect } from 'react';
|
||||
import { FC, useRef, useState } from 'react';
|
||||
import { FC, useRef, useState, useEffect } from 'react';
|
||||
|
||||
import * as SystemApi from '../../api/system';
|
||||
import { FormLoader } from '../../components';
|
||||
import * as SystemApi from 'api/system';
|
||||
import { FormLoader } from 'components';
|
||||
|
||||
import { useI18nContext } from '../../i18n/i18n-react';
|
||||
import { useI18nContext } from 'i18n/i18n-react';
|
||||
|
||||
const RESTART_TIMEOUT = 2 * 60 * 1000;
|
||||
const POLL_TIMEOUT = 2000;
|
||||
|
||||
@@ -3,15 +3,15 @@ import { Navigate, Routes, Route } from 'react-router-dom';
|
||||
|
||||
import { Tab } from '@mui/material';
|
||||
|
||||
import { useRouterTab, RouterTabs, useLayoutTitle, RequireAdmin } from '../../components';
|
||||
import { AuthenticatedContext } from '../../contexts/authentication';
|
||||
import { useRouterTab, RouterTabs, useLayoutTitle, RequireAdmin } from 'components';
|
||||
import { AuthenticatedContext } from 'contexts/authentication';
|
||||
import UploadFileForm from './UploadFileForm';
|
||||
import SystemStatusForm from './SystemStatusForm';
|
||||
import OTASettingsForm from './OTASettingsForm';
|
||||
|
||||
import SystemLog from './SystemLog';
|
||||
|
||||
import { useI18nContext } from '../../i18n/i18n-react';
|
||||
import { useI18nContext } from 'i18n/i18n-react';
|
||||
|
||||
const System: FC = () => {
|
||||
const { LL } = useI18nContext();
|
||||
|
||||
@@ -2,21 +2,21 @@ import { FC, useState, useEffect, useCallback, useLayoutEffect } from 'react';
|
||||
|
||||
import { Box, styled, Button, Checkbox, MenuItem, Grid, Slider, FormLabel } from '@mui/material';
|
||||
|
||||
import * as SystemApi from '../../api/system';
|
||||
import { addAccessTokenParameter } from '../../api/authentication';
|
||||
import * as SystemApi from 'api/system';
|
||||
import { addAccessTokenParameter } from 'api/authentication';
|
||||
|
||||
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 { LogSettings, LogEntry, LogEntries, LogLevel } from 'types';
|
||||
import { updateValue, useRest, extractErrorMessage } from 'utils';
|
||||
|
||||
import DownloadIcon from '@mui/icons-material/GetApp';
|
||||
|
||||
import { useSnackbar } from 'notistack';
|
||||
|
||||
import { EVENT_SOURCE_ROOT } from '../../api/endpoints';
|
||||
import { EVENT_SOURCE_ROOT } from 'api/endpoints';
|
||||
|
||||
import { useI18nContext } from '../../i18n/i18n-react';
|
||||
import { useI18nContext } from 'i18n/i18n-react';
|
||||
|
||||
export const LOG_EVENTSOURCE_URL = EVENT_SOURCE_ROOT + 'log';
|
||||
|
||||
@@ -137,7 +137,7 @@ const SystemLog: FC = () => {
|
||||
|
||||
const onDownload = () => {
|
||||
let result = '';
|
||||
for (let i of logEntries.events) {
|
||||
for (const i of logEntries.events) {
|
||||
result += i.t + ' ' + levelLabel(i.l) + ' ' + i.i + ': [' + i.n + '] ' + i.m + '\n';
|
||||
}
|
||||
const a = document.createElement('a');
|
||||
|
||||
@@ -31,17 +31,17 @@ 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 { 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 { AuthenticatedContext } from 'contexts/authentication';
|
||||
|
||||
import axios from 'axios';
|
||||
import RestartMonitor from './RestartMonitor';
|
||||
|
||||
import { useI18nContext } from '../../i18n/i18n-react';
|
||||
import { useI18nContext } from 'i18n/i18n-react';
|
||||
|
||||
export const VERSIONCHECK_ENDPOINT = 'https://api.github.com/repos/emsesp/EMS-ESP32/releases/latest';
|
||||
export const VERSIONCHECK_DEV_ENDPOINT = 'https://api.github.com/repos/emsesp/EMS-ESP32/releases/tags/latest';
|
||||
@@ -131,7 +131,6 @@ const SystemStatusForm: FC = () => {
|
||||
onClick={restart}
|
||||
disabled={processing}
|
||||
color="primary"
|
||||
autoFocus
|
||||
>
|
||||
{LL.RESTART()}
|
||||
</Button>
|
||||
@@ -238,7 +237,6 @@ const SystemStatusForm: FC = () => {
|
||||
variant="outlined"
|
||||
onClick={factoryReset}
|
||||
disabled={processing}
|
||||
autoFocus
|
||||
color="error"
|
||||
>
|
||||
{LL.FACTORY_RESET()}
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import { FC, useRef, useState } from 'react';
|
||||
|
||||
import * as SystemApi from '../../api/system';
|
||||
import { SectionContent } from '../../components';
|
||||
import { FileUploadConfig } from '../../api/endpoints';
|
||||
import * as SystemApi from 'api/system';
|
||||
import { SectionContent } from 'components';
|
||||
import { FileUploadConfig } from 'api/endpoints';
|
||||
|
||||
import GeneralFileUpload from './GeneralFileUpload';
|
||||
import RestartMonitor from './RestartMonitor';
|
||||
|
||||
import { useI18nContext } from '../../i18n/i18n-react';
|
||||
import { useI18nContext } from 'i18n/i18n-react';
|
||||
|
||||
const UploadFileForm: FC = () => {
|
||||
const [restarting, setRestarting] = useState<boolean>();
|
||||
|
||||
0
interface/src/i18n/FR.svg
Executable file → Normal file
0
interface/src/i18n/FR.svg
Executable file → Normal file
|
Before Width: | Height: | Size: 243 B After Width: | Height: | Size: 243 B |
@@ -2,9 +2,9 @@ import React from 'react';
|
||||
import ReactDOM from 'react-dom/client';
|
||||
import { createBrowserRouter, createRoutesFromElements, Route, RouterProvider } from 'react-router-dom';
|
||||
|
||||
import App from './App';
|
||||
import App from 'App';
|
||||
|
||||
const router = createBrowserRouter(createRoutesFromElements(<Route path="/*" element={<App />}></Route>));
|
||||
const router = createBrowserRouter(createRoutesFromElements(<Route path="/*" element={<App />} />));
|
||||
|
||||
ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
|
||||
<React.StrictMode>
|
||||
|
||||
@@ -3,9 +3,9 @@ import { Navigate, Route, Routes } from 'react-router-dom';
|
||||
|
||||
import { Tab } from '@mui/material';
|
||||
|
||||
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';
|
||||
|
||||
@@ -22,10 +22,9 @@ import {
|
||||
|
||||
import { useSnackbar } from 'notistack';
|
||||
|
||||
import { Table } from '@table-library/react-table-library/table';
|
||||
import { useTheme } from '@table-library/react-table-library/theme';
|
||||
import { useSort, SortToggleType } from '@table-library/react-table-library/sort';
|
||||
import { 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 { useRowSelect } from '@table-library/react-table-library/select';
|
||||
|
||||
import DownloadIcon from '@mui/icons-material/GetApp';
|
||||
@@ -49,13 +48,13 @@ import DeviceIcon from './DeviceIcon';
|
||||
|
||||
import { IconContext } from 'react-icons';
|
||||
|
||||
import { AuthenticatedContext } from '../contexts/authentication';
|
||||
import { AuthenticatedContext } from 'contexts/authentication';
|
||||
|
||||
import { ButtonRow, ValidatedTextField, SectionContent, MessageBox } from '../components';
|
||||
import { ButtonRow, ValidatedTextField, SectionContent, MessageBox } from 'components';
|
||||
|
||||
import * as EMSESP from './api';
|
||||
|
||||
import { numberValue, updateValue, extractErrorMessage } from '../utils';
|
||||
import { numberValue, updateValue, extractErrorMessage } from 'utils';
|
||||
|
||||
import {
|
||||
SensorData,
|
||||
@@ -72,7 +71,7 @@ import {
|
||||
DeviceEntityMask
|
||||
} from './types';
|
||||
|
||||
import { useI18nContext } from '../i18n/i18n-react';
|
||||
import { useI18nContext } from 'i18n/i18n-react';
|
||||
|
||||
const DashboardData: FC = () => {
|
||||
const { me } = useContext(AuthenticatedContext);
|
||||
@@ -502,7 +501,9 @@ const DashboardData: FC = () => {
|
||||
onChange={updateValue(setDeviceValue)}
|
||||
>
|
||||
{deviceValue.l.map((val) => (
|
||||
<MenuItem value={val}>{val}</MenuItem>
|
||||
<MenuItem value={val} key={val}>
|
||||
{val}
|
||||
</MenuItem>
|
||||
))}
|
||||
</ValidatedTextField>
|
||||
)}
|
||||
|
||||
@@ -16,9 +16,8 @@ import {
|
||||
useTheme
|
||||
} from '@mui/material';
|
||||
|
||||
import { Table } from '@table-library/react-table-library/table';
|
||||
import { useTheme as tableTheme } from '@table-library/react-table-library/theme';
|
||||
import { 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 DeviceHubIcon from '@mui/icons-material/DeviceHub';
|
||||
import RefreshIcon from '@mui/icons-material/Refresh';
|
||||
@@ -26,18 +25,18 @@ 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 { AuthenticatedContext } from 'contexts/authentication';
|
||||
|
||||
import { ButtonRow, FormLoader, SectionContent } from '../components';
|
||||
import { ButtonRow, FormLoader, SectionContent } from 'components';
|
||||
|
||||
import { Status, busConnectionStatus, Stat } from './types';
|
||||
|
||||
import { extractErrorMessage, useRest } from '../utils';
|
||||
import { extractErrorMessage, useRest } from 'utils';
|
||||
|
||||
import * as EMSESP from './api';
|
||||
|
||||
import type { Translation } from '../i18n/i18n-types';
|
||||
import { useI18nContext } from '../i18n/i18n-react';
|
||||
import type { Translation } from 'i18n/i18n-types';
|
||||
import { useI18nContext } from 'i18n/i18n-react';
|
||||
|
||||
export const isConnected = ({ status }: Status) => status !== busConnectionStatus.BUS_STATUS_OFFLINE;
|
||||
|
||||
@@ -80,7 +79,7 @@ const DashboardStatus: FC = () => {
|
||||
const { me } = useContext(AuthenticatedContext);
|
||||
|
||||
const showName = (id: any) => {
|
||||
let name: keyof Translation['STATUS_NAMES'] = id;
|
||||
const name: keyof Translation['STATUS_NAMES'] = id;
|
||||
return LL.STATUS_NAMES[name]();
|
||||
};
|
||||
|
||||
@@ -183,7 +182,7 @@ const DashboardStatus: FC = () => {
|
||||
<Button startIcon={<CancelIcon />} variant="outlined" onClick={() => setConfirmScan(false)} color="secondary">
|
||||
{LL.CANCEL()}
|
||||
</Button>
|
||||
<Button startIcon={<PermScanWifiIcon />} variant="outlined" onClick={scan} color="primary" autoFocus>
|
||||
<Button startIcon={<PermScanWifiIcon />} variant="outlined" onClick={scan} color="primary">
|
||||
{LL.SCAN()}
|
||||
</Button>
|
||||
</DialogActions>
|
||||
@@ -226,13 +225,13 @@ const DashboardStatus: FC = () => {
|
||||
}
|
||||
/>
|
||||
</ListItem>
|
||||
<Box m={3}></Box>
|
||||
<Box m={3} />
|
||||
<Table data={{ nodes: data.stats }} theme={stats_theme} layout={{ custom: true }}>
|
||||
{(tableList: any) => (
|
||||
<>
|
||||
<Header>
|
||||
<HeaderRow>
|
||||
<HeaderCell resize></HeaderCell>
|
||||
<HeaderCell resize />
|
||||
<HeaderCell stiff>{LL.SUCCESS()}</HeaderCell>
|
||||
<HeaderCell stiff>{LL.FAIL()}</HeaderCell>
|
||||
<HeaderCell stiff>{LL.QUALITY()}</HeaderCell>
|
||||
|
||||
@@ -1,16 +1,12 @@
|
||||
import { FC } from 'react';
|
||||
|
||||
import { CgSmartHomeBoiler } from 'react-icons/cg';
|
||||
import { MdOutlineSensors } from 'react-icons/md';
|
||||
import { FaSolarPanel } from 'react-icons/fa';
|
||||
import { MdThermostatAuto } from 'react-icons/md';
|
||||
import { AiOutlineControl } from 'react-icons/ai';
|
||||
import { MdThermostatAuto, MdOutlineSensors } from 'react-icons/md';
|
||||
import { GiHeatHaze } from 'react-icons/gi';
|
||||
import { TiFlowSwitch } from 'react-icons/ti';
|
||||
import { VscVmConnect } from 'react-icons/vsc';
|
||||
import { AiOutlineGateway } from 'react-icons/ai';
|
||||
import { AiOutlineAlert } from 'react-icons/ai';
|
||||
import { AiOutlineChrome } from 'react-icons/ai';
|
||||
import { AiOutlineControl, AiOutlineGateway, AiOutlineAlert, AiOutlineChrome } from 'react-icons/ai';
|
||||
|
||||
interface DeviceIconProps {
|
||||
type_id: number;
|
||||
|
||||
@@ -3,9 +3,9 @@ import { Navigate, Route, Routes } from 'react-router-dom';
|
||||
|
||||
import { Tab } from '@mui/material';
|
||||
|
||||
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';
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ import { FC } from 'react';
|
||||
|
||||
import { Typography, Button, Box, List, ListItem, ListItemText, Link, ListItemAvatar } from '@mui/material';
|
||||
|
||||
import { SectionContent } from '../components';
|
||||
import { SectionContent } from 'components';
|
||||
|
||||
import { useSnackbar } from 'notistack';
|
||||
|
||||
@@ -12,9 +12,9 @@ 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 { extractErrorMessage } from 'utils';
|
||||
|
||||
import { useI18nContext } from '../i18n/i18n-react';
|
||||
import { useI18nContext } from 'i18n/i18n-react';
|
||||
|
||||
import * as EMSESP from './api';
|
||||
|
||||
|
||||
@@ -2,15 +2,15 @@ import { FC, useContext } from 'react';
|
||||
|
||||
import { List } from '@mui/material';
|
||||
|
||||
import { AuthenticatedContext } from '../contexts/authentication';
|
||||
import { AuthenticatedContext } from 'contexts/authentication';
|
||||
|
||||
import { PROJECT_PATH } from '../api/env';
|
||||
import { PROJECT_PATH } from 'api/env';
|
||||
|
||||
import { useI18nContext } from '../i18n/i18n-react';
|
||||
import { useI18nContext } from 'i18n/i18n-react';
|
||||
|
||||
import TuneIcon from '@mui/icons-material/Tune';
|
||||
import DashboardIcon from '@mui/icons-material/Dashboard';
|
||||
import LayoutMenuItem from '../components/layout/LayoutMenuItem';
|
||||
import LayoutMenuItem from 'components/layout/LayoutMenuItem';
|
||||
import InfoIcon from '@mui/icons-material/Info';
|
||||
|
||||
const ProjectMenu: FC = () => {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { FC } from 'react';
|
||||
import { Navigate, Routes, Route } from 'react-router-dom';
|
||||
|
||||
import { RequireAdmin } from '../components';
|
||||
import { RequireAdmin } from 'components';
|
||||
|
||||
import Dashboard from './Dashboard';
|
||||
import Settings from './Settings';
|
||||
|
||||
@@ -3,9 +3,9 @@ import { Navigate, Route, Routes } from 'react-router-dom';
|
||||
|
||||
import { Tab } from '@mui/material';
|
||||
|
||||
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 SettingsApplication from './SettingsApplication';
|
||||
import SettingsCustomization from './SettingsCustomization';
|
||||
|
||||
@@ -9,7 +9,7 @@ import WarningIcon from '@mui/icons-material/Warning';
|
||||
import CancelIcon from '@mui/icons-material/Cancel';
|
||||
import PowerSettingsNewIcon from '@mui/icons-material/PowerSettingsNew';
|
||||
|
||||
import { validate } from '../validators';
|
||||
import { validate } from 'validators';
|
||||
import { createSettingsValidator } from './validators';
|
||||
|
||||
import {
|
||||
@@ -20,14 +20,14 @@ import {
|
||||
ButtonRow,
|
||||
MessageBox,
|
||||
BlockNavigation
|
||||
} from '../components';
|
||||
import { numberValue, extractErrorMessage, updateValueDirty, useRest } from '../utils';
|
||||
} from 'components';
|
||||
import { numberValue, extractErrorMessage, updateValueDirty, useRest } from 'utils';
|
||||
|
||||
import * as EMSESP from './api';
|
||||
import { Settings, BOARD_PROFILES } from './types';
|
||||
|
||||
import { useI18nContext } from '../i18n/i18n-react';
|
||||
import RestartMonitor from '../framework/system/RestartMonitor';
|
||||
import { useI18nContext } from 'i18n/i18n-react';
|
||||
import RestartMonitor from 'framework/system/RestartMonitor';
|
||||
|
||||
export function boardProfileSelectItems() {
|
||||
return Object.keys(BOARD_PROFILES).map((code) => (
|
||||
@@ -505,9 +505,9 @@ const SettingsApplication: FC = () => {
|
||||
>
|
||||
<MenuItem value={1}>{LL.ONOFF()}</MenuItem>
|
||||
<MenuItem value={2}>{LL.ONOFF_CAP()}</MenuItem>
|
||||
<MenuItem value={3}>"true"/"false"</MenuItem>
|
||||
<MenuItem value={3}>"true"/"false"</MenuItem>
|
||||
<MenuItem value={4}>true/false</MenuItem>
|
||||
<MenuItem value={5}>"1"/"0"</MenuItem>
|
||||
<MenuItem value={5}>"1"/"0"</MenuItem>
|
||||
<MenuItem value={6}>1/0</MenuItem>
|
||||
</ValidatedTextField>
|
||||
</Grid>
|
||||
|
||||
@@ -19,9 +19,8 @@ import {
|
||||
Link
|
||||
} from '@mui/material';
|
||||
|
||||
import { Table } from '@table-library/react-table-library/table';
|
||||
import { useTheme } from '@table-library/react-table-library/theme';
|
||||
import { 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 { useSnackbar } from 'notistack';
|
||||
|
||||
@@ -36,17 +35,17 @@ import PowerSettingsNewIcon from '@mui/icons-material/PowerSettingsNew';
|
||||
|
||||
import OptionIcon from './OptionIcon';
|
||||
|
||||
import { ButtonRow, FormLoader, ValidatedTextField, SectionContent, MessageBox, BlockNavigation } from '../components';
|
||||
import { ButtonRow, FormLoader, ValidatedTextField, SectionContent, MessageBox, BlockNavigation } from 'components';
|
||||
|
||||
import * as EMSESP from './api';
|
||||
|
||||
import { extractErrorMessage, updateValue } from '../utils';
|
||||
import { extractErrorMessage, updateValue } from 'utils';
|
||||
|
||||
import { DeviceShort, Devices, DeviceEntity, DeviceEntityMask } from './types';
|
||||
|
||||
import { useI18nContext } from '../i18n/i18n-react';
|
||||
import { useI18nContext } from 'i18n/i18n-react';
|
||||
|
||||
import RestartMonitor from '../framework/system/RestartMonitor';
|
||||
import RestartMonitor from 'framework/system/RestartMonitor';
|
||||
|
||||
export const APIURL = window.location.origin + '/api/';
|
||||
|
||||
@@ -57,7 +56,7 @@ const SettingsCustomization: FC = () => {
|
||||
const emptyDeviceEntity = { id: '', v: 0, n: '', cn: '', m: 0, w: false };
|
||||
|
||||
const [numChanges, setNumChanges] = useState<number>(0);
|
||||
let blocker = useBlocker(numChanges !== 0);
|
||||
const blocker = useBlocker(numChanges !== 0);
|
||||
|
||||
const [restarting, setRestarting] = useState<boolean>(false);
|
||||
const [restartNeeded, setRestartNeeded] = useState<boolean>(false);
|
||||
@@ -201,15 +200,15 @@ const SettingsCustomization: FC = () => {
|
||||
}
|
||||
|
||||
const getMaskNumber = (newMask: string[]) => {
|
||||
var new_mask = 0;
|
||||
for (let entry of newMask) {
|
||||
let new_mask = 0;
|
||||
for (const entry of newMask) {
|
||||
new_mask |= Number(entry);
|
||||
}
|
||||
return new_mask;
|
||||
};
|
||||
|
||||
const getMaskString = (m: number) => {
|
||||
var new_masks = [];
|
||||
let new_masks: string[] = [];
|
||||
if ((m & 1) === 1) {
|
||||
new_masks.push('1');
|
||||
}
|
||||
@@ -561,7 +560,6 @@ const SettingsCustomization: FC = () => {
|
||||
</ToggleButtonGroup>
|
||||
)}
|
||||
</Cell>
|
||||
|
||||
<Cell>{!deviceEntity && formatName(de)}</Cell>
|
||||
<Cell>{!deviceEntity && !(de.m & DeviceEntityMask.DV_READONLY) && formatValue(de.mi)}</Cell>
|
||||
<Cell>{!deviceEntity && !(de.m & DeviceEntityMask.DV_READONLY) && formatValue(de.ma)}</Cell>
|
||||
@@ -584,13 +582,7 @@ const SettingsCustomization: FC = () => {
|
||||
<Button startIcon={<CancelIcon />} variant="outlined" onClick={() => setConfirmReset(false)} color="secondary">
|
||||
{LL.CANCEL()}
|
||||
</Button>
|
||||
<Button
|
||||
startIcon={<SettingsBackupRestoreIcon />}
|
||||
variant="outlined"
|
||||
onClick={resetCustomization}
|
||||
autoFocus
|
||||
color="error"
|
||||
>
|
||||
<Button startIcon={<SettingsBackupRestoreIcon />} variant="outlined" onClick={resetCustomization} color="error">
|
||||
{LL.RESET(0)}
|
||||
</Button>
|
||||
</DialogActions>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { AxiosPromise } from 'axios';
|
||||
import { AXIOS, AXIOS_API, AXIOS_BIN } from '../api/endpoints';
|
||||
import { AXIOS, AXIOS_API, AXIOS_BIN } from 'api/endpoints';
|
||||
|
||||
import {
|
||||
BoardProfile,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import Schema, { InternalRuleItem } from 'async-validator';
|
||||
import { IP_OR_HOSTNAME_VALIDATOR } from '../validators/shared';
|
||||
import { IP_OR_HOSTNAME_VALIDATOR } from 'validators/shared';
|
||||
import { Settings } from './types';
|
||||
|
||||
export const GPIO_VALIDATOR = {
|
||||
|
||||
1
interface/src/react-app-env.d.ts
vendored
1
interface/src/react-app-env.d.ts
vendored
@@ -1 +0,0 @@
|
||||
/// <reference types="react-scripts" />
|
||||
@@ -1,19 +0,0 @@
|
||||
const pkg = require('../package.json');
|
||||
const { createProxyMiddleware } = require('http-proxy-middleware');
|
||||
const target = process.env.PROXY || pkg.proxy;
|
||||
|
||||
module.exports = function (app) {
|
||||
app.use(
|
||||
createProxyMiddleware('/api', {
|
||||
target
|
||||
})
|
||||
);
|
||||
|
||||
// app.use(
|
||||
// createProxyMiddleware('/ws', {
|
||||
// target: target,
|
||||
// // target: target.replace(/^http(s?):\/\//, 'ws$1://'),
|
||||
// ws: true
|
||||
// })
|
||||
// );
|
||||
};
|
||||
@@ -1,42 +0,0 @@
|
||||
import * as React from 'react';
|
||||
import { useBeforeUnload, unstable_useBlocker as useBlocker } from 'react-router-dom';
|
||||
|
||||
// You can abstract `useBlocker` to use the browser's `window.confirm` dialog to
|
||||
// determine whether or not the user should navigate within the current origin.
|
||||
// `useBlocker` can also be used in conjunction with `useBeforeUnload` to
|
||||
// prevent navigation away from the current origin.
|
||||
//
|
||||
// IMPORTANT: There are edge cases with this behavior in which React Router
|
||||
// cannot reliably access the correct location in the history stack. In such
|
||||
// cases the user may attempt to stay on the page but the app navigates anyway,
|
||||
// or the app may stay on the correct page but the browser's history stack gets
|
||||
// out of whack. You should test your own implementation thoroughly to make sure
|
||||
// the tradeoffs are right for your users.
|
||||
export default function usePrompt(
|
||||
message: string | null | undefined | false,
|
||||
{ beforeUnload }: { beforeUnload?: boolean } = {}
|
||||
) {
|
||||
let blocker = useBlocker(
|
||||
React.useCallback(() => (typeof message === 'string' ? !window.confirm(message) : false), [message])
|
||||
);
|
||||
let prevState = React.useRef(blocker.state);
|
||||
React.useEffect(() => {
|
||||
if (blocker.state === 'blocked') {
|
||||
blocker.reset();
|
||||
}
|
||||
prevState.current = blocker.state;
|
||||
}, [blocker]);
|
||||
|
||||
useBeforeUnload(
|
||||
React.useCallback(
|
||||
(event) => {
|
||||
if (beforeUnload && typeof message === 'string') {
|
||||
event.preventDefault();
|
||||
event.returnValue = message;
|
||||
}
|
||||
},
|
||||
[message, beforeUnload]
|
||||
),
|
||||
{ capture: true }
|
||||
);
|
||||
}
|
||||
@@ -4,7 +4,7 @@ import { AxiosPromise } from 'axios';
|
||||
|
||||
import { extractErrorMessage } from '.';
|
||||
|
||||
import { useI18nContext } from '../i18n/i18n-react';
|
||||
import { useI18nContext } from 'i18n/i18n-react';
|
||||
|
||||
import { unstable_useBlocker as useBlocker } from 'react-router-dom';
|
||||
|
||||
@@ -26,7 +26,7 @@ export const useRest = <D>({ read, update }: RestRequestOptions<D>) => {
|
||||
const [origData, setOrigData] = useState<D>();
|
||||
const [dirtyFlags, setDirtyFlags] = useState<string[]>();
|
||||
|
||||
let blocker = useBlocker(dirtyFlags?.length !== 0);
|
||||
const blocker = useBlocker(dirtyFlags?.length !== 0);
|
||||
|
||||
const loadData = useCallback(async () => {
|
||||
setData(undefined);
|
||||
|
||||
@@ -2,7 +2,7 @@ import { useCallback, useEffect, useRef, useState } from 'react';
|
||||
import Sockette from 'sockette';
|
||||
import { debounce } from 'lodash-es';
|
||||
|
||||
import { addAccessTokenParameter } from '../api/authentication';
|
||||
import { addAccessTokenParameter } from 'api/authentication';
|
||||
|
||||
interface WebSocketIdMessage {
|
||||
type: 'id';
|
||||
@@ -17,7 +17,7 @@ interface WebSocketPayloadMessage<D> {
|
||||
|
||||
export type WebSocketMessage<D> = WebSocketIdMessage | WebSocketPayloadMessage<D>;
|
||||
|
||||
export const useWs = <D>(wsUrl: string, wsThrottle: number = 100) => {
|
||||
export const useWs = <D>(wsUrl: string, wsThrottle = 100) => {
|
||||
const ws = useRef<Sockette>();
|
||||
const clientId = useRef<string>();
|
||||
|
||||
@@ -43,7 +43,7 @@ export const useWs = <D>(wsUrl: string, wsThrottle: number = 100) => {
|
||||
}
|
||||
}, []);
|
||||
|
||||
const doSaveData = useCallback((newData: D, clearData: boolean = false) => {
|
||||
const doSaveData = useCallback((newData: D, clearData = false) => {
|
||||
if (!ws.current) {
|
||||
return;
|
||||
}
|
||||
@@ -55,11 +55,7 @@ export const useWs = <D>(wsUrl: string, wsThrottle: number = 100) => {
|
||||
|
||||
const saveData = useRef(debounce(doSaveData, wsThrottle));
|
||||
|
||||
const updateData = (
|
||||
newData: React.SetStateAction<D | undefined>,
|
||||
transmitData: boolean = true,
|
||||
clearData: boolean = false
|
||||
) => {
|
||||
const updateData = (newData: React.SetStateAction<D | undefined>, transmitData: true, clearData: false) => {
|
||||
setData(newData);
|
||||
setTransmit(transmitData);
|
||||
setClear(clearData);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import Schema from 'async-validator';
|
||||
import { isAPEnabled } from '../framework/ap/APSettingsForm';
|
||||
import { APSettings } from '../types';
|
||||
import { isAPEnabled } from 'framework/ap/APSettingsForm';
|
||||
import { APSettings } from 'types';
|
||||
import { IP_ADDRESS_VALIDATOR } from './shared';
|
||||
|
||||
export const createAPSettingsValidator = (apSettings: APSettings) =>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import Schema from 'async-validator';
|
||||
import { MqttSettings } from '../types';
|
||||
import { MqttSettings } from 'types';
|
||||
import { IP_OR_HOSTNAME_VALIDATOR } from './shared';
|
||||
|
||||
export const createMqttSettingsValidator = (mqttSettings: MqttSettings) =>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import Schema from 'async-validator';
|
||||
import { NetworkSettings } from '../types';
|
||||
import { NetworkSettings } from 'types';
|
||||
import { HOSTNAME_VALIDATOR, IP_ADDRESS_VALIDATOR } from './shared';
|
||||
|
||||
export const createNetworkSettingsValidator = (networkSettings: NetworkSettings) =>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import Schema, { InternalRuleItem } from 'async-validator';
|
||||
import { User } from '../types';
|
||||
import { User } from 'types';
|
||||
|
||||
export const SECURITY_SETTINGS_VALIDATOR = new Schema({
|
||||
jwt_secret: [
|
||||
|
||||
1
interface/src/vite-env.d.ts
vendored
Normal file
1
interface/src/vite-env.d.ts
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/// <reference types="vite/client" />
|
||||
@@ -1,21 +1,29 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"lib": ["dom", "dom.iterable", "esnext"],
|
||||
"allowJs": true,
|
||||
"target": "ESNext",
|
||||
"useDefineForClassFields": true,
|
||||
"lib": ["DOM", "DOM.Iterable", "ESNext"],
|
||||
"types": ["vite/client", "vite-plugin-svgr/client", "node"],
|
||||
"allowJs": false,
|
||||
"skipLibCheck": true,
|
||||
"esModuleInterop": true,
|
||||
"esModuleInterop": false,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"strict": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"module": "esnext",
|
||||
"moduleResolution": "node",
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "Node",
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"noEmit": true,
|
||||
"useUnknownInCatchVariables": false,
|
||||
"jsx": "react-jsx"
|
||||
"jsx": "react-jsx",
|
||||
"noImplicitAny": false,
|
||||
"baseUrl": "src",
|
||||
"paths": {
|
||||
"@": ["src"],
|
||||
"@/*": ["src/*"]
|
||||
}
|
||||
},
|
||||
"include": ["src"]
|
||||
"include": ["src", "vite.config.ts", "progmem-generator.js"]
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user