From 1966a68638dccc11796687839386cf75117413c2 Mon Sep 17 00:00:00 2001 From: proddy Date: Mon, 15 Apr 2024 22:02:55 +0200 Subject: [PATCH 1/8] always show devices even in test --- src/telegram.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/telegram.h b/src/telegram.h index aba93af64..9ae8dca01 100644 --- a/src/telegram.h +++ b/src/telegram.h @@ -204,16 +204,17 @@ class EMSbus { // checks every 30 seconds if the EMS bus is still alive static bool bus_connected() { -#ifndef EMSESP_STANDALONE +#if defined(EMSESP_STANDALONE) || defined(EMSESP_TEST) + return true; +#else if ((uuid::get_uptime() - last_bus_activity_) > EMS_BUS_TIMEOUT) { bus_connected_ = false; } return bus_connected_; -#else - return true; #endif } + // sets the flag for EMS bus connected static void last_bus_activity(uint32_t timestamp) { // record the first time we connected to the BUS, as this will be our uptime From ae7cd23758c2457e738ec38874a8f70424364d1d Mon Sep 17 00:00:00 2001 From: proddy Date: Mon, 15 Apr 2024 22:03:01 +0200 Subject: [PATCH 2/8] package update --- interface/package.json | 10 +-- interface/yarn.lock | 134 ++++++++++++++++++++--------------------- mock-api/package.json | 2 +- mock-api/yarn.lock | 10 +-- 4 files changed, 78 insertions(+), 78 deletions(-) diff --git a/interface/package.json b/interface/package.json index 48fd73c88..ba9227b8b 100644 --- a/interface/package.json +++ b/interface/package.json @@ -32,10 +32,10 @@ "@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.78", "@types/react-dom": "^18.2.25", "@types/react-router-dom": "^5.3.3", - "alova": "^2.19.0", + "alova": "^2.19.1", "async-validator": "^4.2.5", "eslint-plugin-prettier": "^5.1.3", "history": "^5.3.0", @@ -45,7 +45,7 @@ "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", @@ -54,8 +54,8 @@ "devDependencies": { "@preact/compat": "^17.1.2", "@preact/preset-vite": "^2.8.2", - "@typescript-eslint/eslint-plugin": "^7.6.0", - "@typescript-eslint/parser": "^7.6.0", + "@typescript-eslint/eslint-plugin": "^7.7.0", + "@typescript-eslint/parser": "^7.7.0", "concurrently": "^8.2.2", "eslint": "8.57.0", "eslint-config-prettier": "^9.1.0", diff --git a/interface/yarn.lock b/interface/yarn.lock index 645403c76..d50f50a39 100644 --- a/interface/yarn.lock +++ b/interface/yarn.lock @@ -1547,13 +1547,13 @@ __metadata: languageName: node linkType: hard -"@types/react@npm:^18.2.76": - version: 18.2.76 - resolution: "@types/react@npm:18.2.76" +"@types/react@npm:^18.2.78": + version: 18.2.78 + resolution: "@types/react@npm:18.2.78" dependencies: "@types/prop-types": "npm:*" csstype: "npm:^3.0.2" - checksum: 10/25e9f548ba72be3e0cc624653e3bf2ec7d3ad1ede522e474884375eb352be977098857fe89611295ae3f5dd2f370305955a396996cde93c10fb9d1fbb93a5a74 + checksum: 10/a4bf8104c580fab40535cc6058425ac6a47c19b8dad45b566cdb38aaafa3ffa1f24e7b65ec95e391a6c18ccf4a33738a591c1f723c00300f13d61fc456a1eb8d languageName: node linkType: hard @@ -1589,15 +1589,15 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/eslint-plugin@npm:^7.6.0": - version: 7.6.0 - resolution: "@typescript-eslint/eslint-plugin@npm:7.6.0" +"@typescript-eslint/eslint-plugin@npm:^7.7.0": + version: 7.7.0 + resolution: "@typescript-eslint/eslint-plugin@npm:7.7.0" dependencies: "@eslint-community/regexpp": "npm:^4.10.0" - "@typescript-eslint/scope-manager": "npm:7.6.0" - "@typescript-eslint/type-utils": "npm:7.6.0" - "@typescript-eslint/utils": "npm:7.6.0" - "@typescript-eslint/visitor-keys": "npm:7.6.0" + "@typescript-eslint/scope-manager": "npm:7.7.0" + "@typescript-eslint/type-utils": "npm:7.7.0" + "@typescript-eslint/utils": "npm:7.7.0" + "@typescript-eslint/visitor-keys": "npm:7.7.0" debug: "npm:^4.3.4" graphemer: "npm:^1.4.0" ignore: "npm:^5.3.1" @@ -1610,44 +1610,44 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: 10/6977c5fb5397ac6c9fda8786b149130321ffba45a71b813ca8a800fe711ac626bcbe05d5ace2ef6245eb8f0c4b6feb2b505a0e0e398fa37ce088731e78478b20 + checksum: 10/9e6b6fbb9920581813c01daaa2f89419c3476e42823755c0627f4491640cfaffaebeb0592231ed4f318eefadfcdd4560b77b2903d66ab4e0c8df746a7037a603 languageName: node linkType: hard -"@typescript-eslint/parser@npm:^7.6.0": - version: 7.6.0 - resolution: "@typescript-eslint/parser@npm:7.6.0" +"@typescript-eslint/parser@npm:^7.7.0": + version: 7.7.0 + resolution: "@typescript-eslint/parser@npm:7.7.0" dependencies: - "@typescript-eslint/scope-manager": "npm:7.6.0" - "@typescript-eslint/types": "npm:7.6.0" - "@typescript-eslint/typescript-estree": "npm:7.6.0" - "@typescript-eslint/visitor-keys": "npm:7.6.0" + "@typescript-eslint/scope-manager": "npm:7.7.0" + "@typescript-eslint/types": "npm:7.7.0" + "@typescript-eslint/typescript-estree": "npm:7.7.0" + "@typescript-eslint/visitor-keys": "npm:7.7.0" debug: "npm:^4.3.4" peerDependencies: eslint: ^8.56.0 peerDependenciesMeta: typescript: optional: true - checksum: 10/245b975280691c6c7bd3fe3e9d57943220e0400df62738274b98dffcbd3011b7191fd54c950cb4d0b6328699f3b1a45cea5e46cc5c86528e7f14e533277616c8 + checksum: 10/9f8c53ca29af09cd366e37420410319c8f69e9f4a676513ecd91f5e6d822b9935b6a8ad7ec931d604fc4a0ecd93d51063d0c93227f78f2380196c8a7fa6970d1 languageName: node linkType: hard -"@typescript-eslint/scope-manager@npm:7.6.0": - version: 7.6.0 - resolution: "@typescript-eslint/scope-manager@npm:7.6.0" +"@typescript-eslint/scope-manager@npm:7.7.0": + version: 7.7.0 + resolution: "@typescript-eslint/scope-manager@npm:7.7.0" dependencies: - "@typescript-eslint/types": "npm:7.6.0" - "@typescript-eslint/visitor-keys": "npm:7.6.0" - checksum: 10/1daa0b84f751e740df39abf7303e63dcff26883242a616712d338edb11d24a05a03156d8f5d6b2c42ef01a28c540dbfc5c83853e159f341189870320e4c4acef + "@typescript-eslint/types": "npm:7.7.0" + "@typescript-eslint/visitor-keys": "npm:7.7.0" + checksum: 10/c8890aaf99b57543774e50549c5b178c13695b21a6b30c65292268137fe5e6856cc0e050c118b47b5835dd8a48c96e042fc75891a7f6093a0b94b6b3b251afd9 languageName: node linkType: hard -"@typescript-eslint/type-utils@npm:7.6.0": - version: 7.6.0 - resolution: "@typescript-eslint/type-utils@npm:7.6.0" +"@typescript-eslint/type-utils@npm:7.7.0": + version: 7.7.0 + resolution: "@typescript-eslint/type-utils@npm:7.7.0" dependencies: - "@typescript-eslint/typescript-estree": "npm:7.6.0" - "@typescript-eslint/utils": "npm:7.6.0" + "@typescript-eslint/typescript-estree": "npm:7.7.0" + "@typescript-eslint/utils": "npm:7.7.0" debug: "npm:^4.3.4" ts-api-utils: "npm:^1.3.0" peerDependencies: @@ -1655,23 +1655,23 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: 10/1011e1d3ff15f0167f653652865c5b850a1acb21627abff30b0cf1e15865dd490bfb7e9334fa2f4123477fc1eea1ebf4a5c3c8c5cc1972e3b195a39bd8c03aa8 + checksum: 10/a3f5358b4b7046458ea573607f3d6ea7f48e16524390b24c9360bdf8b03cc89fc6eb5da31b3e541e7f1e5f6958194ecaad5b644ca9b0d90c9a7b182f345451aa languageName: node linkType: hard -"@typescript-eslint/types@npm:7.6.0": - version: 7.6.0 - resolution: "@typescript-eslint/types@npm:7.6.0" - checksum: 10/830c1b12d8a9242285516e9b7e46bf434b52ad835da4fc5cdac19e79f02bf637c9458923d72cc0babe20d474ddcafcdd4dcd8991c2280d00084a014de3d32da0 +"@typescript-eslint/types@npm:7.7.0": + version: 7.7.0 + resolution: "@typescript-eslint/types@npm:7.7.0" + checksum: 10/d54ff9eeea168188fcbf1c8efe42892d1646ead801ea0a0f1312c80cfb74ee5dd61a145bc982919fb396683fb4578f98f7ad90e5d466d7aa1ca593e4338e1a2e languageName: node linkType: hard -"@typescript-eslint/typescript-estree@npm:7.6.0": - version: 7.6.0 - resolution: "@typescript-eslint/typescript-estree@npm:7.6.0" +"@typescript-eslint/typescript-estree@npm:7.7.0": + version: 7.7.0 + resolution: "@typescript-eslint/typescript-estree@npm:7.7.0" dependencies: - "@typescript-eslint/types": "npm:7.6.0" - "@typescript-eslint/visitor-keys": "npm:7.6.0" + "@typescript-eslint/types": "npm:7.7.0" + "@typescript-eslint/visitor-keys": "npm:7.7.0" debug: "npm:^4.3.4" globby: "npm:^11.1.0" is-glob: "npm:^4.0.3" @@ -1681,34 +1681,34 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: 10/a10ae981669180d7c09acdd01e1c3b3dcb544edb8fa44d0c82586c2915d3001e6e15c792ef6b0b75774d6ff705613ec213f2316a7d9477a122e68c5913545a2b + checksum: 10/40af26b3edb07af439f99728aa149bbc8668dae4a700a128abaf98d7f9bc0d5d31f8027aa1d13d6a55b22c20738d7cab84a3046a56417a2551de58671b39dbdf languageName: node linkType: hard -"@typescript-eslint/utils@npm:7.6.0": - version: 7.6.0 - resolution: "@typescript-eslint/utils@npm:7.6.0" +"@typescript-eslint/utils@npm:7.7.0": + version: 7.7.0 + resolution: "@typescript-eslint/utils@npm:7.7.0" dependencies: "@eslint-community/eslint-utils": "npm:^4.4.0" "@types/json-schema": "npm:^7.0.15" "@types/semver": "npm:^7.5.8" - "@typescript-eslint/scope-manager": "npm:7.6.0" - "@typescript-eslint/types": "npm:7.6.0" - "@typescript-eslint/typescript-estree": "npm:7.6.0" + "@typescript-eslint/scope-manager": "npm:7.7.0" + "@typescript-eslint/types": "npm:7.7.0" + "@typescript-eslint/typescript-estree": "npm:7.7.0" semver: "npm:^7.6.0" peerDependencies: eslint: ^8.56.0 - checksum: 10/45bcc1b00ec281cfc997aeff4bca3b3e169f49c656ddfcfad909b18ecdcd8b0d27776df1c452d47d9291cd1346023e0a2d7c8aa67bf3ad917f530033f6b193aa + checksum: 10/4223233ee022460a74f389302b50779537dfbb3bd414486dca356d2628a08d5b2c4c6002bae3bdffad92b368569024faf25faee9be739340d9459c23549a866f languageName: node linkType: hard -"@typescript-eslint/visitor-keys@npm:7.6.0": - version: 7.6.0 - resolution: "@typescript-eslint/visitor-keys@npm:7.6.0" +"@typescript-eslint/visitor-keys@npm:7.7.0": + version: 7.7.0 + resolution: "@typescript-eslint/visitor-keys@npm:7.7.0" dependencies: - "@typescript-eslint/types": "npm:7.6.0" + "@typescript-eslint/types": "npm:7.7.0" eslint-visitor-keys: "npm:^3.4.3" - checksum: 10/2703629f1359f08e7a20706e225f2d83bf12292c282d2effa431eae441b12d4af1fe8c692535f6ef32d5b6d0c15ad61c4c102e4dd157c8fe30eefb94222ba239 + checksum: 10/9f03591ab60b0b164f6bb222b5d5ae75f73fbe7f264be9318f770be9dc5dff8138d34701928940ffc18924058ae80754a738a1e623912a297d57a8a59cdfb41d languageName: node linkType: hard @@ -1735,12 +1735,12 @@ __metadata: "@types/imagemin": "npm:^8.0.5" "@types/lodash-es": "npm:^4.17.12" "@types/node": "npm:^20.12.7" - "@types/react": "npm:^18.2.76" + "@types/react": "npm:^18.2.78" "@types/react-dom": "npm:^18.2.25" "@types/react-router-dom": "npm:^5.3.3" - "@typescript-eslint/eslint-plugin": "npm:^7.6.0" - "@typescript-eslint/parser": "npm:^7.6.0" - alova: "npm:^2.19.0" + "@typescript-eslint/eslint-plugin": "npm:^7.7.0" + "@typescript-eslint/parser": "npm:^7.7.0" + alova: "npm:^2.19.1" async-validator: "npm:^4.2.5" concurrently: "npm:^8.2.2" eslint: "npm:8.57.0" @@ -1760,7 +1760,7 @@ __metadata: react: "npm:latest" react-dom: "npm:latest" react-dropzone: "npm:^14.2.3" - react-icons: "npm:^5.0.1" + react-icons: "npm:^5.1.0" react-router-dom: "npm:^6.22.3" react-toastify: "npm:^10.0.5" rollup-plugin-visualizer: "npm:^5.12.0" @@ -1829,10 +1829,10 @@ __metadata: languageName: node linkType: hard -"alova@npm:^2.19.0": - version: 2.19.0 - resolution: "alova@npm:2.19.0" - checksum: 10/0afdc54ada9b8540f9f4b0f71f3c6147da618865472c10a9bc6c59bc436489dc0d79d1b51c231f6361b7998f0ae594c24c208973b552a9fac3c272581e313a54 +"alova@npm:^2.19.1": + version: 2.19.1 + resolution: "alova@npm:2.19.1" + checksum: 10/2e0dbdb8a52ba3d5282ef183012b7ba48dc7eba8ba20f809a6556d55c6b54ffd873a348a8a458790c20d12251b210b9ff7b84adfbded90f89911e1d95a16390d languageName: node linkType: hard @@ -6804,12 +6804,12 @@ __metadata: languageName: node linkType: hard -"react-icons@npm:^5.0.1": - version: 5.0.1 - resolution: "react-icons@npm:5.0.1" +"react-icons@npm:^5.1.0": + version: 5.1.0 + resolution: "react-icons@npm:5.1.0" peerDependencies: react: "*" - checksum: 10/c4458c643ae32a793ddebc5fa1235c7ec051be1b131205510e8199d15a4c89221a501f95a71fa21c2da93e8dd225290e2e24bb80abd3fb85801e43009e692098 + checksum: 10/00f75809b1846a6cfb48e3d64ddc5e931a1fa74aa429cd594dc4a70223a5702deff62638b02c727c0aeb83120a8875d8034b380601c61a4d803a9227387bac22 languageName: node linkType: hard diff --git a/mock-api/package.json b/mock-api/package.json index 30723727e..7382ce341 100644 --- a/mock-api/package.json +++ b/mock-api/package.json @@ -13,7 +13,7 @@ "@msgpack/msgpack": "^2.8.0", "compression": "^1.7.4", "express": "^4.19.2", - "itty-router": "^5.0.12", + "itty-router": "^5.0.15", "multer": "^1.4.5-lts.1" }, "packageManager": "yarn@4.1.1", diff --git a/mock-api/yarn.lock b/mock-api/yarn.lock index 5279d4931..741ec0c0e 100644 --- a/mock-api/yarn.lock +++ b/mock-api/yarn.lock @@ -140,7 +140,7 @@ __metadata: "@types/multer": "npm:^1.4.11" compression: "npm:^1.7.4" express: "npm:^4.19.2" - itty-router: "npm:^5.0.12" + itty-router: "npm:^5.0.15" multer: "npm:^1.4.5-lts.1" languageName: unknown linkType: soft @@ -526,10 +526,10 @@ __metadata: languageName: node linkType: hard -"itty-router@npm:^5.0.12": - version: 5.0.12 - resolution: "itty-router@npm:5.0.12" - checksum: 10/c103482967564471585c04ca47df7aa0b166b2081f6a746f6b699942c524c924bec598a9a61b73e9c5e31f554b27ec642121370d21f7095f63fe2cdacf365019 +"itty-router@npm:^5.0.15": + version: 5.0.15 + resolution: "itty-router@npm:5.0.15" + checksum: 10/ab437c33a9888f022ee465d3ab62a9434556eae493da1c4154a2621b746a36cdb6b5a5f417fd7ac631631ead69b95789cba01399936f5b1d8755a73934bb0e54 languageName: node linkType: hard From 9dc91f2d69eabf26448e504e23094b25b94eb9cc Mon Sep 17 00:00:00 2001 From: proddy Date: Sat, 20 Apr 2024 20:46:01 +0200 Subject: [PATCH 3/8] new linting, make sure code is type safe --- .gitignore | 1 + .prettierrc | 9 +- .vscode/settings.json | 7 +- interface/.eslintignore | 12 - interface/.eslintrc.json | 108 -- interface/eslint.config.js | 33 + interface/package.json | 23 +- interface/progmem-generator.js | 8 +- interface/src/App.tsx | 8 +- interface/src/AppRouting.tsx | 7 +- interface/src/AuthenticatedRouting.tsx | 7 +- interface/src/CustomTheme.tsx | 5 +- interface/src/SignIn.tsx | 24 +- interface/src/api/ap.ts | 10 +- interface/src/api/authentication.ts | 7 +- interface/src/api/endpoints.ts | 8 +- interface/src/api/mqtt.ts | 3 +- interface/src/api/network.ts | 12 +- interface/src/api/ntp.ts | 12 +- interface/src/api/security.ts | 8 +- interface/src/api/system.ts | 17 +- interface/src/components/ButtonRow.tsx | 3 +- interface/src/components/MessageBox.tsx | 3 +- interface/src/components/SectionContent.tsx | 3 +- .../inputs/BlockFormControlLabel.tsx | 3 +- .../inputs/ValidatedPasswordField.tsx | 5 +- .../components/inputs/ValidatedTextField.tsx | 4 +- interface/src/components/layout/Layout.tsx | 15 +- .../src/components/layout/LayoutAppBar.tsx | 3 +- .../src/components/layout/LayoutDrawer.tsx | 10 +- .../src/components/layout/LayoutMenu.tsx | 26 +- .../src/components/layout/LayoutMenuItem.tsx | 7 +- .../src/components/layout/ListMenuItem.tsx | 5 +- interface/src/components/layout/context.ts | 2 +- .../components/loading/ApplicationError.tsx | 3 +- .../src/components/loading/FormLoader.tsx | 6 +- .../src/components/loading/LoadingSpinner.tsx | 5 +- .../components/routing/BlockNavigation.tsx | 4 +- .../src/components/routing/RequireAdmin.tsx | 4 +- .../routing/RequireAuthenticated.tsx | 8 +- .../routing/RequireUnauthenticated.tsx | 5 +- .../src/components/routing/RouterTabs.tsx | 7 +- .../src/components/upload/SingleUpload.tsx | 11 +- .../authentication/Authentication.tsx | 13 +- .../src/contexts/authentication/context.ts | 1 + interface/src/framework/Settings.tsx | 27 +- interface/src/framework/ap/APSettings.tsx | 22 +- interface/src/framework/ap/APStatus.tsx | 9 +- interface/src/framework/ap/AccessPoint.tsx | 11 +- interface/src/framework/mqtt/Mqtt.tsx | 11 +- interface/src/framework/mqtt/MqttSettings.tsx | 21 +- interface/src/framework/mqtt/MqttStatus.tsx | 8 +- interface/src/framework/network/Network.tsx | 16 +- .../src/framework/network/NetworkSettings.tsx | 62 +- .../src/framework/network/NetworkStatus.tsx | 9 +- .../network/WiFiConnectionContext.tsx | 1 + .../framework/network/WiFiNetworkScanner.tsx | 15 +- .../framework/network/WiFiNetworkSelector.tsx | 19 +- interface/src/framework/ntp/NTPSettings.tsx | 26 +- interface/src/framework/ntp/NTPStatus.tsx | 21 +- interface/src/framework/ntp/NetworkTime.tsx | 11 +- interface/src/framework/ntp/TZ.tsx | 4 +- interface/src/framework/ota/OTASettings.tsx | 18 +- .../src/framework/security/GenerateToken.tsx | 24 +- .../src/framework/security/ManageUsers.tsx | 38 +- interface/src/framework/security/Security.tsx | 13 +- .../framework/security/SecuritySettings.tsx | 15 +- interface/src/framework/security/User.tsx | 16 +- .../src/framework/system/ESPSystemStatus.tsx | 7 +- .../src/framework/system/RestartMonitor.tsx | 6 +- interface/src/framework/system/System.tsx | 13 +- interface/src/framework/system/SystemLog.tsx | 72 +- .../src/framework/system/SystemStatus.tsx | 18 +- .../src/framework/system/UploadDownload.tsx | 47 +- interface/src/i18n/de/index.ts | 2 +- interface/src/i18n/en/index.ts | 2 +- interface/src/i18n/formatters.ts | 3 +- interface/src/i18n/fr/index.ts | 2 +- interface/src/i18n/it/index.ts | 2 +- interface/src/i18n/nl/index.ts | 4 +- interface/src/i18n/no/index.ts | 9 +- interface/src/i18n/pl/index.ts | 6 +- interface/src/i18n/sk/index.ts | 2 +- interface/src/i18n/sv/index.ts | 2 +- interface/src/i18n/tr/index.ts | 2 +- interface/src/index.tsx | 2 +- interface/src/project/ApplicationSettings.tsx | 44 +- interface/src/project/CustomEntities.tsx | 50 +- .../src/project/CustomEntitiesDialog.tsx | 23 +- interface/src/project/Customization.tsx | 86 +- interface/src/project/CustomizationDialog.tsx | 17 +- interface/src/project/DeviceIcon.tsx | 13 +- interface/src/project/Devices.tsx | 88 +- interface/src/project/DevicesDialog.tsx | 47 +- interface/src/project/EntityMaskToggle.tsx | 7 +- interface/src/project/Help.tsx | 25 +- interface/src/project/OptionIcon.tsx | 6 +- interface/src/project/Scheduler.tsx | 43 +- interface/src/project/SchedulerDialog.tsx | 26 +- interface/src/project/Sensors.tsx | 61 +- interface/src/project/SensorsAnalogDialog.tsx | 41 +- .../src/project/SensorsTemperatureDialog.tsx | 31 +- interface/src/project/SystemActivity.tsx | 18 +- interface/src/project/api.ts | 51 +- interface/src/project/deviceValue.ts | 7 +- interface/src/project/types.ts | 20 +- interface/src/project/validators.ts | 5 +- interface/src/types/system.ts | 6 + interface/src/utils/binding.ts | 13 +- interface/src/utils/useRest.ts | 24 +- interface/src/validators/ap.ts | 5 +- interface/src/validators/mqtt.ts | 3 +- interface/src/validators/network.ts | 3 +- interface/src/validators/ntp.ts | 1 + interface/src/validators/shared.ts | 1 - interface/vite.config.ts | 6 +- interface/yarn.lock | 1697 +++-------------- mock-api/es_server.ts | 2 +- mock-api/package.json | 2 +- mock-api/rest_server.ts | 19 +- mock-api/yarn.lock | 10 +- src/version.h | 2 +- 122 files changed, 1194 insertions(+), 2412 deletions(-) delete mode 100644 interface/.eslintignore delete mode 100644 interface/.eslintrc.json create mode 100644 interface/eslint.config.js 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..7bed89b7c 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 + "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/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 ba9227b8b..c19e4b9e0 100644 --- a/interface/package.json +++ b/interface/package.json @@ -19,25 +19,24 @@ "typesafe-i18n": "typesafe-i18n --no-watch", "webUI": "node progmem-generator.js", "format": "prettier --write '**/*.{ts,tsx,js,css,json,md}'", - "lint": "eslint . --cache --fix" + "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.78", + "@types/react": "^18.2.79", "@types/react-dom": "^18.2.25", "@types/react-router-dom": "^5.3.3", - "alova": "^2.19.1", + "alova": "^2.20.0", "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", @@ -52,23 +51,19 @@ "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.7.0", - "@typescript-eslint/parser": "^7.7.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..f8661706d 100644 --- a/interface/progmem-generator.js +++ b/interface/progmem-generator.js @@ -1,8 +1,8 @@ -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 = ' '; 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..6f917408d 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'; diff --git a/interface/src/AuthenticatedRouting.tsx b/interface/src/AuthenticatedRouting.tsx index af3ed76d8..98462e53c 100644 --- a/interface/src/AuthenticatedRouting.tsx +++ b/interface/src/AuthenticatedRouting.tsx @@ -1,7 +1,6 @@ -import { useContext, type FC } from 'react'; -import { Navigate, Routes, Route } from 'react-router-dom'; +import { type FC, useContext } from 'react'; +import { Navigate, Route, Routes } from 'react-router-dom'; -import Help from './project/Help'; import { Layout } from 'components'; import { AuthenticatedContext } from 'contexts/authentication'; import Settings from 'framework/Settings'; @@ -21,6 +20,8 @@ import Devices from 'project/Devices'; import Scheduler from 'project/Scheduler'; import Sensors from 'project/Sensors'; +import Help from './project/Help'; + const AuthenticatedRouting: FC = () => { const { me } = useContext(AuthenticatedContext); return ( diff --git a/interface/src/CustomTheme.tsx b/interface/src/CustomTheme.tsx index c00321984..743935f3d 100644 --- a/interface/src/CustomTheme.tsx +++ b/interface/src/CustomTheme.tsx @@ -1,7 +1,8 @@ -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..c95b444f7 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'; @@ -54,7 +54,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,8 +72,8 @@ 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); } }; diff --git a/interface/src/api/ap.ts b/interface/src/api/ap.ts index 7ffda7668..8545dc3f0 100644 --- a/interface/src/api/ap.ts +++ b/interface/src/api/ap.ts @@ -1,7 +1,7 @@ +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..41b7579f8 100644 --- a/interface/src/api/authentication.ts +++ b/interface/src/api/authentication.ts @@ -1,10 +1,11 @@ -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'; diff --git a/interface/src/api/endpoints.ts b/interface/src/api/endpoints.ts index 1b5413dee..5d6974da8 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 @@ -37,9 +35,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..dd9d03842 100644 --- a/interface/src/api/mqtt.ts +++ b/interface/src/api/mqtt.ts @@ -1,6 +1,7 @@ -import { alovaInstance } from './endpoints'; import type { MqttSettingsType, MqttStatusType } from 'types'; +import { alovaInstance } from './endpoints'; + export const readMqttStatus = () => alovaInstance.Get('/rest/mqttStatus'); export const readMqttSettings = () => alovaInstance.Get('/rest/mqttSettings'); export const updateMqttSettings = (data: MqttSettingsType) => diff --git a/interface/src/api/network.ts b/interface/src/api/network.ts index c5b36dd45..3337f36e9 100644 --- a/interface/src/api/network.ts +++ b/interface/src/api/network.ts @@ -1,8 +1,8 @@ +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 +10,6 @@ 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..6400b5f23 100644 --- a/interface/src/api/ntp.ts +++ b/interface/src/api/ntp.ts @@ -1,11 +1,13 @@ -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