mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2025-12-06 15:59:52 +03:00
43
.github/workflows/sonar_check.yml
vendored
43
.github/workflows/sonar_check.yml
vendored
@@ -1,4 +1,4 @@
|
|||||||
name: Sonar Check
|
name: Sonar Check2
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
@@ -7,51 +7,24 @@ on:
|
|||||||
types: [opened, synchronize, reopened]
|
types: [opened, synchronize, reopened]
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
name: Build
|
name: Build and analyze
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
if: github.repository_owner == 'emsesp'
|
# if: github.repository_owner == 'emsesp'
|
||||||
# if: github.repository == 'emsesp/EMS-ESP32'
|
# if: github.repository == 'emsesp/EMS-ESP32'
|
||||||
env:
|
env:
|
||||||
# https://binaries.sonarsource.com/?prefix=Distribution/sonar-scanner-cli/
|
|
||||||
SONAR_SCANNER_VERSION: 4.7.0.2747
|
|
||||||
SONAR_SERVER_URL: "https://sonarcloud.io"
|
|
||||||
BUILD_WRAPPER_OUT_DIR: build_wrapper_output_directory
|
BUILD_WRAPPER_OUT_DIR: build_wrapper_output_directory
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis
|
fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis
|
||||||
- name: Set up JDK 11
|
- name: Install sonar-scanner and build-wrapper
|
||||||
uses: actions/setup-java@v1
|
uses: SonarSource/sonarcloud-github-c-cpp@v1
|
||||||
with:
|
|
||||||
java-version: 11
|
|
||||||
- name: Cache SonarCloud packages
|
|
||||||
uses: actions/cache@v1
|
|
||||||
with:
|
|
||||||
path: ~/.sonar/cache
|
|
||||||
key: ${{ runner.os }}-sonar
|
|
||||||
restore-keys: ${{ runner.os }}-sonar
|
|
||||||
- name: Download and set up sonar-scanner
|
|
||||||
env:
|
|
||||||
SONAR_SCANNER_DOWNLOAD_URL: https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-${{ env.SONAR_SCANNER_VERSION }}-linux.zip
|
|
||||||
run: |
|
|
||||||
mkdir -p $HOME/.sonar
|
|
||||||
curl -sSLo $HOME/.sonar/sonar-scanner.zip ${{ env.SONAR_SCANNER_DOWNLOAD_URL }}
|
|
||||||
unzip -o $HOME/.sonar/sonar-scanner.zip -d $HOME/.sonar/
|
|
||||||
echo "$HOME/.sonar/sonar-scanner-${{ env.SONAR_SCANNER_VERSION }}-linux/bin" >> $GITHUB_PATH
|
|
||||||
- name: Download and set up build-wrapper
|
|
||||||
env:
|
|
||||||
BUILD_WRAPPER_DOWNLOAD_URL: ${{ env.SONAR_SERVER_URL }}/static/cpp/build-wrapper-linux-x86.zip
|
|
||||||
run: |
|
|
||||||
curl -sSLo $HOME/.sonar/build-wrapper-linux-x86.zip ${{ env.BUILD_WRAPPER_DOWNLOAD_URL }}
|
|
||||||
unzip -o $HOME/.sonar/build-wrapper-linux-x86.zip -d $HOME/.sonar/
|
|
||||||
echo "$HOME/.sonar/build-wrapper-linux-x86" >> $GITHUB_PATH
|
|
||||||
- name: Run build-wrapper
|
- name: Run build-wrapper
|
||||||
run: |
|
run: |
|
||||||
make clean
|
build-wrapper-linux-x86-64 --out-dir ${{ env.BUILD_WRAPPER_OUT_DIR }} make all
|
||||||
build-wrapper-linux-x86-64 --out-dir ${{ env.BUILD_WRAPPER_OUT_DIR }} make clean all
|
|
||||||
- name: Run sonar-scanner
|
- name: Run sonar-scanner
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
|
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
|
||||||
run: |
|
run: |
|
||||||
sonar-scanner
|
sonar-scanner --define sonar.cfamily.build-wrapper-output="${{ env.BUILD_WRAPPER_OUT_DIR }}"
|
||||||
|
|||||||
@@ -24,7 +24,7 @@
|
|||||||
"@msgpack/msgpack": "^2.8.0",
|
"@msgpack/msgpack": "^2.8.0",
|
||||||
"@mui/icons-material": "^5.11.11",
|
"@mui/icons-material": "^5.11.11",
|
||||||
"@mui/material": "^5.11.12",
|
"@mui/material": "^5.11.12",
|
||||||
"@remix-run/router": "^1.3.3",
|
"@remix-run/router": "^1.4.0",
|
||||||
"@table-library/react-table-library": "4.0.29",
|
"@table-library/react-table-library": "4.0.29",
|
||||||
"@types/lodash-es": "^4.17.6",
|
"@types/lodash-es": "^4.17.6",
|
||||||
"@types/node": "^18.15.0",
|
"@types/node": "^18.15.0",
|
||||||
@@ -38,12 +38,12 @@
|
|||||||
"jwt-decode": "^3.1.2",
|
"jwt-decode": "^3.1.2",
|
||||||
"lodash-es": "^4.17.21",
|
"lodash-es": "^4.17.21",
|
||||||
"mime-types": "^2.1.35",
|
"mime-types": "^2.1.35",
|
||||||
"notistack": "2.0.8",
|
|
||||||
"react": "latest",
|
"react": "latest",
|
||||||
"react-dom": "latest",
|
"react-dom": "latest",
|
||||||
"react-dropzone": "^14.2.3",
|
"react-dropzone": "^14.2.3",
|
||||||
"react-icons": "^4.8.0",
|
"react-icons": "^4.8.0",
|
||||||
"react-router-dom": "^6.8.2",
|
"react-router-dom": "^6.9.0",
|
||||||
|
"react-toastify": "^9.1.1",
|
||||||
"sockette": "^2.0.6",
|
"sockette": "^2.0.6",
|
||||||
"typesafe-i18n": "^5.24.2",
|
"typesafe-i18n": "^5.24.2",
|
||||||
"typescript": "^4.9.5"
|
"typescript": "^4.9.5"
|
||||||
@@ -54,7 +54,7 @@
|
|||||||
"@typescript-eslint/eslint-plugin": "^5.54.1",
|
"@typescript-eslint/eslint-plugin": "^5.54.1",
|
||||||
"@typescript-eslint/parser": "^5.54.1",
|
"@typescript-eslint/parser": "^5.54.1",
|
||||||
"@vitejs/plugin-react-swc": "^3.2.0",
|
"@vitejs/plugin-react-swc": "^3.2.0",
|
||||||
"eslint": "^8.35.0",
|
"eslint": "^8.36.0",
|
||||||
"eslint-config-prettier": "^8.7.0",
|
"eslint-config-prettier": "^8.7.0",
|
||||||
"eslint-import-resolver-typescript": "^3.5.3",
|
"eslint-import-resolver-typescript": "^3.5.3",
|
||||||
"eslint-plugin-deprecation": "^1.3.3",
|
"eslint-plugin-deprecation": "^1.3.3",
|
||||||
@@ -65,7 +65,9 @@
|
|||||||
"npm-run-all": "^4.1.5",
|
"npm-run-all": "^4.1.5",
|
||||||
"prettier": "^2.8.4",
|
"prettier": "^2.8.4",
|
||||||
"rollup-plugin-visualizer": "^5.9.0",
|
"rollup-plugin-visualizer": "^5.9.0",
|
||||||
|
"terser": "^5.16.6",
|
||||||
"vite": "^4.1.4",
|
"vite": "^4.1.4",
|
||||||
|
"vite-plugin-minify": "^1.5.2",
|
||||||
"vite-plugin-svgr": "^2.4.0",
|
"vite-plugin-svgr": "^2.4.0",
|
||||||
"vite-tsconfig-paths": "^4.0.5"
|
"vite-tsconfig-paths": "^4.0.5"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
/*
|
/*
|
||||||
* Just supporting latin due to size constrains on the esp chip
|
* Just supporting latin due to size constrains on the esp chip
|
||||||
*
|
*
|
||||||
* The framework only makes use of 400 (regular) + 500 (medium) weight fonts.
|
* The framework only makes use of 400 (regular) weight fonts.
|
||||||
*
|
*
|
||||||
* If using light or strong typography variants you will need to add additional fonts.
|
* If using medium (500), light or strong typography variants you will need to add additional fonts.
|
||||||
*/
|
*/
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Roboto';
|
font-family: 'Roboto';
|
||||||
@@ -14,13 +14,3 @@
|
|||||||
U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF,
|
U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF,
|
||||||
U+FFFD;
|
U+FFFD;
|
||||||
}
|
}
|
||||||
|
|
||||||
@font-face {
|
|
||||||
font-family: 'Roboto';
|
|
||||||
font-style: normal;
|
|
||||||
font-weight: 500;
|
|
||||||
src: local('Roboto Medium'), local('Roboto-Medium'), url(../fonts/md.woff2) format('woff2');
|
|
||||||
unicode-range: U+0000-00FF, U+0104-0107, U+0118-0119, U+0131, U+0141-0144, U+0152-0153, U+015A-015B, U+0179-017C,
|
|
||||||
U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF,
|
|
||||||
U+FFFD;
|
|
||||||
}
|
|
||||||
|
|||||||
Binary file not shown.
@@ -1,8 +1,7 @@
|
|||||||
import { FC, createRef, useEffect, useState, RefObject } from 'react';
|
import { FC, useEffect, useState } from 'react';
|
||||||
import { SnackbarProvider } from 'notistack';
|
|
||||||
|
|
||||||
import { IconButton } from '@mui/material';
|
import { ToastContainer, Slide } from 'react-toastify';
|
||||||
import CloseIcon from '@mui/icons-material/Close';
|
import 'react-toastify/dist/ReactToastify.min.css';
|
||||||
|
|
||||||
import CustomTheme from 'CustomTheme';
|
import CustomTheme from 'CustomTheme';
|
||||||
import AppRouting from 'AppRouting';
|
import AppRouting from 'AppRouting';
|
||||||
@@ -15,12 +14,6 @@ import { loadLocaleAsync } from 'i18n/i18n-util.async';
|
|||||||
const detectedLocale = detectLocale(localStorageDetector);
|
const detectedLocale = detectLocale(localStorageDetector);
|
||||||
|
|
||||||
const App: FC = () => {
|
const App: FC = () => {
|
||||||
const notistackRef: RefObject<any> = createRef();
|
|
||||||
|
|
||||||
const onClickDismiss = (key: string | number | undefined) => () => {
|
|
||||||
notistackRef.current.closeSnackbar(key);
|
|
||||||
};
|
|
||||||
|
|
||||||
const [wasLoaded, setWasLoaded] = useState(false);
|
const [wasLoaded, setWasLoaded] = useState(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -32,18 +25,21 @@ const App: FC = () => {
|
|||||||
return (
|
return (
|
||||||
<TypesafeI18n locale={detectedLocale}>
|
<TypesafeI18n locale={detectedLocale}>
|
||||||
<CustomTheme>
|
<CustomTheme>
|
||||||
<SnackbarProvider
|
|
||||||
maxSnack={3}
|
|
||||||
anchorOrigin={{ vertical: 'bottom', horizontal: 'left' }}
|
|
||||||
ref={notistackRef}
|
|
||||||
action={(key) => (
|
|
||||||
<IconButton onClick={onClickDismiss(key)} size="small">
|
|
||||||
<CloseIcon />
|
|
||||||
</IconButton>
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<AppRouting />
|
<AppRouting />
|
||||||
</SnackbarProvider>
|
<ToastContainer
|
||||||
|
position="bottom-left"
|
||||||
|
autoClose={2000}
|
||||||
|
hideProgressBar={false}
|
||||||
|
newestOnTop={false}
|
||||||
|
closeOnClick={true}
|
||||||
|
rtl={false}
|
||||||
|
pauseOnFocusLoss={false}
|
||||||
|
draggable={false}
|
||||||
|
pauseOnHover={false}
|
||||||
|
transition={Slide}
|
||||||
|
closeButton={false}
|
||||||
|
theme="light"
|
||||||
|
/>
|
||||||
</CustomTheme>
|
</CustomTheme>
|
||||||
</TypesafeI18n>
|
</TypesafeI18n>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { FC, useContext, useEffect } from 'react';
|
|||||||
|
|
||||||
import { Route, Routes, Navigate, useLocation } from 'react-router-dom';
|
import { Route, Routes, Navigate, useLocation } from 'react-router-dom';
|
||||||
|
|
||||||
import { useSnackbar, VariantType } from 'notistack';
|
import { toast } from 'react-toastify';
|
||||||
|
|
||||||
import { useI18nContext } from 'i18n/i18n-react';
|
import { useI18nContext } from 'i18n/i18n-react';
|
||||||
|
|
||||||
@@ -14,17 +14,15 @@ import AuthenticatedRouting from 'AuthenticatedRouting';
|
|||||||
|
|
||||||
interface SecurityRedirectProps {
|
interface SecurityRedirectProps {
|
||||||
message: string;
|
message: string;
|
||||||
variant?: VariantType;
|
|
||||||
signOut?: boolean;
|
signOut?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const RootRedirect: FC<SecurityRedirectProps> = ({ message, variant, signOut }) => {
|
const RootRedirect: FC<SecurityRedirectProps> = ({ message, signOut }) => {
|
||||||
const authenticationContext = useContext(AuthenticationContext);
|
const authenticationContext = useContext(AuthenticationContext);
|
||||||
const { enqueueSnackbar } = useSnackbar();
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
signOut && authenticationContext.signOut(false);
|
signOut && authenticationContext.signOut(false);
|
||||||
enqueueSnackbar(message, { variant });
|
toast.success(message);
|
||||||
}, [message, variant, signOut, authenticationContext, enqueueSnackbar]);
|
}, [message, signOut, authenticationContext]);
|
||||||
return <Navigate to="/" />;
|
return <Navigate to="/" />;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -50,7 +48,7 @@ const AppRouting: FC = () => {
|
|||||||
<RemoveTrailingSlashes />
|
<RemoveTrailingSlashes />
|
||||||
<Routes>
|
<Routes>
|
||||||
<Route path="/unauthorized" element={<RootRedirect message={LL.PLEASE_SIGNIN()} signOut />} />
|
<Route path="/unauthorized" element={<RootRedirect message={LL.PLEASE_SIGNIN()} signOut />} />
|
||||||
<Route path="/fileUpdated" element={<RootRedirect message={LL.UPLOAD_SUCCESSFUL()} variant="success" />} />
|
<Route path="/fileUpdated" element={<RootRedirect message={LL.UPLOAD_SUCCESSFUL()} />} />
|
||||||
<Route
|
<Route
|
||||||
path="/"
|
path="/"
|
||||||
element={
|
element={
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { FC, useContext, useState } from 'react';
|
import { FC, useContext, useState } from 'react';
|
||||||
import { ValidateFieldsError } from 'async-validator';
|
import { ValidateFieldsError } from 'async-validator';
|
||||||
import { useSnackbar } from 'notistack';
|
import { toast } from 'react-toastify';
|
||||||
|
|
||||||
import { Box, Fab, Paper, Typography, Button } from '@mui/material';
|
import { Box, Fab, Paper, Typography, Button } from '@mui/material';
|
||||||
import ForwardIcon from '@mui/icons-material/Forward';
|
import ForwardIcon from '@mui/icons-material/Forward';
|
||||||
@@ -29,7 +29,6 @@ import { ReactComponent as TRflag } from 'i18n/TR.svg';
|
|||||||
|
|
||||||
const SignIn: FC = () => {
|
const SignIn: FC = () => {
|
||||||
const authenticationContext = useContext(AuthenticationContext);
|
const authenticationContext = useContext(AuthenticationContext);
|
||||||
const { enqueueSnackbar } = useSnackbar();
|
|
||||||
|
|
||||||
const [signInRequest, setSignInRequest] = useState<SignInRequest>({
|
const [signInRequest, setSignInRequest] = useState<SignInRequest>({
|
||||||
username: '',
|
username: '',
|
||||||
@@ -61,10 +60,10 @@ const SignIn: FC = () => {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error.response) {
|
if (error.response) {
|
||||||
if (error.response?.status === 401) {
|
if (error.response?.status === 401) {
|
||||||
enqueueSnackbar(LL.INVALID_LOGIN(), { variant: 'warning' });
|
toast.warn(LL.INVALID_LOGIN());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
enqueueSnackbar(extractErrorMessage(error, LL.ERROR()), { variant: 'error' });
|
toast.error(extractErrorMessage(error, LL.ERROR()));
|
||||||
}
|
}
|
||||||
setProcessing(false);
|
setProcessing(false);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { useCallback, useEffect, useState } from 'react';
|
import { useCallback, useEffect, useState } from 'react';
|
||||||
import axios, { AxiosPromise, CancelTokenSource, AxiosProgressEvent } from 'axios';
|
import axios, { AxiosPromise, CancelTokenSource, AxiosProgressEvent } from 'axios';
|
||||||
import { useSnackbar } from 'notistack';
|
import { toast } from 'react-toastify';
|
||||||
|
|
||||||
import { extractErrorMessage } from 'utils';
|
import { extractErrorMessage } from 'utils';
|
||||||
import { FileUploadConfig } from 'api/endpoints';
|
import { FileUploadConfig } from 'api/endpoints';
|
||||||
@@ -14,7 +14,6 @@ interface MediaUploadOptions {
|
|||||||
const useFileUpload = ({ upload }: MediaUploadOptions) => {
|
const useFileUpload = ({ upload }: MediaUploadOptions) => {
|
||||||
const { LL } = useI18nContext();
|
const { LL } = useI18nContext();
|
||||||
|
|
||||||
const { enqueueSnackbar } = useSnackbar();
|
|
||||||
const [uploading, setUploading] = useState<boolean>(false);
|
const [uploading, setUploading] = useState<boolean>(false);
|
||||||
const [md5, setMd5] = useState<string>('');
|
const [md5, setMd5] = useState<string>('');
|
||||||
const [uploadProgress, setUploadProgress] = useState<AxiosProgressEvent>();
|
const [uploadProgress, setUploadProgress] = useState<AxiosProgressEvent>();
|
||||||
@@ -49,17 +48,17 @@ const useFileUpload = ({ upload }: MediaUploadOptions) => {
|
|||||||
});
|
});
|
||||||
resetUploadingStates();
|
resetUploadingStates();
|
||||||
if (response.status === 200) {
|
if (response.status === 200) {
|
||||||
enqueueSnackbar(LL.UPLOAD() + ' ' + LL.SUCCESSFUL(), { variant: 'success' });
|
toast.success(LL.UPLOAD() + ' ' + LL.SUCCESSFUL());
|
||||||
} else if (response.status === 201) {
|
} else if (response.status === 201) {
|
||||||
setMd5(String(response.data));
|
setMd5(String(response.data));
|
||||||
enqueueSnackbar(LL.UPLOAD() + ' MD5 ' + LL.SUCCESSFUL(), { variant: 'success' });
|
toast.success(LL.UPLOAD() + ' MD5 ' + LL.SUCCESSFUL());
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (axios.isCancel(error)) {
|
if (axios.isCancel(error)) {
|
||||||
enqueueSnackbar(LL.UPLOAD() + ' ' + LL.ABORTED(), { variant: 'warning' });
|
toast.warning(LL.UPLOAD() + ' ' + LL.ABORTED());
|
||||||
} else {
|
} else {
|
||||||
resetUploadingStates();
|
resetUploadingStates();
|
||||||
enqueueSnackbar(extractErrorMessage(error, LL.UPLOAD() + ' ' + LL.FAILED()), { variant: 'error' });
|
toast.error(extractErrorMessage(error, LL.UPLOAD() + ' ' + LL.FAILED()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { FC, useCallback, useEffect, useState } from 'react';
|
import { FC, useCallback, useEffect, useState } from 'react';
|
||||||
import { useSnackbar } from 'notistack';
|
import { toast } from 'react-toastify';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
|
|
||||||
import { useI18nContext } from 'i18n/i18n-react';
|
import { useI18nContext } from 'i18n/i18n-react';
|
||||||
@@ -15,7 +15,6 @@ const Authentication: FC<RequiredChildrenProps> = ({ children }) => {
|
|||||||
const { LL } = useI18nContext();
|
const { LL } = useI18nContext();
|
||||||
|
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const { enqueueSnackbar } = useSnackbar();
|
|
||||||
|
|
||||||
const [initialized, setInitialized] = useState<boolean>(false);
|
const [initialized, setInitialized] = useState<boolean>(false);
|
||||||
const [me, setMe] = useState<Me>();
|
const [me, setMe] = useState<Me>();
|
||||||
@@ -25,7 +24,7 @@ const Authentication: FC<RequiredChildrenProps> = ({ children }) => {
|
|||||||
AuthenticationApi.getStorage().setItem(ACCESS_TOKEN, accessToken);
|
AuthenticationApi.getStorage().setItem(ACCESS_TOKEN, accessToken);
|
||||||
const decodedMe = AuthenticationApi.decodeMeJWT(accessToken);
|
const decodedMe = AuthenticationApi.decodeMeJWT(accessToken);
|
||||||
setMe(decodedMe);
|
setMe(decodedMe);
|
||||||
enqueueSnackbar(LL.LOGGED_IN({ name: decodedMe.username }), { variant: 'success' });
|
toast.success(LL.LOGGED_IN({ name: decodedMe.username }));
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
setMe(undefined);
|
setMe(undefined);
|
||||||
throw new Error('Failed to parse JWT');
|
throw new Error('Failed to parse JWT');
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { FC, useContext, useEffect, useState } from 'react';
|
import { FC, useContext, useEffect, useState } from 'react';
|
||||||
import { useSnackbar } from 'notistack';
|
import { toast } from 'react-toastify';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Avatar,
|
Avatar,
|
||||||
@@ -48,7 +48,6 @@ import RestartMonitor from '../system/RestartMonitor';
|
|||||||
|
|
||||||
const WiFiSettingsForm: FC = () => {
|
const WiFiSettingsForm: FC = () => {
|
||||||
const { LL } = useI18nContext();
|
const { LL } = useI18nContext();
|
||||||
const { enqueueSnackbar } = useSnackbar();
|
|
||||||
|
|
||||||
const { selectedNetwork, deselectNetwork } = useContext(WiFiConnectionContext);
|
const { selectedNetwork, deselectNetwork } = useContext(WiFiConnectionContext);
|
||||||
|
|
||||||
@@ -118,7 +117,7 @@ const WiFiSettingsForm: FC = () => {
|
|||||||
await EMSESP.restart();
|
await EMSESP.restart();
|
||||||
setRestarting(true);
|
setRestarting(true);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
enqueueSnackbar(LL.PROBLEM_UPDATING(), { variant: 'error' });
|
toast.error(LL.PROBLEM_UPDATING());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { useEffect, FC, useState, useCallback, useRef } from 'react';
|
import { useEffect, FC, useState, useCallback, useRef } from 'react';
|
||||||
import { useSnackbar } from 'notistack';
|
import { toast } from 'react-toastify';
|
||||||
|
|
||||||
import { Button } from '@mui/material';
|
import { Button } from '@mui/material';
|
||||||
import PermScanWifiIcon from '@mui/icons-material/PermScanWifi';
|
import PermScanWifiIcon from '@mui/icons-material/PermScanWifi';
|
||||||
@@ -24,20 +24,15 @@ const compareNetworks = (network1: WiFiNetwork, network2: WiFiNetwork) => {
|
|||||||
const WiFiNetworkScanner: FC = () => {
|
const WiFiNetworkScanner: FC = () => {
|
||||||
const { LL } = useI18nContext();
|
const { LL } = useI18nContext();
|
||||||
|
|
||||||
const { enqueueSnackbar } = useSnackbar();
|
|
||||||
|
|
||||||
const pollCount = useRef(0);
|
const pollCount = useRef(0);
|
||||||
const [networkList, setNetworkList] = useState<WiFiNetworkList>();
|
const [networkList, setNetworkList] = useState<WiFiNetworkList>();
|
||||||
const [errorMessage, setErrorMessage] = useState<string>();
|
const [errorMessage, setErrorMessage] = useState<string>();
|
||||||
|
|
||||||
const finishedWithError = useCallback(
|
const finishedWithError = useCallback((message: string) => {
|
||||||
(message: string) => {
|
toast.error(message);
|
||||||
enqueueSnackbar(message, { variant: 'error' });
|
|
||||||
setNetworkList(undefined);
|
setNetworkList(undefined);
|
||||||
setErrorMessage(message);
|
setErrorMessage(message);
|
||||||
},
|
}, []);
|
||||||
[enqueueSnackbar]
|
|
||||||
);
|
|
||||||
|
|
||||||
const pollNetworkList = useCallback(async () => {
|
const pollNetworkList = useCallback(async () => {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { FC, useContext, useState } from 'react';
|
import { FC, useContext, useState } from 'react';
|
||||||
import { useSnackbar } from 'notistack';
|
import { toast } from 'react-toastify';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Avatar,
|
Avatar,
|
||||||
@@ -55,7 +55,6 @@ const NTPStatusForm: FC = () => {
|
|||||||
const [localTime, setLocalTime] = useState<string>('');
|
const [localTime, setLocalTime] = useState<string>('');
|
||||||
const [settingTime, setSettingTime] = useState<boolean>(false);
|
const [settingTime, setSettingTime] = useState<boolean>(false);
|
||||||
const [processing, setProcessing] = useState<boolean>(false);
|
const [processing, setProcessing] = useState<boolean>(false);
|
||||||
const { enqueueSnackbar } = useSnackbar();
|
|
||||||
const { me } = useContext(AuthenticatedContext);
|
const { me } = useContext(AuthenticatedContext);
|
||||||
|
|
||||||
const { LL } = useI18nContext();
|
const { LL } = useI18nContext();
|
||||||
@@ -88,11 +87,11 @@ const NTPStatusForm: FC = () => {
|
|||||||
await NTPApi.updateTime({
|
await NTPApi.updateTime({
|
||||||
local_time: formatLocalDateTime(new Date(localTime))
|
local_time: formatLocalDateTime(new Date(localTime))
|
||||||
});
|
});
|
||||||
enqueueSnackbar(LL.TIME_SET(), { variant: 'success' });
|
toast.success(LL.TIME_SET());
|
||||||
setSettingTime(false);
|
setSettingTime(false);
|
||||||
loadData();
|
loadData();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_UPDATING()), { variant: 'error' });
|
toast.error(extractErrorMessage(error, LL.PROBLEM_UPDATING()));
|
||||||
} finally {
|
} finally {
|
||||||
setProcessing(false);
|
setProcessing(false);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import {
|
|||||||
import CloseIcon from '@mui/icons-material/Close';
|
import CloseIcon from '@mui/icons-material/Close';
|
||||||
|
|
||||||
import { extractErrorMessage } from 'utils';
|
import { extractErrorMessage } from 'utils';
|
||||||
import { useSnackbar } from 'notistack';
|
import { toast } from 'react-toastify';
|
||||||
import { MessageBox } from 'components';
|
import { MessageBox } from 'components';
|
||||||
import * as SecurityApi from 'api/security';
|
import * as SecurityApi from 'api/security';
|
||||||
import { Token } from 'types';
|
import { Token } from 'types';
|
||||||
@@ -32,15 +32,13 @@ const GenerateToken: FC<GenerateTokenProps> = ({ username, onClose }) => {
|
|||||||
|
|
||||||
const { LL } = useI18nContext();
|
const { LL } = useI18nContext();
|
||||||
|
|
||||||
const { enqueueSnackbar } = useSnackbar();
|
|
||||||
|
|
||||||
const getToken = useCallback(async () => {
|
const getToken = useCallback(async () => {
|
||||||
try {
|
try {
|
||||||
setToken((await SecurityApi.generateToken(username)).data);
|
setToken((await SecurityApi.generateToken(username)).data);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_UPDATING()), { variant: 'error' });
|
toast.error(extractErrorMessage(error, LL.PROBLEM_UPDATING()));
|
||||||
}
|
}
|
||||||
}, [username, enqueueSnackbar, LL]);
|
}, [username, LL]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (open) {
|
if (open) {
|
||||||
|
|||||||
@@ -50,8 +50,7 @@ const ManageUsersForm: FC = () => {
|
|||||||
color: #90CAF9;
|
color: #90CAF9;
|
||||||
.th {
|
.th {
|
||||||
padding: 8px;
|
padding: 8px;
|
||||||
height: 42px;
|
height: 36px;
|
||||||
font-weight: 500;
|
|
||||||
border-bottom: 1px solid #565656;
|
border-bottom: 1px solid #565656;
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import { SingleUpload, useFileUpload } from 'components';
|
|||||||
|
|
||||||
import DownloadIcon from '@mui/icons-material/GetApp';
|
import DownloadIcon from '@mui/icons-material/GetApp';
|
||||||
|
|
||||||
import { useSnackbar } from 'notistack';
|
import { toast } from 'react-toastify';
|
||||||
|
|
||||||
import { extractErrorMessage } from 'utils';
|
import { extractErrorMessage } from 'utils';
|
||||||
|
|
||||||
@@ -24,8 +24,6 @@ interface UploadFileProps {
|
|||||||
const GeneralFileUpload: FC<UploadFileProps> = ({ uploadGeneralFile }) => {
|
const GeneralFileUpload: FC<UploadFileProps> = ({ uploadGeneralFile }) => {
|
||||||
const [uploadFile, cancelUpload, uploading, uploadProgress, md5] = useFileUpload({ upload: uploadGeneralFile });
|
const [uploadFile, cancelUpload, uploading, uploadProgress, md5] = useFileUpload({ upload: uploadGeneralFile });
|
||||||
|
|
||||||
const { enqueueSnackbar } = useSnackbar();
|
|
||||||
|
|
||||||
const { LL } = useI18nContext();
|
const { LL } = useI18nContext();
|
||||||
|
|
||||||
const saveFile = (json: any, endpoint: string) => {
|
const saveFile = (json: any, endpoint: string) => {
|
||||||
@@ -40,19 +38,18 @@ const GeneralFileUpload: FC<UploadFileProps> = ({ uploadGeneralFile }) => {
|
|||||||
document.body.appendChild(a);
|
document.body.appendChild(a);
|
||||||
a.click();
|
a.click();
|
||||||
document.body.removeChild(a);
|
document.body.removeChild(a);
|
||||||
enqueueSnackbar(LL.DOWNLOAD_SUCCESSFUL(), { variant: 'info' });
|
toast.info(LL.DOWNLOAD_SUCCESSFUL());
|
||||||
};
|
};
|
||||||
|
|
||||||
const downloadSettings = async () => {
|
const downloadSettings = async () => {
|
||||||
try {
|
try {
|
||||||
const response = await EMSESP.getSettings();
|
const response = await EMSESP.getSettings();
|
||||||
if (response.status !== 200) {
|
if (response.status !== 200) {
|
||||||
enqueueSnackbar(LL.PROBLEM_LOADING(), { variant: 'error' });
|
toast.error(LL.PROBLEM_LOADING());
|
||||||
} else {
|
|
||||||
saveFile(response.data, 'settings');
|
saveFile(response.data, 'settings');
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_LOADING()), { variant: 'error' });
|
toast.error(extractErrorMessage(error, LL.PROBLEM_LOADING()));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -60,12 +57,12 @@ const GeneralFileUpload: FC<UploadFileProps> = ({ uploadGeneralFile }) => {
|
|||||||
try {
|
try {
|
||||||
const response = await EMSESP.getCustomizations();
|
const response = await EMSESP.getCustomizations();
|
||||||
if (response.status !== 200) {
|
if (response.status !== 200) {
|
||||||
enqueueSnackbar(LL.PROBLEM_LOADING(), { variant: 'error' });
|
toast.error(LL.PROBLEM_LOADING());
|
||||||
} else {
|
} else {
|
||||||
saveFile(response.data, 'customizations');
|
saveFile(response.data, 'customizations');
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_LOADING()), { variant: 'error' });
|
toast.error(extractErrorMessage(error, LL.PROBLEM_LOADING()));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -73,12 +70,11 @@ const GeneralFileUpload: FC<UploadFileProps> = ({ uploadGeneralFile }) => {
|
|||||||
try {
|
try {
|
||||||
const response = await EMSESP.readSchedule();
|
const response = await EMSESP.readSchedule();
|
||||||
if (response.status !== 200) {
|
if (response.status !== 200) {
|
||||||
enqueueSnackbar(LL.PROBLEM_LOADING(), { variant: 'error' });
|
toast.error(LL.PROBLEM_LOADING());
|
||||||
} else {
|
|
||||||
saveFile(response.data, 'schedule');
|
saveFile(response.data, 'schedule');
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_LOADING()), { variant: 'error' });
|
toast.error(extractErrorMessage(error, LL.PROBLEM_LOADING()));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import { updateValue, useRest, extractErrorMessage } from 'utils';
|
|||||||
|
|
||||||
import DownloadIcon from '@mui/icons-material/GetApp';
|
import DownloadIcon from '@mui/icons-material/GetApp';
|
||||||
|
|
||||||
import { useSnackbar } from 'notistack';
|
import { toast } from 'react-toastify';
|
||||||
|
|
||||||
import { EVENT_SOURCE_ROOT } from 'api/endpoints';
|
import { EVENT_SOURCE_ROOT } from 'api/endpoints';
|
||||||
|
|
||||||
@@ -93,8 +93,6 @@ const SystemLog: FC = () => {
|
|||||||
|
|
||||||
const updateFormValue = updateValue(setData);
|
const updateFormValue = updateValue(setData);
|
||||||
|
|
||||||
const { enqueueSnackbar } = useSnackbar();
|
|
||||||
|
|
||||||
const reloadPage = () => {
|
const reloadPage = () => {
|
||||||
window.location.reload();
|
window.location.reload();
|
||||||
};
|
};
|
||||||
@@ -108,10 +106,10 @@ const SystemLog: FC = () => {
|
|||||||
compact: data.compact
|
compact: data.compact
|
||||||
});
|
});
|
||||||
if (response.status !== 200) {
|
if (response.status !== 200) {
|
||||||
enqueueSnackbar(LL.PROBLEM_UPDATING(), { variant: 'error' });
|
toast.error(LL.PROBLEM_UPDATING());
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_UPDATING()), { variant: 'error' });
|
toast.error(extractErrorMessage(error, LL.PROBLEM_UPDATING()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { FC, useContext, useState, useEffect } from 'react';
|
import { FC, useContext, useState, useEffect } from 'react';
|
||||||
import { useSnackbar } from 'notistack';
|
import { toast } from 'react-toastify';
|
||||||
import {
|
import {
|
||||||
Avatar,
|
Avatar,
|
||||||
Box,
|
Box,
|
||||||
@@ -61,7 +61,6 @@ const SystemStatusForm: FC = () => {
|
|||||||
const [confirmRestart, setConfirmRestart] = useState<boolean>(false);
|
const [confirmRestart, setConfirmRestart] = useState<boolean>(false);
|
||||||
const [confirmFactoryReset, setConfirmFactoryReset] = useState<boolean>(false);
|
const [confirmFactoryReset, setConfirmFactoryReset] = useState<boolean>(false);
|
||||||
const [processing, setProcessing] = useState<boolean>(false);
|
const [processing, setProcessing] = useState<boolean>(false);
|
||||||
const { enqueueSnackbar } = useSnackbar();
|
|
||||||
const [showingVersion, setShowingVersion] = useState<boolean>(false);
|
const [showingVersion, setShowingVersion] = useState<boolean>(false);
|
||||||
const [latestVersion, setLatestVersion] = useState<Version>();
|
const [latestVersion, setLatestVersion] = useState<Version>();
|
||||||
const [latestDevVersion, setLatestDevVersion] = useState<Version>();
|
const [latestDevVersion, setLatestDevVersion] = useState<Version>();
|
||||||
@@ -91,7 +90,7 @@ const SystemStatusForm: FC = () => {
|
|||||||
setRestarting(true);
|
setRestarting(true);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_LOADING()), { variant: 'error' });
|
toast.error(extractErrorMessage(error, LL.PROBLEM_LOADING()));
|
||||||
} finally {
|
} finally {
|
||||||
setConfirmRestart(false);
|
setConfirmRestart(false);
|
||||||
setProcessing(false);
|
setProcessing(false);
|
||||||
@@ -104,7 +103,7 @@ const SystemStatusForm: FC = () => {
|
|||||||
await SystemApi.partition();
|
await SystemApi.partition();
|
||||||
setRestarting(true);
|
setRestarting(true);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_LOADING()), { variant: 'error' });
|
toast.error(extractErrorMessage(error, LL.PROBLEM_LOADING()));
|
||||||
} finally {
|
} finally {
|
||||||
setConfirmRestart(false);
|
setConfirmRestart(false);
|
||||||
setProcessing(false);
|
setProcessing(false);
|
||||||
@@ -211,7 +210,7 @@ const SystemStatusForm: FC = () => {
|
|||||||
await SystemApi.factoryReset();
|
await SystemApi.factoryReset();
|
||||||
setRestarting(true);
|
setRestarting(true);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_UPDATING()), { variant: 'error' });
|
toast.error(extractErrorMessage(error, LL.PROBLEM_UPDATING()));
|
||||||
} finally {
|
} finally {
|
||||||
setConfirmFactoryReset(false);
|
setConfirmFactoryReset(false);
|
||||||
setProcessing(false);
|
setProcessing(false);
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ import {
|
|||||||
Checkbox
|
Checkbox
|
||||||
} from '@mui/material';
|
} from '@mui/material';
|
||||||
|
|
||||||
import { useSnackbar } from 'notistack';
|
import { toast } from 'react-toastify';
|
||||||
|
|
||||||
import { useTheme } from '@table-library/react-table-library/theme';
|
import { useTheme } from '@table-library/react-table-library/theme';
|
||||||
import { useSort, SortToggleType } from '@table-library/react-table-library/sort';
|
import { useSort, SortToggleType } from '@table-library/react-table-library/sort';
|
||||||
@@ -78,8 +78,6 @@ const DashboardData: FC = () => {
|
|||||||
|
|
||||||
const { LL } = useI18nContext();
|
const { LL } = useI18nContext();
|
||||||
|
|
||||||
const { enqueueSnackbar } = useSnackbar();
|
|
||||||
|
|
||||||
const [coreData, setCoreData] = useState<CoreData>({
|
const [coreData, setCoreData] = useState<CoreData>({
|
||||||
connected: true,
|
connected: true,
|
||||||
devices: [],
|
devices: [],
|
||||||
@@ -122,7 +120,6 @@ const DashboardData: FC = () => {
|
|||||||
|
|
||||||
&.tr.tr-body.row-select.row-select-single-selected {
|
&.tr.tr-body.row-select.row-select-single-selected {
|
||||||
background-color: #3d4752;
|
background-color: #3d4752;
|
||||||
color: white;
|
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -160,8 +157,7 @@ const DashboardData: FC = () => {
|
|||||||
HeaderRow: `
|
HeaderRow: `
|
||||||
.th {
|
.th {
|
||||||
padding: 8px;
|
padding: 8px;
|
||||||
height: 42px;
|
height: 36px;
|
||||||
font-weight: 500;
|
|
||||||
`
|
`
|
||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
@@ -184,7 +180,7 @@ const DashboardData: FC = () => {
|
|||||||
`,
|
`,
|
||||||
HeaderRow: `
|
HeaderRow: `
|
||||||
.th {
|
.th {
|
||||||
height: 32px;
|
height: 36px;
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
Row: `
|
Row: `
|
||||||
@@ -363,9 +359,9 @@ const DashboardData: FC = () => {
|
|||||||
try {
|
try {
|
||||||
setCoreData((await EMSESP.readCoreData()).data);
|
setCoreData((await EMSESP.readCoreData()).data);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_LOADING()), { variant: 'error' });
|
toast.error(extractErrorMessage(error, LL.PROBLEM_LOADING()));
|
||||||
}
|
}
|
||||||
}, [enqueueSnackbar, LL]);
|
}, [LL]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetchCoreData();
|
fetchCoreData();
|
||||||
@@ -384,7 +380,7 @@ const DashboardData: FC = () => {
|
|||||||
try {
|
try {
|
||||||
setDeviceData((await EMSESP.readDeviceData({ id: unique_id })).data);
|
setDeviceData((await EMSESP.readDeviceData({ id: unique_id })).data);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_LOADING()), { variant: 'error' });
|
toast.error(extractErrorMessage(error, LL.PROBLEM_LOADING()));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -392,7 +388,7 @@ const DashboardData: FC = () => {
|
|||||||
try {
|
try {
|
||||||
setSensorData((await EMSESP.readSensorData()).data);
|
setSensorData((await EMSESP.readSensorData()).data);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_LOADING()), { variant: 'error' });
|
toast.error(extractErrorMessage(error, LL.PROBLEM_LOADING()));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -468,15 +464,15 @@ const DashboardData: FC = () => {
|
|||||||
devicevalue: deviceValue
|
devicevalue: deviceValue
|
||||||
});
|
});
|
||||||
if (response.status === 204) {
|
if (response.status === 204) {
|
||||||
enqueueSnackbar(LL.WRITE_CMD_FAILED(), { variant: 'error' });
|
toast.error(LL.WRITE_CMD_FAILED());
|
||||||
} else if (response.status === 403) {
|
} else if (response.status === 403) {
|
||||||
enqueueSnackbar(LL.ACCESS_DENIED(), { variant: 'error' });
|
toast.error(LL.ACCESS_DENIED());
|
||||||
} else {
|
} else {
|
||||||
enqueueSnackbar(LL.WRITE_CMD_SENT(), { variant: 'success' });
|
toast.success(LL.WRITE_CMD_SENT());
|
||||||
}
|
}
|
||||||
setDeviceValue(undefined);
|
setDeviceValue(undefined);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_UPDATING()), { variant: 'error' });
|
toast.error(extractErrorMessage(error, LL.PROBLEM_UPDATING()));
|
||||||
} finally {
|
} finally {
|
||||||
refreshData();
|
refreshData();
|
||||||
setDeviceValue(undefined);
|
setDeviceValue(undefined);
|
||||||
@@ -562,15 +558,15 @@ const DashboardData: FC = () => {
|
|||||||
offset: sensor.o
|
offset: sensor.o
|
||||||
});
|
});
|
||||||
if (response.status === 204) {
|
if (response.status === 204) {
|
||||||
enqueueSnackbar(LL.UPLOAD_OF(LL.SENSOR()) + ' ' + LL.FAILED(), { variant: 'error' });
|
toast.error(LL.UPLOAD_OF(LL.SENSOR()) + ' ' + LL.FAILED());
|
||||||
} else if (response.status === 403) {
|
} else if (response.status === 403) {
|
||||||
enqueueSnackbar(LL.ACCESS_DENIED(), { variant: 'error' });
|
toast.error(LL.ACCESS_DENIED());
|
||||||
} else {
|
} else {
|
||||||
enqueueSnackbar(LL.UPDATED_OF(LL.SENSOR()), { variant: 'success' });
|
toast.success(LL.UPDATED_OF(LL.SENSOR()));
|
||||||
}
|
}
|
||||||
setSensor(undefined);
|
setSensor(undefined);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_UPDATING()), { variant: 'error' });
|
toast.error(extractErrorMessage(error, LL.PROBLEM_UPDATING()));
|
||||||
} finally {
|
} finally {
|
||||||
setSensor(undefined);
|
setSensor(undefined);
|
||||||
fetchSensorData();
|
fetchSensorData();
|
||||||
@@ -991,14 +987,14 @@ const DashboardData: FC = () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (response.status === 204) {
|
if (response.status === 204) {
|
||||||
enqueueSnackbar(LL.DELETION_OF(LL.ANALOG_SENSOR()) + ' ' + LL.FAILED(), { variant: 'error' });
|
toast.error(LL.DELETION_OF(LL.ANALOG_SENSOR()) + ' ' + LL.FAILED());
|
||||||
} else if (response.status === 403) {
|
} else if (response.status === 403) {
|
||||||
enqueueSnackbar(LL.ACCESS_DENIED(), { variant: 'error' });
|
toast.error(LL.ACCESS_DENIED());
|
||||||
} else {
|
} else {
|
||||||
enqueueSnackbar(LL.REMOVED_OF(LL.ANALOG_SENSOR()), { variant: 'success' });
|
toast.success(LL.REMOVED_OF(LL.ANALOG_SENSOR()));
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_UPDATING()), { variant: 'error' });
|
toast.error(extractErrorMessage(error, LL.PROBLEM_UPDATING()));
|
||||||
} finally {
|
} finally {
|
||||||
setAnalog(undefined);
|
setAnalog(undefined);
|
||||||
fetchSensorData();
|
fetchSensorData();
|
||||||
@@ -1019,14 +1015,14 @@ const DashboardData: FC = () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (response.status === 204) {
|
if (response.status === 204) {
|
||||||
enqueueSnackbar(LL.UPDATE_OF(LL.ANALOG_SENSOR()) + ' ' + LL.FAILED(), { variant: 'error' });
|
toast.error(LL.UPDATE_OF(LL.ANALOG_SENSOR()) + ' ' + LL.FAILED());
|
||||||
} else if (response.status === 403) {
|
} else if (response.status === 403) {
|
||||||
enqueueSnackbar(LL.ACCESS_DENIED(), { variant: 'error' });
|
toast.error(LL.ACCESS_DENIED());
|
||||||
} else {
|
} else {
|
||||||
enqueueSnackbar(LL.UPDATED_OF(LL.ANALOG_SENSOR()), { variant: 'success' });
|
toast.success(LL.UPDATED_OF(LL.ANALOG_SENSOR()));
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_UPDATING()), { variant: 'error' });
|
toast.error(extractErrorMessage(error, LL.PROBLEM_UPDATING()));
|
||||||
} finally {
|
} finally {
|
||||||
setAnalog(undefined);
|
setAnalog(undefined);
|
||||||
fetchSensorData();
|
fetchSensorData();
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { FC, useState, useContext, useEffect } from 'react';
|
import { FC, useState, useContext, useEffect } from 'react';
|
||||||
import { useSnackbar } from 'notistack';
|
import { toast } from 'react-toastify';
|
||||||
import {
|
import {
|
||||||
Avatar,
|
Avatar,
|
||||||
Button,
|
Button,
|
||||||
@@ -74,7 +74,6 @@ const DashboardStatus: FC = () => {
|
|||||||
|
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const [confirmScan, setConfirmScan] = useState<boolean>(false);
|
const [confirmScan, setConfirmScan] = useState<boolean>(false);
|
||||||
const { enqueueSnackbar } = useSnackbar();
|
|
||||||
|
|
||||||
const { me } = useContext(AuthenticatedContext);
|
const { me } = useContext(AuthenticatedContext);
|
||||||
|
|
||||||
@@ -109,8 +108,7 @@ const DashboardStatus: FC = () => {
|
|||||||
color: #90CAF9;
|
color: #90CAF9;
|
||||||
|
|
||||||
.th {
|
.th {
|
||||||
height: 42px;
|
height: 36px;
|
||||||
font-weight: 500;
|
|
||||||
border-bottom: 1px solid #565656;
|
border-bottom: 1px solid #565656;
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
@@ -146,9 +144,9 @@ const DashboardStatus: FC = () => {
|
|||||||
const scan = async () => {
|
const scan = async () => {
|
||||||
try {
|
try {
|
||||||
await EMSESP.scanDevices();
|
await EMSESP.scanDevices();
|
||||||
enqueueSnackbar(LL.SCANNING() + '...', { variant: 'info' });
|
toast.info(LL.SCANNING() + '...');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_UPDATING()), { variant: 'error' });
|
toast.error(extractErrorMessage(error, LL.PROBLEM_UPDATING()));
|
||||||
} finally {
|
} finally {
|
||||||
setConfirmScan(false);
|
setConfirmScan(false);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { Typography, Button, Box, List, ListItem, ListItemText, Link, ListItemAv
|
|||||||
|
|
||||||
import { SectionContent } from 'components';
|
import { SectionContent } from 'components';
|
||||||
|
|
||||||
import { useSnackbar } from 'notistack';
|
import { toast } from 'react-toastify';
|
||||||
|
|
||||||
import CommentIcon from '@mui/icons-material/CommentTwoTone';
|
import CommentIcon from '@mui/icons-material/CommentTwoTone';
|
||||||
import MenuBookIcon from '@mui/icons-material/MenuBookTwoTone';
|
import MenuBookIcon from '@mui/icons-material/MenuBookTwoTone';
|
||||||
@@ -21,8 +21,6 @@ import * as EMSESP from './api';
|
|||||||
const HelpInformation: FC = () => {
|
const HelpInformation: FC = () => {
|
||||||
const { LL } = useI18nContext();
|
const { LL } = useI18nContext();
|
||||||
|
|
||||||
const { enqueueSnackbar } = useSnackbar();
|
|
||||||
|
|
||||||
const saveFile = (json: any, endpoint: string) => {
|
const saveFile = (json: any, endpoint: string) => {
|
||||||
const a = document.createElement('a');
|
const a = document.createElement('a');
|
||||||
const filename = 'emsesp_' + endpoint + '.txt';
|
const filename = 'emsesp_' + endpoint + '.txt';
|
||||||
@@ -35,7 +33,7 @@ const HelpInformation: FC = () => {
|
|||||||
document.body.appendChild(a);
|
document.body.appendChild(a);
|
||||||
a.click();
|
a.click();
|
||||||
document.body.removeChild(a);
|
document.body.removeChild(a);
|
||||||
enqueueSnackbar(LL.DOWNLOAD_SUCCESSFUL(), { variant: 'info' });
|
toast.info(LL.DOWNLOAD_SUCCESSFUL());
|
||||||
};
|
};
|
||||||
|
|
||||||
const callAPI = async (endpoint: string) => {
|
const callAPI = async (endpoint: string) => {
|
||||||
@@ -46,12 +44,12 @@ const HelpInformation: FC = () => {
|
|||||||
id: 0
|
id: 0
|
||||||
});
|
});
|
||||||
if (response.status !== 200) {
|
if (response.status !== 200) {
|
||||||
enqueueSnackbar(LL.PROBLEM_LOADING(), { variant: 'error' });
|
toast.error(LL.PROBLEM_LOADING());
|
||||||
} else {
|
} else {
|
||||||
saveFile(response.data, endpoint);
|
saveFile(response.data, endpoint);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_LOADING()), { variant: 'error' });
|
toast.error(extractErrorMessage(error, LL.PROBLEM_LOADING()));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { FC, useState } from 'react';
|
import { FC, useState } from 'react';
|
||||||
import { ValidateFieldsError } from 'async-validator';
|
import { ValidateFieldsError } from 'async-validator';
|
||||||
|
|
||||||
import { useSnackbar } from 'notistack';
|
import { toast } from 'react-toastify';
|
||||||
|
|
||||||
import { Box, Button, Checkbox, MenuItem, Grid, Typography, Divider, InputAdornment } from '@mui/material';
|
import { Box, Button, Checkbox, MenuItem, Grid, Typography, Divider, InputAdornment } from '@mui/material';
|
||||||
|
|
||||||
@@ -58,8 +58,6 @@ const SettingsApplication: FC = () => {
|
|||||||
|
|
||||||
const { LL } = useI18nContext();
|
const { LL } = useI18nContext();
|
||||||
|
|
||||||
const { enqueueSnackbar } = useSnackbar();
|
|
||||||
|
|
||||||
const updateFormValue = updateValueDirty(origData, dirtyFlags, setDirtyFlags, setData);
|
const updateFormValue = updateValueDirty(origData, dirtyFlags, setDirtyFlags, setData);
|
||||||
|
|
||||||
const [fieldErrors, setFieldErrors] = useState<ValidateFieldsError>();
|
const [fieldErrors, setFieldErrors] = useState<ValidateFieldsError>();
|
||||||
@@ -85,7 +83,7 @@ const SettingsApplication: FC = () => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_UPDATING()), { variant: 'error' });
|
toast.error(extractErrorMessage(error, LL.PROBLEM_UPDATING()));
|
||||||
} finally {
|
} finally {
|
||||||
setProcessingBoard(false);
|
setProcessingBoard(false);
|
||||||
}
|
}
|
||||||
@@ -124,7 +122,7 @@ const SettingsApplication: FC = () => {
|
|||||||
await EMSESP.restart();
|
await EMSESP.restart();
|
||||||
setRestarting(true);
|
setRestarting(true);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_UPDATING()), { variant: 'error' });
|
toast.error(extractErrorMessage(error, LL.PROBLEM_UPDATING()));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ import {
|
|||||||
import { useTheme } from '@table-library/react-table-library/theme';
|
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 { useSnackbar } from 'notistack';
|
import { toast } from 'react-toastify';
|
||||||
|
|
||||||
import WarningIcon from '@mui/icons-material/Warning';
|
import WarningIcon from '@mui/icons-material/Warning';
|
||||||
import CancelIcon from '@mui/icons-material/Cancel';
|
import CancelIcon from '@mui/icons-material/Cancel';
|
||||||
@@ -51,7 +51,6 @@ export const APIURL = window.location.origin + '/api/';
|
|||||||
|
|
||||||
const SettingsCustomization: FC = () => {
|
const SettingsCustomization: FC = () => {
|
||||||
const { LL } = useI18nContext();
|
const { LL } = useI18nContext();
|
||||||
const { enqueueSnackbar } = useSnackbar();
|
|
||||||
|
|
||||||
const emptyDeviceEntity = { id: '', v: 0, n: '', cn: '', m: 0, w: false };
|
const emptyDeviceEntity = { id: '', v: 0, n: '', cn: '', m: 0, w: false };
|
||||||
|
|
||||||
@@ -103,8 +102,7 @@ const SettingsCustomization: FC = () => {
|
|||||||
|
|
||||||
.th {
|
.th {
|
||||||
border-bottom: 1px solid #565656;
|
border-bottom: 1px solid #565656;
|
||||||
font-weight: 500;
|
height: 36px;
|
||||||
height: 32px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
&:nth-of-type(1) .th {
|
&:nth-of-type(1) .th {
|
||||||
@@ -123,8 +121,6 @@ const SettingsCustomization: FC = () => {
|
|||||||
|
|
||||||
&.tr.tr-body.row-select.row-select-single-selected {
|
&.tr.tr-body.row-select.row-select-single-selected {
|
||||||
background-color: #3d4752;
|
background-color: #3d4752;
|
||||||
color: white;
|
|
||||||
font-weight: normal;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover .td {
|
&:hover .td {
|
||||||
@@ -257,9 +253,9 @@ const SettingsCustomization: FC = () => {
|
|||||||
const resetCustomization = async () => {
|
const resetCustomization = async () => {
|
||||||
try {
|
try {
|
||||||
await EMSESP.resetCustomizations();
|
await EMSESP.resetCustomizations();
|
||||||
enqueueSnackbar(LL.CUSTOMIZATIONS_RESTART(), { variant: 'info' });
|
toast.info(LL.CUSTOMIZATIONS_RESTART());
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_UPDATING()), { variant: 'error' });
|
toast.error(extractErrorMessage(error, LL.PROBLEM_UPDATING()));
|
||||||
} finally {
|
} finally {
|
||||||
setConfirmReset(false);
|
setConfirmReset(false);
|
||||||
}
|
}
|
||||||
@@ -296,7 +292,7 @@ const SettingsCustomization: FC = () => {
|
|||||||
await EMSESP.restart();
|
await EMSESP.restart();
|
||||||
setRestarting(true);
|
setRestarting(true);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_UPDATING()), { variant: 'error' });
|
toast.error(extractErrorMessage(error, LL.PROBLEM_UPDATING()));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -307,7 +303,7 @@ const SettingsCustomization: FC = () => {
|
|||||||
// check size in bytes to match buffer in CPP, which is 2048
|
// check size in bytes to match buffer in CPP, which is 2048
|
||||||
const bytes = new TextEncoder().encode(JSON.stringify(masked_entities)).length;
|
const bytes = new TextEncoder().encode(JSON.stringify(masked_entities)).length;
|
||||||
if (bytes > 2000) {
|
if (bytes > 2000) {
|
||||||
enqueueSnackbar(LL.CUSTOMIZATIONS_FULL(), { variant: 'warning' });
|
toast.warning(LL.CUSTOMIZATIONS_FULL());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -317,14 +313,14 @@ const SettingsCustomization: FC = () => {
|
|||||||
entity_ids: masked_entities
|
entity_ids: masked_entities
|
||||||
});
|
});
|
||||||
if (response.status === 200) {
|
if (response.status === 200) {
|
||||||
enqueueSnackbar(LL.CUSTOMIZATIONS_SAVED(), { variant: 'success' });
|
toast.success(LL.CUSTOMIZATIONS_SAVED());
|
||||||
} else if (response.status === 201) {
|
} else if (response.status === 201) {
|
||||||
setRestartNeeded(true);
|
setRestartNeeded(true);
|
||||||
} else {
|
} else {
|
||||||
enqueueSnackbar(LL.PROBLEM_UPDATING(), { variant: 'error' });
|
toast.error(LL.PROBLEM_UPDATING());
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_UPDATING()), { variant: 'error' });
|
toast.error(extractErrorMessage(error, LL.PROBLEM_UPDATING()));
|
||||||
}
|
}
|
||||||
setOriginalSettings(deviceEntities);
|
setOriginalSettings(deviceEntities);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ import {
|
|||||||
import { useTheme } from '@table-library/react-table-library/theme';
|
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 { useSnackbar } from 'notistack';
|
import { toast } from 'react-toastify';
|
||||||
|
|
||||||
import RemoveIcon from '@mui/icons-material/RemoveCircleOutline';
|
import RemoveIcon from '@mui/icons-material/RemoveCircleOutline';
|
||||||
import WarningIcon from '@mui/icons-material/Warning';
|
import WarningIcon from '@mui/icons-material/Warning';
|
||||||
@@ -66,8 +66,6 @@ function makeid() {
|
|||||||
const SettingsScheduler: FC = () => {
|
const SettingsScheduler: FC = () => {
|
||||||
const { LL, locale } = useI18nContext();
|
const { LL, locale } = useI18nContext();
|
||||||
|
|
||||||
const { enqueueSnackbar } = useSnackbar();
|
|
||||||
|
|
||||||
const [numChanges, setNumChanges] = useState<number>(0);
|
const [numChanges, setNumChanges] = useState<number>(0);
|
||||||
const blocker = useBlocker(numChanges !== 0);
|
const blocker = useBlocker(numChanges !== 0);
|
||||||
|
|
||||||
@@ -130,7 +128,6 @@ const SettingsScheduler: FC = () => {
|
|||||||
color: #90CAF9;
|
color: #90CAF9;
|
||||||
.th {
|
.th {
|
||||||
border-bottom: 1px solid #565656;
|
border-bottom: 1px solid #565656;
|
||||||
font-weight: 500;
|
|
||||||
height: 36px;
|
height: 36px;
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
@@ -142,11 +139,6 @@ const SettingsScheduler: FC = () => {
|
|||||||
border-top: 1px solid #565656;
|
border-top: 1px solid #565656;
|
||||||
border-bottom: 1px solid #565656;
|
border-bottom: 1px solid #565656;
|
||||||
}
|
}
|
||||||
&.tr.tr-body.row-select.row-select-single-selected {
|
|
||||||
background-color: #3d4752;
|
|
||||||
color: white;
|
|
||||||
font-weight: normal;
|
|
||||||
}
|
|
||||||
&:hover .td {
|
&:hover .td {
|
||||||
border-top: 1px solid #177ac9;
|
border-top: 1px solid #177ac9;
|
||||||
border-bottom: 1px solid #177ac9;
|
border-bottom: 1px solid #177ac9;
|
||||||
@@ -263,12 +255,12 @@ const SettingsScheduler: FC = () => {
|
|||||||
})
|
})
|
||||||
});
|
});
|
||||||
if (response.status === 200) {
|
if (response.status === 200) {
|
||||||
enqueueSnackbar(LL.SCHEDULE_SAVED(), { variant: 'success' });
|
toast.success(LL.SCHEDULE_SAVED());
|
||||||
} else {
|
} else {
|
||||||
enqueueSnackbar(LL.PROBLEM_UPDATING(), { variant: 'error' });
|
toast.error(LL.PROBLEM_UPDATING());
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_UPDATING()), { variant: 'error' });
|
toast.error(extractErrorMessage(error, LL.PROBLEM_UPDATING()));
|
||||||
}
|
}
|
||||||
setOriginalSchedule(schedule);
|
setOriginalSchedule(schedule);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { useCallback, useEffect, useState } from 'react';
|
import { useCallback, useEffect, useState } from 'react';
|
||||||
import { useSnackbar } from 'notistack';
|
import { toast } from 'react-toastify';
|
||||||
|
|
||||||
import { AxiosPromise } from 'axios';
|
import { AxiosPromise } from 'axios';
|
||||||
|
|
||||||
import { extractErrorMessage } from '.';
|
import { extractErrorMessage } from '.';
|
||||||
@@ -16,8 +17,6 @@ export interface RestRequestOptions<D> {
|
|||||||
export const useRest = <D>({ read, update }: RestRequestOptions<D>) => {
|
export const useRest = <D>({ read, update }: RestRequestOptions<D>) => {
|
||||||
const { LL } = useI18nContext();
|
const { LL } = useI18nContext();
|
||||||
|
|
||||||
const { enqueueSnackbar } = useSnackbar();
|
|
||||||
|
|
||||||
const [data, setData] = useState<D>();
|
const [data, setData] = useState<D>();
|
||||||
const [saving, setSaving] = useState<boolean>(false);
|
const [saving, setSaving] = useState<boolean>(false);
|
||||||
const [errorMessage, setErrorMessage] = useState<string>();
|
const [errorMessage, setErrorMessage] = useState<string>();
|
||||||
@@ -38,10 +37,10 @@ export const useRest = <D>({ read, update }: RestRequestOptions<D>) => {
|
|||||||
setOrigData(fetch_data);
|
setOrigData(fetch_data);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
const message = extractErrorMessage(error, LL.PROBLEM_LOADING());
|
const message = extractErrorMessage(error, LL.PROBLEM_LOADING());
|
||||||
enqueueSnackbar(message, { variant: 'error' });
|
toast.error(message);
|
||||||
setErrorMessage(message);
|
setErrorMessage(message);
|
||||||
}
|
}
|
||||||
}, [read, enqueueSnackbar, LL]);
|
}, [read, LL]);
|
||||||
|
|
||||||
const save = useCallback(
|
const save = useCallback(
|
||||||
async (toSave: D) => {
|
async (toSave: D) => {
|
||||||
@@ -58,18 +57,18 @@ export const useRest = <D>({ read, update }: RestRequestOptions<D>) => {
|
|||||||
if (response.status === 202) {
|
if (response.status === 202) {
|
||||||
setRestartNeeded(true);
|
setRestartNeeded(true);
|
||||||
} else {
|
} else {
|
||||||
enqueueSnackbar(LL.UPDATED_OF(LL.SETTINGS_OF('')), { variant: 'success' });
|
toast.success(LL.UPDATED_OF(LL.SETTINGS_OF('')));
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
const message = extractErrorMessage(error, LL.PROBLEM_UPDATING());
|
const message = extractErrorMessage(error, LL.PROBLEM_UPDATING());
|
||||||
enqueueSnackbar(message, { variant: 'error' });
|
toast.error(message);
|
||||||
setErrorMessage(message);
|
setErrorMessage(message);
|
||||||
} finally {
|
} finally {
|
||||||
setSaving(false);
|
setSaving(false);
|
||||||
setDirtyFlags([]);
|
setDirtyFlags([]);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[update, enqueueSnackbar, LL]
|
[update, LL]
|
||||||
);
|
);
|
||||||
|
|
||||||
const saveData = () => data && save(data);
|
const saveData = () => data && save(data);
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { defineConfig, type PluginOption } from 'vite';
|
|||||||
import react from '@vitejs/plugin-react-swc';
|
import react from '@vitejs/plugin-react-swc';
|
||||||
import viteTsconfigPaths from 'vite-tsconfig-paths';
|
import viteTsconfigPaths from 'vite-tsconfig-paths';
|
||||||
import svgrPlugin from 'vite-plugin-svgr';
|
import svgrPlugin from 'vite-plugin-svgr';
|
||||||
|
// import { ViteMinifyPlugin } from 'vite-plugin-minify';
|
||||||
import { visualizer } from 'rollup-plugin-visualizer';
|
import { visualizer } from 'rollup-plugin-visualizer';
|
||||||
import ProgmemGenerator from './progmem-generator';
|
import ProgmemGenerator from './progmem-generator';
|
||||||
|
|
||||||
@@ -18,12 +19,30 @@ export default defineConfig(({ command, mode }) => {
|
|||||||
react(),
|
react(),
|
||||||
viteTsconfigPaths(),
|
viteTsconfigPaths(),
|
||||||
svgrPlugin(),
|
svgrPlugin(),
|
||||||
|
// ViteMinifyPlugin({
|
||||||
|
// removeAttributeQuotes: true,
|
||||||
|
// minifyCSS: true,
|
||||||
|
// minifyJS: true,
|
||||||
|
// decodeEntities: true,
|
||||||
|
// removeComments: true,
|
||||||
|
// removeEmptyAttributes: true,
|
||||||
|
// removeOptionalTags: true,
|
||||||
|
// removeEmptyElements: true,
|
||||||
|
// removeScriptTypeAttributes: true,
|
||||||
|
// removeTagWhitespace: true,
|
||||||
|
// minifyURLs: true
|
||||||
|
// }),
|
||||||
ProgmemGenerator({ outputPath: '../lib/framework/WWWData.h', bytesPerLine: 20 })
|
ProgmemGenerator({ outputPath: '../lib/framework/WWWData.h', bytesPerLine: 20 })
|
||||||
],
|
],
|
||||||
|
|
||||||
build: {
|
build: {
|
||||||
outDir: 'build',
|
outDir: 'build',
|
||||||
chunkSizeWarningLimit: 1024
|
chunkSizeWarningLimit: 1024,
|
||||||
|
sourcemap: false,
|
||||||
|
manifest: false,
|
||||||
|
minify: mode === 'development' ? false : 'terser'
|
||||||
},
|
},
|
||||||
|
|
||||||
server: {
|
server: {
|
||||||
open: true,
|
open: true,
|
||||||
port: 3000,
|
port: 3000,
|
||||||
|
|||||||
@@ -560,27 +560,45 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@eslint/eslintrc@npm:^2.0.0":
|
"@eslint-community/eslint-utils@npm:^4.2.0":
|
||||||
version: 2.0.0
|
version: 4.2.0
|
||||||
resolution: "@eslint/eslintrc@npm:2.0.0"
|
resolution: "@eslint-community/eslint-utils@npm:4.2.0"
|
||||||
|
dependencies:
|
||||||
|
eslint-visitor-keys: ^3.3.0
|
||||||
|
peerDependencies:
|
||||||
|
eslint: ^6.0.0 || ^7.0.0 || >=8.0.0
|
||||||
|
checksum: 82fdd1cc2a5d169def0e665ec790580ef708e7df9c91f20006595dc90e3bd42ec31c8976a2eeccd336286301a72e937c0ddf3ab4b7377d7014997c36333a7d22
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
|
"@eslint-community/regexpp@npm:^4.4.0":
|
||||||
|
version: 4.4.0
|
||||||
|
resolution: "@eslint-community/regexpp@npm:4.4.0"
|
||||||
|
checksum: 2d127af0c752b80e8a782eacfe996a86925d21de92da3ffc6f9e615e701145e44a62e26bdd88bfac2cd76779c39ba8d9875a91046ec5e7e5f23cb647c247ea6a
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
|
"@eslint/eslintrc@npm:^2.0.1":
|
||||||
|
version: 2.0.1
|
||||||
|
resolution: "@eslint/eslintrc@npm:2.0.1"
|
||||||
dependencies:
|
dependencies:
|
||||||
ajv: ^6.12.4
|
ajv: ^6.12.4
|
||||||
debug: ^4.3.2
|
debug: ^4.3.2
|
||||||
espree: ^9.4.0
|
espree: ^9.5.0
|
||||||
globals: ^13.19.0
|
globals: ^13.19.0
|
||||||
ignore: ^5.2.0
|
ignore: ^5.2.0
|
||||||
import-fresh: ^3.2.1
|
import-fresh: ^3.2.1
|
||||||
js-yaml: ^4.1.0
|
js-yaml: ^4.1.0
|
||||||
minimatch: ^3.1.2
|
minimatch: ^3.1.2
|
||||||
strip-json-comments: ^3.1.1
|
strip-json-comments: ^3.1.1
|
||||||
checksum: 31119c8ca06723d80384f18f5c78e0530d8e6306ad36379868650131a8b10dd7cffd7aff79a5deb3a2e9933660823052623d268532bae9538ded53d5b19a69a6
|
checksum: 56b9192a687a450db53a7b883daf9f0f447c43b3510189cf88808a7a2467c2a302a42a50f184cc6d5a9faf3d1df890a2ef0fd0d60b751f32a3e9dfea717c6b48
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@eslint/js@npm:8.35.0":
|
"@eslint/js@npm:8.36.0":
|
||||||
version: 8.35.0
|
version: 8.36.0
|
||||||
resolution: "@eslint/js@npm:8.35.0"
|
resolution: "@eslint/js@npm:8.36.0"
|
||||||
checksum: 6687ceff659a6d617e37823f809dc9c4b096535961a81acead27d26b1a51a4cf608a5e59d831ddd57f24f6f8bb99340a4a0e19f9c99b390fbb4b275f51ed5f5e
|
checksum: b7d6b84b823c8c7784be390741196617565527b1f7c0977fde9455bfb57fd88f81c074a03dd878757d2c33fa29f24291e9ecbc1425710f067917324b55e1bf3a
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
@@ -626,7 +644,7 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@jridgewell/gen-mapping@npm:^0.3.2":
|
"@jridgewell/gen-mapping@npm:^0.3.0, @jridgewell/gen-mapping@npm:^0.3.2":
|
||||||
version: 0.3.2
|
version: 0.3.2
|
||||||
resolution: "@jridgewell/gen-mapping@npm:0.3.2"
|
resolution: "@jridgewell/gen-mapping@npm:0.3.2"
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -651,6 +669,16 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"@jridgewell/source-map@npm:^0.3.2":
|
||||||
|
version: 0.3.2
|
||||||
|
resolution: "@jridgewell/source-map@npm:0.3.2"
|
||||||
|
dependencies:
|
||||||
|
"@jridgewell/gen-mapping": ^0.3.0
|
||||||
|
"@jridgewell/trace-mapping": ^0.3.9
|
||||||
|
checksum: 1b83f0eb944e77b70559a394d5d3b3f98a81fcc186946aceb3ef42d036762b52ef71493c6c0a3b7c1d2f08785f53ba2df1277fe629a06e6109588ff4cdcf7482
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"@jridgewell/sourcemap-codec@npm:1.4.14, @jridgewell/sourcemap-codec@npm:^1.4.10":
|
"@jridgewell/sourcemap-codec@npm:1.4.14, @jridgewell/sourcemap-codec@npm:^1.4.10":
|
||||||
version: 1.4.14
|
version: 1.4.14
|
||||||
resolution: "@jridgewell/sourcemap-codec@npm:1.4.14"
|
resolution: "@jridgewell/sourcemap-codec@npm:1.4.14"
|
||||||
@@ -930,10 +958,10 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@remix-run/router@npm:1.3.3, @remix-run/router@npm:^1.3.3":
|
"@remix-run/router@npm:1.4.0, @remix-run/router@npm:^1.4.0":
|
||||||
version: 1.3.3
|
version: 1.4.0
|
||||||
resolution: "@remix-run/router@npm:1.3.3"
|
resolution: "@remix-run/router@npm:1.4.0"
|
||||||
checksum: 9280f1c3e44c0fb84a74b401b5a47022dace06d5da0f26a7a68c7c0e57ad5ef95d30f3c2d333df2db3b63f84de81f7f8caa7e53189a7709d6c3eb466d126ed76
|
checksum: 707dce35a2b8138005cf19e63f6fd3c4da05b4b892e9e9118e8b727c3b95953efe27307ca2df35084044df30fa1fc367cf0bbc98d1ded9020c82e61e6242caaf
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
@@ -1785,7 +1813,7 @@ __metadata:
|
|||||||
"@msgpack/msgpack": ^2.8.0
|
"@msgpack/msgpack": ^2.8.0
|
||||||
"@mui/icons-material": ^5.11.11
|
"@mui/icons-material": ^5.11.11
|
||||||
"@mui/material": ^5.11.12
|
"@mui/material": ^5.11.12
|
||||||
"@remix-run/router": ^1.3.3
|
"@remix-run/router": ^1.4.0
|
||||||
"@table-library/react-table-library": 4.0.29
|
"@table-library/react-table-library": 4.0.29
|
||||||
"@types/lodash-es": ^4.17.6
|
"@types/lodash-es": ^4.17.6
|
||||||
"@types/mime-types": ^2
|
"@types/mime-types": ^2
|
||||||
@@ -1800,7 +1828,7 @@ __metadata:
|
|||||||
"@yarnpkg/pnpify": ^4.0.0-rc.40
|
"@yarnpkg/pnpify": ^4.0.0-rc.40
|
||||||
async-validator: ^4.2.5
|
async-validator: ^4.2.5
|
||||||
axios: ^1.3.4
|
axios: ^1.3.4
|
||||||
eslint: ^8.35.0
|
eslint: ^8.36.0
|
||||||
eslint-config-prettier: ^8.7.0
|
eslint-config-prettier: ^8.7.0
|
||||||
eslint-import-resolver-typescript: ^3.5.3
|
eslint-import-resolver-typescript: ^3.5.3
|
||||||
eslint-plugin-deprecation: ^1.3.3
|
eslint-plugin-deprecation: ^1.3.3
|
||||||
@@ -1812,19 +1840,21 @@ __metadata:
|
|||||||
lodash-es: ^4.17.21
|
lodash-es: ^4.17.21
|
||||||
mime-types: ^2.1.35
|
mime-types: ^2.1.35
|
||||||
nodemon: ^2.0.21
|
nodemon: ^2.0.21
|
||||||
notistack: 2.0.8
|
|
||||||
npm-run-all: ^4.1.5
|
npm-run-all: ^4.1.5
|
||||||
prettier: ^2.8.4
|
prettier: ^2.8.4
|
||||||
react: latest
|
react: latest
|
||||||
react-dom: latest
|
react-dom: latest
|
||||||
react-dropzone: ^14.2.3
|
react-dropzone: ^14.2.3
|
||||||
react-icons: ^4.8.0
|
react-icons: ^4.8.0
|
||||||
react-router-dom: ^6.8.2
|
react-router-dom: ^6.9.0
|
||||||
|
react-toastify: ^9.1.1
|
||||||
rollup-plugin-visualizer: ^5.9.0
|
rollup-plugin-visualizer: ^5.9.0
|
||||||
sockette: ^2.0.6
|
sockette: ^2.0.6
|
||||||
|
terser: ^5.16.6
|
||||||
typesafe-i18n: ^5.24.2
|
typesafe-i18n: ^5.24.2
|
||||||
typescript: ^4.9.5
|
typescript: ^4.9.5
|
||||||
vite: ^4.1.4
|
vite: ^4.1.4
|
||||||
|
vite-plugin-minify: ^1.5.2
|
||||||
vite-plugin-svgr: ^2.4.0
|
vite-plugin-svgr: ^2.4.0
|
||||||
vite-tsconfig-paths: ^4.0.5
|
vite-tsconfig-paths: ^4.0.5
|
||||||
languageName: unknown
|
languageName: unknown
|
||||||
@@ -1846,7 +1876,7 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"acorn@npm:^8.8.0":
|
"acorn@npm:^8.5.0, acorn@npm:^8.8.0":
|
||||||
version: 8.8.2
|
version: 8.8.2
|
||||||
resolution: "acorn@npm:8.8.2"
|
resolution: "acorn@npm:8.8.2"
|
||||||
bin:
|
bin:
|
||||||
@@ -2160,6 +2190,13 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"buffer-from@npm:^1.0.0":
|
||||||
|
version: 1.1.2
|
||||||
|
resolution: "buffer-from@npm:1.1.2"
|
||||||
|
checksum: 0448524a562b37d4d7ed9efd91685a5b77a50672c556ea254ac9a6d30e3403a517d8981f10e565db24e8339413b43c97ca2951f10e399c6125a0d8911f5679bb
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"cacache@npm:^16.1.0":
|
"cacache@npm:^16.1.0":
|
||||||
version: 16.1.3
|
version: 16.1.3
|
||||||
resolution: "cacache@npm:16.1.3"
|
resolution: "cacache@npm:16.1.3"
|
||||||
@@ -2225,6 +2262,16 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"camel-case@npm:^4.1.2":
|
||||||
|
version: 4.1.2
|
||||||
|
resolution: "camel-case@npm:4.1.2"
|
||||||
|
dependencies:
|
||||||
|
pascal-case: ^3.1.2
|
||||||
|
tslib: ^2.0.3
|
||||||
|
checksum: bcbd25cd253b3cbc69be3f535750137dbf2beb70f093bdc575f73f800acc8443d34fd52ab8f0a2413c34f1e8203139ffc88428d8863e4dfe530cfb257a379ad6
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"camelcase@npm:^5.3.1":
|
"camelcase@npm:^5.3.1":
|
||||||
version: 5.3.1
|
version: 5.3.1
|
||||||
resolution: "camelcase@npm:5.3.1"
|
resolution: "camelcase@npm:5.3.1"
|
||||||
@@ -2310,6 +2357,15 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"clean-css@npm:^5.2.2":
|
||||||
|
version: 5.3.2
|
||||||
|
resolution: "clean-css@npm:5.3.2"
|
||||||
|
dependencies:
|
||||||
|
source-map: ~0.6.0
|
||||||
|
checksum: 8787b281acc9878f309b5f835d410085deedfd4e126472666773040a6a8a72f472a1d24185947d23b87b1c419bf2c5ed429395d5c5ff8279c98b05d8011e9758
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"clean-stack@npm:^2.0.0":
|
"clean-stack@npm:^2.0.0":
|
||||||
version: 2.2.0
|
version: 2.2.0
|
||||||
resolution: "clean-stack@npm:2.2.0"
|
resolution: "clean-stack@npm:2.2.0"
|
||||||
@@ -2355,7 +2411,7 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"clsx@npm:^1.1.0, clsx@npm:^1.2.1":
|
"clsx@npm:^1.1.1, clsx@npm:^1.2.1":
|
||||||
version: 1.2.1
|
version: 1.2.1
|
||||||
resolution: "clsx@npm:1.2.1"
|
resolution: "clsx@npm:1.2.1"
|
||||||
checksum: 30befca8019b2eb7dbad38cff6266cf543091dae2825c856a62a8ccf2c3ab9c2907c4d12b288b73101196767f66812365400a227581484a05f968b0307cfaf12
|
checksum: 30befca8019b2eb7dbad38cff6266cf543091dae2825c856a62a8ccf2c3ab9c2907c4d12b288b73101196767f66812365400a227581484a05f968b0307cfaf12
|
||||||
@@ -2412,6 +2468,20 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"commander@npm:^2.20.0":
|
||||||
|
version: 2.20.3
|
||||||
|
resolution: "commander@npm:2.20.3"
|
||||||
|
checksum: ab8c07884e42c3a8dbc5dd9592c606176c7eb5c1ca5ff274bcf907039b2c41de3626f684ea75ccf4d361ba004bbaff1f577d5384c155f3871e456bdf27becf9e
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
|
"commander@npm:^8.3.0":
|
||||||
|
version: 8.3.0
|
||||||
|
resolution: "commander@npm:8.3.0"
|
||||||
|
checksum: 0f82321821fc27b83bd409510bb9deeebcfa799ff0bf5d102128b500b7af22872c0c92cb6a0ebc5a4cf19c6b550fba9cedfa7329d18c6442a625f851377bacf0
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"concat-map@npm:0.0.1":
|
"concat-map@npm:0.0.1":
|
||||||
version: 0.0.1
|
version: 0.0.1
|
||||||
resolution: "concat-map@npm:0.0.1"
|
resolution: "concat-map@npm:0.0.1"
|
||||||
@@ -2635,6 +2705,16 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"dot-case@npm:^3.0.4":
|
||||||
|
version: 3.0.4
|
||||||
|
resolution: "dot-case@npm:3.0.4"
|
||||||
|
dependencies:
|
||||||
|
no-case: ^3.0.4
|
||||||
|
tslib: ^2.0.3
|
||||||
|
checksum: a65e3519414856df0228b9f645332f974f2bf5433370f544a681122eab59e66038fc3349b4be1cdc47152779dac71a5864f1ccda2f745e767c46e9c6543b1169
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"electron-to-chromium@npm:^1.4.284":
|
"electron-to-chromium@npm:^1.4.284":
|
||||||
version: 1.4.315
|
version: 1.4.315
|
||||||
resolution: "electron-to-chromium@npm:1.4.315"
|
resolution: "electron-to-chromium@npm:1.4.315"
|
||||||
@@ -3088,12 +3168,14 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"eslint@npm:^8.35.0":
|
"eslint@npm:^8.36.0":
|
||||||
version: 8.35.0
|
version: 8.36.0
|
||||||
resolution: "eslint@npm:8.35.0"
|
resolution: "eslint@npm:8.36.0"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@eslint/eslintrc": ^2.0.0
|
"@eslint-community/eslint-utils": ^4.2.0
|
||||||
"@eslint/js": 8.35.0
|
"@eslint-community/regexpp": ^4.4.0
|
||||||
|
"@eslint/eslintrc": ^2.0.1
|
||||||
|
"@eslint/js": 8.36.0
|
||||||
"@humanwhocodes/config-array": ^0.11.8
|
"@humanwhocodes/config-array": ^0.11.8
|
||||||
"@humanwhocodes/module-importer": ^1.0.1
|
"@humanwhocodes/module-importer": ^1.0.1
|
||||||
"@nodelib/fs.walk": ^1.2.8
|
"@nodelib/fs.walk": ^1.2.8
|
||||||
@@ -3104,9 +3186,8 @@ __metadata:
|
|||||||
doctrine: ^3.0.0
|
doctrine: ^3.0.0
|
||||||
escape-string-regexp: ^4.0.0
|
escape-string-regexp: ^4.0.0
|
||||||
eslint-scope: ^7.1.1
|
eslint-scope: ^7.1.1
|
||||||
eslint-utils: ^3.0.0
|
|
||||||
eslint-visitor-keys: ^3.3.0
|
eslint-visitor-keys: ^3.3.0
|
||||||
espree: ^9.4.0
|
espree: ^9.5.0
|
||||||
esquery: ^1.4.2
|
esquery: ^1.4.2
|
||||||
esutils: ^2.0.2
|
esutils: ^2.0.2
|
||||||
fast-deep-equal: ^3.1.3
|
fast-deep-equal: ^3.1.3
|
||||||
@@ -3128,24 +3209,23 @@ __metadata:
|
|||||||
minimatch: ^3.1.2
|
minimatch: ^3.1.2
|
||||||
natural-compare: ^1.4.0
|
natural-compare: ^1.4.0
|
||||||
optionator: ^0.9.1
|
optionator: ^0.9.1
|
||||||
regexpp: ^3.2.0
|
|
||||||
strip-ansi: ^6.0.1
|
strip-ansi: ^6.0.1
|
||||||
strip-json-comments: ^3.1.0
|
strip-json-comments: ^3.1.0
|
||||||
text-table: ^0.2.0
|
text-table: ^0.2.0
|
||||||
bin:
|
bin:
|
||||||
eslint: bin/eslint.js
|
eslint: bin/eslint.js
|
||||||
checksum: 6212173691d90b1bc94dd3d640e1f210374b30c3905fc0a15e501cf71c6ca52aa3d80ea7a9a245adaaed26d6019169e01fb6881b3f2885b188d37069c749308c
|
checksum: e9a961fc3b3de5cff5a1cb2c92eeffaa7e155a715489e30b3e1e76f186bd1255e0481e09564f2094733c0b1dbd3453499fb72ae7c043c83156e11e6d965b2304
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"espree@npm:^9.4.0":
|
"espree@npm:^9.5.0":
|
||||||
version: 9.4.1
|
version: 9.5.0
|
||||||
resolution: "espree@npm:9.4.1"
|
resolution: "espree@npm:9.5.0"
|
||||||
dependencies:
|
dependencies:
|
||||||
acorn: ^8.8.0
|
acorn: ^8.8.0
|
||||||
acorn-jsx: ^5.3.2
|
acorn-jsx: ^5.3.2
|
||||||
eslint-visitor-keys: ^3.3.0
|
eslint-visitor-keys: ^3.3.0
|
||||||
checksum: 4d266b0cf81c7dfe69e542c7df0f246e78d29f5b04dda36e514eb4c7af117ee6cfbd3280e560571ed82ff6c9c3f0003c05b82583fc7a94006db7497c4fe4270e
|
checksum: a7f110aefb6407e0d3237aa635ab3cea87106ae63748dd23c67031afccc640d04c4209fca2daf16e2233c82efb505faead0fb84097478fd9cc6e8f8dd80bf99d
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
@@ -3689,6 +3769,15 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"he@npm:^1.2.0":
|
||||||
|
version: 1.2.0
|
||||||
|
resolution: "he@npm:1.2.0"
|
||||||
|
bin:
|
||||||
|
he: bin/he
|
||||||
|
checksum: 3d4d6babccccd79c5c5a3f929a68af33360d6445587d628087f39a965079d84f18ce9c3d3f917ee1e3978916fc833bb8b29377c3b403f919426f91bc6965e7a7
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"history@npm:^5.3.0":
|
"history@npm:^5.3.0":
|
||||||
version: 5.3.0
|
version: 5.3.0
|
||||||
resolution: "history@npm:5.3.0"
|
resolution: "history@npm:5.3.0"
|
||||||
@@ -3714,6 +3803,23 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"html-minifier-terser@npm:^6.1.0":
|
||||||
|
version: 6.1.0
|
||||||
|
resolution: "html-minifier-terser@npm:6.1.0"
|
||||||
|
dependencies:
|
||||||
|
camel-case: ^4.1.2
|
||||||
|
clean-css: ^5.2.2
|
||||||
|
commander: ^8.3.0
|
||||||
|
he: ^1.2.0
|
||||||
|
param-case: ^3.0.4
|
||||||
|
relateurl: ^0.2.7
|
||||||
|
terser: ^5.10.0
|
||||||
|
bin:
|
||||||
|
html-minifier-terser: cli.js
|
||||||
|
checksum: ac52c14006476f773204c198b64838477859dc2879490040efab8979c0207424da55d59df7348153f412efa45a0840a1ca3c757bf14767d23a15e3e389d37a93
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"http-cache-semantics@npm:^4.0.0, http-cache-semantics@npm:^4.1.0":
|
"http-cache-semantics@npm:^4.0.0, http-cache-semantics@npm:^4.1.0":
|
||||||
version: 4.1.1
|
version: 4.1.1
|
||||||
resolution: "http-cache-semantics@npm:4.1.1"
|
resolution: "http-cache-semantics@npm:4.1.1"
|
||||||
@@ -4326,6 +4432,15 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"lower-case@npm:^2.0.2":
|
||||||
|
version: 2.0.2
|
||||||
|
resolution: "lower-case@npm:2.0.2"
|
||||||
|
dependencies:
|
||||||
|
tslib: ^2.0.3
|
||||||
|
checksum: 83a0a5f159ad7614bee8bf976b96275f3954335a84fad2696927f609ddae902802c4f3312d86668722e668bef41400254807e1d3a7f2e8c3eede79691aa1f010
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"lowercase-keys@npm:^2.0.0":
|
"lowercase-keys@npm:^2.0.0":
|
||||||
version: 2.0.0
|
version: 2.0.0
|
||||||
resolution: "lowercase-keys@npm:2.0.0"
|
resolution: "lowercase-keys@npm:2.0.0"
|
||||||
@@ -4605,6 +4720,16 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"no-case@npm:^3.0.4":
|
||||||
|
version: 3.0.4
|
||||||
|
resolution: "no-case@npm:3.0.4"
|
||||||
|
dependencies:
|
||||||
|
lower-case: ^2.0.2
|
||||||
|
tslib: ^2.0.3
|
||||||
|
checksum: 0b2ebc113dfcf737d48dde49cfebf3ad2d82a8c3188e7100c6f375e30eafbef9e9124aadc3becef237b042fd5eb0aad2fd78669c20972d045bbe7fea8ba0be5c
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"node-gyp@npm:latest":
|
"node-gyp@npm:latest":
|
||||||
version: 9.3.1
|
version: 9.3.1
|
||||||
resolution: "node-gyp@npm:9.3.1"
|
resolution: "node-gyp@npm:9.3.1"
|
||||||
@@ -4700,27 +4825,6 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"notistack@npm:2.0.8":
|
|
||||||
version: 2.0.8
|
|
||||||
resolution: "notistack@npm:2.0.8"
|
|
||||||
dependencies:
|
|
||||||
clsx: ^1.1.0
|
|
||||||
hoist-non-react-statics: ^3.3.0
|
|
||||||
peerDependencies:
|
|
||||||
"@emotion/react": ^11.4.1
|
|
||||||
"@emotion/styled": ^11.3.0
|
|
||||||
"@mui/material": ^5.0.0
|
|
||||||
react: ^16.8.0 || ^17.0.0 || ^18.0.0
|
|
||||||
react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0
|
|
||||||
peerDependenciesMeta:
|
|
||||||
"@emotion/react":
|
|
||||||
optional: true
|
|
||||||
"@emotion/styled":
|
|
||||||
optional: true
|
|
||||||
checksum: f95952ea7209840f6f05a65e74f0fb4e7a1bb321753b2955ae6052f2205d47a6a3c50a42b72db11eac2fc491c4105b4687bed89e79287399530973fa133a5380
|
|
||||||
languageName: node
|
|
||||||
linkType: hard
|
|
||||||
|
|
||||||
"npm-run-all@npm:^4.1.5":
|
"npm-run-all@npm:^4.1.5":
|
||||||
version: 4.1.5
|
version: 4.1.5
|
||||||
resolution: "npm-run-all@npm:4.1.5"
|
resolution: "npm-run-all@npm:4.1.5"
|
||||||
@@ -4924,6 +5028,16 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"param-case@npm:^3.0.4":
|
||||||
|
version: 3.0.4
|
||||||
|
resolution: "param-case@npm:3.0.4"
|
||||||
|
dependencies:
|
||||||
|
dot-case: ^3.0.4
|
||||||
|
tslib: ^2.0.3
|
||||||
|
checksum: b34227fd0f794e078776eb3aa6247442056cb47761e9cd2c4c881c86d84c64205f6a56ef0d70b41ee7d77da02c3f4ed2f88e3896a8fefe08bdfb4deca037c687
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"parent-module@npm:^1.0.0":
|
"parent-module@npm:^1.0.0":
|
||||||
version: 1.0.1
|
version: 1.0.1
|
||||||
resolution: "parent-module@npm:1.0.1"
|
resolution: "parent-module@npm:1.0.1"
|
||||||
@@ -4955,6 +5069,16 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"pascal-case@npm:^3.1.2":
|
||||||
|
version: 3.1.2
|
||||||
|
resolution: "pascal-case@npm:3.1.2"
|
||||||
|
dependencies:
|
||||||
|
no-case: ^3.0.4
|
||||||
|
tslib: ^2.0.3
|
||||||
|
checksum: ba98bfd595fc91ef3d30f4243b1aee2f6ec41c53b4546bfa3039487c367abaa182471dcfc830a1f9e1a0df00c14a370514fa2b3a1aacc68b15a460c31116873e
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"path-exists@npm:^4.0.0":
|
"path-exists@npm:^4.0.0":
|
||||||
version: 4.0.0
|
version: 4.0.0
|
||||||
resolution: "path-exists@npm:4.0.0"
|
resolution: "path-exists@npm:4.0.0"
|
||||||
@@ -5184,27 +5308,39 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"react-router-dom@npm:^6.8.2":
|
"react-router-dom@npm:^6.9.0":
|
||||||
version: 6.8.2
|
version: 6.9.0
|
||||||
resolution: "react-router-dom@npm:6.8.2"
|
resolution: "react-router-dom@npm:6.9.0"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@remix-run/router": 1.3.3
|
"@remix-run/router": 1.4.0
|
||||||
react-router: 6.8.2
|
react-router: 6.9.0
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
react: ">=16.8"
|
react: ">=16.8"
|
||||||
react-dom: ">=16.8"
|
react-dom: ">=16.8"
|
||||||
checksum: eddc8b88e26c66408df894bdcf95efd6731e21b7cbfd7417cd456f0043916279e0559b06c6cdc19c2a55c6aefc4cc745fa4065d3505e519a95adbef0cc89e77f
|
checksum: 4d593491ab8db5611feda70002c62902baebb84d5c1c5e5b6172496f31f91130deee132bf4240dea634a88cb86c76d6da348f15b9cd5e5197be455efd88edf72
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"react-router@npm:6.8.2":
|
"react-router@npm:6.9.0":
|
||||||
version: 6.8.2
|
version: 6.9.0
|
||||||
resolution: "react-router@npm:6.8.2"
|
resolution: "react-router@npm:6.9.0"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@remix-run/router": 1.3.3
|
"@remix-run/router": 1.4.0
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
react: ">=16.8"
|
react: ">=16.8"
|
||||||
checksum: 9e98d03e1f18bfd5a35144a0c675adaf7c46a9ad436efdea2b52ef3a6e501ac6174a67ea90004e1339cd45019d6b1eb370627518320f7af9323ae74e0c6756ad
|
checksum: b2a5f42e042bee7a7f116ca7817b0e58359e5353d84887c9fe7a633d7490c03b1e0ae37cd01830c2a381e3d1e7d501bb4751e53cc3d491e25f36582d3f6e0546
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
|
"react-toastify@npm:^9.1.1":
|
||||||
|
version: 9.1.1
|
||||||
|
resolution: "react-toastify@npm:9.1.1"
|
||||||
|
dependencies:
|
||||||
|
clsx: ^1.1.1
|
||||||
|
peerDependencies:
|
||||||
|
react: ">=16"
|
||||||
|
react-dom: ">=16"
|
||||||
|
checksum: 2039255539961a9b4d77b2656f120b20abe46cb0c699a7f3c0af23b4ef669d9c4d24dae6b8f4954b5efd83edf6d6e23614a29e94e9ee0d2647741fba9ba2db85
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
@@ -5311,6 +5447,13 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"relateurl@npm:^0.2.7":
|
||||||
|
version: 0.2.7
|
||||||
|
resolution: "relateurl@npm:0.2.7"
|
||||||
|
checksum: 5891e792eae1dfc3da91c6fda76d6c3de0333a60aa5ad848982ebb6dccaa06e86385fb1235a1582c680a3d445d31be01c6bfc0804ebbcab5aaf53fa856fde6b6
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"require-directory@npm:^2.1.1":
|
"require-directory@npm:^2.1.1":
|
||||||
version: 2.1.1
|
version: 2.1.1
|
||||||
resolution: "require-directory@npm:2.1.1"
|
resolution: "require-directory@npm:2.1.1"
|
||||||
@@ -5661,6 +5804,16 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"source-map-support@npm:~0.5.20":
|
||||||
|
version: 0.5.21
|
||||||
|
resolution: "source-map-support@npm:0.5.21"
|
||||||
|
dependencies:
|
||||||
|
buffer-from: ^1.0.0
|
||||||
|
source-map: ^0.6.0
|
||||||
|
checksum: 43e98d700d79af1d36f859bdb7318e601dfc918c7ba2e98456118ebc4c4872b327773e5a1df09b0524e9e5063bb18f0934538eace60cca2710d1fa687645d137
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"source-map@npm:^0.5.7":
|
"source-map@npm:^0.5.7":
|
||||||
version: 0.5.7
|
version: 0.5.7
|
||||||
resolution: "source-map@npm:0.5.7"
|
resolution: "source-map@npm:0.5.7"
|
||||||
@@ -5668,6 +5821,13 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"source-map@npm:^0.6.0, source-map@npm:~0.6.0":
|
||||||
|
version: 0.6.1
|
||||||
|
resolution: "source-map@npm:0.6.1"
|
||||||
|
checksum: 59ce8640cf3f3124f64ac289012c2b8bd377c238e316fb323ea22fbfe83da07d81e000071d7242cad7a23cd91c7de98e4df8830ec3f133cb6133a5f6e9f67bc2
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"source-map@npm:^0.7.4":
|
"source-map@npm:^0.7.4":
|
||||||
version: 0.7.4
|
version: 0.7.4
|
||||||
resolution: "source-map@npm:0.7.4"
|
resolution: "source-map@npm:0.7.4"
|
||||||
@@ -5896,6 +6056,20 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"terser@npm:^5.10.0, terser@npm:^5.16.6":
|
||||||
|
version: 5.16.6
|
||||||
|
resolution: "terser@npm:5.16.6"
|
||||||
|
dependencies:
|
||||||
|
"@jridgewell/source-map": ^0.3.2
|
||||||
|
acorn: ^8.5.0
|
||||||
|
commander: ^2.20.0
|
||||||
|
source-map-support: ~0.5.20
|
||||||
|
bin:
|
||||||
|
terser: bin/terser
|
||||||
|
checksum: f763a7bcc7b98cb2bfc41434f7b92bfe8a701a12c92ea6049377736c8e6de328240d654a20dfe15ce170fd783491b9873fad9f4cd8fee4f6c6fb8ca407859dee
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"text-table@npm:^0.2.0":
|
"text-table@npm:^0.2.0":
|
||||||
version: 0.2.0
|
version: 0.2.0
|
||||||
resolution: "text-table@npm:0.2.0"
|
resolution: "text-table@npm:0.2.0"
|
||||||
@@ -5987,7 +6161,7 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"tslib@npm:^2.3.1, tslib@npm:^2.4.0, tslib@npm:^2.5.0":
|
"tslib@npm:^2.0.3, tslib@npm:^2.3.1, tslib@npm:^2.4.0, tslib@npm:^2.5.0":
|
||||||
version: 2.5.0
|
version: 2.5.0
|
||||||
resolution: "tslib@npm:2.5.0"
|
resolution: "tslib@npm:2.5.0"
|
||||||
checksum: ae3ed5f9ce29932d049908ebfdf21b3a003a85653a9a140d614da6b767a93ef94f460e52c3d787f0e4f383546981713f165037dc2274df212ea9f8a4541004e1
|
checksum: ae3ed5f9ce29932d049908ebfdf21b3a003a85653a9a140d614da6b767a93ef94f460e52c3d787f0e4f383546981713f165037dc2274df212ea9f8a4541004e1
|
||||||
@@ -6154,6 +6328,17 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"vite-plugin-minify@npm:^1.5.2":
|
||||||
|
version: 1.5.2
|
||||||
|
resolution: "vite-plugin-minify@npm:1.5.2"
|
||||||
|
dependencies:
|
||||||
|
html-minifier-terser: ^6.1.0
|
||||||
|
peerDependencies:
|
||||||
|
vite: "*"
|
||||||
|
checksum: e2b2af79b26430245a5532e8012f7d09e51b9997871ea281f4050aa065c09dbe52231d16605bfc155ad7499d2f4f907b6bd367d26b35e213bc5e3c80dcc31761
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"vite-plugin-svgr@npm:^2.4.0":
|
"vite-plugin-svgr@npm:^2.4.0":
|
||||||
version: 2.4.0
|
version: 2.4.0
|
||||||
resolution: "vite-plugin-svgr@npm:2.4.0"
|
resolution: "vite-plugin-svgr@npm:2.4.0"
|
||||||
|
|||||||
@@ -9,6 +9,8 @@
|
|||||||
; -DEMSESP_DEBUG_SENSOR ; additional debug for the dallas sensors
|
; -DEMSESP_DEBUG_SENSOR ; additional debug for the dallas sensors
|
||||||
; -DCORE_DEBUG_LEVEL=5 ; verbose core level debugging 5=verbose, 4=debug, 3=info
|
; -DCORE_DEBUG_LEVEL=5 ; verbose core level debugging 5=verbose, 4=debug, 3=info
|
||||||
; -DEMSESP_TEST ; enable the tests. EN language only
|
; -DEMSESP_TEST ; enable the tests. EN language only
|
||||||
|
; -DEMSESP_DE_ONLY ; only DE translated entity names
|
||||||
|
; -DEMSESP_EN_ONLY ; only EN translated entity names
|
||||||
; my_build_flags = -DEMSESP_DEBUG
|
; my_build_flags = -DEMSESP_DEBUG
|
||||||
|
|
||||||
[env:esp32_4M]
|
[env:esp32_4M]
|
||||||
|
|||||||
@@ -6,6 +6,4 @@ sonar.sources=./src
|
|||||||
sonar.cfamily.build-wrapper-output=build_wrapper_output_directory
|
sonar.cfamily.build-wrapper-output=build_wrapper_output_directory
|
||||||
sonar.sourceEncoding=UTF-8
|
sonar.sourceEncoding=UTF-8
|
||||||
sonar.host.url=https://sonarcloud.io
|
sonar.host.url=https://sonarcloud.io
|
||||||
sonar.cfamily.threads=2
|
sonar.cfamily.threads=4
|
||||||
sonar.cfamily.cache.enabled=false
|
|
||||||
; sonar.cfamily.cache.path=./sonar/cache
|
|
||||||
|
|||||||
@@ -52,9 +52,11 @@ using string_vector = std::vector<const char *>;
|
|||||||
#define F_(string_name) (__pstr__##string_name)
|
#define F_(string_name) (__pstr__##string_name)
|
||||||
#define FL_(list_name) (__pstr__L_##list_name)
|
#define FL_(list_name) (__pstr__L_##list_name)
|
||||||
|
|
||||||
#if defined(EMSESP_TEST)
|
#if defined(EMSESP_TEST) || defined(EMSESP_EN_ONLY)
|
||||||
// In testing just take one language (en) to save on Flash space
|
// In testing just take one language (en) to save on Flash space
|
||||||
#define MAKE_TRANSLATION(list_name, shortname, en, ...) static const char * const __pstr__L_##list_name[] = {shortname, en, nullptr};
|
#define MAKE_TRANSLATION(list_name, shortname, en, ...) static const char * const __pstr__L_##list_name[] = {shortname, en, nullptr};
|
||||||
|
#elif defined(EMSESP_DE_ONLY)
|
||||||
|
#define MAKE_TRANSLATION(list_name, shortname, en, de, ...) static const char * const __pstr__L_##list_name[] = {shortname, de, nullptr};
|
||||||
#else
|
#else
|
||||||
#define MAKE_TRANSLATION(list_name, ...) static const char * const __pstr__L_##list_name[] = {__VA_ARGS__, nullptr};
|
#define MAKE_TRANSLATION(list_name, ...) static const char * const __pstr__L_##list_name[] = {__VA_ARGS__, nullptr};
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -252,7 +252,7 @@ MAKE_TRANSLATION(outside_basepoint, "outside basepoint", "Basispunkt Außentemp.
|
|||||||
MAKE_TRANSLATION(functioning_mode, "functioning mode", "Funktionsweise", "Functiemodus", "Driftläge", "tryb pracy", "driftsmodus", "mode de fonctionnement", "işletme konumu")
|
MAKE_TRANSLATION(functioning_mode, "functioning mode", "Funktionsweise", "Functiemodus", "Driftläge", "tryb pracy", "driftsmodus", "mode de fonctionnement", "işletme konumu")
|
||||||
|
|
||||||
// MQTT Discovery - this is special device entity for 'climate'
|
// MQTT Discovery - this is special device entity for 'climate'
|
||||||
MAKE_TRANSLATION(haclimate, "haclimate", "Discovery current room temperature") // TODO translate
|
MAKE_TRANSLATION(haclimate, "haclimate", "Discovery current room temperature", "Discovery Temperatur") // TODO translate
|
||||||
|
|
||||||
// mixer
|
// mixer
|
||||||
MAKE_TRANSLATION(stopped, "stopped", "gestoppt", "gestopt", "stoppad", "zatrzymany", "stoppet", "arrêté", "durdu")
|
MAKE_TRANSLATION(stopped, "stopped", "gestoppt", "gestopt", "stoppad", "zatrzymany", "stoppet", "arrêté", "durdu")
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
#define EMSESP_APP_VERSION "3.6.0-dev.5"
|
#define EMSESP_APP_VERSION "3.6.0-dev.6"
|
||||||
|
|||||||
Reference in New Issue
Block a user