From 8cbae88dc36edb88495725dbed8341c8a357ba25 Mon Sep 17 00:00:00 2001 From: Proddy Date: Fri, 10 Mar 2023 20:28:43 +0100 Subject: [PATCH 01/15] replace notistack --- .gitignore | 2 + interface/package.json | 2 +- interface/src/App.tsx | 38 +++++++--------- interface/src/AppRouting.tsx | 14 +++--- interface/src/SignIn.tsx | 7 ++- .../src/components/upload/useFileUpload.ts | 11 +++-- .../authentication/Authentication.tsx | 5 +-- .../framework/network/NetworkSettingsForm.tsx | 5 +-- .../framework/network/WiFiNetworkScanner.tsx | 17 +++---- interface/src/framework/ntp/NTPStatusForm.tsx | 7 ++- .../src/framework/security/GenerateToken.tsx | 8 ++-- .../framework/system/GeneralFileUpload.tsx | 20 ++++----- interface/src/framework/system/SystemLog.tsx | 8 ++-- .../src/framework/system/SystemStatusForm.tsx | 9 ++-- interface/src/project/DashboardData.tsx | 44 +++++++++---------- interface/src/project/DashboardStatus.tsx | 7 ++- interface/src/project/HelpInformation.tsx | 10 ++--- interface/src/project/SettingsApplication.tsx | 8 ++-- .../src/project/SettingsCustomization.tsx | 17 ++++--- interface/src/project/SettingsScheduler.tsx | 10 ++--- interface/src/utils/useRest.ts | 15 +++---- interface/yarn.lock | 37 ++++++---------- 22 files changed, 129 insertions(+), 172 deletions(-) diff --git a/.gitignore b/.gitignore index a4d5706dd..22e24ea0a 100644 --- a/.gitignore +++ b/.gitignore @@ -51,3 +51,5 @@ build_wrapper_output_directory/ # entity dump results dump_entities.csv dump_entities.xls* + +react-toastify/ \ No newline at end of file diff --git a/interface/package.json b/interface/package.json index 4d8f6f314..d19e380d4 100644 --- a/interface/package.json +++ b/interface/package.json @@ -38,12 +38,12 @@ "jwt-decode": "^3.1.2", "lodash-es": "^4.17.21", "mime-types": "^2.1.35", - "notistack": "2.0.8", "react": "latest", "react-dom": "latest", "react-dropzone": "^14.2.3", "react-icons": "^4.8.0", "react-router-dom": "^6.8.2", + "react-toastify": "^9.1.1", "sockette": "^2.0.6", "typesafe-i18n": "^5.24.2", "typescript": "^4.9.5" diff --git a/interface/src/App.tsx b/interface/src/App.tsx index 2556fd06c..553c5045d 100644 --- a/interface/src/App.tsx +++ b/interface/src/App.tsx @@ -1,8 +1,7 @@ -import { FC, createRef, useEffect, useState, RefObject } from 'react'; -import { SnackbarProvider } from 'notistack'; +import { FC, useEffect, useState } from 'react'; -import { IconButton } from '@mui/material'; -import CloseIcon from '@mui/icons-material/Close'; +import { ToastContainer } from 'react-toastify'; +import 'react-toastify/dist/ReactToastify.minimal.css'; import CustomTheme from 'CustomTheme'; import AppRouting from 'AppRouting'; @@ -15,12 +14,6 @@ import { loadLocaleAsync } from 'i18n/i18n-util.async'; const detectedLocale = detectLocale(localStorageDetector); const App: FC = () => { - const notistackRef: RefObject = createRef(); - - const onClickDismiss = (key: string | number | undefined) => () => { - notistackRef.current.closeSnackbar(key); - }; - const [wasLoaded, setWasLoaded] = useState(false); useEffect(() => { @@ -32,18 +25,19 @@ const App: FC = () => { return ( - ( - - - - )} - > - - + + ); diff --git a/interface/src/AppRouting.tsx b/interface/src/AppRouting.tsx index 472b6d9ee..0fbde8ea2 100644 --- a/interface/src/AppRouting.tsx +++ b/interface/src/AppRouting.tsx @@ -2,7 +2,7 @@ import { FC, useContext, useEffect } from 'react'; 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'; @@ -14,17 +14,17 @@ import AuthenticatedRouting from 'AuthenticatedRouting'; interface SecurityRedirectProps { message: string; - variant?: VariantType; + // variant?: VariantType; signOut?: boolean; } -const RootRedirect: FC = ({ message, variant, signOut }) => { +const RootRedirect: FC = ({ message, signOut }) => { const authenticationContext = useContext(AuthenticationContext); - const { enqueueSnackbar } = useSnackbar(); useEffect(() => { signOut && authenticationContext.signOut(false); - enqueueSnackbar(message, { variant }); - }, [message, variant, signOut, authenticationContext, enqueueSnackbar]); + // TODO toast variant + toast.error(message); + }, [message, signOut, authenticationContext]); return ; }; @@ -50,7 +50,7 @@ const AppRouting: FC = () => { } /> - } /> + } /> { const authenticationContext = useContext(AuthenticationContext); - const { enqueueSnackbar } = useSnackbar(); const [signInRequest, setSignInRequest] = useState({ username: '', @@ -61,10 +60,10 @@ const SignIn: FC = () => { } catch (error) { if (error.response) { if (error.response?.status === 401) { - enqueueSnackbar(LL.INVALID_LOGIN(), { variant: 'warning' }); + toast.warn(LL.INVALID_LOGIN()); } } else { - enqueueSnackbar(extractErrorMessage(error, LL.ERROR()), { variant: 'error' }); + toast.error(extractErrorMessage(error, LL.ERROR())); } setProcessing(false); } diff --git a/interface/src/components/upload/useFileUpload.ts b/interface/src/components/upload/useFileUpload.ts index bf6d80a3f..afa41aaa7 100644 --- a/interface/src/components/upload/useFileUpload.ts +++ b/interface/src/components/upload/useFileUpload.ts @@ -1,6 +1,6 @@ import { useCallback, useEffect, useState } from 'react'; import axios, { AxiosPromise, CancelTokenSource, AxiosProgressEvent } from 'axios'; -import { useSnackbar } from 'notistack'; +import { toast } from 'react-toastify'; import { extractErrorMessage } from 'utils'; import { FileUploadConfig } from 'api/endpoints'; @@ -14,7 +14,6 @@ interface MediaUploadOptions { const useFileUpload = ({ upload }: MediaUploadOptions) => { const { LL } = useI18nContext(); - const { enqueueSnackbar } = useSnackbar(); const [uploading, setUploading] = useState(false); const [md5, setMd5] = useState(''); const [uploadProgress, setUploadProgress] = useState(); @@ -49,17 +48,17 @@ const useFileUpload = ({ upload }: MediaUploadOptions) => { }); resetUploadingStates(); if (response.status === 200) { - enqueueSnackbar(LL.UPLOAD() + ' ' + LL.SUCCESSFUL(), { variant: 'success' }); + toast.success(LL.UPLOAD() + ' ' + LL.SUCCESSFUL()); } else if (response.status === 201) { setMd5(String(response.data)); - enqueueSnackbar(LL.UPLOAD() + ' MD5 ' + LL.SUCCESSFUL(), { variant: 'success' }); + toast.success(LL.UPLOAD() + ' MD5 ' + LL.SUCCESSFUL()); } } catch (error) { if (axios.isCancel(error)) { - enqueueSnackbar(LL.UPLOAD() + ' ' + LL.ABORTED(), { variant: 'warning' }); + toast.warning(LL.UPLOAD() + ' ' + LL.ABORTED()); } else { resetUploadingStates(); - enqueueSnackbar(extractErrorMessage(error, LL.UPLOAD() + ' ' + LL.FAILED()), { variant: 'error' }); + toast.error(extractErrorMessage(error, LL.UPLOAD() + ' ' + LL.FAILED())); } } }; diff --git a/interface/src/contexts/authentication/Authentication.tsx b/interface/src/contexts/authentication/Authentication.tsx index 426e81312..d997356e4 100644 --- a/interface/src/contexts/authentication/Authentication.tsx +++ b/interface/src/contexts/authentication/Authentication.tsx @@ -1,5 +1,5 @@ import { FC, useCallback, useEffect, useState } from 'react'; -import { useSnackbar } from 'notistack'; +import { toast } from 'react-toastify'; import { useNavigate } from 'react-router-dom'; import { useI18nContext } from 'i18n/i18n-react'; @@ -15,7 +15,6 @@ const Authentication: FC = ({ children }) => { const { LL } = useI18nContext(); const navigate = useNavigate(); - const { enqueueSnackbar } = useSnackbar(); const [initialized, setInitialized] = useState(false); const [me, setMe] = useState(); @@ -25,7 +24,7 @@ const Authentication: FC = ({ children }) => { AuthenticationApi.getStorage().setItem(ACCESS_TOKEN, accessToken); const decodedMe = AuthenticationApi.decodeMeJWT(accessToken); setMe(decodedMe); - enqueueSnackbar(LL.LOGGED_IN({ name: decodedMe.username }), { variant: 'success' }); + toast.success(LL.LOGGED_IN({ name: decodedMe.username })); } catch (error) { setMe(undefined); throw new Error('Failed to parse JWT'); diff --git a/interface/src/framework/network/NetworkSettingsForm.tsx b/interface/src/framework/network/NetworkSettingsForm.tsx index 59ab5afaf..ad980f34a 100644 --- a/interface/src/framework/network/NetworkSettingsForm.tsx +++ b/interface/src/framework/network/NetworkSettingsForm.tsx @@ -1,5 +1,5 @@ import { FC, useContext, useEffect, useState } from 'react'; -import { useSnackbar } from 'notistack'; +import { toast } from 'react-toastify'; import { Avatar, @@ -48,7 +48,6 @@ import RestartMonitor from '../system/RestartMonitor'; const WiFiSettingsForm: FC = () => { const { LL } = useI18nContext(); - const { enqueueSnackbar } = useSnackbar(); const { selectedNetwork, deselectNetwork } = useContext(WiFiConnectionContext); @@ -118,7 +117,7 @@ const WiFiSettingsForm: FC = () => { await EMSESP.restart(); setRestarting(true); } catch (error) { - enqueueSnackbar(LL.PROBLEM_UPDATING(), { variant: 'error' }); + toast.error(LL.PROBLEM_UPDATING()); } }; diff --git a/interface/src/framework/network/WiFiNetworkScanner.tsx b/interface/src/framework/network/WiFiNetworkScanner.tsx index bfbb12c9e..61bb39aed 100644 --- a/interface/src/framework/network/WiFiNetworkScanner.tsx +++ b/interface/src/framework/network/WiFiNetworkScanner.tsx @@ -1,5 +1,5 @@ import { useEffect, FC, useState, useCallback, useRef } from 'react'; -import { useSnackbar } from 'notistack'; +import { toast } from 'react-toastify'; import { Button } from '@mui/material'; import PermScanWifiIcon from '@mui/icons-material/PermScanWifi'; @@ -24,20 +24,15 @@ const compareNetworks = (network1: WiFiNetwork, network2: WiFiNetwork) => { const WiFiNetworkScanner: FC = () => { const { LL } = useI18nContext(); - const { enqueueSnackbar } = useSnackbar(); - const pollCount = useRef(0); const [networkList, setNetworkList] = useState(); const [errorMessage, setErrorMessage] = useState(); - const finishedWithError = useCallback( - (message: string) => { - enqueueSnackbar(message, { variant: 'error' }); - setNetworkList(undefined); - setErrorMessage(message); - }, - [enqueueSnackbar] - ); + const finishedWithError = useCallback((message: string) => { + toast.error(message); + setNetworkList(undefined); + setErrorMessage(message); + }, []); const pollNetworkList = useCallback(async () => { try { diff --git a/interface/src/framework/ntp/NTPStatusForm.tsx b/interface/src/framework/ntp/NTPStatusForm.tsx index 54793125f..9f2c42b0a 100644 --- a/interface/src/framework/ntp/NTPStatusForm.tsx +++ b/interface/src/framework/ntp/NTPStatusForm.tsx @@ -1,5 +1,5 @@ import { FC, useContext, useState } from 'react'; -import { useSnackbar } from 'notistack'; +import { toast } from 'react-toastify'; import { Avatar, @@ -55,7 +55,6 @@ const NTPStatusForm: FC = () => { const [localTime, setLocalTime] = useState(''); const [settingTime, setSettingTime] = useState(false); const [processing, setProcessing] = useState(false); - const { enqueueSnackbar } = useSnackbar(); const { me } = useContext(AuthenticatedContext); const { LL } = useI18nContext(); @@ -88,11 +87,11 @@ const NTPStatusForm: FC = () => { await NTPApi.updateTime({ local_time: formatLocalDateTime(new Date(localTime)) }); - enqueueSnackbar(LL.TIME_SET(), { variant: 'success' }); + toast.success(LL.TIME_SET()); setSettingTime(false); loadData(); } catch (error) { - enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_UPDATING()), { variant: 'error' }); + toast.error(extractErrorMessage(error, LL.PROBLEM_UPDATING())); } finally { setProcessing(false); } diff --git a/interface/src/framework/security/GenerateToken.tsx b/interface/src/framework/security/GenerateToken.tsx index ccbc0e5e2..2b0c0e9fd 100644 --- a/interface/src/framework/security/GenerateToken.tsx +++ b/interface/src/framework/security/GenerateToken.tsx @@ -14,7 +14,7 @@ import { import CloseIcon from '@mui/icons-material/Close'; import { extractErrorMessage } from 'utils'; -import { useSnackbar } from 'notistack'; +import { toast } from 'react-toastify'; import { MessageBox } from 'components'; import * as SecurityApi from 'api/security'; import { Token } from 'types'; @@ -32,15 +32,13 @@ const GenerateToken: FC = ({ username, onClose }) => { const { LL } = useI18nContext(); - const { enqueueSnackbar } = useSnackbar(); - const getToken = useCallback(async () => { try { setToken((await SecurityApi.generateToken(username)).data); } catch (error) { - enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_UPDATING()), { variant: 'error' }); + toast.error(extractErrorMessage(error, LL.PROBLEM_UPDATING())); } - }, [username, enqueueSnackbar, LL]); + }, [username, LL]); useEffect(() => { if (open) { diff --git a/interface/src/framework/system/GeneralFileUpload.tsx b/interface/src/framework/system/GeneralFileUpload.tsx index 14e284c8c..51c8a48b2 100644 --- a/interface/src/framework/system/GeneralFileUpload.tsx +++ b/interface/src/framework/system/GeneralFileUpload.tsx @@ -9,7 +9,7 @@ import { SingleUpload, useFileUpload } from 'components'; import DownloadIcon from '@mui/icons-material/GetApp'; -import { useSnackbar } from 'notistack'; +import { toast } from 'react-toastify'; import { extractErrorMessage } from 'utils'; @@ -24,8 +24,6 @@ interface UploadFileProps { const GeneralFileUpload: FC = ({ uploadGeneralFile }) => { const [uploadFile, cancelUpload, uploading, uploadProgress, md5] = useFileUpload({ upload: uploadGeneralFile }); - const { enqueueSnackbar } = useSnackbar(); - const { LL } = useI18nContext(); const saveFile = (json: any, endpoint: string) => { @@ -40,19 +38,18 @@ const GeneralFileUpload: FC = ({ uploadGeneralFile }) => { document.body.appendChild(a); a.click(); document.body.removeChild(a); - enqueueSnackbar(LL.DOWNLOAD_SUCCESSFUL(), { variant: 'info' }); + toast.info(LL.DOWNLOAD_SUCCESSFUL()); }; const downloadSettings = async () => { try { const response = await EMSESP.getSettings(); if (response.status !== 200) { - enqueueSnackbar(LL.PROBLEM_LOADING(), { variant: 'error' }); - } else { + toast.error(LL.PROBLEM_LOADING()); saveFile(response.data, 'settings'); } } catch (error) { - enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_LOADING()), { variant: 'error' }); + toast.error(extractErrorMessage(error, LL.PROBLEM_LOADING())); } }; @@ -60,12 +57,12 @@ const GeneralFileUpload: FC = ({ uploadGeneralFile }) => { try { const response = await EMSESP.getCustomizations(); if (response.status !== 200) { - enqueueSnackbar(LL.PROBLEM_LOADING(), { variant: 'error' }); + toast.error(LL.PROBLEM_LOADING()); } else { saveFile(response.data, 'customizations'); } } catch (error) { - enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_LOADING()), { variant: 'error' }); + toast.error(extractErrorMessage(error, LL.PROBLEM_LOADING())); } }; @@ -73,12 +70,11 @@ const GeneralFileUpload: FC = ({ uploadGeneralFile }) => { try { const response = await EMSESP.readSchedule(); if (response.status !== 200) { - enqueueSnackbar(LL.PROBLEM_LOADING(), { variant: 'error' }); - } else { + toast.error(LL.PROBLEM_LOADING()); saveFile(response.data, 'schedule'); } } catch (error) { - enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_LOADING()), { variant: 'error' }); + toast.error(extractErrorMessage(error, LL.PROBLEM_LOADING())); } }; diff --git a/interface/src/framework/system/SystemLog.tsx b/interface/src/framework/system/SystemLog.tsx index 5b2aad646..b79b02248 100644 --- a/interface/src/framework/system/SystemLog.tsx +++ b/interface/src/framework/system/SystemLog.tsx @@ -12,7 +12,7 @@ import { updateValue, useRest, extractErrorMessage } from 'utils'; import DownloadIcon from '@mui/icons-material/GetApp'; -import { useSnackbar } from 'notistack'; +import { toast } from 'react-toastify'; import { EVENT_SOURCE_ROOT } from 'api/endpoints'; @@ -93,8 +93,6 @@ const SystemLog: FC = () => { const updateFormValue = updateValue(setData); - const { enqueueSnackbar } = useSnackbar(); - const reloadPage = () => { window.location.reload(); }; @@ -108,10 +106,10 @@ const SystemLog: FC = () => { compact: data.compact }); if (response.status !== 200) { - enqueueSnackbar(LL.PROBLEM_UPDATING(), { variant: 'error' }); + toast.error(LL.PROBLEM_UPDATING()); } } catch (error) { - enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_UPDATING()), { variant: 'error' }); + toast.error(extractErrorMessage(error, LL.PROBLEM_UPDATING())); } } }; diff --git a/interface/src/framework/system/SystemStatusForm.tsx b/interface/src/framework/system/SystemStatusForm.tsx index 453db573a..f0d078da9 100644 --- a/interface/src/framework/system/SystemStatusForm.tsx +++ b/interface/src/framework/system/SystemStatusForm.tsx @@ -1,5 +1,5 @@ import { FC, useContext, useState, useEffect } from 'react'; -import { useSnackbar } from 'notistack'; +import { toast } from 'react-toastify'; import { Avatar, Box, @@ -61,7 +61,6 @@ const SystemStatusForm: FC = () => { const [confirmRestart, setConfirmRestart] = useState(false); const [confirmFactoryReset, setConfirmFactoryReset] = useState(false); const [processing, setProcessing] = useState(false); - const { enqueueSnackbar } = useSnackbar(); const [showingVersion, setShowingVersion] = useState(false); const [latestVersion, setLatestVersion] = useState(); const [latestDevVersion, setLatestDevVersion] = useState(); @@ -91,7 +90,7 @@ const SystemStatusForm: FC = () => { setRestarting(true); } } catch (error) { - enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_LOADING()), { variant: 'error' }); + toast.error(extractErrorMessage(error, LL.PROBLEM_LOADING())); } finally { setConfirmRestart(false); setProcessing(false); @@ -104,7 +103,7 @@ const SystemStatusForm: FC = () => { await SystemApi.partition(); setRestarting(true); } catch (error) { - enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_LOADING()), { variant: 'error' }); + toast.error(extractErrorMessage(error, LL.PROBLEM_LOADING())); } finally { setConfirmRestart(false); setProcessing(false); @@ -211,7 +210,7 @@ const SystemStatusForm: FC = () => { await SystemApi.factoryReset(); setRestarting(true); } catch (error) { - enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_UPDATING()), { variant: 'error' }); + toast.error(extractErrorMessage(error, LL.PROBLEM_UPDATING())); } finally { setConfirmFactoryReset(false); setProcessing(false); diff --git a/interface/src/project/DashboardData.tsx b/interface/src/project/DashboardData.tsx index c20887e62..b7bfdd84b 100644 --- a/interface/src/project/DashboardData.tsx +++ b/interface/src/project/DashboardData.tsx @@ -20,7 +20,7 @@ import { Checkbox } from '@mui/material'; -import { useSnackbar } from 'notistack'; +import { toast } from 'react-toastify'; import { useTheme } from '@table-library/react-table-library/theme'; import { useSort, SortToggleType } from '@table-library/react-table-library/sort'; @@ -78,8 +78,6 @@ const DashboardData: FC = () => { const { LL } = useI18nContext(); - const { enqueueSnackbar } = useSnackbar(); - const [coreData, setCoreData] = useState({ connected: true, devices: [], @@ -363,9 +361,9 @@ const DashboardData: FC = () => { try { setCoreData((await EMSESP.readCoreData()).data); } catch (error) { - enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_LOADING()), { variant: 'error' }); + toast.error(extractErrorMessage(error, LL.PROBLEM_LOADING())); } - }, [enqueueSnackbar, LL]); + }, [LL]); useEffect(() => { fetchCoreData(); @@ -384,7 +382,7 @@ const DashboardData: FC = () => { try { setDeviceData((await EMSESP.readDeviceData({ id: unique_id })).data); } catch (error) { - enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_LOADING()), { variant: 'error' }); + toast.error(extractErrorMessage(error, LL.PROBLEM_LOADING())); } }; @@ -392,7 +390,7 @@ const DashboardData: FC = () => { try { setSensorData((await EMSESP.readSensorData()).data); } catch (error) { - enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_LOADING()), { variant: 'error' }); + toast.error(extractErrorMessage(error, LL.PROBLEM_LOADING())); } }; @@ -468,15 +466,15 @@ const DashboardData: FC = () => { devicevalue: deviceValue }); if (response.status === 204) { - enqueueSnackbar(LL.WRITE_CMD_FAILED(), { variant: 'error' }); + toast.error(LL.WRITE_CMD_FAILED()); } else if (response.status === 403) { - enqueueSnackbar(LL.ACCESS_DENIED(), { variant: 'error' }); + toast.error(LL.ACCESS_DENIED()); } else { - enqueueSnackbar(LL.WRITE_CMD_SENT(), { variant: 'success' }); + toast.success(LL.WRITE_CMD_SENT()); } setDeviceValue(undefined); } catch (error) { - enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_UPDATING()), { variant: 'error' }); + toast.error(extractErrorMessage(error, LL.PROBLEM_UPDATING())); } finally { refreshData(); setDeviceValue(undefined); @@ -562,15 +560,15 @@ const DashboardData: FC = () => { offset: sensor.o }); 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) { - enqueueSnackbar(LL.ACCESS_DENIED(), { variant: 'error' }); + toast.error(LL.ACCESS_DENIED()); } else { - enqueueSnackbar(LL.UPDATED_OF(LL.SENSOR()), { variant: 'success' }); + toast.success(LL.UPDATED_OF(LL.SENSOR())); } setSensor(undefined); } catch (error) { - enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_UPDATING()), { variant: 'error' }); + toast.error(extractErrorMessage(error, LL.PROBLEM_UPDATING())); } finally { setSensor(undefined); fetchSensorData(); @@ -991,14 +989,14 @@ const DashboardData: FC = () => { }); 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) { - enqueueSnackbar(LL.ACCESS_DENIED(), { variant: 'error' }); + toast.error(LL.ACCESS_DENIED()); } else { - enqueueSnackbar(LL.REMOVED_OF(LL.ANALOG_SENSOR()), { variant: 'success' }); + toast.success(LL.REMOVED_OF(LL.ANALOG_SENSOR())); } } catch (error) { - enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_UPDATING()), { variant: 'error' }); + toast.error(extractErrorMessage(error, LL.PROBLEM_UPDATING())); } finally { setAnalog(undefined); fetchSensorData(); @@ -1019,14 +1017,14 @@ const DashboardData: FC = () => { }); 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) { - enqueueSnackbar(LL.ACCESS_DENIED(), { variant: 'error' }); + toast.error(LL.ACCESS_DENIED()); } else { - enqueueSnackbar(LL.UPDATED_OF(LL.ANALOG_SENSOR()), { variant: 'success' }); + toast.success(LL.UPDATED_OF(LL.ANALOG_SENSOR())); } } catch (error) { - enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_UPDATING()), { variant: 'error' }); + toast.error(extractErrorMessage(error, LL.PROBLEM_UPDATING())); } finally { setAnalog(undefined); fetchSensorData(); diff --git a/interface/src/project/DashboardStatus.tsx b/interface/src/project/DashboardStatus.tsx index 87b22537b..30c053e7d 100644 --- a/interface/src/project/DashboardStatus.tsx +++ b/interface/src/project/DashboardStatus.tsx @@ -1,5 +1,5 @@ import { FC, useState, useContext, useEffect } from 'react'; -import { useSnackbar } from 'notistack'; +import { toast } from 'react-toastify'; import { Avatar, Button, @@ -74,7 +74,6 @@ const DashboardStatus: FC = () => { const theme = useTheme(); const [confirmScan, setConfirmScan] = useState(false); - const { enqueueSnackbar } = useSnackbar(); const { me } = useContext(AuthenticatedContext); @@ -146,9 +145,9 @@ const DashboardStatus: FC = () => { const scan = async () => { try { await EMSESP.scanDevices(); - enqueueSnackbar(LL.SCANNING() + '...', { variant: 'info' }); + toast.info(LL.SCANNING() + '...'); } catch (error) { - enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_UPDATING()), { variant: 'error' }); + toast.error(extractErrorMessage(error, LL.PROBLEM_UPDATING())); } finally { setConfirmScan(false); } diff --git a/interface/src/project/HelpInformation.tsx b/interface/src/project/HelpInformation.tsx index e9bfd97fd..4b0c6288b 100644 --- a/interface/src/project/HelpInformation.tsx +++ b/interface/src/project/HelpInformation.tsx @@ -4,7 +4,7 @@ import { Typography, Button, Box, List, ListItem, ListItemText, Link, ListItemAv import { SectionContent } from 'components'; -import { useSnackbar } from 'notistack'; +import { toast } from 'react-toastify'; import CommentIcon from '@mui/icons-material/CommentTwoTone'; import MenuBookIcon from '@mui/icons-material/MenuBookTwoTone'; @@ -21,8 +21,6 @@ import * as EMSESP from './api'; const HelpInformation: FC = () => { const { LL } = useI18nContext(); - const { enqueueSnackbar } = useSnackbar(); - const saveFile = (json: any, endpoint: string) => { const a = document.createElement('a'); const filename = 'emsesp_' + endpoint + '.txt'; @@ -35,7 +33,7 @@ const HelpInformation: FC = () => { document.body.appendChild(a); a.click(); document.body.removeChild(a); - enqueueSnackbar(LL.DOWNLOAD_SUCCESSFUL(), { variant: 'info' }); + toast.info(LL.DOWNLOAD_SUCCESSFUL()); }; const callAPI = async (endpoint: string) => { @@ -46,12 +44,12 @@ const HelpInformation: FC = () => { id: 0 }); if (response.status !== 200) { - enqueueSnackbar(LL.PROBLEM_LOADING(), { variant: 'error' }); + toast.error(LL.PROBLEM_LOADING()); } else { saveFile(response.data, endpoint); } } catch (error) { - enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_LOADING()), { variant: 'error' }); + toast.error(extractErrorMessage(error, LL.PROBLEM_LOADING())); } }; diff --git a/interface/src/project/SettingsApplication.tsx b/interface/src/project/SettingsApplication.tsx index 40063dc1b..3f24ff9c5 100644 --- a/interface/src/project/SettingsApplication.tsx +++ b/interface/src/project/SettingsApplication.tsx @@ -1,7 +1,7 @@ import { FC, useState } from 'react'; 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'; @@ -58,8 +58,6 @@ const SettingsApplication: FC = () => { const { LL } = useI18nContext(); - const { enqueueSnackbar } = useSnackbar(); - const updateFormValue = updateValueDirty(origData, dirtyFlags, setDirtyFlags, setData); const [fieldErrors, setFieldErrors] = useState(); @@ -85,7 +83,7 @@ const SettingsApplication: FC = () => { }); } } catch (error) { - enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_UPDATING()), { variant: 'error' }); + toast.error(extractErrorMessage(error, LL.PROBLEM_UPDATING())); } finally { setProcessingBoard(false); } @@ -124,7 +122,7 @@ const SettingsApplication: FC = () => { await EMSESP.restart(); setRestarting(true); } catch (error) { - enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_UPDATING()), { variant: 'error' }); + toast.error(extractErrorMessage(error, LL.PROBLEM_UPDATING())); } }; diff --git a/interface/src/project/SettingsCustomization.tsx b/interface/src/project/SettingsCustomization.tsx index 796e46a6a..ff05ac1b4 100644 --- a/interface/src/project/SettingsCustomization.tsx +++ b/interface/src/project/SettingsCustomization.tsx @@ -22,7 +22,7 @@ import { 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 { useSnackbar } from 'notistack'; +import { toast } from 'react-toastify'; import WarningIcon from '@mui/icons-material/Warning'; import CancelIcon from '@mui/icons-material/Cancel'; @@ -51,7 +51,6 @@ export const APIURL = window.location.origin + '/api/'; const SettingsCustomization: FC = () => { const { LL } = useI18nContext(); - const { enqueueSnackbar } = useSnackbar(); const emptyDeviceEntity = { id: '', v: 0, n: '', cn: '', m: 0, w: false }; @@ -257,9 +256,9 @@ const SettingsCustomization: FC = () => { const resetCustomization = async () => { try { await EMSESP.resetCustomizations(); - enqueueSnackbar(LL.CUSTOMIZATIONS_RESTART(), { variant: 'info' }); + toast.info(LL.CUSTOMIZATIONS_RESTART()); } catch (error) { - enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_UPDATING()), { variant: 'error' }); + toast.error(extractErrorMessage(error, LL.PROBLEM_UPDATING())); } finally { setConfirmReset(false); } @@ -296,7 +295,7 @@ const SettingsCustomization: FC = () => { await EMSESP.restart(); setRestarting(true); } catch (error) { - enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_UPDATING()), { variant: 'error' }); + toast.error(extractErrorMessage(error, LL.PROBLEM_UPDATING())); } }; @@ -307,7 +306,7 @@ const SettingsCustomization: FC = () => { // check size in bytes to match buffer in CPP, which is 2048 const bytes = new TextEncoder().encode(JSON.stringify(masked_entities)).length; if (bytes > 2000) { - enqueueSnackbar(LL.CUSTOMIZATIONS_FULL(), { variant: 'warning' }); + toast.warning(LL.CUSTOMIZATIONS_FULL()); return; } @@ -317,14 +316,14 @@ const SettingsCustomization: FC = () => { entity_ids: masked_entities }); if (response.status === 200) { - enqueueSnackbar(LL.CUSTOMIZATIONS_SAVED(), { variant: 'success' }); + toast.success(LL.CUSTOMIZATIONS_SAVED()); } else if (response.status === 201) { setRestartNeeded(true); } else { - enqueueSnackbar(LL.PROBLEM_UPDATING(), { variant: 'error' }); + toast.error(LL.PROBLEM_UPDATING()); } } catch (error) { - enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_UPDATING()), { variant: 'error' }); + toast.error(extractErrorMessage(error, LL.PROBLEM_UPDATING())); } setOriginalSettings(deviceEntities); } diff --git a/interface/src/project/SettingsScheduler.tsx b/interface/src/project/SettingsScheduler.tsx index bf2bff71a..c37f34ced 100644 --- a/interface/src/project/SettingsScheduler.tsx +++ b/interface/src/project/SettingsScheduler.tsx @@ -21,7 +21,7 @@ import { 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 { useSnackbar } from 'notistack'; +import { toast } from 'react-toastify'; import RemoveIcon from '@mui/icons-material/RemoveCircleOutline'; import WarningIcon from '@mui/icons-material/Warning'; @@ -66,8 +66,6 @@ function makeid() { const SettingsScheduler: FC = () => { const { LL, locale } = useI18nContext(); - const { enqueueSnackbar } = useSnackbar(); - const [numChanges, setNumChanges] = useState(0); const blocker = useBlocker(numChanges !== 0); @@ -263,12 +261,12 @@ const SettingsScheduler: FC = () => { }) }); if (response.status === 200) { - enqueueSnackbar(LL.SCHEDULE_SAVED(), { variant: 'success' }); + toast.success(LL.SCHEDULE_SAVED()); } else { - enqueueSnackbar(LL.PROBLEM_UPDATING(), { variant: 'error' }); + toast.error(LL.PROBLEM_UPDATING()); } } catch (error) { - enqueueSnackbar(extractErrorMessage(error, LL.PROBLEM_UPDATING()), { variant: 'error' }); + toast.error(extractErrorMessage(error, LL.PROBLEM_UPDATING())); } setOriginalSchedule(schedule); } diff --git a/interface/src/utils/useRest.ts b/interface/src/utils/useRest.ts index ed86b7142..f57d20ec0 100644 --- a/interface/src/utils/useRest.ts +++ b/interface/src/utils/useRest.ts @@ -1,5 +1,6 @@ import { useCallback, useEffect, useState } from 'react'; -import { useSnackbar } from 'notistack'; +import { toast } from 'react-toastify'; + import { AxiosPromise } from 'axios'; import { extractErrorMessage } from '.'; @@ -16,8 +17,6 @@ export interface RestRequestOptions { export const useRest = ({ read, update }: RestRequestOptions) => { const { LL } = useI18nContext(); - const { enqueueSnackbar } = useSnackbar(); - const [data, setData] = useState(); const [saving, setSaving] = useState(false); const [errorMessage, setErrorMessage] = useState(); @@ -38,10 +37,10 @@ export const useRest = ({ read, update }: RestRequestOptions) => { setOrigData(fetch_data); } catch (error) { const message = extractErrorMessage(error, LL.PROBLEM_LOADING()); - enqueueSnackbar(message, { variant: 'error' }); + toast.error(message); setErrorMessage(message); } - }, [read, enqueueSnackbar, LL]); + }, [read, LL]); const save = useCallback( async (toSave: D) => { @@ -58,18 +57,18 @@ export const useRest = ({ read, update }: RestRequestOptions) => { if (response.status === 202) { setRestartNeeded(true); } else { - enqueueSnackbar(LL.UPDATED_OF(LL.SETTINGS_OF('')), { variant: 'success' }); + toast.success(LL.UPDATED_OF(LL.SETTINGS_OF(''))); } } catch (error) { const message = extractErrorMessage(error, LL.PROBLEM_UPDATING()); - enqueueSnackbar(message, { variant: 'error' }); + toast.error(message); setErrorMessage(message); } finally { setSaving(false); setDirtyFlags([]); } }, - [update, enqueueSnackbar, LL] + [update, LL] ); const saveData = () => data && save(data); diff --git a/interface/yarn.lock b/interface/yarn.lock index cb1f4362e..77b40d8c5 100644 --- a/interface/yarn.lock +++ b/interface/yarn.lock @@ -1812,7 +1812,6 @@ __metadata: lodash-es: ^4.17.21 mime-types: ^2.1.35 nodemon: ^2.0.21 - notistack: 2.0.8 npm-run-all: ^4.1.5 prettier: ^2.8.4 react: latest @@ -1820,6 +1819,7 @@ __metadata: react-dropzone: ^14.2.3 react-icons: ^4.8.0 react-router-dom: ^6.8.2 + react-toastify: ^9.1.1 rollup-plugin-visualizer: ^5.9.0 sockette: ^2.0.6 typesafe-i18n: ^5.24.2 @@ -2355,7 +2355,7 @@ __metadata: languageName: node 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 resolution: "clsx@npm:1.2.1" checksum: 30befca8019b2eb7dbad38cff6266cf543091dae2825c856a62a8ccf2c3ab9c2907c4d12b288b73101196767f66812365400a227581484a05f968b0307cfaf12 @@ -4700,27 +4700,6 @@ __metadata: languageName: node 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": version: 4.1.5 resolution: "npm-run-all@npm:4.1.5" @@ -5208,6 +5187,18 @@ __metadata: 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 + linkType: hard + "react-transition-group@npm:^4.4.5": version: 4.4.5 resolution: "react-transition-group@npm:4.4.5" From cc5a28ca14039ab830dc063d8ca7803f49f5a5e3 Mon Sep 17 00:00:00 2001 From: proddy Date: Sat, 11 Mar 2023 09:22:55 +0100 Subject: [PATCH 02/15] remove bold font and replace notistack to save flash --- interface/package.json | 6 +- interface/public/css/roboto.css | 14 +-- interface/public/fonts/md.woff2 | Bin 17232 -> 0 bytes interface/src/App.tsx | 13 +-- .../framework/security/ManageUsersForm.tsx | 3 +- interface/src/project/DashboardData.tsx | 7 +- interface/src/project/DashboardStatus.tsx | 3 +- .../src/project/SettingsCustomization.tsx | 5 +- interface/src/project/SettingsScheduler.tsx | 6 -- interface/yarn.lock | 98 +++++++++++------- 10 files changed, 75 insertions(+), 80 deletions(-) delete mode 100644 interface/public/fonts/md.woff2 diff --git a/interface/package.json b/interface/package.json index d19e380d4..bfebd9e4a 100644 --- a/interface/package.json +++ b/interface/package.json @@ -24,7 +24,7 @@ "@msgpack/msgpack": "^2.8.0", "@mui/icons-material": "^5.11.11", "@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", "@types/lodash-es": "^4.17.6", "@types/node": "^18.15.0", @@ -42,7 +42,7 @@ "react-dom": "latest", "react-dropzone": "^14.2.3", "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", "typesafe-i18n": "^5.24.2", @@ -54,7 +54,7 @@ "@typescript-eslint/eslint-plugin": "^5.54.1", "@typescript-eslint/parser": "^5.54.1", "@vitejs/plugin-react-swc": "^3.2.0", - "eslint": "^8.35.0", + "eslint": "^8.36.0", "eslint-config-prettier": "^8.7.0", "eslint-import-resolver-typescript": "^3.5.3", "eslint-plugin-deprecation": "^1.3.3", diff --git a/interface/public/css/roboto.css b/interface/public/css/roboto.css index f0a860dda..43dced13f 100644 --- a/interface/public/css/roboto.css +++ b/interface/public/css/roboto.css @@ -1,9 +1,9 @@ /* * 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-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+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; -} diff --git a/interface/public/fonts/md.woff2 b/interface/public/fonts/md.woff2 deleted file mode 100644 index 9f8bc681e65113a9828698da0835698d02671dc8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17232 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 { autoClose={2000} hideProgressBar={false} newestOnTop={false} - closeOnClick + closeOnClick={false} rtl={false} - pauseOnFocusLoss + pauseOnFocusLoss={false} draggable={false} - pauseOnHover - theme="dark" + pauseOnHover={false} + transition={Slide} + theme="light" /> diff --git a/interface/src/framework/security/ManageUsersForm.tsx b/interface/src/framework/security/ManageUsersForm.tsx index 5e7ca5186..43d7b45a5 100644 --- a/interface/src/framework/security/ManageUsersForm.tsx +++ b/interface/src/framework/security/ManageUsersForm.tsx @@ -50,8 +50,7 @@ const ManageUsersForm: FC = () => { color: #90CAF9; .th { padding: 8px; - height: 42px; - font-weight: 500; + height: 36px; border-bottom: 1px solid #565656; } `, diff --git a/interface/src/project/DashboardData.tsx b/interface/src/project/DashboardData.tsx index b7bfdd84b..566fd6a97 100644 --- a/interface/src/project/DashboardData.tsx +++ b/interface/src/project/DashboardData.tsx @@ -120,8 +120,6 @@ const DashboardData: FC = () => { &.tr.tr-body.row-select.row-select-single-selected { background-color: #3d4752; - color: white; - font-weight: normal; } &:hover .td { @@ -158,8 +156,7 @@ const DashboardData: FC = () => { HeaderRow: ` .th { padding: 8px; - height: 42px; - font-weight: 500; + height: 36px; ` } ]); @@ -182,7 +179,7 @@ const DashboardData: FC = () => { `, HeaderRow: ` .th { - height: 32px; + height: 86px; } `, Row: ` diff --git a/interface/src/project/DashboardStatus.tsx b/interface/src/project/DashboardStatus.tsx index 30c053e7d..842bd0371 100644 --- a/interface/src/project/DashboardStatus.tsx +++ b/interface/src/project/DashboardStatus.tsx @@ -108,8 +108,7 @@ const DashboardStatus: FC = () => { color: #90CAF9; .th { - height: 42px; - font-weight: 500; + height: 36px; border-bottom: 1px solid #565656; } `, diff --git a/interface/src/project/SettingsCustomization.tsx b/interface/src/project/SettingsCustomization.tsx index ff05ac1b4..00e2b5711 100644 --- a/interface/src/project/SettingsCustomization.tsx +++ b/interface/src/project/SettingsCustomization.tsx @@ -102,8 +102,7 @@ const SettingsCustomization: FC = () => { .th { border-bottom: 1px solid #565656; - font-weight: 500; - height: 32px; + height: 36px; } &:nth-of-type(1) .th { @@ -122,8 +121,6 @@ const SettingsCustomization: FC = () => { &.tr.tr-body.row-select.row-select-single-selected { background-color: #3d4752; - color: white; - font-weight: normal; } &:hover .td { diff --git a/interface/src/project/SettingsScheduler.tsx b/interface/src/project/SettingsScheduler.tsx index c37f34ced..8d4e200a0 100644 --- a/interface/src/project/SettingsScheduler.tsx +++ b/interface/src/project/SettingsScheduler.tsx @@ -128,7 +128,6 @@ const SettingsScheduler: FC = () => { color: #90CAF9; .th { border-bottom: 1px solid #565656; - font-weight: 500; height: 36px; } `, @@ -140,11 +139,6 @@ const SettingsScheduler: FC = () => { border-top: 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 { border-top: 1px solid #177ac9; border-bottom: 1px solid #177ac9; diff --git a/interface/yarn.lock b/interface/yarn.lock index 77b40d8c5..9994bd695 100644 --- a/interface/yarn.lock +++ b/interface/yarn.lock @@ -560,27 +560,45 @@ __metadata: languageName: node linkType: hard -"@eslint/eslintrc@npm:^2.0.0": - version: 2.0.0 - resolution: "@eslint/eslintrc@npm:2.0.0" +"@eslint-community/eslint-utils@npm:^4.2.0": + version: 4.2.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: ajv: ^6.12.4 debug: ^4.3.2 - espree: ^9.4.0 + espree: ^9.5.0 globals: ^13.19.0 ignore: ^5.2.0 import-fresh: ^3.2.1 js-yaml: ^4.1.0 minimatch: ^3.1.2 strip-json-comments: ^3.1.1 - checksum: 31119c8ca06723d80384f18f5c78e0530d8e6306ad36379868650131a8b10dd7cffd7aff79a5deb3a2e9933660823052623d268532bae9538ded53d5b19a69a6 + checksum: 56b9192a687a450db53a7b883daf9f0f447c43b3510189cf88808a7a2467c2a302a42a50f184cc6d5a9faf3d1df890a2ef0fd0d60b751f32a3e9dfea717c6b48 languageName: node linkType: hard -"@eslint/js@npm:8.35.0": - version: 8.35.0 - resolution: "@eslint/js@npm:8.35.0" - checksum: 6687ceff659a6d617e37823f809dc9c4b096535961a81acead27d26b1a51a4cf608a5e59d831ddd57f24f6f8bb99340a4a0e19f9c99b390fbb4b275f51ed5f5e +"@eslint/js@npm:8.36.0": + version: 8.36.0 + resolution: "@eslint/js@npm:8.36.0" + checksum: b7d6b84b823c8c7784be390741196617565527b1f7c0977fde9455bfb57fd88f81c074a03dd878757d2c33fa29f24291e9ecbc1425710f067917324b55e1bf3a languageName: node linkType: hard @@ -930,10 +948,10 @@ __metadata: languageName: node linkType: hard -"@remix-run/router@npm:1.3.3, @remix-run/router@npm:^1.3.3": - version: 1.3.3 - resolution: "@remix-run/router@npm:1.3.3" - checksum: 9280f1c3e44c0fb84a74b401b5a47022dace06d5da0f26a7a68c7c0e57ad5ef95d30f3c2d333df2db3b63f84de81f7f8caa7e53189a7709d6c3eb466d126ed76 +"@remix-run/router@npm:1.4.0, @remix-run/router@npm:^1.4.0": + version: 1.4.0 + resolution: "@remix-run/router@npm:1.4.0" + checksum: 707dce35a2b8138005cf19e63f6fd3c4da05b4b892e9e9118e8b727c3b95953efe27307ca2df35084044df30fa1fc367cf0bbc98d1ded9020c82e61e6242caaf languageName: node linkType: hard @@ -1785,7 +1803,7 @@ __metadata: "@msgpack/msgpack": ^2.8.0 "@mui/icons-material": ^5.11.11 "@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 "@types/lodash-es": ^4.17.6 "@types/mime-types": ^2 @@ -1800,7 +1818,7 @@ __metadata: "@yarnpkg/pnpify": ^4.0.0-rc.40 async-validator: ^4.2.5 axios: ^1.3.4 - eslint: ^8.35.0 + eslint: ^8.36.0 eslint-config-prettier: ^8.7.0 eslint-import-resolver-typescript: ^3.5.3 eslint-plugin-deprecation: ^1.3.3 @@ -1818,7 +1836,7 @@ __metadata: react-dom: latest react-dropzone: ^14.2.3 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 sockette: ^2.0.6 @@ -3088,12 +3106,14 @@ __metadata: languageName: node linkType: hard -"eslint@npm:^8.35.0": - version: 8.35.0 - resolution: "eslint@npm:8.35.0" +"eslint@npm:^8.36.0": + version: 8.36.0 + resolution: "eslint@npm:8.36.0" dependencies: - "@eslint/eslintrc": ^2.0.0 - "@eslint/js": 8.35.0 + "@eslint-community/eslint-utils": ^4.2.0 + "@eslint-community/regexpp": ^4.4.0 + "@eslint/eslintrc": ^2.0.1 + "@eslint/js": 8.36.0 "@humanwhocodes/config-array": ^0.11.8 "@humanwhocodes/module-importer": ^1.0.1 "@nodelib/fs.walk": ^1.2.8 @@ -3104,9 +3124,8 @@ __metadata: doctrine: ^3.0.0 escape-string-regexp: ^4.0.0 eslint-scope: ^7.1.1 - eslint-utils: ^3.0.0 eslint-visitor-keys: ^3.3.0 - espree: ^9.4.0 + espree: ^9.5.0 esquery: ^1.4.2 esutils: ^2.0.2 fast-deep-equal: ^3.1.3 @@ -3128,24 +3147,23 @@ __metadata: minimatch: ^3.1.2 natural-compare: ^1.4.0 optionator: ^0.9.1 - regexpp: ^3.2.0 strip-ansi: ^6.0.1 strip-json-comments: ^3.1.0 text-table: ^0.2.0 bin: eslint: bin/eslint.js - checksum: 6212173691d90b1bc94dd3d640e1f210374b30c3905fc0a15e501cf71c6ca52aa3d80ea7a9a245adaaed26d6019169e01fb6881b3f2885b188d37069c749308c + checksum: e9a961fc3b3de5cff5a1cb2c92eeffaa7e155a715489e30b3e1e76f186bd1255e0481e09564f2094733c0b1dbd3453499fb72ae7c043c83156e11e6d965b2304 languageName: node linkType: hard -"espree@npm:^9.4.0": - version: 9.4.1 - resolution: "espree@npm:9.4.1" +"espree@npm:^9.5.0": + version: 9.5.0 + resolution: "espree@npm:9.5.0" dependencies: acorn: ^8.8.0 acorn-jsx: ^5.3.2 eslint-visitor-keys: ^3.3.0 - checksum: 4d266b0cf81c7dfe69e542c7df0f246e78d29f5b04dda36e514eb4c7af117ee6cfbd3280e560571ed82ff6c9c3f0003c05b82583fc7a94006db7497c4fe4270e + checksum: a7f110aefb6407e0d3237aa635ab3cea87106ae63748dd23c67031afccc640d04c4209fca2daf16e2233c82efb505faead0fb84097478fd9cc6e8f8dd80bf99d languageName: node linkType: hard @@ -5163,27 +5181,27 @@ __metadata: languageName: node linkType: hard -"react-router-dom@npm:^6.8.2": - version: 6.8.2 - resolution: "react-router-dom@npm:6.8.2" +"react-router-dom@npm:^6.9.0": + version: 6.9.0 + resolution: "react-router-dom@npm:6.9.0" dependencies: - "@remix-run/router": 1.3.3 - react-router: 6.8.2 + "@remix-run/router": 1.4.0 + react-router: 6.9.0 peerDependencies: react: ">=16.8" react-dom: ">=16.8" - checksum: eddc8b88e26c66408df894bdcf95efd6731e21b7cbfd7417cd456f0043916279e0559b06c6cdc19c2a55c6aefc4cc745fa4065d3505e519a95adbef0cc89e77f + checksum: 4d593491ab8db5611feda70002c62902baebb84d5c1c5e5b6172496f31f91130deee132bf4240dea634a88cb86c76d6da348f15b9cd5e5197be455efd88edf72 languageName: node linkType: hard -"react-router@npm:6.8.2": - version: 6.8.2 - resolution: "react-router@npm:6.8.2" +"react-router@npm:6.9.0": + version: 6.9.0 + resolution: "react-router@npm:6.9.0" dependencies: - "@remix-run/router": 1.3.3 + "@remix-run/router": 1.4.0 peerDependencies: react: ">=16.8" - checksum: 9e98d03e1f18bfd5a35144a0c675adaf7c46a9ad436efdea2b52ef3a6e501ac6174a67ea90004e1339cd45019d6b1eb370627518320f7af9323ae74e0c6756ad + checksum: b2a5f42e042bee7a7f116ca7817b0e58359e5353d84887c9fe7a633d7490c03b1e0ae37cd01830c2a381e3d1e7d501bb4751e53cc3d491e25f36582d3f6e0546 languageName: node linkType: hard From c677fed91686a8237fe4f83257579f020eb5ca43 Mon Sep 17 00:00:00 2001 From: Proddy Date: Sat, 11 Mar 2023 11:08:56 +0100 Subject: [PATCH 03/15] cleanup --- .gitignore | 2 -- 1 file changed, 2 deletions(-) diff --git a/.gitignore b/.gitignore index 22e24ea0a..a4d5706dd 100644 --- a/.gitignore +++ b/.gitignore @@ -51,5 +51,3 @@ build_wrapper_output_directory/ # entity dump results dump_entities.csv dump_entities.xls* - -react-toastify/ \ No newline at end of file From 13211249c906c73cc9e66cbba051f35d8c8c97c9 Mon Sep 17 00:00:00 2001 From: Proddy Date: Sat, 11 Mar 2023 11:09:14 +0100 Subject: [PATCH 04/15] toast styling --- interface/src/App.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/interface/src/App.tsx b/interface/src/App.tsx index 7f2526d05..4dff16984 100644 --- a/interface/src/App.tsx +++ b/interface/src/App.tsx @@ -31,12 +31,13 @@ const App: FC = () => { autoClose={2000} hideProgressBar={false} newestOnTop={false} - closeOnClick={false} + closeOnClick={true} rtl={false} pauseOnFocusLoss={false} draggable={false} pauseOnHover={false} transition={Slide} + closeButton={false} theme="light" /> From 00e87dc3b02868ce4d7505ea3316b9a2093e4473 Mon Sep 17 00:00:00 2001 From: Proddy Date: Sat, 11 Mar 2023 11:09:27 +0100 Subject: [PATCH 05/15] fix table not showing on edit --- .../src/project/SettingsCustomization.tsx | 104 +++++++++--------- 1 file changed, 51 insertions(+), 53 deletions(-) diff --git a/interface/src/project/SettingsCustomization.tsx b/interface/src/project/SettingsCustomization.tsx index 00e2b5711..e2e5f09b0 100644 --- a/interface/src/project/SettingsCustomization.tsx +++ b/interface/src/project/SettingsCustomization.tsx @@ -503,61 +503,59 @@ const SettingsCustomization: FC = () => { {tableList.map((de: DeviceEntity) => ( editEntity(de)}> - {!deviceEntity && ( - { - de.m = getMaskNumber(mask); - if (de.n === '' && de.m & DeviceEntityMask.DV_READONLY) { - de.m = de.m | DeviceEntityMask.DV_WEB_EXCLUDE; + { + de.m = getMaskNumber(mask); + if (de.n === '' && de.m & DeviceEntityMask.DV_READONLY) { + de.m = de.m | DeviceEntityMask.DV_WEB_EXCLUDE; + } + if (de.m & DeviceEntityMask.DV_WEB_EXCLUDE) { + de.m = de.m & ~DeviceEntityMask.DV_FAVORITE; + } + setMasks(['']); // forces a refresh + }} + > + + + + = 3}> + + + + - - - - = 3}> - - - - - - - - - - - - - )} + /> + + + + + + + + - {!deviceEntity && formatName(de)} - {!deviceEntity && !(de.m & DeviceEntityMask.DV_READONLY) && formatValue(de.mi)} - {!deviceEntity && !(de.m & DeviceEntityMask.DV_READONLY) && formatValue(de.ma)} - {!deviceEntity && formatValue(de.v)} + {formatName(de)} + {!(de.m & DeviceEntityMask.DV_READONLY) && formatValue(de.mi)} + {!(de.m & DeviceEntityMask.DV_READONLY) && formatValue(de.ma)} + {formatValue(de.v)} ))} From a3759b19595b3812314d2624e789f8ada3eedaad Mon Sep 17 00:00:00 2001 From: Proddy Date: Sat, 11 Mar 2023 11:31:33 +0100 Subject: [PATCH 06/15] add minify and use terser --- interface/package.json | 2 + interface/vite.config.ts | 21 ++++- interface/yarn.lock | 182 ++++++++++++++++++++++++++++++++++++++- src/version.h | 2 +- 4 files changed, 202 insertions(+), 5 deletions(-) diff --git a/interface/package.json b/interface/package.json index bfebd9e4a..74a6e2dfb 100644 --- a/interface/package.json +++ b/interface/package.json @@ -65,7 +65,9 @@ "npm-run-all": "^4.1.5", "prettier": "^2.8.4", "rollup-plugin-visualizer": "^5.9.0", + "terser": "^5.16.6", "vite": "^4.1.4", + "vite-plugin-minify": "^1.5.2", "vite-plugin-svgr": "^2.4.0", "vite-tsconfig-paths": "^4.0.5" }, diff --git a/interface/vite.config.ts b/interface/vite.config.ts index e9ca2ffaa..bfbb6a2af 100644 --- a/interface/vite.config.ts +++ b/interface/vite.config.ts @@ -2,6 +2,7 @@ import { defineConfig, type PluginOption } from 'vite'; import react from '@vitejs/plugin-react-swc'; import viteTsconfigPaths from 'vite-tsconfig-paths'; import svgrPlugin from 'vite-plugin-svgr'; +import { ViteMinifyPlugin } from 'vite-plugin-minify'; import { visualizer } from 'rollup-plugin-visualizer'; import ProgmemGenerator from './progmem-generator'; @@ -18,12 +19,30 @@ export default defineConfig(({ command, mode }) => { react(), viteTsconfigPaths(), 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 }) ], + build: { outDir: 'build', - chunkSizeWarningLimit: 1024 + chunkSizeWarningLimit: 1024, + sourcemap: false, + manifest: false, + minify: mode === 'development' ? false : 'terser' }, + server: { open: true, port: 3000, diff --git a/interface/yarn.lock b/interface/yarn.lock index 9994bd695..f29f24dd7 100644 --- a/interface/yarn.lock +++ b/interface/yarn.lock @@ -644,7 +644,7 @@ __metadata: languageName: node 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 resolution: "@jridgewell/gen-mapping@npm:0.3.2" dependencies: @@ -669,6 +669,16 @@ __metadata: languageName: node 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": version: 1.4.14 resolution: "@jridgewell/sourcemap-codec@npm:1.4.14" @@ -1840,9 +1850,11 @@ __metadata: react-toastify: ^9.1.1 rollup-plugin-visualizer: ^5.9.0 sockette: ^2.0.6 + terser: ^5.16.6 typesafe-i18n: ^5.24.2 typescript: ^4.9.5 vite: ^4.1.4 + vite-plugin-minify: ^1.5.2 vite-plugin-svgr: ^2.4.0 vite-tsconfig-paths: ^4.0.5 languageName: unknown @@ -1864,7 +1876,7 @@ __metadata: languageName: node linkType: hard -"acorn@npm:^8.8.0": +"acorn@npm:^8.5.0, acorn@npm:^8.8.0": version: 8.8.2 resolution: "acorn@npm:8.8.2" bin: @@ -2178,6 +2190,13 @@ __metadata: languageName: node 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": version: 16.1.3 resolution: "cacache@npm:16.1.3" @@ -2243,6 +2262,16 @@ __metadata: languageName: node 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": version: 5.3.1 resolution: "camelcase@npm:5.3.1" @@ -2328,6 +2357,15 @@ __metadata: languageName: node 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": version: 2.2.0 resolution: "clean-stack@npm:2.2.0" @@ -2430,6 +2468,20 @@ __metadata: languageName: node 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": version: 0.0.1 resolution: "concat-map@npm:0.0.1" @@ -2653,6 +2705,16 @@ __metadata: languageName: node 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": version: 1.4.315 resolution: "electron-to-chromium@npm:1.4.315" @@ -3707,6 +3769,15 @@ __metadata: languageName: node 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": version: 5.3.0 resolution: "history@npm:5.3.0" @@ -3732,6 +3803,23 @@ __metadata: languageName: node 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": version: 4.1.1 resolution: "http-cache-semantics@npm:4.1.1" @@ -4344,6 +4432,15 @@ __metadata: languageName: node 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": version: 2.0.0 resolution: "lowercase-keys@npm:2.0.0" @@ -4623,6 +4720,16 @@ __metadata: languageName: node 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": version: 9.3.1 resolution: "node-gyp@npm:9.3.1" @@ -4921,6 +5028,16 @@ __metadata: languageName: node 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": version: 1.0.1 resolution: "parent-module@npm:1.0.1" @@ -4952,6 +5069,16 @@ __metadata: languageName: node 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": version: 4.0.0 resolution: "path-exists@npm:4.0.0" @@ -5320,6 +5447,13 @@ __metadata: languageName: node 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": version: 2.1.1 resolution: "require-directory@npm:2.1.1" @@ -5670,6 +5804,16 @@ __metadata: languageName: node 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": version: 0.5.7 resolution: "source-map@npm:0.5.7" @@ -5677,6 +5821,13 @@ __metadata: languageName: node 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": version: 0.7.4 resolution: "source-map@npm:0.7.4" @@ -5905,6 +6056,20 @@ __metadata: languageName: node 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": version: 0.2.0 resolution: "text-table@npm:0.2.0" @@ -5996,7 +6161,7 @@ __metadata: languageName: node 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 resolution: "tslib@npm:2.5.0" checksum: ae3ed5f9ce29932d049908ebfdf21b3a003a85653a9a140d614da6b767a93ef94f460e52c3d787f0e4f383546981713f165037dc2274df212ea9f8a4541004e1 @@ -6163,6 +6328,17 @@ __metadata: languageName: node 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": version: 2.4.0 resolution: "vite-plugin-svgr@npm:2.4.0" diff --git a/src/version.h b/src/version.h index beca50b2e..5f092fe69 100644 --- a/src/version.h +++ b/src/version.h @@ -1 +1 @@ -#define EMSESP_APP_VERSION "3.6.0-dev.5" +#define EMSESP_APP_VERSION "3.6.0-dev.6" From 955c8b4346f44fee12672a070d2210ac70fbf540 Mon Sep 17 00:00:00 2001 From: Proddy Date: Sat, 11 Mar 2023 13:45:05 +0100 Subject: [PATCH 07/15] remove minify --- interface/vite.config.ts | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/interface/vite.config.ts b/interface/vite.config.ts index bfbb6a2af..83f3cfe81 100644 --- a/interface/vite.config.ts +++ b/interface/vite.config.ts @@ -2,7 +2,7 @@ import { defineConfig, type PluginOption } from 'vite'; import react from '@vitejs/plugin-react-swc'; import viteTsconfigPaths from 'vite-tsconfig-paths'; import svgrPlugin from 'vite-plugin-svgr'; -import { ViteMinifyPlugin } from 'vite-plugin-minify'; +// import { ViteMinifyPlugin } from 'vite-plugin-minify'; import { visualizer } from 'rollup-plugin-visualizer'; import ProgmemGenerator from './progmem-generator'; @@ -19,19 +19,19 @@ export default defineConfig(({ command, mode }) => { react(), viteTsconfigPaths(), svgrPlugin(), - ViteMinifyPlugin({ - removeAttributeQuotes: true, - minifyCSS: true, - minifyJS: true, - decodeEntities: true, - removeComments: true, - removeEmptyAttributes: true, - removeOptionalTags: true, - removeEmptyElements: true, - removeScriptTypeAttributes: true, - removeTagWhitespace: true, - minifyURLs: true - }), + // 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 }) ], From 3c03f4b18f371b2fdad2257f24e62c0f64d7679f Mon Sep 17 00:00:00 2001 From: Proddy Date: Sat, 11 Mar 2023 15:22:43 +0100 Subject: [PATCH 08/15] test new sonar --- .github/workflows/sonar_check2.yml | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 .github/workflows/sonar_check2.yml diff --git a/.github/workflows/sonar_check2.yml b/.github/workflows/sonar_check2.yml new file mode 100644 index 000000000..f3fa7f785 --- /dev/null +++ b/.github/workflows/sonar_check2.yml @@ -0,0 +1,30 @@ +name: Sonar Check2 +on: + push: + branches: + - dev + pull_request: + types: [opened, synchronize, reopened] +jobs: + build: + name: Build and analyze + runs-on: ubuntu-latest + # if: github.repository_owner == 'emsesp' + # if: github.repository == 'emsesp/EMS-ESP32' + env: + BUILD_WRAPPER_OUT_DIR: build_wrapper_output_directory + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis + - name: Install sonar-scanner and build-wrapper + uses: SonarSource/sonarcloud-github-c-cpp@v1 + - name: Run build-wrapper + run: | + build-wrapper-linux-x86-64 --out-dir ${{ env.BUILD_WRAPPER_OUT_DIR }} make all + - name: Run sonar-scanner + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} + run: | + sonar-scanner --define sonar.cfamily.build-wrapper-output="${{ env.BUILD_WRAPPER_OUT_DIR }}" From 77798085ce4c73395c0cf10bca4e5bba44f40e7d Mon Sep 17 00:00:00 2001 From: Proddy Date: Sat, 11 Mar 2023 15:32:14 +0100 Subject: [PATCH 09/15] upgraded sonar --- .github/workflows/sonar_check.yml | 43 ++++++------------------------ .github/workflows/sonar_check2.yml | 30 --------------------- sonar-project.properties | 4 +-- 3 files changed, 9 insertions(+), 68 deletions(-) delete mode 100644 .github/workflows/sonar_check2.yml diff --git a/.github/workflows/sonar_check.yml b/.github/workflows/sonar_check.yml index b638df864..f3fa7f785 100644 --- a/.github/workflows/sonar_check.yml +++ b/.github/workflows/sonar_check.yml @@ -1,4 +1,4 @@ -name: Sonar Check +name: Sonar Check2 on: push: branches: @@ -7,51 +7,24 @@ on: types: [opened, synchronize, reopened] jobs: build: - name: Build + name: Build and analyze runs-on: ubuntu-latest - if: github.repository_owner == 'emsesp' + # if: github.repository_owner == 'emsesp' # if: github.repository == 'emsesp/EMS-ESP32' 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 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 with: fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis - - name: Set up JDK 11 - uses: actions/setup-java@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: Install sonar-scanner and build-wrapper + uses: SonarSource/sonarcloud-github-c-cpp@v1 - name: Run build-wrapper run: | - make clean - build-wrapper-linux-x86-64 --out-dir ${{ env.BUILD_WRAPPER_OUT_DIR }} make clean all + build-wrapper-linux-x86-64 --out-dir ${{ env.BUILD_WRAPPER_OUT_DIR }} make all - name: Run sonar-scanner env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} run: | - sonar-scanner + sonar-scanner --define sonar.cfamily.build-wrapper-output="${{ env.BUILD_WRAPPER_OUT_DIR }}" diff --git a/.github/workflows/sonar_check2.yml b/.github/workflows/sonar_check2.yml deleted file mode 100644 index f3fa7f785..000000000 --- a/.github/workflows/sonar_check2.yml +++ /dev/null @@ -1,30 +0,0 @@ -name: Sonar Check2 -on: - push: - branches: - - dev - pull_request: - types: [opened, synchronize, reopened] -jobs: - build: - name: Build and analyze - runs-on: ubuntu-latest - # if: github.repository_owner == 'emsesp' - # if: github.repository == 'emsesp/EMS-ESP32' - env: - BUILD_WRAPPER_OUT_DIR: build_wrapper_output_directory - steps: - - uses: actions/checkout@v3 - with: - fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis - - name: Install sonar-scanner and build-wrapper - uses: SonarSource/sonarcloud-github-c-cpp@v1 - - name: Run build-wrapper - run: | - build-wrapper-linux-x86-64 --out-dir ${{ env.BUILD_WRAPPER_OUT_DIR }} make all - - name: Run sonar-scanner - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} - run: | - sonar-scanner --define sonar.cfamily.build-wrapper-output="${{ env.BUILD_WRAPPER_OUT_DIR }}" diff --git a/sonar-project.properties b/sonar-project.properties index 701849280..6c1e9b537 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -6,6 +6,4 @@ sonar.sources=./src sonar.cfamily.build-wrapper-output=build_wrapper_output_directory sonar.sourceEncoding=UTF-8 sonar.host.url=https://sonarcloud.io -sonar.cfamily.threads=2 -sonar.cfamily.cache.enabled=false -; sonar.cfamily.cache.path=./sonar/cache +sonar.cfamily.threads=4 From dc3c6cad0520a2244531db12750e1e85679b6ce5 Mon Sep 17 00:00:00 2001 From: Proddy Date: Sat, 11 Mar 2023 15:41:46 +0100 Subject: [PATCH 10/15] success toast after upload --- interface/src/AppRouting.tsx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/interface/src/AppRouting.tsx b/interface/src/AppRouting.tsx index 0fbde8ea2..b71c9eba2 100644 --- a/interface/src/AppRouting.tsx +++ b/interface/src/AppRouting.tsx @@ -14,7 +14,6 @@ import AuthenticatedRouting from 'AuthenticatedRouting'; interface SecurityRedirectProps { message: string; - // variant?: VariantType; signOut?: boolean; } @@ -22,8 +21,7 @@ const RootRedirect: FC = ({ message, signOut }) => { const authenticationContext = useContext(AuthenticationContext); useEffect(() => { signOut && authenticationContext.signOut(false); - // TODO toast variant - toast.error(message); + toast.success(message); }, [message, signOut, authenticationContext]); return ; }; From c960db5180d0a4590ac27a46f66a40e1632c59b7 Mon Sep 17 00:00:00 2001 From: Proddy Date: Sat, 11 Mar 2023 17:23:41 +0100 Subject: [PATCH 11/15] added compile flag -DEMSESP_DE_ONLY --- pio_local.ini_example | 1 + src/common.h | 2 ++ src/locale_translations.h | 2 +- 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/pio_local.ini_example b/pio_local.ini_example index 6e919359e..e8850a979 100644 --- a/pio_local.ini_example +++ b/pio_local.ini_example @@ -9,6 +9,7 @@ ; -DEMSESP_DEBUG_SENSOR ; additional debug for the dallas sensors ; -DCORE_DEBUG_LEVEL=5 ; verbose core level debugging 5=verbose, 4=debug, 3=info ; -DEMSESP_TEST ; enable the tests. EN language only +; -DEMSESP_DE_ONLY ; only DE translated entity names ; my_build_flags = -DEMSESP_DEBUG [env:esp32_4M] diff --git a/src/common.h b/src/common.h index a5f59dadc..e1c987df5 100644 --- a/src/common.h +++ b/src/common.h @@ -55,6 +55,8 @@ using string_vector = std::vector; #if defined(EMSESP_TEST) // 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}; +#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 #define MAKE_TRANSLATION(list_name, ...) static const char * const __pstr__L_##list_name[] = {__VA_ARGS__, nullptr}; #endif diff --git a/src/locale_translations.h b/src/locale_translations.h index 648821f25..ebdac3a9a 100644 --- a/src/locale_translations.h +++ b/src/locale_translations.h @@ -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") // 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 MAKE_TRANSLATION(stopped, "stopped", "gestoppt", "gestopt", "stoppad", "zatrzymany", "stoppet", "arrêté", "durdu") From 8b29c1973de6464e4c5f0d009112fbec6767e172 Mon Sep 17 00:00:00 2001 From: Proddy Date: Sat, 11 Mar 2023 17:31:33 +0100 Subject: [PATCH 12/15] DEMSESP_EN_ONLY --- pio_local.ini_example | 1 + src/common.h | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/pio_local.ini_example b/pio_local.ini_example index e8850a979..eed96ed5e 100644 --- a/pio_local.ini_example +++ b/pio_local.ini_example @@ -10,6 +10,7 @@ ; -DCORE_DEBUG_LEVEL=5 ; verbose core level debugging 5=verbose, 4=debug, 3=info ; -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 [env:esp32_4M] diff --git a/src/common.h b/src/common.h index e1c987df5..b63ca01a6 100644 --- a/src/common.h +++ b/src/common.h @@ -52,7 +52,7 @@ using string_vector = std::vector; #define F_(string_name) (__pstr__##string_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 #define MAKE_TRANSLATION(list_name, shortname, en, ...) static const char * const __pstr__L_##list_name[] = {shortname, en, nullptr}; #elif defined(EMSESP_DE_ONLY) From d0ccbc2963cc4f961c4a7da3254d40d53a40aa2a Mon Sep 17 00:00:00 2001 From: Proddy Date: Sat, 11 Mar 2023 17:38:08 +0100 Subject: [PATCH 13/15] typo in table header height --- interface/src/project/DashboardData.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/project/DashboardData.tsx b/interface/src/project/DashboardData.tsx index 566fd6a97..37c42aad2 100644 --- a/interface/src/project/DashboardData.tsx +++ b/interface/src/project/DashboardData.tsx @@ -179,7 +179,7 @@ const DashboardData: FC = () => { `, HeaderRow: ` .th { - height: 86px; + height: 36px; } `, Row: ` From 0d81dcde100a34f472b7b823a688523cb2bc87c1 Mon Sep 17 00:00:00 2001 From: Proddy Date: Sat, 11 Mar 2023 17:42:02 +0100 Subject: [PATCH 14/15] don't bold row selection --- interface/src/project/DashboardData.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/interface/src/project/DashboardData.tsx b/interface/src/project/DashboardData.tsx index 37c42aad2..bb4d7f335 100644 --- a/interface/src/project/DashboardData.tsx +++ b/interface/src/project/DashboardData.tsx @@ -120,6 +120,7 @@ const DashboardData: FC = () => { &.tr.tr-body.row-select.row-select-single-selected { background-color: #3d4752; + font-weight: normal; } &:hover .td { From 64b202225a8b9db48cdfa0cbd83bcb0727ec6e00 Mon Sep 17 00:00:00 2001 From: proddy Date: Sun, 12 Mar 2023 08:48:56 +0100 Subject: [PATCH 15/15] rollback changes --- .../src/project/SettingsCustomization.tsx | 104 +++++++++--------- 1 file changed, 53 insertions(+), 51 deletions(-) diff --git a/interface/src/project/SettingsCustomization.tsx b/interface/src/project/SettingsCustomization.tsx index e2e5f09b0..00e2b5711 100644 --- a/interface/src/project/SettingsCustomization.tsx +++ b/interface/src/project/SettingsCustomization.tsx @@ -503,59 +503,61 @@ const SettingsCustomization: FC = () => { {tableList.map((de: DeviceEntity) => ( editEntity(de)}> - { - de.m = getMaskNumber(mask); - if (de.n === '' && de.m & DeviceEntityMask.DV_READONLY) { - de.m = de.m | DeviceEntityMask.DV_WEB_EXCLUDE; - } - if (de.m & DeviceEntityMask.DV_WEB_EXCLUDE) { - de.m = de.m & ~DeviceEntityMask.DV_FAVORITE; - } - setMasks(['']); // forces a refresh - }} - > - - - - = 3}> - - - - { + de.m = getMaskNumber(mask); + if (de.n === '' && de.m & DeviceEntityMask.DV_READONLY) { + de.m = de.m | DeviceEntityMask.DV_WEB_EXCLUDE; } - /> - - - - - - - - + if (de.m & DeviceEntityMask.DV_WEB_EXCLUDE) { + de.m = de.m & ~DeviceEntityMask.DV_FAVORITE; + } + setMasks(['']); // forces a refresh + }} + > + + + + = 3}> + + + + + + + + + + + + + )} - {formatName(de)} - {!(de.m & DeviceEntityMask.DV_READONLY) && formatValue(de.mi)} - {!(de.m & DeviceEntityMask.DV_READONLY) && formatValue(de.ma)} - {formatValue(de.v)} + {!deviceEntity && formatName(de)} + {!deviceEntity && !(de.m & DeviceEntityMask.DV_READONLY) && formatValue(de.mi)} + {!deviceEntity && !(de.m & DeviceEntityMask.DV_READONLY) && formatValue(de.ma)} + {!deviceEntity && formatValue(de.v)} ))}