Browse Source

WIP config overhaul

pull/82/head
Sacha Weatherstone 3 years ago
parent
commit
6340809ab3
No known key found for this signature in database GPG Key ID: 7AB2D7E206124B31
  1. 10
      package.json
  2. 214
      pnpm-lock.yaml
  3. 41
      src/components/PageComponents/Config/Bluetooth.tsx
  4. 41
      src/components/PageComponents/Config/Device.tsx
  5. 51
      src/components/PageComponents/Config/Display.tsx
  6. 41
      src/components/PageComponents/Config/LoRa.tsx
  7. 47
      src/components/PageComponents/Config/Network.tsx
  8. 106
      src/components/PageComponents/Config/Position.tsx
  9. 41
      src/components/PageComponents/Config/Power.tsx
  10. 1
      src/components/Sidebar.tsx
  11. 3
      src/components/form/Form.tsx
  12. 58
      src/core/stores/deviceStore.ts
  13. 18
      src/pages/Config/DeviceConfig.tsx
  14. 3
      src/validation/config/lora.ts
  15. 2
      src/validation/config/network.ts

10
package.json

@ -20,11 +20,11 @@
"homepage": "https://meshtastic.org", "homepage": "https://meshtastic.org",
"dependencies": { "dependencies": {
"@emeraldpay/hashicon-react": "^0.5.2", "@emeraldpay/hashicon-react": "^0.5.2",
"@headlessui/react": "^1.7.7", "@headlessui/react": "^1.7.8",
"@heroicons/react": "^2.0.14", "@heroicons/react": "^2.0.14",
"@hookform/error-message": "^2.0.1", "@hookform/error-message": "^2.0.1",
"@hookform/resolvers": "^2.9.10", "@hookform/resolvers": "^2.9.10",
"@meshtastic/meshtasticjs": "2.0.13-5", "@meshtastic/meshtasticjs": "2.0.15-0",
"@primer/octicons-react": "^17.11.1", "@primer/octicons-react": "^17.11.1",
"@tailwindcss/typography": "^0.5.9", "@tailwindcss/typography": "^0.5.9",
"@turf/turf": "^6.5.0", "@turf/turf": "^6.5.0",
@ -36,7 +36,7 @@
"date-fns": "^2.29.3", "date-fns": "^2.29.3",
"geodesy": "^2.4.0", "geodesy": "^2.4.0",
"i18next": "^22.4.9", "i18next": "^22.4.9",
"immer": "^9.0.18", "immer": "^9.0.19",
"mapbox-gl": "npm:empty-npm-package@^1.0.0", "mapbox-gl": "npm:empty-npm-package@^1.0.0",
"maplibre-gl": "2.4.0", "maplibre-gl": "2.4.0",
"pretty-ms": "^8.0.0", "pretty-ms": "^8.0.0",
@ -66,7 +66,7 @@
"@typescript-eslint/parser": "^5.49.0", "@typescript-eslint/parser": "^5.49.0",
"@vitejs/plugin-react": "^3.0.1", "@vitejs/plugin-react": "^3.0.1",
"autoprefixer": "^10.4.13", "autoprefixer": "^10.4.13",
"eslint": "^8.32.0", "eslint": "^8.33.0",
"eslint-config-prettier": "^8.6.0", "eslint-config-prettier": "^8.6.0",
"eslint-import-resolver-typescript": "^3.5.3", "eslint-import-resolver-typescript": "^3.5.3",
"eslint-plugin-import": "^2.27.5", "eslint-plugin-import": "^2.27.5",
@ -79,7 +79,7 @@
"rollup-plugin-visualizer": "^5.9.0", "rollup-plugin-visualizer": "^5.9.0",
"tailwindcss": "^3.2.4", "tailwindcss": "^3.2.4",
"tar": "^6.1.13", "tar": "^6.1.13",
"tslib": "^2.4.1", "tslib": "^2.5.0",
"typescript": "^4.9.4", "typescript": "^4.9.4",
"vite": "^4.0.4", "vite": "^4.0.4",
"vite-plugin-environment": "^1.1.3", "vite-plugin-environment": "^1.1.3",

214
pnpm-lock.yaml

@ -2,11 +2,11 @@ lockfileVersion: 5.4
specifiers: specifiers:
'@emeraldpay/hashicon-react': ^0.5.2 '@emeraldpay/hashicon-react': ^0.5.2
'@headlessui/react': ^1.7.7 '@headlessui/react': ^1.7.8
'@heroicons/react': ^2.0.14 '@heroicons/react': ^2.0.14
'@hookform/error-message': ^2.0.1 '@hookform/error-message': ^2.0.1
'@hookform/resolvers': ^2.9.10 '@hookform/resolvers': ^2.9.10
'@meshtastic/meshtasticjs': 2.0.13-5 '@meshtastic/meshtasticjs': 2.0.15-0
'@primer/octicons-react': ^17.11.1 '@primer/octicons-react': ^17.11.1
'@tailwindcss/forms': ^0.5.3 '@tailwindcss/forms': ^0.5.3
'@tailwindcss/typography': ^0.5.9 '@tailwindcss/typography': ^0.5.9
@ -28,7 +28,7 @@ specifiers:
class-transformer: ^0.5.1 class-transformer: ^0.5.1
class-validator: ^0.14.0 class-validator: ^0.14.0
date-fns: ^2.29.3 date-fns: ^2.29.3
eslint: ^8.32.0 eslint: ^8.33.0
eslint-config-prettier: ^8.6.0 eslint-config-prettier: ^8.6.0
eslint-import-resolver-typescript: ^3.5.3 eslint-import-resolver-typescript: ^3.5.3
eslint-plugin-import: ^2.27.5 eslint-plugin-import: ^2.27.5
@ -37,7 +37,7 @@ specifiers:
geodesy: ^2.4.0 geodesy: ^2.4.0
gzipper: ^7.2.0 gzipper: ^7.2.0
i18next: ^22.4.9 i18next: ^22.4.9
immer: ^9.0.18 immer: ^9.0.19
mapbox-gl: npm:empty-npm-package@^1.0.0 mapbox-gl: npm:empty-npm-package@^1.0.0
maplibre-gl: 2.4.0 maplibre-gl: 2.4.0
postcss: ^8.4.21 postcss: ^8.4.21
@ -58,7 +58,7 @@ specifiers:
tailwindcss: ^3.2.4 tailwindcss: ^3.2.4
tar: ^6.1.13 tar: ^6.1.13
timeago-react: ^3.0.5 timeago-react: ^3.0.5
tslib: ^2.4.1 tslib: ^2.5.0
typescript: ^4.9.4 typescript: ^4.9.4
vite: ^4.0.4 vite: ^4.0.4
vite-plugin-environment: ^1.1.3 vite-plugin-environment: ^1.1.3
@ -67,11 +67,11 @@ specifiers:
dependencies: dependencies:
'@emeraldpay/hashicon-react': 0.5.2 '@emeraldpay/hashicon-react': 0.5.2
'@headlessui/react': 1.7.7_biqbaboplfbrettd7655fr4n2y '@headlessui/react': 1.7.8_biqbaboplfbrettd7655fr4n2y
'@heroicons/react': 2.0[email protected] '@heroicons/react': 2.0[email protected]
'@hookform/error-message': 2.0.1_uno7536xd2i6xn2dtvbywz2sva '@hookform/error-message': 2.0.1_uno7536xd2i6xn2dtvbywz2sva
'@hookform/resolvers': 2.9[email protected] '@hookform/resolvers': 2.9[email protected]
'@meshtastic/meshtasticjs': 2.0.13-5 '@meshtastic/meshtasticjs': 2.0.15-0
'@primer/octicons-react': 17.11[email protected] '@primer/octicons-react': 17.11[email protected]
'@tailwindcss/typography': 0.5[email protected] '@tailwindcss/typography': 0.5[email protected]
'@turf/turf': 6.5.0 '@turf/turf': 6.5.0
@ -83,7 +83,7 @@ dependencies:
date-fns: 2.29.3 date-fns: 2.29.3
geodesy: 2.4.0 geodesy: 2.4.0
i18next: 22.4.9 i18next: 22.4.9
immer: 9.0.18 immer: 9.0.19
mapbox-gl: /empty-npm-package/1.0.0 mapbox-gl: /empty-npm-package/1.0.0
maplibre-gl: 2.4.0 maplibre-gl: 2.4.0
pretty-ms: 8.0.0 pretty-ms: 8.0.0
@ -98,7 +98,7 @@ dependencies:
react-qrcode-logo: 2.8.0_biqbaboplfbrettd7655fr4n2y react-qrcode-logo: 2.8.0_biqbaboplfbrettd7655fr4n2y
rfc4648: 1.5.2 rfc4648: 1.5.2
timeago-react: 3.0[email protected] timeago-react: 3.0[email protected]
zustand: 4.3[email protected]8[email protected] zustand: 4.3[email protected]9[email protected]
devDependencies: devDependencies:
'@tailwindcss/forms': 0.5[email protected] '@tailwindcss/forms': 0.5[email protected]
@ -109,16 +109,16 @@ devDependencies:
'@types/react-dom': 18.0.10 '@types/react-dom': 18.0.10
'@types/w3c-web-serial': 1.0.3 '@types/w3c-web-serial': 1.0.3
'@types/web-bluetooth': 0.0.16 '@types/web-bluetooth': 0.0.16
'@typescript-eslint/eslint-plugin': 5.49.0_iu322prlnwsygkcra5kbpy22si '@typescript-eslint/eslint-plugin': 5.49.0_rsaczafy73x3xqauzesvzbsgzy
'@typescript-eslint/parser': 5.49.0_7uibuqfxkfaozanbtbziikiqje '@typescript-eslint/parser': 5.49.0_zkdaqh7it7uc4cvz2haft7rc6u
'@vitejs/plugin-react': 3.0[email protected] '@vitejs/plugin-react': 3.0[email protected]
autoprefixer: 10.4[email protected] autoprefixer: 10.4[email protected]
eslint: 8.32.0 eslint: 8.33.0
eslint-config-prettier: 8.6[email protected]2.0 eslint-config-prettier: 8.6[email protected]3.0
eslint-import-resolver-typescript: 3.5.3_ps7hf4l2dvbuxvtusmrfhmzsba eslint-import-resolver-typescript: 3.5.3_ohdts44xlqyeyrlje4qnefqeay
eslint-plugin-import: 2.27.5_tto3jvfrcbe7ndbi56p7uxhaki eslint-plugin-import: 2.27.5_c6pjvta7aysubsdnhvgec47vxe
eslint-plugin-react: 7.32[email protected]2.0 eslint-plugin-react: 7.32[email protected]3.0
eslint-plugin-react-hooks: 4.6[email protected]2.0 eslint-plugin-react-hooks: 4.6[email protected]3.0
gzipper: 7.2.0 gzipper: 7.2.0
postcss: 8.4.21 postcss: 8.4.21
prettier: 2.8.3 prettier: 2.8.3
@ -126,7 +126,7 @@ devDependencies:
rollup-plugin-visualizer: 5.9.0 rollup-plugin-visualizer: 5.9.0
tailwindcss: 3.2[email protected] tailwindcss: 3.2[email protected]
tar: 6.1.13 tar: 6.1.13
tslib: 2.4.1 tslib: 2.5.0
typescript: 4.9.4 typescript: 4.9.4
vite: 4.0.4_@[email protected] vite: 4.0.4_@[email protected]
vite-plugin-environment: 1.1[email protected] vite-plugin-environment: 1.1[email protected]
@ -161,8 +161,8 @@ packages:
'@babel/highlight': 7.18.6 '@babel/highlight': 7.18.6
dev: true dev: true
/@babel/compat-data/7.20.10: /@babel/compat-data/7.20.14:
resolution: {integrity: sha512-sEnuDPpOJR/fcafHMjpcpGN5M2jbUGUHwmuWKM/YdPzeEDJg8bgmbcWQFUfE32MQjti1koACvoPVsDe8Uq+idg==} resolution: {integrity: sha512-0YpKHD6ImkWMEINCyDAD0HLLUH/lPCefG8ld9it8DJB2wnApraKuhgYTvTY1z7UFIfBTGy5LwncZ+5HWWGbhFw==}
engines: {node: '>=6.9.0'} engines: {node: '>=6.9.0'}
dev: true dev: true
@ -172,7 +172,7 @@ packages:
dependencies: dependencies:
'@ampproject/remapping': 2.2.0 '@ampproject/remapping': 2.2.0
'@babel/code-frame': 7.18.6 '@babel/code-frame': 7.18.6
'@babel/generator': 7.20.7 '@babel/generator': 7.20.14
'@babel/helper-compilation-targets': 7.20.7_@[email protected] '@babel/helper-compilation-targets': 7.20.7_@[email protected]
'@babel/helper-module-transforms': 7.20.11 '@babel/helper-module-transforms': 7.20.11
'@babel/helpers': 7.20.13 '@babel/helpers': 7.20.13
@ -189,8 +189,8 @@ packages:
- supports-color - supports-color
dev: true dev: true
/@babel/generator/7.20.7: /@babel/generator/7.20.14:
resolution: {integrity: sha512-7wqMOJq8doJMZmP4ApXTzLxSr7+oO2jroJURrVEp6XShrQUObV8Tq/D0NCcoYg2uHqUrjzO0zwBjoYzelxK+sw==} resolution: {integrity: sha512-AEmuXHdcD3A52HHXxaTmYlb8q/xMEhoRP67B3T4Oq7lbmSoqroMZzjnGj3+i1io3pdnF8iBYVu4Ilj+c4hBxYg==}
engines: {node: '>=6.9.0'} engines: {node: '>=6.9.0'}
dependencies: dependencies:
'@babel/types': 7.20.7 '@babel/types': 7.20.7
@ -219,7 +219,7 @@ packages:
peerDependencies: peerDependencies:
'@babel/core': ^7.0.0 '@babel/core': ^7.0.0
dependencies: dependencies:
'@babel/compat-data': 7.20.10 '@babel/compat-data': 7.20.14
'@babel/core': 7.20.12 '@babel/core': 7.20.12
'@babel/helper-validator-option': 7.18.6 '@babel/helper-validator-option': 7.18.6
browserslist: 4.21.4 browserslist: 4.21.4
@ -583,7 +583,7 @@ packages:
peerDependencies: peerDependencies:
'@babel/core': ^7.0.0-0 '@babel/core': ^7.0.0-0
dependencies: dependencies:
'@babel/compat-data': 7.20.10 '@babel/compat-data': 7.20.14
'@babel/core': 7.20.12 '@babel/core': 7.20.12
'@babel/helper-compilation-targets': 7.20.7_@[email protected] '@babel/helper-compilation-targets': 7.20.7_@[email protected]
'@babel/helper-plugin-utils': 7.20.2 '@babel/helper-plugin-utils': 7.20.2
@ -826,8 +826,8 @@ packages:
'@babel/helper-plugin-utils': 7.20.2 '@babel/helper-plugin-utils': 7.20.2
dev: true dev: true
/@babel/plugin-transform-block-scoping/7.20.11_@[email protected]: /@babel/plugin-transform-block-scoping/7.20.14_@[email protected]:
resolution: {integrity: sha512-tA4N427a7fjf1P0/2I4ScsHGc5jcHPbb30xMbaTke2gxDuWpUfXDuX1FEymJwKk4tuGUvGcejAR6HdZVqmmPyw==} resolution: {integrity: sha512-sMPepQtsOs5fM1bwNvuJJHvaCfOEQfmc01FGw0ELlTpTJj5Ql/zuNRRldYhAPys4ghXdBIQJbRVYi44/7QflQQ==}
engines: {node: '>=6.9.0'} engines: {node: '>=6.9.0'}
peerDependencies: peerDependencies:
'@babel/core': ^7.0.0-0 '@babel/core': ^7.0.0-0
@ -1179,7 +1179,7 @@ packages:
peerDependencies: peerDependencies:
'@babel/core': ^7.0.0-0 '@babel/core': ^7.0.0-0
dependencies: dependencies:
'@babel/compat-data': 7.20.10 '@babel/compat-data': 7.20.14
'@babel/core': 7.20.12 '@babel/core': 7.20.12
'@babel/helper-compilation-targets': 7.20.7_@[email protected] '@babel/helper-compilation-targets': 7.20.7_@[email protected]
'@babel/helper-plugin-utils': 7.20.2 '@babel/helper-plugin-utils': 7.20.2
@ -1219,7 +1219,7 @@ packages:
'@babel/plugin-transform-arrow-functions': 7.20.7_@[email protected] '@babel/plugin-transform-arrow-functions': 7.20.7_@[email protected]
'@babel/plugin-transform-async-to-generator': 7.20.7_@[email protected] '@babel/plugin-transform-async-to-generator': 7.20.7_@[email protected]
'@babel/plugin-transform-block-scoped-functions': 7.18.6_@[email protected] '@babel/plugin-transform-block-scoped-functions': 7.18.6_@[email protected]
'@babel/plugin-transform-block-scoping': 7.20.11_@[email protected] '@babel/plugin-transform-block-scoping': 7.20.14_@[email protected]
'@babel/plugin-transform-classes': 7.20.7_@[email protected] '@babel/plugin-transform-classes': 7.20.7_@[email protected]
'@babel/plugin-transform-computed-properties': 7.20.7_@[email protected] '@babel/plugin-transform-computed-properties': 7.20.7_@[email protected]
'@babel/plugin-transform-destructuring': 7.20.7_@[email protected] '@babel/plugin-transform-destructuring': 7.20.7_@[email protected]
@ -1292,7 +1292,7 @@ packages:
engines: {node: '>=6.9.0'} engines: {node: '>=6.9.0'}
dependencies: dependencies:
'@babel/code-frame': 7.18.6 '@babel/code-frame': 7.18.6
'@babel/generator': 7.20.7 '@babel/generator': 7.20.14
'@babel/helper-environment-visitor': 7.18.9 '@babel/helper-environment-visitor': 7.18.9
'@babel/helper-function-name': 7.19.0 '@babel/helper-function-name': 7.19.0
'@babel/helper-hoist-variables': 7.18.6 '@babel/helper-hoist-variables': 7.18.6
@ -1314,8 +1314,8 @@ packages:
to-fast-properties: 2.0.0 to-fast-properties: 2.0.0
dev: true dev: true
/@buf/meshtastic_protobufs.bufbuild_es/1.0.0-20230114035636-d95aa4c6a33c.1_@[email protected]: /@buf/meshtastic_protobufs.bufbuild_es/1.0.0-20230129055417-f11f156e79a6.1_@[email protected]:
resolution: {registry: https://buf.build/gen/npm/v1, tarball: https://buf.build/gen/npm/v1/@buf/meshtastic_protobufs.bufbuild_es/1.0.0-20230114035636-d95aa4c6a33c.1/tarball} resolution: {registry: https://buf.build/gen/npm/v1, tarball: https://buf.build/gen/npm/v1/@buf/meshtastic_protobufs.bufbuild_es/1.0.0-20230129055417-f11f156e79a6.1/tarball}
peerDependencies: peerDependencies:
'@bufbuild/protobuf': ^1.0.0 '@bufbuild/protobuf': ^1.0.0
dependencies: dependencies:
@ -1547,7 +1547,7 @@ packages:
ajv: 6.12.6 ajv: 6.12.6
debug: 4.3.4 debug: 4.3.4
espree: 9.4.1 espree: 9.4.1
globals: 13.19.0 globals: 13.20.0
ignore: 5.2.4 ignore: 5.2.4
import-fresh: 3.3.0 import-fresh: 3.3.0
js-yaml: 4.1.0 js-yaml: 4.1.0
@ -1564,8 +1564,8 @@ packages:
base64-js: 1.5.1 base64-js: 1.5.1
dev: true dev: true
/@headlessui/react/1.7.7_biqbaboplfbrettd7655fr4n2y: /@headlessui/react/1.7.8_biqbaboplfbrettd7655fr4n2y:
resolution: {integrity: sha512-BqDOd/tB9u2tA0T3Z0fn18ktw+KbVwMnkxxsGPIH2hzssrQhKB5n/6StZOyvLYP/FsYtvuXfi9I0YowKPv2c1w==} resolution: {integrity: sha512-zcwb0kd7L05hxmoAMIioEaOn235Dg0fUO+iGbLPgLVSjzl/l39V6DTpC2Df49PE5aG5/f5q0PZ9ZHZ78ENNV+A==}
engines: {node: '>=10'} engines: {node: '>=10'}
peerDependencies: peerDependencies:
react: ^16 || ^17 || ^18 react: ^16 || ^17 || ^18
@ -1713,13 +1713,16 @@ packages:
engines: {node: '>=6.0.0'} engines: {node: '>=6.0.0'}
dev: false dev: false
/@meshtastic/meshtasticjs/2.0.13-5: /@meshtastic/meshtasticjs/2.0.15-0:
resolution: {integrity: sha512-4nddyKCPvujgwZa0Y+Bz4m7MFkOq7D2q5iuDqXbnE8xq2sqAjQde9DzK+ihnFe89enf7a5hz5d2bxZBqmMDYmg==} resolution: {integrity: sha512-CEfLP/PQWsQoUoFkQ2FVSNUKhjH+6J3QaTgvaRcP8YWq269SA8/A4ZFIIdg28DMKkPNcGPfVv/6PX7y98C6zmA==}
dependencies: dependencies:
'@buf/meshtastic_protobufs.bufbuild_es': 1.0.0-20230114035636-d95aa4c6a33c.1_@[email protected] '@buf/meshtastic_protobufs.bufbuild_es': 1.0.0-20230129055417-f11f156e79a6.1_@[email protected]
'@bufbuild/protobuf': 1.0.0 '@bufbuild/protobuf': 1.0.0
crc: 4.3.1
sub-events: 1.9.0 sub-events: 1.9.0
tslog: 4.7.1 tslog: 4.7.1
transitivePeerDependencies:
- buffer
dev: false dev: false
/@nodelib/fs.scandir/2.1.5: /@nodelib/fs.scandir/2.1.5:
@ -1749,7 +1752,7 @@ packages:
open: 8.4.0 open: 8.4.0
picocolors: 1.0.0 picocolors: 1.0.0
tiny-glob: 0.2.9 tiny-glob: 0.2.9
tslib: 2.4.1 tslib: 2.5.0
dev: true dev: true
/@primer/octicons-react/[email protected]: /@primer/octicons-react/[email protected]:
@ -1803,7 +1806,7 @@ packages:
rollup: 2.79.1 rollup: 2.79.1
dev: true dev: true
/@rollup/plugin-replace/[email protected]0.1: /@rollup/plugin-replace/[email protected]2.0:
resolution: {integrity: sha512-M9YXNekv/C/iHHK+cvORzfRYfPbq0RDD8r0G+bMiTXjNGKulPnCT9O3Ss46WfhI6ZOCgApOP7xAdmCQJ+U2LAA==} resolution: {integrity: sha512-M9YXNekv/C/iHHK+cvORzfRYfPbq0RDD8r0G+bMiTXjNGKulPnCT9O3Ss46WfhI6ZOCgApOP7xAdmCQJ+U2LAA==}
engines: {node: '>=14.0.0'} engines: {node: '>=14.0.0'}
peerDependencies: peerDependencies:
@ -1812,9 +1815,9 @@ packages:
rollup: rollup:
optional: true optional: true
dependencies: dependencies:
'@rollup/pluginutils': 5.0[email protected]0.1 '@rollup/pluginutils': 5.0[email protected]2.0
magic-string: 0.27.0 magic-string: 0.27.0
rollup: 3.10.1 rollup: 3.12.0
dev: true dev: true
/@rollup/pluginutils/[email protected]: /@rollup/pluginutils/[email protected]:
@ -1829,7 +1832,7 @@ packages:
rollup: 2.79.1 rollup: 2.79.1
dev: true dev: true
/@rollup/pluginutils/[email protected]0.1: /@rollup/pluginutils/[email protected]2.0:
resolution: {integrity: sha512-pTd9rIsP92h+B6wWwFbW8RkZv4hiR/xKsqre4SIuAOaOEQRxi0lqLke9k2/7WegC85GgUs9pjmOjCUi3In4vwA==} resolution: {integrity: sha512-pTd9rIsP92h+B6wWwFbW8RkZv4hiR/xKsqre4SIuAOaOEQRxi0lqLke9k2/7WegC85GgUs9pjmOjCUi3In4vwA==}
engines: {node: '>=14.0.0'} engines: {node: '>=14.0.0'}
peerDependencies: peerDependencies:
@ -1841,7 +1844,7 @@ packages:
'@types/estree': 1.0.0 '@types/estree': 1.0.0
estree-walker: 2.0.2 estree-walker: 2.0.2
picomatch: 2.3.1 picomatch: 2.3.1
rollup: 3.10.1 rollup: 3.12.0
dev: true dev: true
/@stablelib/binary/1.0.1: /@stablelib/binary/1.0.1:
@ -3058,7 +3061,7 @@ packages:
resolution: {integrity: sha512-oh8q2Zc32S6gd/j50GowEjKLoOVOwHP/bWVjKJInBwQqdOYMdPrf1oVlelTlyfFK3CKxL1uahMDAr+vy8T7yMQ==} resolution: {integrity: sha512-oh8q2Zc32S6gd/j50GowEjKLoOVOwHP/bWVjKJInBwQqdOYMdPrf1oVlelTlyfFK3CKxL1uahMDAr+vy8T7yMQ==}
dev: true dev: true
/@typescript-eslint/eslint-plugin/5.49.0_iu322prlnwsygkcra5kbpy22si: /@typescript-eslint/eslint-plugin/5.49.0_rsaczafy73x3xqauzesvzbsgzy:
resolution: {integrity: sha512-IhxabIpcf++TBaBa1h7jtOWyon80SXPRLDq0dVz5SLFC/eW6tofkw/O7Ar3lkx5z5U6wzbKDrl2larprp5kk5Q==} resolution: {integrity: sha512-IhxabIpcf++TBaBa1h7jtOWyon80SXPRLDq0dVz5SLFC/eW6tofkw/O7Ar3lkx5z5U6wzbKDrl2larprp5kk5Q==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
peerDependencies: peerDependencies:
@ -3069,12 +3072,12 @@ packages:
typescript: typescript:
optional: true optional: true
dependencies: dependencies:
'@typescript-eslint/parser': 5.49.0_7uibuqfxkfaozanbtbziikiqje '@typescript-eslint/parser': 5.49.0_zkdaqh7it7uc4cvz2haft7rc6u
'@typescript-eslint/scope-manager': 5.49.0 '@typescript-eslint/scope-manager': 5.49.0
'@typescript-eslint/type-utils': 5.49.0_7uibuqfxkfaozanbtbziikiqje '@typescript-eslint/type-utils': 5.49.0_zkdaqh7it7uc4cvz2haft7rc6u
'@typescript-eslint/utils': 5.49.0_7uibuqfxkfaozanbtbziikiqje '@typescript-eslint/utils': 5.49.0_zkdaqh7it7uc4cvz2haft7rc6u
debug: 4.3.4 debug: 4.3.4
eslint: 8.32.0 eslint: 8.33.0
ignore: 5.2.4 ignore: 5.2.4
natural-compare-lite: 1.4.0 natural-compare-lite: 1.4.0
regexpp: 3.2.0 regexpp: 3.2.0
@ -3085,7 +3088,7 @@ packages:
- supports-color - supports-color
dev: true dev: true
/@typescript-eslint/parser/5.49.0_7uibuqfxkfaozanbtbziikiqje: /@typescript-eslint/parser/5.49.0_zkdaqh7it7uc4cvz2haft7rc6u:
resolution: {integrity: sha512-veDlZN9mUhGqU31Qiv2qEp+XrJj5fgZpJ8PW30sHU+j/8/e5ruAhLaVDAeznS7A7i4ucb/s8IozpDtt9NqCkZg==} resolution: {integrity: sha512-veDlZN9mUhGqU31Qiv2qEp+XrJj5fgZpJ8PW30sHU+j/8/e5ruAhLaVDAeznS7A7i4ucb/s8IozpDtt9NqCkZg==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
peerDependencies: peerDependencies:
@ -3099,7 +3102,7 @@ packages:
'@typescript-eslint/types': 5.49.0 '@typescript-eslint/types': 5.49.0
'@typescript-eslint/typescript-estree': 5.49[email protected] '@typescript-eslint/typescript-estree': 5.49[email protected]
debug: 4.3.4 debug: 4.3.4
eslint: 8.32.0 eslint: 8.33.0
typescript: 4.9.4 typescript: 4.9.4
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
@ -3113,7 +3116,7 @@ packages:
'@typescript-eslint/visitor-keys': 5.49.0 '@typescript-eslint/visitor-keys': 5.49.0
dev: true dev: true
/@typescript-eslint/type-utils/5.49.0_7uibuqfxkfaozanbtbziikiqje: /@typescript-eslint/type-utils/5.49.0_zkdaqh7it7uc4cvz2haft7rc6u:
resolution: {integrity: sha512-eUgLTYq0tR0FGU5g1YHm4rt5H/+V2IPVkP0cBmbhRyEmyGe4XvJ2YJ6sYTmONfjmdMqyMLad7SB8GvblbeESZA==} resolution: {integrity: sha512-eUgLTYq0tR0FGU5g1YHm4rt5H/+V2IPVkP0cBmbhRyEmyGe4XvJ2YJ6sYTmONfjmdMqyMLad7SB8GvblbeESZA==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
peerDependencies: peerDependencies:
@ -3124,9 +3127,9 @@ packages:
optional: true optional: true
dependencies: dependencies:
'@typescript-eslint/typescript-estree': 5.49[email protected] '@typescript-eslint/typescript-estree': 5.49[email protected]
'@typescript-eslint/utils': 5.49.0_7uibuqfxkfaozanbtbziikiqje '@typescript-eslint/utils': 5.49.0_zkdaqh7it7uc4cvz2haft7rc6u
debug: 4.3.4 debug: 4.3.4
eslint: 8.32.0 eslint: 8.33.0
tsutils: 3.21[email protected] tsutils: 3.21[email protected]
typescript: 4.9.4 typescript: 4.9.4
transitivePeerDependencies: transitivePeerDependencies:
@ -3159,7 +3162,7 @@ packages:
- supports-color - supports-color
dev: true dev: true
/@typescript-eslint/utils/5.49.0_7uibuqfxkfaozanbtbziikiqje: /@typescript-eslint/utils/5.49.0_zkdaqh7it7uc4cvz2haft7rc6u:
resolution: {integrity: sha512-cPJue/4Si25FViIb74sHCLtM4nTSBXtLx1d3/QT6mirQ/c65bV8arBEebBJJizfq8W2YyMoPI/WWPFWitmNqnQ==} resolution: {integrity: sha512-cPJue/4Si25FViIb74sHCLtM4nTSBXtLx1d3/QT6mirQ/c65bV8arBEebBJJizfq8W2YyMoPI/WWPFWitmNqnQ==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
peerDependencies: peerDependencies:
@ -3170,9 +3173,9 @@ packages:
'@typescript-eslint/scope-manager': 5.49.0 '@typescript-eslint/scope-manager': 5.49.0
'@typescript-eslint/types': 5.49.0 '@typescript-eslint/types': 5.49.0
'@typescript-eslint/typescript-estree': 5.49[email protected] '@typescript-eslint/typescript-estree': 5.49[email protected]
eslint: 8.32.0 eslint: 8.33.0
eslint-scope: 5.1.1 eslint-scope: 5.1.1
eslint-utils: 3.0[email protected]2.0 eslint-utils: 3.0[email protected]3.0
semver: 7.3.8 semver: 7.3.8
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
@ -3347,7 +3350,7 @@ packages:
postcss: ^8.1.0 postcss: ^8.1.0
dependencies: dependencies:
browserslist: 4.21.4 browserslist: 4.21.4
caniuse-lite: 1.0.30001448 caniuse-lite: 1.0.30001449
fraction.js: 4.2.0 fraction.js: 4.2.0
normalize-range: 0.1.2 normalize-range: 0.1.2
picocolors: 1.0.0 picocolors: 1.0.0
@ -3365,7 +3368,7 @@ packages:
peerDependencies: peerDependencies:
'@babel/core': ^7.0.0-0 '@babel/core': ^7.0.0-0
dependencies: dependencies:
'@babel/compat-data': 7.20.10 '@babel/compat-data': 7.20.14
'@babel/core': 7.20.12 '@babel/core': 7.20.12
'@babel/helper-define-polyfill-provider': 0.3.3_@[email protected] '@babel/helper-define-polyfill-provider': 0.3.3_@[email protected]
semver: 6.3.0 semver: 6.3.0
@ -3435,7 +3438,7 @@ packages:
engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
hasBin: true hasBin: true
dependencies: dependencies:
caniuse-lite: 1.0.30001448 caniuse-lite: 1.0.30001449
electron-to-chromium: 1.4.284 electron-to-chromium: 1.4.284
node-releases: 2.0.8 node-releases: 2.0.8
update-browserslist-db: 1.0[email protected] update-browserslist-db: 1.0[email protected]
@ -3465,8 +3468,8 @@ packages:
resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==} resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==}
engines: {node: '>= 6'} engines: {node: '>= 6'}
/caniuse-lite/1.0.30001448: /caniuse-lite/1.0.30001449:
resolution: {integrity: sha512-tq2YI+MJnooG96XpbTRYkBxLxklZPOdLmNIOdIhvf7SNJan6u5vCKum8iT7ZfCt70m1GPkuC7P3TtX6UuhupuA==} resolution: {integrity: sha512-CPB+UL9XMT/Av+pJxCKGhdx+yg1hzplvFJQlJ2n68PyQGMz9L/E2zCyLdOL8uasbouTUgnPl+y0tccI/se+BEw==}
dev: true dev: true
/chalk/2.4.2: /chalk/2.4.2:
@ -3619,6 +3622,13 @@ packages:
resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==}
dev: true dev: true
/crc/4.3.1:
resolution: {integrity: sha512-xj9aHWoSZ3QjIrfhaDjWFObTOuCKgI4PDuzORvgzCIJ3qDw9Z3dOVK/Oj++N0kWdFLWBbOjSi+/0SLleiy/4OQ==}
engines: {node: '>=12'}
peerDependencies:
buffer: '>=6.0.3'
dev: false
/cross-spawn/7.0.3: /cross-spawn/7.0.3:
resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==}
engines: {node: '>= 8'} engines: {node: '>= 8'}
@ -3957,13 +3967,13 @@ packages:
engines: {node: '>=10'} engines: {node: '>=10'}
dev: true dev: true
/eslint-config-prettier/[email protected]2.0: /eslint-config-prettier/[email protected]3.0:
resolution: {integrity: sha512-bAF0eLpLVqP5oEVUFKpMA+NnRFICwn9X8B5jrR9FcqnYBuPbqWEjTEspPWMj5ye6czoSLDweCzSo3Ko7gGrZaA==} resolution: {integrity: sha512-bAF0eLpLVqP5oEVUFKpMA+NnRFICwn9X8B5jrR9FcqnYBuPbqWEjTEspPWMj5ye6czoSLDweCzSo3Ko7gGrZaA==}
hasBin: true hasBin: true
peerDependencies: peerDependencies:
eslint: '>=7.0.0' eslint: '>=7.0.0'
dependencies: dependencies:
eslint: 8.32.0 eslint: 8.33.0
dev: true dev: true
/eslint-import-resolver-node/0.3.7: /eslint-import-resolver-node/0.3.7:
@ -3976,7 +3986,7 @@ packages:
- supports-color - supports-color
dev: true dev: true
/eslint-import-resolver-typescript/3.5.3_ps7hf4l2dvbuxvtusmrfhmzsba: /eslint-import-resolver-typescript/3.5.3_ohdts44xlqyeyrlje4qnefqeay:
resolution: {integrity: sha512-njRcKYBc3isE42LaTcJNVANR3R99H9bAxBDMNDr2W7yq5gYPxbU3MkdhsQukxZ/Xg9C2vcyLlDsbKfRDg0QvCQ==} resolution: {integrity: sha512-njRcKYBc3isE42LaTcJNVANR3R99H9bAxBDMNDr2W7yq5gYPxbU3MkdhsQukxZ/Xg9C2vcyLlDsbKfRDg0QvCQ==}
engines: {node: ^14.18.0 || >=16.0.0} engines: {node: ^14.18.0 || >=16.0.0}
peerDependencies: peerDependencies:
@ -3985,18 +3995,18 @@ packages:
dependencies: dependencies:
debug: 4.3.4 debug: 4.3.4
enhanced-resolve: 5.12.0 enhanced-resolve: 5.12.0
eslint: 8.32.0 eslint: 8.33.0
eslint-plugin-import: 2.27.5_tto3jvfrcbe7ndbi56p7uxhaki eslint-plugin-import: 2.27.5_c6pjvta7aysubsdnhvgec47vxe
get-tsconfig: 4.3.0 get-tsconfig: 4.3.0
globby: 13.1.3 globby: 13.1.3
is-core-module: 2.11.0 is-core-module: 2.11.0
is-glob: 4.0.3 is-glob: 4.0.3
synckit: 0.8.4 synckit: 0.8.5
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
dev: true dev: true
/eslint-module-utils/2.7.4_xoxtsypck35xtelm3fn5dkquvy: /eslint-module-utils/2.7.4_5hqjyc62h4cn6t4zslmr6l4rke:
resolution: {integrity: sha512-j4GT+rqzCoRKHwURX7pddtIPGySnX9Si/cgMI5ztrcqOPtk5dDEeZ34CQVPphnqkJytlc97Vuk05Um2mJ3gEQA==} resolution: {integrity: sha512-j4GT+rqzCoRKHwURX7pddtIPGySnX9Si/cgMI5ztrcqOPtk5dDEeZ34CQVPphnqkJytlc97Vuk05Um2mJ3gEQA==}
engines: {node: '>=4'} engines: {node: '>=4'}
peerDependencies: peerDependencies:
@ -4017,16 +4027,16 @@ packages:
eslint-import-resolver-webpack: eslint-import-resolver-webpack:
optional: true optional: true
dependencies: dependencies:
'@typescript-eslint/parser': 5.49.0_7uibuqfxkfaozanbtbziikiqje '@typescript-eslint/parser': 5.49.0_zkdaqh7it7uc4cvz2haft7rc6u
debug: 3.2.7 debug: 3.2.7
eslint: 8.32.0 eslint: 8.33.0
eslint-import-resolver-node: 0.3.7 eslint-import-resolver-node: 0.3.7
eslint-import-resolver-typescript: 3.5.3_ps7hf4l2dvbuxvtusmrfhmzsba eslint-import-resolver-typescript: 3.5.3_ohdts44xlqyeyrlje4qnefqeay
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
dev: true dev: true
/eslint-plugin-import/2.27.5_tto3jvfrcbe7ndbi56p7uxhaki: /eslint-plugin-import/2.27.5_c6pjvta7aysubsdnhvgec47vxe:
resolution: {integrity: sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow==} resolution: {integrity: sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow==}
engines: {node: '>=4'} engines: {node: '>=4'}
peerDependencies: peerDependencies:
@ -4036,15 +4046,15 @@ packages:
'@typescript-eslint/parser': '@typescript-eslint/parser':
optional: true optional: true
dependencies: dependencies:
'@typescript-eslint/parser': 5.49.0_7uibuqfxkfaozanbtbziikiqje '@typescript-eslint/parser': 5.49.0_zkdaqh7it7uc4cvz2haft7rc6u
array-includes: 3.1.6 array-includes: 3.1.6
array.prototype.flat: 1.3.1 array.prototype.flat: 1.3.1
array.prototype.flatmap: 1.3.1 array.prototype.flatmap: 1.3.1
debug: 3.2.7 debug: 3.2.7
doctrine: 2.1.0 doctrine: 2.1.0
eslint: 8.32.0 eslint: 8.33.0
eslint-import-resolver-node: 0.3.7 eslint-import-resolver-node: 0.3.7
eslint-module-utils: 2.7.4_xoxtsypck35xtelm3fn5dkquvy eslint-module-utils: 2.7.4_5hqjyc62h4cn6t4zslmr6l4rke
has: 1.0.3 has: 1.0.3
is-core-module: 2.11.0 is-core-module: 2.11.0
is-glob: 4.0.3 is-glob: 4.0.3
@ -4059,16 +4069,16 @@ packages:
- supports-color - supports-color
dev: true dev: true
/eslint-plugin-react-hooks/[email protected]2.0: /eslint-plugin-react-hooks/[email protected]3.0:
resolution: {integrity: sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==} resolution: {integrity: sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==}
engines: {node: '>=10'} engines: {node: '>=10'}
peerDependencies: peerDependencies:
eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0
dependencies: dependencies:
eslint: 8.32.0 eslint: 8.33.0
dev: true dev: true
/eslint-plugin-react/[email protected]2.0: /eslint-plugin-react/[email protected]3.0:
resolution: {integrity: sha512-vOjdgyd0ZHBXNsmvU+785xY8Bfe57EFbTYYk8XrROzWpr9QBvpjITvAXt9xqcE6+8cjR/g1+mfumPToxsl1www==} resolution: {integrity: sha512-vOjdgyd0ZHBXNsmvU+785xY8Bfe57EFbTYYk8XrROzWpr9QBvpjITvAXt9xqcE6+8cjR/g1+mfumPToxsl1www==}
engines: {node: '>=4'} engines: {node: '>=4'}
peerDependencies: peerDependencies:
@ -4078,7 +4088,7 @@ packages:
array.prototype.flatmap: 1.3.1 array.prototype.flatmap: 1.3.1
array.prototype.tosorted: 1.1.1 array.prototype.tosorted: 1.1.1
doctrine: 2.1.0 doctrine: 2.1.0
eslint: 8.32.0 eslint: 8.33.0
estraverse: 5.3.0 estraverse: 5.3.0
jsx-ast-utils: 3.3.3 jsx-ast-utils: 3.3.3
minimatch: 3.1.2 minimatch: 3.1.2
@ -4108,13 +4118,13 @@ packages:
estraverse: 5.3.0 estraverse: 5.3.0
dev: true dev: true
/eslint-utils/[email protected]2.0: /eslint-utils/[email protected]3.0:
resolution: {integrity: sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==} resolution: {integrity: sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==}
engines: {node: ^10.0.0 || ^12.0.0 || >= 14.0.0} engines: {node: ^10.0.0 || ^12.0.0 || >= 14.0.0}
peerDependencies: peerDependencies:
eslint: '>=5' eslint: '>=5'
dependencies: dependencies:
eslint: 8.32.0 eslint: 8.33.0
eslint-visitor-keys: 2.1.0 eslint-visitor-keys: 2.1.0
dev: true dev: true
@ -4128,8 +4138,8 @@ packages:
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
dev: true dev: true
/eslint/8.32.0: /eslint/8.33.0:
resolution: {integrity: sha512-nETVXpnthqKPFyuY2FNjz/bEd6nbosRgKbkgS/y1C7LJop96gYHWpiguLecMHQ2XCPxn77DS0P+68WzG6vkZSQ==} resolution: {integrity: sha512-WjOpFQgKK8VrCnAtl8We0SUOy/oVZ5NHykyMiagV1M9r8IFpIJX7DduK6n1mpfhlG7T1NLWm2SuD8QB7KFySaA==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
hasBin: true hasBin: true
dependencies: dependencies:
@ -4144,7 +4154,7 @@ packages:
doctrine: 3.0.0 doctrine: 3.0.0
escape-string-regexp: 4.0.0 escape-string-regexp: 4.0.0
eslint-scope: 7.1.1 eslint-scope: 7.1.1
eslint-utils: 3.0[email protected]2.0 eslint-utils: 3.0[email protected]3.0
eslint-visitor-keys: 3.3.0 eslint-visitor-keys: 3.3.0
espree: 9.4.1 espree: 9.4.1
esquery: 1.4.0 esquery: 1.4.0
@ -4153,7 +4163,7 @@ packages:
file-entry-cache: 6.0.1 file-entry-cache: 6.0.1
find-up: 5.0.0 find-up: 5.0.0
glob-parent: 6.0.2 glob-parent: 6.0.2
globals: 13.19.0 globals: 13.20.0
grapheme-splitter: 1.0.4 grapheme-splitter: 1.0.4
ignore: 5.2.4 ignore: 5.2.4
import-fresh: 3.3.0 import-fresh: 3.3.0
@ -4446,8 +4456,8 @@ packages:
engines: {node: '>=4'} engines: {node: '>=4'}
dev: true dev: true
/globals/13.19.0: /globals/13.20.0:
resolution: {integrity: sha512-dkQ957uSRWHw7CFXLUtUHQI3g3aWApYhfNR2O6jn/907riyTYKVBmxYVROkBcY614FSSeSJh7Xm7SrUWCxvJMQ==} resolution: {integrity: sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==}
engines: {node: '>=8'} engines: {node: '>=8'}
dependencies: dependencies:
type-fest: 0.20.2 type-fest: 0.20.2
@ -4588,8 +4598,8 @@ packages:
engines: {node: '>= 4'} engines: {node: '>= 4'}
dev: true dev: true
/immer/9.0.18: /immer/9.0.19:
resolution: {integrity: sha512-eAPNpsj7Ax1q6Y/3lm2PmlwRcFzpON7HSNQ3ru5WQH1/PSpnyed/HpNOELl2CxLKoj4r+bAHgdyKqW5gc2Se1A==} resolution: {integrity: sha512-eY+Y0qcsB4TZKwgQzLaE/lqYMlKhv5J9dyd2RhhtGhNo2njPXDqU9XPfcNfa3MIDsdtZt5KlkIsirlo4dHsWdQ==}
dev: false dev: false
/import-fresh/3.3.0: /import-fresh/3.3.0:
@ -5887,8 +5897,8 @@ packages:
fsevents: 2.3.2 fsevents: 2.3.2
dev: true dev: true
/rollup/3.10.1: /rollup/3.12.0:
resolution: {integrity: sha512-3Er+yel3bZbZX1g2kjVM+FW+RUWDxbG87fcqFM5/9HbPCTpbVp6JOLn7jlxnNlbu7s/N/uDA4EV/91E2gWnxzw==} resolution: {integrity: sha512-4MZ8kA2HNYahIjz63rzrMMRvDqQDeS9LoriJvMuV0V6zIGysP36e9t4yObUfwdT9h/szXoHQideICftcdZklWg==}
engines: {node: '>=14.18.0', npm: '>=8.0.0'} engines: {node: '>=14.18.0', npm: '>=8.0.0'}
hasBin: true hasBin: true
optionalDependencies: optionalDependencies:
@ -6148,12 +6158,12 @@ packages:
resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
engines: {node: '>= 0.4'} engines: {node: '>= 0.4'}
/synckit/0.8.4: /synckit/0.8.5:
resolution: {integrity: sha512-Dn2ZkzMdSX827QbowGbU/4yjWuvNaCoScLLoMo/yKbu+P4GBR6cRGKZH27k6a9bRzdqcyd1DE96pQtQ6uNkmyw==} resolution: {integrity: sha512-L1dapNV6vu2s/4Sputv8xGsCdAVlb5nRDMFU/E27D44l5U6cw1g0dGd45uLc+OXjNMmF4ntiMdCimzcjFKQI8Q==}
engines: {node: ^14.18.0 || >=16.0.0} engines: {node: ^14.18.0 || >=16.0.0}
dependencies: dependencies:
'@pkgr/utils': 2.3.1 '@pkgr/utils': 2.3.1
tslib: 2.4.1 tslib: 2.5.0
dev: true dev: true
/tailwindcss/[email protected]: /tailwindcss/[email protected]:
@ -6325,8 +6335,8 @@ packages:
resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==}
dev: true dev: true
/tslib/2.4.1: /tslib/2.5.0:
resolution: {integrity: sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==} resolution: {integrity: sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==}
dev: true dev: true
/tslog/4.7.1: /tslog/4.7.1:
@ -6484,11 +6494,11 @@ packages:
peerDependencies: peerDependencies:
vite: ^3.1.0 || ^4.0.0 vite: ^3.1.0 || ^4.0.0
dependencies: dependencies:
'@rollup/plugin-replace': 5.0[email protected]0.1 '@rollup/plugin-replace': 5.0[email protected]2.0
debug: 4.3.4 debug: 4.3.4
fast-glob: 3.2.12 fast-glob: 3.2.12
pretty-bytes: 6.0.0 pretty-bytes: 6.0.0
rollup: 3.10.1 rollup: 3.12.0
vite: 4.0.4_@[email protected] vite: 4.0.4_@[email protected]
workbox-build: 6.5.4 workbox-build: 6.5.4
workbox-window: 6.5.4 workbox-window: 6.5.4
@ -6526,7 +6536,7 @@ packages:
esbuild: 0.16.17 esbuild: 0.16.17
postcss: 8.4.21 postcss: 8.4.21
resolve: 1.22.1 resolve: 1.22.1
rollup: 3.10.1 rollup: 3.12.0
optionalDependencies: optionalDependencies:
fsevents: 2.3.2 fsevents: 2.3.2
dev: true dev: true
@ -6810,7 +6820,7 @@ packages:
engines: {node: '>=10'} engines: {node: '>=10'}
dev: true dev: true
/zustand/[email protected]8[email protected]: /zustand/[email protected]9[email protected]:
resolution: {integrity: sha512-rd4haDmlwMTVWVqwvgy00ny8rtti/klRoZjFbL/MAcDnmD5qSw/RZc+Vddstdv90M5Lv6RPgWvm1Hivyn0QgJw==} resolution: {integrity: sha512-rd4haDmlwMTVWVqwvgy00ny8rtti/klRoZjFbL/MAcDnmD5qSw/RZc+Vddstdv90M5Lv6RPgWvm1Hivyn0QgJw==}
engines: {node: '>=12.7.0'} engines: {node: '>=12.7.0'}
peerDependencies: peerDependencies:
@ -6822,7 +6832,7 @@ packages:
react: react:
optional: true optional: true
dependencies: dependencies:
immer: 9.0.18 immer: 9.0.19
react: 18.2.0 react: 18.2.0
use-sync-external-store: 1.2[email protected] use-sync-external-store: 1.2[email protected]
dev: false dev: false

41
src/components/PageComponents/Config/Bluetooth.tsx

@ -15,7 +15,7 @@ import { classValidatorResolver } from "@hookform/resolvers/class-validator";
import { Protobuf } from "@meshtastic/meshtasticjs"; import { Protobuf } from "@meshtastic/meshtasticjs";
export const Bluetooth = (): JSX.Element => { export const Bluetooth = (): JSX.Element => {
const { config, connection, setConfig } = useDevice(); const { config, setWorkingConfig } = useDevice();
const { const {
register, register,
@ -24,6 +24,7 @@ export const Bluetooth = (): JSX.Element => {
control, control,
reset reset
} = useForm<BluetoothValidation>({ } = useForm<BluetoothValidation>({
mode: "onChange",
defaultValues: config.bluetooth, defaultValues: config.bluetooth,
resolver: classValidatorResolver(BluetoothValidation) resolver: classValidatorResolver(BluetoothValidation)
}); });
@ -33,34 +34,14 @@ export const Bluetooth = (): JSX.Element => {
}, [reset, config.bluetooth]); }, [reset, config.bluetooth]);
const onSubmit = handleSubmit((data) => { const onSubmit = handleSubmit((data) => {
if (connection) { setWorkingConfig(
void toast.promise( new Protobuf.Config({
connection payloadVariant: {
.setConfig( case: "bluetooth",
new Protobuf.Config({ value: data
payloadVariant: {
case: "bluetooth",
value: data
}
})
)
.then(() =>
setConfig(
new Protobuf.Config({
payloadVariant: {
case: "bluetooth",
value: data
}
})
)
),
{
loading: "Saving...",
success: "Saved Bluetooth Config, Restarting Node",
error: "No response received"
} }
); })
} );
}); });
const pairingMode = useWatch({ const pairingMode = useWatch({
@ -70,9 +51,7 @@ export const Bluetooth = (): JSX.Element => {
}); });
return ( return (
<Form <Form onSubmit={onSubmit}>
onSubmit={onSubmit}
>
<Controller <Controller
name="enabled" name="enabled"
control={control} control={control}

41
src/components/PageComponents/Config/Device.tsx

@ -15,7 +15,7 @@ import { classValidatorResolver } from "@hookform/resolvers/class-validator";
import { Protobuf } from "@meshtastic/meshtasticjs"; import { Protobuf } from "@meshtastic/meshtasticjs";
export const Device = (): JSX.Element => { export const Device = (): JSX.Element => {
const { config, connection, setConfig } = useDevice(); const { config, setWorkingConfig } = useDevice();
const { const {
register, register,
handleSubmit, handleSubmit,
@ -23,6 +23,7 @@ export const Device = (): JSX.Element => {
control, control,
reset reset
} = useForm<DeviceValidation>({ } = useForm<DeviceValidation>({
mode: "onChange",
defaultValues: config.device, defaultValues: config.device,
resolver: classValidatorResolver(DeviceValidation) resolver: classValidatorResolver(DeviceValidation)
}); });
@ -32,40 +33,18 @@ export const Device = (): JSX.Element => {
}, [reset, config.device]); }, [reset, config.device]);
const onSubmit = handleSubmit((data) => { const onSubmit = handleSubmit((data) => {
if (connection) { setWorkingConfig(
void toast.promise( new Protobuf.Config({
connection payloadVariant: {
.setConfig( case: "device",
new Protobuf.Config({ value: data
payloadVariant: {
case: "device",
value: data
}
})
)
.then(() =>
setConfig(
new Protobuf.Config({
payloadVariant: {
case: "device",
value: data
}
})
)
),
{
loading: "Saving...",
success: "Saved Device Config, Restarting Node",
error: "No response received"
} }
); })
} );
}); });
return ( return (
<Form <Form onSubmit={onSubmit}>
onSubmit={onSubmit}
>
<Select <Select
label="Role" label="Role"
description="What role the device performs on the mesh" description="What role the device performs on the mesh"

51
src/components/PageComponents/Config/Display.tsx

@ -7,7 +7,7 @@ import { toast } from "react-hot-toast";
import { Input } from "@app/components/form/Input.js"; import { Input } from "@app/components/form/Input.js";
import { Select } from "@app/components/form/Select.js"; import { Select } from "@app/components/form/Select.js";
import { Toggle } from "@app/components/form/Toggle.js"; import { Toggle } from "@app/components/form/Toggle.js";
import type { DisplayValidation } from "@app/validation/config/display.js"; import { DisplayValidation } from "@app/validation/config/display.js";
import { Form } from "@components/form/Form"; import { Form } from "@components/form/Form";
import { useDevice } from "@core/providers/useDevice.js"; import { useDevice } from "@core/providers/useDevice.js";
import { renderOptions } from "@core/utils/selectEnumOptions.js"; import { renderOptions } from "@core/utils/selectEnumOptions.js";
@ -15,7 +15,7 @@ import { classValidatorResolver } from "@hookform/resolvers/class-validator";
import { Protobuf } from "@meshtastic/meshtasticjs"; import { Protobuf } from "@meshtastic/meshtasticjs";
export const Display = (): JSX.Element => { export const Display = (): JSX.Element => {
const { config, connection, setConfig } = useDevice(); const { config, setWorkingConfig } = useDevice();
const { const {
register, register,
handleSubmit, handleSubmit,
@ -23,43 +23,24 @@ export const Display = (): JSX.Element => {
reset, reset,
control control
} = useForm<DisplayValidation>({ } = useForm<DisplayValidation>({
defaultValues: config.display mode: "onChange",
// resolver: classValidatorResolver(DisplayValidation) defaultValues: config.display,
resolver: classValidatorResolver(DisplayValidation)
}); });
// useEffect(() => { useEffect(() => {
// reset(config.display); reset(config.display);
// }, [reset, config.display]); }, [reset, config.display]);
const onSubmit = handleSubmit((data) => { const onSubmit = handleSubmit((data) => {
// if (connection) { setWorkingConfig(
// void toast.promise( new Protobuf.Config({
// connection payloadVariant: {
// .setConfig( case: "display",
// new Protobuf.Config({ value: data
// payloadVariant: { }
// case: "display", })
// value: data );
// }
// })
// )
// .then(() =>
// setConfig(
// new Protobuf.Config({
// payloadVariant: {
// case: "display",
// value: data
// }
// })
// )
// ),
// {
// loading: "Saving...",
// success: "Saved Display Config, Restarting Node",
// error: "No response received"
// }
// );
// }
}); });
return ( return (

41
src/components/PageComponents/Config/LoRa.tsx

@ -16,7 +16,7 @@ import { classValidatorResolver } from "@hookform/resolvers/class-validator";
import { Protobuf } from "@meshtastic/meshtasticjs"; import { Protobuf } from "@meshtastic/meshtasticjs";
export const LoRa = (): JSX.Element => { export const LoRa = (): JSX.Element => {
const { config, connection, setConfig } = useDevice(); const { config, setWorkingConfig } = useDevice();
const { const {
register, register,
@ -25,6 +25,7 @@ export const LoRa = (): JSX.Element => {
control, control,
reset reset
} = useForm<LoRaValidation>({ } = useForm<LoRaValidation>({
mode: "onChange",
defaultValues: config.lora, defaultValues: config.lora,
resolver: classValidatorResolver(LoRaValidation) resolver: classValidatorResolver(LoRaValidation)
}); });
@ -40,40 +41,18 @@ export const LoRa = (): JSX.Element => {
}, [reset, config.lora]); }, [reset, config.lora]);
const onSubmit = handleSubmit((data) => { const onSubmit = handleSubmit((data) => {
if (connection) { setWorkingConfig(
void toast.promise( new Protobuf.Config({
connection payloadVariant: {
.setConfig( case: "lora",
new Protobuf.Config({ value: data
payloadVariant: {
case: "lora",
value: data
}
})
)
.then(() =>
setConfig(
new Protobuf.Config({
payloadVariant: {
case: "lora",
value: data
}
})
)
),
{
loading: "Saving...",
success: "Saved LoRa Config, Restarting Node",
error: "No response received"
} }
); })
} );
}); });
return ( return (
<Form <Form onSubmit={onSubmit}>
onSubmit={onSubmit}
>
<FormSection title="Modem Settings"> <FormSection title="Modem Settings">
<Controller <Controller
name="usePreset" name="usePreset"

47
src/components/PageComponents/Config/Network.tsx

@ -18,7 +18,7 @@ import { classValidatorResolver } from "@hookform/resolvers/class-validator";
import { Protobuf } from "@meshtastic/meshtasticjs"; import { Protobuf } from "@meshtastic/meshtasticjs";
export const Network = (): JSX.Element => { export const Network = (): JSX.Element => {
const { config, connection, setConfig } = useDevice(); const { config, setWorkingConfig } = useDevice();
const { const {
register, register,
handleSubmit, handleSubmit,
@ -26,6 +26,7 @@ export const Network = (): JSX.Element => {
control, control,
reset reset
} = useForm<NetworkValidation>({ } = useForm<NetworkValidation>({
mode: "onChange",
defaultValues: config.network, defaultValues: config.network,
resolver: classValidatorResolver(NetworkValidation) resolver: classValidatorResolver(NetworkValidation)
}); });
@ -53,40 +54,18 @@ export const Network = (): JSX.Element => {
}, [reset, config.network]); }, [reset, config.network]);
const onSubmit = handleSubmit((data) => { const onSubmit = handleSubmit((data) => {
if (connection) { setWorkingConfig(
void toast.promise( new Protobuf.Config({
connection payloadVariant: {
.setConfig( case: "network",
new Protobuf.Config({ value: data
payloadVariant: {
case: "network",
value: new Protobuf.Config_NetworkConfig(data)
}
})
)
.then(() =>
setConfig(
new Protobuf.Config({
payloadVariant: {
case: "network",
value: data
}
})
)
),
{
loading: "Saving...",
success: "Saved Network Config, Restarting Node",
error: "No response received"
} }
); })
} );
}); });
return ( return (
<Form <Form onSubmit={onSubmit}>
onSubmit={onSubmit}
>
<ErrorMessage errors={errors} name="wifiEnabled" /> <ErrorMessage errors={errors} name="wifiEnabled" />
<ErrorMessage errors={errors} name="wifiMode" /> <ErrorMessage errors={errors} name="wifiMode" />
<ErrorMessage errors={errors} name="wifiSsid" /> <ErrorMessage errors={errors} name="wifiSsid" />
@ -190,6 +169,12 @@ export const Network = (): JSX.Element => {
error={errors.ntpServer?.message} error={errors.ntpServer?.message}
{...register("ntpServer")} {...register("ntpServer")}
/> />
<Input
label="Rsyslog Server"
description="Rsyslog server for external logging"
error={errors.rsyslogServer?.message}
{...register("rsyslogServer")}
/>
</Form> </Form>
); );
}; };

106
src/components/PageComponents/Config/Position.tsx

@ -15,7 +15,7 @@ import { classValidatorResolver } from "@hookform/resolvers/class-validator";
import { Protobuf } from "@meshtastic/meshtasticjs"; import { Protobuf } from "@meshtastic/meshtasticjs";
export const Position = (): JSX.Element => { export const Position = (): JSX.Element => {
const { config, connection, nodes, hardware, setConfig } = useDevice(); const { config, nodes, hardware, setWorkingConfig } = useDevice();
const myNode = nodes.find((n) => n.data.num === hardware.myNodeNum); const myNode = nodes.find((n) => n.data.num === hardware.myNodeNum);
@ -26,6 +26,7 @@ export const Position = (): JSX.Element => {
reset, reset,
control control
} = useForm<PositionValidation>({ } = useForm<PositionValidation>({
mode: "onChange",
defaultValues: { defaultValues: {
fixedAlt: myNode?.data.position?.altitude, fixedAlt: myNode?.data.position?.altitude,
fixedLat: (myNode?.data.position?.latitudeI ?? 0) / 1e7, fixedLat: (myNode?.data.position?.latitudeI ?? 0) / 1e7,
@ -58,58 +59,65 @@ export const Position = (): JSX.Element => {
new Protobuf.Config_PositionConfig(rest) new Protobuf.Config_PositionConfig(rest)
); );
if (connection) { setWorkingConfig(
void toast.promise( new Protobuf.Config({
connection payloadVariant: {
.setPosition( case: "position",
new Protobuf.Position({ value: rest
altitude: fixedAlt,
latitudeI: fixedLat * 1e7,
longitudeI: fixedLng * 1e7
})
)
.then(() => reset({ ...data })),
{
loading: "Saving...",
success: "Saved Position Config, Restarting Node",
error: "No response received"
} }
); })
if (configHasChanged) { );
void toast.promise(
connection // if (connection) {
.setConfig( // void toast.promise(
new Protobuf.Config({ // connection
payloadVariant: { // .setPosition(
case: "position", // new Protobuf.Position({
value: rest // altitude: fixedAlt,
} // latitudeI: fixedLat * 1e7,
}) // longitudeI: fixedLng * 1e7
) // })
.then(() => // )
setConfig( // .then(() => reset({ ...data })),
new Protobuf.Config({ // {
payloadVariant: { // loading: "Saving...",
case: "position", // success: "Saved Position Config, Restarting Node",
value: rest // error: "No response received"
} // }
}) // );
) // if (configHasChanged) {
), // void toast.promise(
{ // connection
loading: "Saving...", // .setConfig(
success: "Saved Position Config, Restarting Node", // new Protobuf.Config({
error: "No response received" // payloadVariant: {
} // case: "position",
); // value: rest
} // }
} // })
// )
// .then(() =>
// setConfig(
// new Protobuf.Config({
// payloadVariant: {
// case: "position",
// value: rest
// }
// })
// )
// ),
// {
// loading: "Saving...",
// success: "Saved Position Config, Restarting Node",
// error: "No response received"
// }
// );
// }
// }
}); });
return ( return (
<Form <Form onSubmit={onSubmit}>
onSubmit={onSubmit}
>
<Controller <Controller
name="gpsEnabled" name="gpsEnabled"
control={control} control={control}

41
src/components/PageComponents/Config/Power.tsx

@ -14,7 +14,7 @@ import { classValidatorResolver } from "@hookform/resolvers/class-validator";
import { Protobuf } from "@meshtastic/meshtasticjs"; import { Protobuf } from "@meshtastic/meshtasticjs";
export const Power = (): JSX.Element => { export const Power = (): JSX.Element => {
const { config, connection, setConfig } = useDevice(); const { config, setWorkingConfig } = useDevice();
const { const {
register, register,
handleSubmit, handleSubmit,
@ -22,6 +22,7 @@ export const Power = (): JSX.Element => {
reset, reset,
control control
} = useForm<PowerValidation>({ } = useForm<PowerValidation>({
mode: "onChange",
defaultValues: config.power, defaultValues: config.power,
resolver: classValidatorResolver(PowerValidation) resolver: classValidatorResolver(PowerValidation)
}); });
@ -31,40 +32,18 @@ export const Power = (): JSX.Element => {
}, [reset, config.power]); }, [reset, config.power]);
const onSubmit = handleSubmit((data) => { const onSubmit = handleSubmit((data) => {
if (connection) { setWorkingConfig(
void toast.promise( new Protobuf.Config({
connection payloadVariant: {
.setConfig( case: "power",
new Protobuf.Config({ value: data
payloadVariant: {
case: "power",
value: data
}
})
)
.then(() =>
setConfig(
new Protobuf.Config({
payloadVariant: {
case: "power",
value: data
}
})
)
),
{
loading: "Saving...",
success: "Saved Power Config, Restarting Node",
error: "No response received"
} }
); })
} );
}); });
return ( return (
<Form <Form onSubmit={onSubmit}>
onSubmit={onSubmit}
>
<Input <Input
label="Shutdown on battery delay" label="Shutdown on battery delay"
description="Automatically shutdown node after this long when on battery, 0 for indefinite" description="Automatically shutdown node after this long when on battery, 0 for indefinite"

1
src/components/Sidebar.tsx

@ -12,6 +12,7 @@ import { CommandLineIcon } from "@heroicons/react/24/outline";
import { Types } from "@meshtastic/meshtasticjs"; import { Types } from "@meshtastic/meshtasticjs";
import { Input } from "./form/Input.js"; import { Input } from "./form/Input.js";
import { Button } from "./form/Button.js";
export const Sidebar = (): JSX.Element => { export const Sidebar = (): JSX.Element => {
const { removeDevice } = useDeviceStore(); const { removeDevice } = useDeviceStore();

3
src/components/form/Form.tsx

@ -2,7 +2,7 @@ import type React from "react";
import type { HTMLProps } from "react"; import type { HTMLProps } from "react";
export interface FormProps extends HTMLProps<HTMLFormElement> { export interface FormProps extends HTMLProps<HTMLFormElement> {
onSubmit: (event: React.FormEvent<HTMLFormElement>) => Promise<void>; onSubmit?: (event: React.FormEvent<HTMLFormElement>) => Promise<void>;
} }
export const Form = ({ export const Form = ({
@ -14,6 +14,7 @@ export const Form = ({
<form <form
className="mr-2 w-full rounded-md bg-backgroundSecondary px-2" className="mr-2 w-full rounded-md bg-backgroundSecondary px-2"
onSubmit={onSubmit} onSubmit={onSubmit}
onChange={onSubmit}
{...props} {...props}
> >
<div className="flex flex-col gap-3 p-4">{children}</div> <div className="flex flex-col gap-3 p-4">{children}</div>

58
src/core/stores/deviceStore.ts

@ -52,16 +52,6 @@ export interface processPacketParams {
time: number; time: number;
} }
export type WorkingConfig = [
Protobuf.Config_DeviceConfig?,
Protobuf.Config_PositionConfig?,
Protobuf.Config_PowerConfig?,
Protobuf.Config_NetworkConfig?,
Protobuf.Config_DisplayConfig?,
Protobuf.Config_LoRaConfig?,
Protobuf.Config_BluetoothConfig?
];
export type DialogVariant = "import" | "QR" | "shutdown" | "reboot"; export type DialogVariant = "import" | "QR" | "shutdown" | "reboot";
export interface Device { export interface Device {
@ -71,6 +61,8 @@ export interface Device {
channels: Channel[]; channels: Channel[];
config: Protobuf.LocalConfig; config: Protobuf.LocalConfig;
moduleConfig: Protobuf.LocalModuleConfig; moduleConfig: Protobuf.LocalModuleConfig;
workingConfig: Protobuf.Config[];
workingModuleConfig: Protobuf.ModuleConfig[];
hardware: Protobuf.MyNodeInfo; hardware: Protobuf.MyNodeInfo;
nodes: Node[]; nodes: Node[];
connection?: Types.ConnectionType; connection?: Types.ConnectionType;
@ -82,7 +74,6 @@ export interface Device {
currentMetrics: Protobuf.DeviceMetrics; currentMetrics: Protobuf.DeviceMetrics;
pendingSettingsChanges: boolean; pendingSettingsChanges: boolean;
messageDraft: string; messageDraft: string;
workingConfig: WorkingConfig;
dialog: { dialog: {
import: boolean; import: boolean;
QR: boolean; QR: boolean;
@ -94,6 +85,8 @@ export interface Device {
setStatus: (status: Types.DeviceStatusEnum) => void; setStatus: (status: Types.DeviceStatusEnum) => void;
setConfig: (config: Protobuf.Config) => void; setConfig: (config: Protobuf.Config) => void;
setModuleConfig: (config: Protobuf.ModuleConfig) => void; setModuleConfig: (config: Protobuf.ModuleConfig) => void;
setWorkingConfig: (config: Protobuf.Config) => void;
setWorkingModuleConfig: (config: Protobuf.ModuleConfig) => void;
setHardware: (hardware: Protobuf.MyNodeInfo) => void; setHardware: (hardware: Protobuf.MyNodeInfo) => void;
setMetrics: (metrics: Types.PacketMetadata<Protobuf.Telemetry>) => void; setMetrics: (metrics: Types.PacketMetadata<Protobuf.Telemetry>) => void;
setActivePage: (page: Page) => void; setActivePage: (page: Page) => void;
@ -145,6 +138,8 @@ export const useDeviceStore = create<DeviceState>((set, get) => ({
channels: [], channels: [],
config: new Protobuf.LocalConfig(), config: new Protobuf.LocalConfig(),
moduleConfig: new Protobuf.LocalModuleConfig(), moduleConfig: new Protobuf.LocalModuleConfig(),
workingConfig: [],
workingModuleConfig: [],
hardware: new Protobuf.MyNodeInfo(), hardware: new Protobuf.MyNodeInfo(),
nodes: [], nodes: [],
connection: undefined, connection: undefined,
@ -162,7 +157,6 @@ export const useDeviceStore = create<DeviceState>((set, get) => ({
}, },
pendingSettingsChanges: false, pendingSettingsChanges: false,
messageDraft: "", messageDraft: "",
workingConfig: [],
setReady: (ready: boolean) => { setReady: (ready: boolean) => {
set( set(
@ -260,6 +254,46 @@ export const useDeviceStore = create<DeviceState>((set, get) => ({
}) })
); );
}, },
setWorkingConfig: (config: Protobuf.Config) => {
set(
produce<DeviceState>((draft) => {
const device = draft.devices.get(id);
if (!device) {
return;
}
const workingConfigIndex = device?.workingConfig.findIndex(
(wc) => wc.payloadVariant.case === config.payloadVariant.case
);
if (workingConfigIndex !== -1) {
device.workingConfig[workingConfigIndex] = config;
} else {
device?.workingConfig.push(config);
}
})
);
},
setWorkingModuleConfig: (moduleConfig: Protobuf.ModuleConfig) => {
set(
produce<DeviceState>((draft) => {
const device = draft.devices.get(id);
if (!device) {
return;
}
const workingModuleConfigIndex =
device?.workingModuleConfig.findIndex(
(wmc) =>
wmc.payloadVariant.case ===
moduleConfig.payloadVariant.case
);
if (workingModuleConfigIndex !== -1) {
device.workingModuleConfig[workingModuleConfigIndex] =
moduleConfig;
} else {
device?.workingModuleConfig.push(moduleConfig);
}
})
);
},
setHardware: (hardware: Protobuf.MyNodeInfo) => { setHardware: (hardware: Protobuf.MyNodeInfo) => {
set( set(
produce<DeviceState>((draft) => { produce<DeviceState>((draft) => {

18
src/pages/Config/DeviceConfig.tsx

@ -16,7 +16,7 @@ import { Button } from "@app/components/form/Button.js";
import { CheckIcon } from "@primer/octicons-react"; import { CheckIcon } from "@primer/octicons-react";
export const DeviceConfig = (): JSX.Element => { export const DeviceConfig = (): JSX.Element => {
const { hardware } = useDevice(); const { hardware, workingConfig, connection } = useDevice();
const configSections = [ const configSections = [
{ {
@ -71,7 +71,17 @@ export const DeviceConfig = (): JSX.Element => {
))} ))}
</ol> </ol>
<div className="ml-auto"> <div className="ml-auto">
<Button iconBefore={<CheckIcon className="w-4" />}>Save</Button> <Button
onClick={async () => {
workingConfig.map(async (config) => {
await connection?.setConfig(config);
});
await connection?.commitEditSettings();
}}
iconBefore={<CheckIcon className="w-4" />}
>
Apply & Reboot
</Button>
</div> </div>
</div> </div>
@ -88,7 +98,9 @@ export const DeviceConfig = (): JSX.Element => {
}`} }`}
> >
{Config.label} {Config.label}
<span className="ml-auto bg-accent rounded-full px-3 text-textPrimary">3</span> <span className="ml-auto rounded-full bg-accent px-3 text-textPrimary">
3
</span>
</div> </div>
)} )}
</Tab> </Tab>

3
src/validation/config/lora.ts

@ -48,6 +48,9 @@ export class LoRaValidation
@IsBoolean() @IsBoolean()
overrideDutyCycle: boolean; overrideDutyCycle: boolean;
@IsBoolean()
sx126xRxBoostedGain: boolean;
@IsArray() @IsArray()
ignoreIncoming: number[]; ignoreIncoming: number[];
} }

2
src/validation/config/network.ts

@ -30,6 +30,8 @@ export class NetworkValidation
addressMode: Protobuf.Config_NetworkConfig_AddressMode; addressMode: Protobuf.Config_NetworkConfig_AddressMode;
ipv4Config: NetworkValidation_IpV4Config; ipv4Config: NetworkValidation_IpV4Config;
rsyslogServer: string;
} }
export class NetworkValidation_IpV4Config export class NetworkValidation_IpV4Config

Loading…
Cancel
Save