diff --git a/.gitignore b/.gitignore index fb5e5348d..6ace7c70c 100644 --- a/.gitignore +++ b/.gitignore @@ -63,3 +63,4 @@ bw-output/ # standalone executable for testing emsesp +interface/tsconfig.tsbuildinfo diff --git a/.prettierrc b/.prettierrc index 4197de585..c2f70575b 100644 --- a/.prettierrc +++ b/.prettierrc @@ -1,8 +1,13 @@ { + "plugins": ["@trivago/prettier-plugin-sort-imports"], "trailingComma": "none", "tabWidth": 2, "semi": true, "singleQuote": true, - "printWidth": 120, - "bracketSpacing": true -} \ No newline at end of file + "printWidth": 85, + "bracketSpacing": true, + "importOrder": ["^react", "^@mui/(.*)$", "^api*/(.*)$", "", "^[./]"], + "importOrderSeparation": true, + "importOrderSortSpecifiers": true, + "importOrderGroupNamespaceSpecifiers": true +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index 493bf41fe..373f1a25e 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -6,6 +6,10 @@ "editor.codeActionsOnSave": { "source.fixAll": "explicit" }, + "eslint.validate": [ + "typescript" + ], + "eslint.codeActionsOnSave.rules": null, "eslint.nodePath": "interface/.yarn/sdks", "eslint.workingDirectories": ["interface"], "prettier.prettierPath": "", @@ -87,5 +91,6 @@ "cSpell.enableFiletypes": [ "!cpp", "!typescript" - ] + ], + "typescript.preferences.preferTypeOnlyAutoImports": true } \ No newline at end of file diff --git a/interface/.eslintignore b/interface/.eslintignore deleted file mode 100644 index c04eade2b..000000000 --- a/interface/.eslintignore +++ /dev/null @@ -1,12 +0,0 @@ -node_modules/ -build/ -dist/ -.yarn/ - -.prettierrc -.eslintrc* -env.d.ts -progmem-generator.js -unpack.ts -vite.config.ts -package.json \ No newline at end of file diff --git a/interface/.eslintrc.json b/interface/.eslintrc.json deleted file mode 100644 index 781a0705b..000000000 --- a/interface/.eslintrc.json +++ /dev/null @@ -1,108 +0,0 @@ -{ - "env": { - "browser": true, - "es6": true - }, - "extends": [ - "eslint:recommended", - // "airbnb/hooks", - // "airbnb-typescript", - "plugin:react/recommended", - "plugin:react/jsx-runtime", - "plugin:@typescript-eslint/recommended", - "plugin:@typescript-eslint/recommended-requiring-type-checking", - "plugin:prettier/recommended", - "plugin:import/recommended" - ], - "parser": "@typescript-eslint/parser", - "parserOptions": { - "ecmaFeatures": { - "jsx": true - }, - "ecmaVersion": "latest", - "sourceType": "module", - "tsconfigRootDir": ".", - "project": ["tsconfig.json"] - }, - "plugins": ["react", "@typescript-eslint", "autofix", "react-hooks"], - "settings": { - "import/resolver": { - "typescript": { - "project": "./tsconfig.json" - } - }, - "react": { - "version": "18.x" - } - }, - "rules": { - "object-shorthand": "error", - "no-console": "warn", - "@typescript-eslint/consistent-type-definitions": ["off", "type"], - "@typescript-eslint/explicit-function-return-type": "off", - "@typescript-eslint/no-unsafe-call": "off", - "@typescript-eslint/no-unsafe-enum-comparison": "off", - "@typescript-eslint/no-unsafe-assignment": "off", - "@typescript-eslint/no-unsafe-return": "off", - "@typescript-eslint/no-unsafe-member-access": "off", - "@typescript-eslint/naming-convention": "off", - "@typescript-eslint/no-explicit-any": "off", - "@typescript-eslint/no-unsafe-argument": "off", - "@typescript-eslint/restrict-plus-operands": "off", - "@typescript-eslint/no-unused-expressions": "off", - "@typescript-eslint/no-implied-eval": "off", - "@typescript-eslint/no-misused-promises": "off", - "arrow-body-style": ["error", "as-needed"], - "react-hooks/exhaustive-deps": "warn", - "@typescript-eslint/consistent-type-imports": [ - "error", - { - "prefer": "type-imports" - } - ], - "import/order": [ - "warn", - { - "groups": ["builtin", "external", "parent", "sibling", "index", "object", "type"], - "pathGroups": [ - { - "pattern": "@/**/**", - "group": "parent", - "position": "before" - } - ], - "alphabetize": { "order": "asc" } - } - ], - // "autofix/no-unused-vars": [ - // "error", - // { - // "argsIgnorePattern": "^_", - // "ignoreRestSiblings": true, - // "destructuredArrayIgnorePattern": "^_" - // } - // ], - "react/self-closing-comp": [ - "error", - { - "component": true, - "html": true - } - ], - "@typescript-eslint/ban-types": [ - "error", - { - "extendDefaults": true, - "types": { - "{}": false - } - } - ], - "prettier/prettier": [ - "error", - { - "endOfLine": "auto" - } - ] - } -} diff --git a/interface/.prettierignore b/interface/.prettierignore index e3510820a..ed086a320 100644 --- a/interface/.prettierignore +++ b/interface/.prettierignore @@ -1,6 +1,8 @@ node_modules/ build/ dist/ +src/i18n/* + .prettierrc .yarn/ .typesafe-i18n.json \ No newline at end of file diff --git a/interface/eslint.config.js b/interface/eslint.config.js new file mode 100644 index 000000000..bae746842 --- /dev/null +++ b/interface/eslint.config.js @@ -0,0 +1,33 @@ +// @ts-check +import eslint from '@eslint/js'; +import prettierConfig from 'eslint-config-prettier'; +import tseslint from 'typescript-eslint'; + +export default tseslint.config( + eslint.configs.recommended, + ...tseslint.configs.recommendedTypeChecked, + prettierConfig, + { + languageOptions: { + parserOptions: { + project: true, + tsconfigRootDir: import.meta.dirname + } + } + }, + { + ignores: ['dist/*', '*.js', '**/*.cjs', '**/unpack.ts'] + }, + { + rules: { + '@typescript-eslint/no-unsafe-enum-comparison': 'off', + '@typescript-eslint/no-unsafe-assignment': 'off', + '@typescript-eslint/no-misused-promises': [ + 'error', + { + checksVoidReturn: false + } + ] + } + } +); diff --git a/interface/package.json b/interface/package.json index 48fd73c88..b4120bd77 100644 --- a/interface/package.json +++ b/interface/package.json @@ -18,26 +18,25 @@ "standalone": "concurrently -c \"auto\" \"typesafe-i18n\" \"npm:mock-api\" \"npm:mock-es\" \"npm:mock-upload\" \"vite\"", "typesafe-i18n": "typesafe-i18n --no-watch", "webUI": "node progmem-generator.js", - "format": "prettier --write '**/*.{ts,tsx,js,css,json,md}'", - "lint": "eslint . --cache --fix" + "format": "prettier -l -w '**/*.{ts,tsx,js,css,json,md}'", + "lint": "eslint . --fix" }, "dependencies": { "@alova/adapter-xhr": "^1.0.3", + "@alova/scene-react": "^1.5.0", "@babel/core": "^7.24.4", "@emotion/react": "^11.11.4", "@emotion/styled": "^11.11.5", "@mui/icons-material": "^5.15.15", "@mui/material": "^5.15.15", "@table-library/react-table-library": "4.1.7", - "@types/imagemin": "^8.0.5", "@types/lodash-es": "^4.17.12", "@types/node": "^20.12.7", - "@types/react": "^18.2.76", + "@types/react": "^18.2.79", "@types/react-dom": "^18.2.25", "@types/react-router-dom": "^5.3.3", - "alova": "^2.19.0", + "alova": "2.19.2", "async-validator": "^4.2.5", - "eslint-plugin-prettier": "^5.1.3", "history": "^5.3.0", "jwt-decode": "^4.0.0", "lodash-es": "^4.17.21", @@ -45,30 +44,26 @@ "react": "latest", "react-dom": "latest", "react-dropzone": "^14.2.3", - "react-icons": "^5.0.1", + "react-icons": "^5.1.0", "react-router-dom": "^6.22.3", "react-toastify": "^10.0.5", "typesafe-i18n": "^5.26.2", "typescript": "^5.4.5" }, "devDependencies": { + "@eslint/js": "^9.1.1", "@preact/compat": "^17.1.2", "@preact/preset-vite": "^2.8.2", - "@typescript-eslint/eslint-plugin": "^7.6.0", - "@typescript-eslint/parser": "^7.6.0", + "@trivago/prettier-plugin-sort-imports": "^4.3.0", "concurrently": "^8.2.2", - "eslint": "8.57.0", + "eslint": "^9.1.0", "eslint-config-prettier": "^9.1.0", - "eslint-import-resolver-typescript": "^3.6.1", - "eslint-plugin-autofix": "^1.1.0", - "eslint-plugin-import": "^2.29.1", - "eslint-plugin-react": "^7.34.1", - "eslint-plugin-react-hooks": "^4.6.0", "preact": "^10.20.2", "prettier": "^3.2.5", "rollup-plugin-visualizer": "^5.12.0", "terser": "^5.30.3", - "vite": "^5.2.8", + "typescript-eslint": "^7.7.0", + "vite": "^5.2.10", "vite-plugin-imagemin": "^0.6.1", "vite-tsconfig-paths": "^4.3.2" }, diff --git a/interface/progmem-generator.js b/interface/progmem-generator.js index b8935e04b..aca4bddf8 100644 --- a/interface/progmem-generator.js +++ b/interface/progmem-generator.js @@ -1,8 +1,14 @@ -import { readdirSync, existsSync, unlinkSync, readFileSync, createWriteStream } from 'fs'; -import { resolve, relative, sep } from 'path'; -import zlib from 'zlib'; -import mime from 'mime-types'; import crypto from 'crypto'; +import { + createWriteStream, + existsSync, + readFileSync, + readdirSync, + unlinkSync +} from 'fs'; +import mime from 'mime-types'; +import { relative, resolve, sep } from 'path'; +import zlib from 'zlib'; const ARDUINO_INCLUDES = '#include \n\n'; const INDENT = ' '; @@ -18,12 +24,7 @@ const generateWWWClass = () => class WWWData { ${indent}public: ${indent.repeat(2)}static void registerRoutes(RouteRegistrationHandler handler) { -${fileInfo - .map( - (file) => - `${indent.repeat(3)}handler("${file.uri}", "${file.mimeType}", ${file.variable}, ${file.size}, "${file.hash}");` - ) - .join('\n')} +${fileInfo.map((file) => `${indent.repeat(3)}handler("${file.uri}", "${file.mimeType}", ${file.variable}, ${file.size}, "${file.hash}");`).join('\n')} ${indent.repeat(2)}} }; `; diff --git a/interface/public/css/roboto.css b/interface/public/css/roboto.css index 36f599b8a..639165cb6 100644 --- a/interface/public/css/roboto.css +++ b/interface/public/css/roboto.css @@ -12,7 +12,8 @@ local('Roboto'), local('Roboto-Regular'), url(../fonts/re.woff2) format('woff2'); - unicode-range: U+0000-00FF, U+0104-0107, U+0118-0119, U+011E-011F, U+0130-0131, U+0141-0144, U+0152-0153, U+015A-015B, - U+015E-015F, 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, + unicode-range: U+0000-00FF, U+0104-0107, U+0118-0119, U+011E-011F, U+0130-0131, + U+0141-0144, U+0152-0153, U+015A-015B, U+015E-015F, 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/src/App.tsx b/interface/src/App.tsx index 18398cf4e..b5ac62222 100644 --- a/interface/src/App.tsx +++ b/interface/src/App.tsx @@ -1,16 +1,14 @@ import { useEffect, useState } from 'react'; -import { ToastContainer, Slide } from 'react-toastify'; - +import type { FC } from 'react'; +import { Slide, ToastContainer } from 'react-toastify'; import 'react-toastify/dist/ReactToastify.min.css'; -import { localStorageDetector } from 'typesafe-i18n/detectors'; -import type { FC } from 'react'; import AppRouting from 'AppRouting'; import CustomTheme from 'CustomTheme'; - import TypesafeI18n from 'i18n/i18n-react'; import { detectLocale } from 'i18n/i18n-util'; import { loadLocaleAsync } from 'i18n/i18n-util.async'; +import { localStorageDetector } from 'typesafe-i18n/detectors'; const detectedLocale = detectLocale(localStorageDetector); diff --git a/interface/src/AppRouting.tsx b/interface/src/AppRouting.tsx index 7e6507621..e54f8023f 100644 --- a/interface/src/AppRouting.tsx +++ b/interface/src/AppRouting.tsx @@ -1,14 +1,11 @@ import { useContext, useEffect } from 'react'; - -import { Route, Routes, Navigate, useLocation } from 'react-router-dom'; - -import { toast } from 'react-toastify'; import type { FC } from 'react'; +import { Navigate, Route, Routes, useLocation } from 'react-router-dom'; +import { toast } from 'react-toastify'; import AuthenticatedRouting from 'AuthenticatedRouting'; import SignIn from 'SignIn'; import { RequireAuthenticated, RequireUnauthenticated } from 'components'; - import { Authentication, AuthenticationContext } from 'contexts/authentication'; import { useI18nContext } from 'i18n/i18n-react'; @@ -47,8 +44,14 @@ const AppRouting: FC = () => { - } /> - } /> + } + /> + } + /> { const { me } = useContext(AuthenticatedContext); return ( @@ -44,7 +45,10 @@ const AuthenticatedRouting: FC = () => { } /> } /> } /> - } /> + } + /> } /> )} diff --git a/interface/src/CustomTheme.tsx b/interface/src/CustomTheme.tsx index c00321984..03c03c6a3 100644 --- a/interface/src/CustomTheme.tsx +++ b/interface/src/CustomTheme.tsx @@ -1,7 +1,12 @@ -import { CssBaseline } from '@mui/material'; -import { createTheme, responsiveFontSizes, ThemeProvider } from '@mui/material/styles'; import type { FC } from 'react'; +import { CssBaseline } from '@mui/material'; +import { + ThemeProvider, + createTheme, + responsiveFontSizes +} from '@mui/material/styles'; + import type { RequiredChildrenProps } from 'utils'; export const dialogStyle = { diff --git a/interface/src/SignIn.tsx b/interface/src/SignIn.tsx index de3838a00..984cc8af8 100644 --- a/interface/src/SignIn.tsx +++ b/interface/src/SignIn.tsx @@ -1,19 +1,17 @@ -import ForwardIcon from '@mui/icons-material/Forward'; -import { Box, Paper, Typography, MenuItem, TextField, Button } from '@mui/material'; -import { useRequest } from 'alova'; import { useContext, useState } from 'react'; -import { toast } from 'react-toastify'; -import type { ValidateFieldsError } from 'async-validator'; - -import type { Locales } from 'i18n/i18n-types'; import type { ChangeEventHandler, FC } from 'react'; -import type { SignInRequest } from 'types'; +import { toast } from 'react-toastify'; + +import ForwardIcon from '@mui/icons-material/Forward'; +import { Box, Button, MenuItem, Paper, TextField, Typography } from '@mui/material'; + import * as AuthenticationApi from 'api/authentication'; import { PROJECT_NAME } from 'api/env'; +import { useRequest } from 'alova'; +import type { ValidateFieldsError } from 'async-validator'; import { ValidatedPasswordField, ValidatedTextField } from 'components'; import { AuthenticationContext } from 'contexts/authentication'; - import DEflag from 'i18n/DE.svg'; import FRflag from 'i18n/FR.svg'; import GBflag from 'i18n/GB.svg'; @@ -25,7 +23,9 @@ import SKflag from 'i18n/SK.svg'; import SVflag from 'i18n/SV.svg'; import TRflag from 'i18n/TR.svg'; import { I18nContext } from 'i18n/i18n-react'; +import type { Locales } from 'i18n/i18n-types'; import { loadLocaleAsync } from 'i18n/i18n-util.async'; +import type { SignInRequest } from 'types'; import { onEnterCallback, updateValue } from 'utils'; import { SIGN_IN_REQUEST_VALIDATOR, validate } from 'validators'; @@ -41,9 +41,12 @@ const SignIn: FC = () => { const [processing, setProcessing] = useState(false); const [fieldErrors, setFieldErrors] = useState(); - const { send: callSignIn, onSuccess } = useRequest((request: SignInRequest) => AuthenticationApi.signIn(request), { - immediate: false - }); + const { send: callSignIn, onSuccess } = useRequest( + (request: SignInRequest) => AuthenticationApi.signIn(request), + { + immediate: false + } + ); onSuccess((response) => { if (response.data) { @@ -54,7 +57,7 @@ const SignIn: FC = () => { const updateLoginRequestValue = updateValue(setSignInRequest); const signIn = async () => { - await callSignIn(signInRequest).catch((event) => { + await callSignIn(signInRequest).catch((event: Error) => { if (event.message === 'Unauthorized') { toast.warning(LL.INVALID_LOGIN()); } else { @@ -72,15 +75,17 @@ const SignIn: FC = () => { try { await validate(SIGN_IN_REQUEST_VALIDATOR, signInRequest); await signIn(); - } catch (errors: any) { - setFieldErrors(errors); + } catch (error) { + setFieldErrors(error as ValidateFieldsError); setProcessing(false); } }; const submitOnEnter = onEnterCallback(signIn); - const onLocaleSelected: ChangeEventHandler = async ({ target }) => { + const onLocaleSelected: ChangeEventHandler = async ({ + target + }) => { const loc = target.value as Locales; localStorage.setItem('lang', loc); await loadLocaleAsync(loc); @@ -110,7 +115,14 @@ const SignIn: FC = () => { > {PROJECT_NAME} - +  DE @@ -182,7 +194,13 @@ const SignIn: FC = () => { /> - diff --git a/interface/src/api/ap.ts b/interface/src/api/ap.ts index 7ffda7668..6106c05f5 100644 --- a/interface/src/api/ap.ts +++ b/interface/src/api/ap.ts @@ -1,7 +1,9 @@ +import type { APSettingsType, APStatusType } from 'types'; + import { alovaInstance } from './endpoints'; -import type { APSettings, APStatus } from 'types'; - -export const readAPStatus = () => alovaInstance.Get('/rest/apStatus'); -export const readAPSettings = () => alovaInstance.Get('/rest/apSettings'); -export const updateAPSettings = (data: APSettings) => alovaInstance.Post('/rest/apSettings', data); +export const readAPStatus = () => alovaInstance.Get('/rest/apStatus'); +export const readAPSettings = () => + alovaInstance.Get('/rest/apSettings'); +export const updateAPSettings = (data: APSettingsType) => + alovaInstance.Post('/rest/apSettings', data); diff --git a/interface/src/api/authentication.ts b/interface/src/api/authentication.ts index c54ed2c64..076b69bd5 100644 --- a/interface/src/api/authentication.ts +++ b/interface/src/api/authentication.ts @@ -1,15 +1,18 @@ -import { jwtDecode } from 'jwt-decode'; -import { ACCESS_TOKEN, alovaInstance } from './endpoints'; -import type * as H from 'history'; import type { Path } from 'react-router-dom'; +import type * as H from 'history'; +import { jwtDecode } from 'jwt-decode'; import type { Me, SignInRequest, SignInResponse } from 'types'; +import { ACCESS_TOKEN, alovaInstance } from './endpoints'; + export const SIGN_IN_PATHNAME = 'loginPathname'; export const SIGN_IN_SEARCH = 'loginSearch'; -export const verifyAuthorization = () => alovaInstance.Get('/rest/verifyAuthorization'); -export const signIn = (request: SignInRequest) => alovaInstance.Post('/rest/signIn', request); +export const verifyAuthorization = () => + alovaInstance.Get('/rest/verifyAuthorization'); +export const signIn = (request: SignInRequest) => + alovaInstance.Post('/rest/signIn', request); export function getStorage() { return localStorage || sessionStorage; diff --git a/interface/src/api/endpoints.ts b/interface/src/api/endpoints.ts index 1b5413dee..e2f351f8f 100644 --- a/interface/src/api/endpoints.ts +++ b/interface/src/api/endpoints.ts @@ -1,13 +1,11 @@ import { xhrRequestAdapter } from '@alova/adapter-xhr'; import { createAlova } from 'alova'; import ReactHook from 'alova/react'; + import { unpack } from '../api/unpack'; export const ACCESS_TOKEN = 'access_token'; -const host = window.location.host; -export const EVENT_SOURCE_ROOT = 'http://' + host + '/es/'; - export const alovaInstance = createAlova({ statesHook: ReactHook, timeout: 3000, // 3 seconds but throwing a timeout error @@ -21,7 +19,8 @@ export const alovaInstance = createAlova({ requestAdapter: xhrRequestAdapter(), beforeRequest(method) { if (localStorage.getItem(ACCESS_TOKEN)) { - method.config.headers.Authorization = 'Bearer ' + localStorage.getItem(ACCESS_TOKEN); + method.config.headers.Authorization = + 'Bearer ' + localStorage.getItem(ACCESS_TOKEN); } }, @@ -37,9 +36,9 @@ export const alovaInstance = createAlova({ } else if (response.status >= 400) { throw new Error(response.statusText); } - const data = await response.data; + const data: ArrayBuffer = (await response.data) as ArrayBuffer; if (response.data instanceof ArrayBuffer) { - return unpack(data); + return unpack(data) as ArrayBuffer; } return data; } diff --git a/interface/src/api/mqtt.ts b/interface/src/api/mqtt.ts index 9605d843d..7ccc31d10 100644 --- a/interface/src/api/mqtt.ts +++ b/interface/src/api/mqtt.ts @@ -1,7 +1,10 @@ -import { alovaInstance } from './endpoints'; import type { MqttSettingsType, MqttStatusType } from 'types'; -export const readMqttStatus = () => alovaInstance.Get('/rest/mqttStatus'); -export const readMqttSettings = () => alovaInstance.Get('/rest/mqttSettings'); +import { alovaInstance } from './endpoints'; + +export const readMqttStatus = () => + alovaInstance.Get('/rest/mqttStatus'); +export const readMqttSettings = () => + alovaInstance.Get('/rest/mqttSettings'); export const updateMqttSettings = (data: MqttSettingsType) => alovaInstance.Post('/rest/mqttSettings', data); diff --git a/interface/src/api/network.ts b/interface/src/api/network.ts index c5b36dd45..ebbec684a 100644 --- a/interface/src/api/network.ts +++ b/interface/src/api/network.ts @@ -1,8 +1,9 @@ +import type { NetworkSettingsType, NetworkStatusType, WiFiNetworkList } from 'types'; + import { alovaInstance } from './endpoints'; -import type { WiFiNetworkList, NetworkSettings, NetworkStatus } from 'types'; - -export const readNetworkStatus = () => alovaInstance.Get('/rest/networkStatus'); +export const readNetworkStatus = () => + alovaInstance.Get('/rest/networkStatus'); export const scanNetworks = () => alovaInstance.Get('/rest/scanNetworks'); export const listNetworks = () => alovaInstance.Get('/rest/listNetworks', { @@ -10,6 +11,8 @@ export const listNetworks = () => timeout: 20000 // timeout 20 seconds }); export const readNetworkSettings = () => - alovaInstance.Get('/rest/networkSettings', { name: 'networkSettings' }); -export const updateNetworkSettings = (wifiSettings: NetworkSettings) => - alovaInstance.Post('/rest/networkSettings', wifiSettings); + alovaInstance.Get('/rest/networkSettings', { + name: 'networkSettings' + }); +export const updateNetworkSettings = (wifiSettings: NetworkSettingsType) => + alovaInstance.Post('/rest/networkSettings', wifiSettings); diff --git a/interface/src/api/ntp.ts b/interface/src/api/ntp.ts index 74da189d1..69e7471b4 100644 --- a/interface/src/api/ntp.ts +++ b/interface/src/api/ntp.ts @@ -1,11 +1,15 @@ -import { alovaInstance } from './endpoints'; -import type { NTPSettings, NTPStatus, Time } from 'types'; +import type { NTPSettingsType, NTPStatusType, Time } from 'types'; -export const readNTPStatus = () => alovaInstance.Get('/rest/ntpStatus'); +import { alovaInstance } from './endpoints'; + +export const readNTPStatus = () => + alovaInstance.Get('/rest/ntpStatus'); export const readNTPSettings = () => - alovaInstance.Get('/rest/ntpSettings', { + alovaInstance.Get('/rest/ntpSettings', { name: 'ntpSettings' }); -export const updateNTPSettings = (data: NTPSettings) => alovaInstance.Post('/rest/ntpSettings', data); +export const updateNTPSettings = (data: NTPSettingsType) => + alovaInstance.Post('/rest/ntpSettings', data); -export const updateTime = (data: Time) => alovaInstance.Post