Browse Source

Required changes + consistency fixes

pull/2/head
Sacha Weatherstone 5 years ago
parent
commit
b000054596
  1. 6
      package.json
  2. 325
      pnpm-lock.yaml
  3. 28
      public/index.html
  4. 4
      public/site.webmanifest
  5. 4
      snowpack.config.mjs
  6. 4
      src/App.tsx
  7. 2
      src/components/generic/Button.tsx
  8. 8
      src/components/menu/Logo.tsx
  9. 5
      src/pages/About.tsx
  10. 18
      src/pages/NotFound.tsx
  11. 138
      src/pages/settings/Connection.tsx
  12. 2
      src/pages/settings/Device.tsx
  13. 84
      src/pages/settings/Interface.tsx
  14. 46
      src/pages/settings/Radio.tsx

6
package.json

@ -6,7 +6,7 @@
"scripts": {
"start": "NODE_ENV=development snowpack dev",
"build": "snowpack build",
"package": "gzipper c -i html,js,css,png,ico,svg,webmanifest build build/output && tar -cvf build/build.tar -C ./build/output/static/ $(ls ./build/output/static)",
"package": "gzipper c -i html,js,css,png,ico,svg,webmanifest build build/output && tar -cvf build/build.tar -C ./build/output/ $(ls ./build/output/)",
"format": "prettier --write 'src/**/*.{ts,tsx}'",
"lint": "eslint 'src/**/*.{ts,tsx}'"
},
@ -17,7 +17,7 @@
"@reduxjs/toolkit": "^1.6.2",
"apexcharts": "^3.28.3",
"boring-avatars": "^1.5.8",
"i18next": "^21.2.4",
"i18next": "^21.2.6",
"i18next-browser-languagedetector": "^6.1.2",
"moment": "^2.29.1",
"react": "^17.0.2",
@ -44,7 +44,7 @@
"@verypossible/eslint-config": "^1.6.1",
"autoprefixer": "^10.3.7",
"babel-plugin-module-resolver": "^4.1.0",
"eslint": "^7.32.0",
"eslint": "^8.0.0",
"eslint-config-prettier": "^8.3.0",
"eslint-import-resolver-babel-module": "^5.3.1",
"eslint-import-resolver-typescript": "^2.5.0",

325
pnpm-lock.yaml

@ -20,7 +20,7 @@ specifiers:
autoprefixer: ^10.3.7
babel-plugin-module-resolver: ^4.1.0
boring-avatars: ^1.5.8
eslint: ^7.32.0
eslint: ^8.0.0
eslint-config-prettier: ^8.3.0
eslint-import-resolver-babel-module: ^5.3.1
eslint-import-resolver-typescript: ^2.5.0
@ -28,7 +28,7 @@ specifiers:
eslint-plugin-react: ^7.26.1
eslint-plugin-react-hooks: ^4.2.0
gzipper: ^5.0.1
i18next: ^21.2.4
i18next: ^21.2.6
i18next-browser-languagedetector: ^6.1.2
moment: ^2.29.1
postcss: ^8.3.9
@ -54,7 +54,7 @@ dependencies:
'@reduxjs/toolkit': 1.6[email protected][email protected]
apexcharts: 3.28.3
boring-avatars: 1.5.8
i18next: 21.2.4
i18next: 21.2.6
i18next-browser-languagedetector: 6.1.2
moment: 2.29.1
react: 17.0.2
@ -62,7 +62,7 @@ dependencies:
react-dom: 17.0[email protected]
react-flags-select: 2.1[email protected][email protected]
react-hook-form: 7.17[email protected]
react-i18next: 11.12[email protected].4[email protected]
react-i18next: 11.12[email protected].6[email protected]
react-redux: 7.2[email protected][email protected]
type-route: 0.6.0
use-breakpoint: 2.0[email protected][email protected]
@ -76,18 +76,18 @@ devDependencies:
'@types/react-dom': 17.0.9
'@types/react-redux': 7.1.19
'@types/snowpack-env': 2.3.4
'@typescript-eslint/eslint-plugin': 4.33.0_d753869925cce96d3eb2141eeedafe57
'@typescript-eslint/parser': 4.33.0_eslint@7.32[email protected]
'@typescript-eslint/eslint-plugin': 4.33.0_09137341fc1e2b64b3a2a80b526ae803
'@typescript-eslint/parser': 4.33.0_eslint@8.0[email protected]
'@verypossible/eslint-config': 1.6[email protected]
autoprefixer: 10.3[email protected]
babel-plugin-module-resolver: 4.1.0
eslint: 7.32.0
eslint-config-prettier: 8.3.0_eslint@7.32.0
eslint: 8.0.0
eslint-config-prettier: 8.3.0_eslint@8.0.0
eslint-import-resolver-babel-module: 5.3.1_e51044130ac762fd207a8cd2109b5344
eslint-import-resolver-typescript: 2.5.0_b7a4de75e7d0094cbe979e30a9a325ab
eslint-plugin-import: 2.24.2_eslint@7.32.0
eslint-plugin-react: 7.26.1_eslint@7.32.0
eslint-plugin-react-hooks: 4.2.0_eslint@7.32.0
eslint-import-resolver-typescript: 2.5.0_4037f6cf62ed6e95b8492c2ccc3d744a
eslint-plugin-import: 2.24.2_eslint@8.0.0
eslint-plugin-react: 7.26.1_eslint@8.0.0
eslint-plugin-react-hooks: 4.2.0_eslint@8.0.0
gzipper: 5.0.1
postcss: 8.3.9
prettier: 2.4.1
@ -354,6 +354,23 @@ packages:
- supports-color
dev: true
/@eslint/eslintrc/1.0.2:
resolution: {integrity: sha512-x1ZXdEFsvTcnbTZgqcWUL9w2ybgZCw/qbKTPQnab+XnYA2bMQpJCh+/bBzCRfDJaJdlrrQlOk49jNtru9gL/6Q==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
dependencies:
ajv: 6.12.6
debug: 4.3.2
espree: 9.0.0
globals: 13.11.0
ignore: 4.0.6
import-fresh: 3.3.0
js-yaml: 3.14.1
minimatch: 3.0.4
strip-json-comments: 3.1.1
transitivePeerDependencies:
- supports-color
dev: true
/@gar/promisify/1.1.2:
resolution: {integrity: sha512-82cpyJyKRoQoRi+14ibCeGPu0CwypgtBAdBhq1WfvagpCZNKqwXbKwXllYSMG91DhmG4jt9gN8eP6lGOtozuaw==}
dev: true
@ -388,6 +405,17 @@ packages:
- supports-color
dev: true
/@humanwhocodes/config-array/0.6.0:
resolution: {integrity: sha512-JQlEKbcgEUjBFhLIF4iqM7u/9lwgHRBcpHrmUNCALK0Q3amXN6lxdoXLnF0sm11E9VqTmBALR87IlUg1bZ8A9A==}
engines: {node: '>=10.10.0'}
dependencies:
'@humanwhocodes/object-schema': 1.2.0
debug: 4.3.2
minimatch: 3.0.4
transitivePeerDependencies:
- supports-color
dev: true
/@humanwhocodes/object-schema/1.2.0:
resolution: {integrity: sha512-wdppn25U8z/2yiaT6YGquE6X8sSv7hNMWSXYSSU1jGv/yd6XqjXgTDJ8KP4NgjTXfJ3GbRjeeb8RTV7a/VpM+w==}
dev: true
@ -802,6 +830,32 @@ packages:
resolution: {integrity: sha512-zYzMb2aMyzXW5VgOQHy+FgI8N5tLFb+tIsUqk35CIgSr9pT4pji2GR8BCOTMdniusVuRHIp/DaYQNQGYGLVZHQ==}
dev: true
/@typescript-eslint/eslint-plugin/4.33.0_09137341fc1e2b64b3a2a80b526ae803:
resolution: {integrity: sha512-aINiAxGVdOl1eJyVjaWn/YcVAq4Gi/Yo35qHGCnqbWVz61g39D0h23veY/MA0rFFGfxK7TySg2uwDeNv+JgVpg==}
engines: {node: ^10.12.0 || >=12.0.0}
peerDependencies:
'@typescript-eslint/parser': ^4.0.0
eslint: ^5.0.0 || ^6.0.0 || ^7.0.0
typescript: '*'
peerDependenciesMeta:
typescript:
optional: true
dependencies:
'@typescript-eslint/experimental-utils': 4.33[email protected][email protected]
'@typescript-eslint/parser': 4.33[email protected][email protected]
'@typescript-eslint/scope-manager': 4.33.0
debug: 4.3.2
eslint: 8.0.0
functional-red-black-tree: 1.0.1
ignore: 5.1.8
regexpp: 3.2.0
semver: 7.3.5
tsutils: 3.21[email protected]
typescript: 4.4.3
transitivePeerDependencies:
- supports-color
dev: true
/@typescript-eslint/eslint-plugin/4.33.0_d753869925cce96d3eb2141eeedafe57:
resolution: {integrity: sha512-aINiAxGVdOl1eJyVjaWn/YcVAq4Gi/Yo35qHGCnqbWVz61g39D0h23veY/MA0rFFGfxK7TySg2uwDeNv+JgVpg==}
engines: {node: ^10.12.0 || >=12.0.0}
@ -846,6 +900,24 @@ packages:
- typescript
dev: true
/@typescript-eslint/experimental-utils/[email protected][email protected]:
resolution: {integrity: sha512-zeQjOoES5JFjTnAhI5QY7ZviczMzDptls15GFsI6jyUOq0kOf9+WonkhtlIhh0RgHRnqj5gdNxW5j1EvAyYg6Q==}
engines: {node: ^10.12.0 || >=12.0.0}
peerDependencies:
eslint: '*'
dependencies:
'@types/json-schema': 7.0.9
'@typescript-eslint/scope-manager': 4.33.0
'@typescript-eslint/types': 4.33.0
'@typescript-eslint/typescript-estree': 4.33[email protected]
eslint: 8.0.0
eslint-scope: 5.1.1
eslint-utils: 3.0[email protected]
transitivePeerDependencies:
- supports-color
- typescript
dev: true
/@typescript-eslint/parser/[email protected][email protected]:
resolution: {integrity: sha512-ZohdsbXadjGBSK0/r+d87X0SBmKzOq4/S5nzK6SBgJspFo9/CUDJ7hjayuze+JK7CZQLDMroqytp7pOcFKTxZA==}
engines: {node: ^10.12.0 || >=12.0.0}
@ -866,6 +938,26 @@ packages:
- supports-color
dev: true
/@typescript-eslint/parser/[email protected][email protected]:
resolution: {integrity: sha512-ZohdsbXadjGBSK0/r+d87X0SBmKzOq4/S5nzK6SBgJspFo9/CUDJ7hjayuze+JK7CZQLDMroqytp7pOcFKTxZA==}
engines: {node: ^10.12.0 || >=12.0.0}
peerDependencies:
eslint: ^5.0.0 || ^6.0.0 || ^7.0.0
typescript: '*'
peerDependenciesMeta:
typescript:
optional: true
dependencies:
'@typescript-eslint/scope-manager': 4.33.0
'@typescript-eslint/types': 4.33.0
'@typescript-eslint/typescript-estree': 4.33[email protected]
debug: 4.3.2
eslint: 8.0.0
typescript: 4.4.3
transitivePeerDependencies:
- supports-color
dev: true
/@typescript-eslint/scope-manager/4.33.0:
resolution: {integrity: sha512-5IfJHpgTsTZuONKbODctL4kKuQje/bzBRkwHE8UOZ4f89Zeddg+EGZs8PD8NcN4LdM3ygHWYB3ukPAYjvl/qbQ==}
engines: {node: ^8.10.0 || ^10.13.0 || >=11.10.1}
@ -940,6 +1032,14 @@ packages:
acorn: 7.4.1
dev: true
/acorn-jsx/[email protected]:
resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==}
peerDependencies:
acorn: ^6.0.0 || ^7.0.0 || ^8.0.0
dependencies:
acorn: 8.5.0
dev: true
/acorn-node/1.8.2:
resolution: {integrity: sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A==}
dependencies:
@ -959,6 +1059,12 @@ packages:
hasBin: true
dev: true
/acorn/8.5.0:
resolution: {integrity: sha512-yXbYeFy+jUuYd3/CDcg2NkIYE991XYX/bje7LmjJigUciaeO1JR4XxXgCIV1/Zc/dRuFEyw1L0pbA+qynJkW5Q==}
engines: {node: '>=0.4.0'}
hasBin: true
dev: true
/address/1.1.2:
resolution: {integrity: sha512-aT6camzM4xEA54YVJYSqxz1kv4IHnQZRtThJJHhUMRExaU5spC7jX5ugSwTaTgJliIgs4VhZOk7htClvQ/LmRA==}
engines: {node: '>= 0.12.0'}
@ -1079,6 +1185,10 @@ packages:
sprintf-js: 1.0.3
dev: true
/argparse/2.0.1:
resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==}
dev: true
/array-includes/3.1.4:
resolution: {integrity: sha512-ZTNSQkmWumEbiHO2GF4GmWxYVTiQyJy2XOTa15sdQSrvKn7l+180egQMqlrMOUMCyLMD7pmyQe4mMDUT6Behrw==}
engines: {node: '>= 0.4'}
@ -1254,7 +1364,7 @@ packages:
hasBin: true
dependencies:
caniuse-lite: 1.0.30001265
electron-to-chromium: 1.3.863
electron-to-chromium: 1.3.864
escalade: 3.1.1
node-releases: 1.1.77
picocolors: 0.2.1
@ -1375,7 +1485,7 @@ packages:
resolution: {integrity: sha512-qocaHPv5ypefh6YNxvnbABM07KMxExbtbfuJoIie3iZXX1ERwYmJcIiRrr9H05ucQP1k28dav8rpdDgjQd8drg==}
dependencies:
css-select: 4.1.3
css-what: 5.0.1
css-what: 5.1.0
domelementtype: 2.2.0
domhandler: 4.2.2
domutils: 2.8.0
@ -1567,7 +1677,7 @@ packages:
resolution: {integrity: sha512-gT3wBNd9Nj49rAbmtFHj1cljIAOLYSX1nZ8CB7TBO3INYckygm5B7LISU/szY//YmdiSLbJvDLOx9VnMVpMBxA==}
dependencies:
boolbase: 1.0.0
css-what: 5.0.1
css-what: 5.1.0
domhandler: 4.2.2
domutils: 2.8.0
nth-check: 2.0.1
@ -1577,8 +1687,8 @@ packages:
resolution: {integrity: sha512-IiJwMC8rdZE0+xiEZHeru6YoONC4rfPMqGm2W85jMIbkFvv5nFTwJVFHam2eFrN6txmoUYFAFXiv8ICVeTO0MA==}
dev: true
/css-what/5.0.1:
resolution: {integrity: sha512-FYDTSHb/7KXsWICVsxdmiExPjCfRC4qRFBdVwv7Ax9hMnvMmEjP9RfxTEZ3qPZGmADDn2vAKSo9UcN1jKVYscg==}
/css-what/5.1.0:
resolution: {integrity: sha512-arSMRWIIFY0hV8pIxZMEfmMI47Wj3R/aWpZDDxWYCPEiOMv6tfOrnpDtgxBYPEQD4V0Y/958+1TdC3iWTFcUPw==}
engines: {node: '>= 6'}
dev: true
@ -1804,8 +1914,8 @@ packages:
safer-buffer: 2.1.2
dev: true
/electron-to-chromium/1.3.863:
resolution: {integrity: sha512-C+dLP4xM1DCqvEUjtqCGhd6DJGnXq1t03QR2ZxEWUQPkaXxDlzPUyWsSh17LHLQBEfmBCRfTbA3LpjiVikWsxg==}
/electron-to-chromium/1.3.864:
resolution: {integrity: sha512-v4rbad8GO6/yVI92WOeU9Wgxc4NA0n4f6P1FvZTY+jyY7JHEhw3bduYu60v3Q1h81Cg6eo4ApZrFPuycwd5hGw==}
dev: true
/emoji-regex/8.0.0:
@ -1967,6 +2077,15 @@ packages:
eslint: 7.32.0
dev: true
/eslint-config-prettier/[email protected]:
resolution: {integrity: sha512-BgZuLUSeKzvlL/VUjx/Yb787VQ26RU3gGjA3iiFvdsp/2bMfVIWUVP7tjxtjS0e+HP409cPlPvNkQloz8C91ew==}
hasBin: true
peerDependencies:
eslint: '>=7.0.0'
dependencies:
eslint: 8.0.0
dev: true
/eslint-import-resolver-babel-module/5.3.1_e51044130ac762fd207a8cd2109b5344:
resolution: {integrity: sha512-WomQAkjO7lUNOdU3FG2zgNgylkoAVUmaw04bHgSpM9QrMWuOLLWa2qcP6CrsBd4VWuLRbUPyzrgBc9ZQIx9agw==}
engines: {node: '>=10.0.0'}
@ -1986,6 +2105,24 @@ packages:
resolve: 1.20.0
dev: true
/eslint-import-resolver-typescript/2.5.0_4037f6cf62ed6e95b8492c2ccc3d744a:
resolution: {integrity: sha512-qZ6e5CFr+I7K4VVhQu3M/9xGv9/YmwsEXrsm3nimw8vWaVHRDrQRp26BgCypTxBp3vUp4o5aVEJRiy0F2DFddQ==}
engines: {node: '>=4'}
peerDependencies:
eslint: '*'
eslint-plugin-import: '*'
dependencies:
debug: 4.3.2
eslint: 8.0.0
eslint-plugin-import: 2.24[email protected]
glob: 7.2.0
is-glob: 4.0.3
resolve: 1.20.0
tsconfig-paths: 3.11.0
transitivePeerDependencies:
- supports-color
dev: true
/eslint-import-resolver-typescript/2.5.0_b7a4de75e7d0094cbe979e30a9a325ab:
resolution: {integrity: sha512-qZ6e5CFr+I7K4VVhQu3M/9xGv9/YmwsEXrsm3nimw8vWaVHRDrQRp26BgCypTxBp3vUp4o5aVEJRiy0F2DFddQ==}
engines: {node: '>=4'}
@ -2036,6 +2173,30 @@ packages:
tsconfig-paths: 3.11.0
dev: true
/eslint-plugin-import/[email protected]:
resolution: {integrity: sha512-hNVtyhiEtZmpsabL4neEj+6M5DCLgpYyG9nzJY8lZQeQXEn5UPW1DpUdsMHMXsq98dbNm7nt1w9ZMSVpfJdi8Q==}
engines: {node: '>=4'}
peerDependencies:
eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0
dependencies:
array-includes: 3.1.4
array.prototype.flat: 1.2.5
debug: 2.6.9
doctrine: 2.1.0
eslint: 8.0.0
eslint-import-resolver-node: 0.3.6
eslint-module-utils: 2.6.2
find-up: 2.1.0
has: 1.0.3
is-core-module: 2.7.0
minimatch: 3.0.4
object.values: 1.1.5
pkg-up: 2.0.0
read-pkg-up: 3.0.0
resolve: 1.20.0
tsconfig-paths: 3.11.0
dev: true
/eslint-plugin-react-hooks/[email protected]:
resolution: {integrity: sha512-623WEiZJqxR7VdxFCKLI6d6LLpwJkGPYKODnkH3D7WpOG5KM8yWueBd8TLsNAetEJNF5iJmolaAKO3F8yzyVBQ==}
engines: {node: '>=10'}
@ -2045,6 +2206,15 @@ packages:
eslint: 7.32.0
dev: true
/eslint-plugin-react-hooks/[email protected]:
resolution: {integrity: sha512-623WEiZJqxR7VdxFCKLI6d6LLpwJkGPYKODnkH3D7WpOG5KM8yWueBd8TLsNAetEJNF5iJmolaAKO3F8yzyVBQ==}
engines: {node: '>=10'}
peerDependencies:
eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0
dependencies:
eslint: 8.0.0
dev: true
/eslint-plugin-react/[email protected]:
resolution: {integrity: sha512-Lug0+NOFXeOE+ORZ5pbsh6mSKjBKXDXItUD2sQoT+5Yl0eoT82DqnXeTMfUare4QVCn9QwXbfzO/dBLjLXwVjQ==}
engines: {node: '>=4'}
@ -2068,6 +2238,29 @@ packages:
string.prototype.matchall: 4.0.6
dev: true
/eslint-plugin-react/[email protected]:
resolution: {integrity: sha512-Lug0+NOFXeOE+ORZ5pbsh6mSKjBKXDXItUD2sQoT+5Yl0eoT82DqnXeTMfUare4QVCn9QwXbfzO/dBLjLXwVjQ==}
engines: {node: '>=4'}
peerDependencies:
eslint: ^3 || ^4 || ^5 || ^6 || ^7
dependencies:
array-includes: 3.1.4
array.prototype.flatmap: 1.2.5
doctrine: 2.1.0
eslint: 8.0.0
estraverse: 5.2.0
jsx-ast-utils: 3.2.1
minimatch: 3.0.4
object.entries: 1.1.5
object.fromentries: 2.0.5
object.hasown: 1.1.0
object.values: 1.1.5
prop-types: 15.7.2
resolve: 2.0.0-next.3
semver: 6.3.0
string.prototype.matchall: 4.0.6
dev: true
/eslint-scope/5.1.1:
resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==}
engines: {node: '>=8.0.0'}
@ -2076,6 +2269,14 @@ packages:
estraverse: 4.3.0
dev: true
/eslint-scope/6.0.0:
resolution: {integrity: sha512-uRDL9MWmQCkaFus8RF5K9/L/2fn+80yoW3jkD53l4shjCh26fCtvJGasxjUqP5OT87SYTxCVA3BwTUzuELx9kA==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
dependencies:
esrecurse: 4.3.0
estraverse: 5.2.0
dev: true
/eslint-utils/2.1.0:
resolution: {integrity: sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==}
engines: {node: '>=6'}
@ -2093,6 +2294,16 @@ packages:
eslint-visitor-keys: 2.1.0
dev: true
/eslint-utils/[email protected]:
resolution: {integrity: sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==}
engines: {node: ^10.0.0 || ^12.0.0 || >= 14.0.0}
peerDependencies:
eslint: '>=5'
dependencies:
eslint: 8.0.0
eslint-visitor-keys: 2.1.0
dev: true
/eslint-visitor-keys/1.3.0:
resolution: {integrity: sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==}
engines: {node: '>=4'}
@ -2103,6 +2314,11 @@ packages:
engines: {node: '>=10'}
dev: true
/eslint-visitor-keys/3.0.0:
resolution: {integrity: sha512-mJOZa35trBTb3IyRmo8xmKBZlxf+N7OnUl4+ZhJHs/r+0770Wh/LEACE2pqMGMe27G/4y8P2bYGk4J70IC5k1Q==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
dev: true
/eslint/7.32.0:
resolution: {integrity: sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA==}
engines: {node: ^10.12.0 || >=12.0.0}
@ -2152,6 +2368,53 @@ packages:
- supports-color
dev: true
/eslint/8.0.0:
resolution: {integrity: sha512-03spzPzMAO4pElm44m60Nj08nYonPGQXmw6Ceai/S4QK82IgwWO1EXx1s9namKzVlbVu3Jf81hb+N+8+v21/HQ==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
hasBin: true
dependencies:
'@eslint/eslintrc': 1.0.2
'@humanwhocodes/config-array': 0.6.0
ajv: 6.12.6
chalk: 4.1.2
cross-spawn: 7.0.3
debug: 4.3.2
doctrine: 3.0.0
enquirer: 2.3.6
escape-string-regexp: 4.0.0
eslint-scope: 6.0.0
eslint-utils: 3.0[email protected]
eslint-visitor-keys: 3.0.0
espree: 9.0.0
esquery: 1.4.0
esutils: 2.0.3
fast-deep-equal: 3.1.3
file-entry-cache: 6.0.1
functional-red-black-tree: 1.0.1
glob-parent: 6.0.2
globals: 13.11.0
ignore: 4.0.6
import-fresh: 3.3.0
imurmurhash: 0.1.4
is-glob: 4.0.3
js-yaml: 4.1.0
json-stable-stringify-without-jsonify: 1.0.1
levn: 0.4.1
lodash.merge: 4.6.2
minimatch: 3.0.4
natural-compare: 1.4.0
optionator: 0.9.1
progress: 2.0.3
regexpp: 3.2.0
semver: 7.3.5
strip-ansi: 6.0.1
strip-json-comments: 3.1.1
text-table: 0.2.0
v8-compile-cache: 2.3.0
transitivePeerDependencies:
- supports-color
dev: true
/espree/7.3.1:
resolution: {integrity: sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==}
engines: {node: ^10.12.0 || >=12.0.0}
@ -2161,6 +2424,15 @@ packages:
eslint-visitor-keys: 1.3.0
dev: true
/espree/9.0.0:
resolution: {integrity: sha512-r5EQJcYZ2oaGbeR0jR0fFVijGOcwai07/690YRXLINuhmVeRY4UKSAsQPe/0BNuDgwP7Ophoc1PRsr2E3tkbdQ==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
dependencies:
acorn: 8.5.0
acorn-jsx: 5.3[email protected]
eslint-visitor-keys: 3.0.0
dev: true
/esprima/4.0.1:
resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==}
engines: {node: '>=4'}
@ -2714,8 +2986,8 @@ packages:
'@babel/runtime': 7.15.4
dev: false
/i18next/21.2.4:
resolution: {integrity: sha512-+81XmiwJOLWJFjRZJK5ASFahAo5TXZGz5IrBT4CfLJ3CyXho61A1cj1Kmh8za8TYtGFou0cEkUSjEaqfya7Wfg==}
/i18next/21.2.6:
resolution: {integrity: sha512-xnCodgPo1ASLfdPs2/GS8jQFqQsaWrQKdsqfYgf5juANavIos4kjahgBkrMU8SUCn2kv7TSssfnyVu5LZjBWXw==}
dependencies:
'@babel/runtime': 7.15.4
dev: false
@ -3070,6 +3342,13 @@ packages:
esprima: 4.0.1
dev: true
/js-yaml/4.1.0:
resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==}
hasBin: true
dependencies:
argparse: 2.0.1
dev: true
/jsbn/0.1.1:
resolution: {integrity: sha1-peZUwuWi3rXyAdls77yoDA7y9RM=}
dev: true
@ -4277,7 +4556,7 @@ packages:
react: 17.0.2
dev: false
/react-i18next/[email protected].4[email protected]:
/react-i18next/[email protected].6[email protected]:
resolution: {integrity: sha512-M9BT+hqVG03ywrl+L7CK74ugK+4jIo7AeKJ17+g9BoqJz2+/aVbs8SIVXT4KMQ1rjIdcw+GcSRDy1CXjcz6tLQ==}
peerDependencies:
i18next: '>= 19.0.0'
@ -4285,7 +4564,7 @@ packages:
dependencies:
'@babel/runtime': 7.15.4
html-parse-stringify: 3.0.1
i18next: 21.2.4
i18next: 21.2.6
react: 17.0.2
dev: false

28
public/index.html

@ -2,26 +2,12 @@
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="shortcut icon" href="/static/favicon.ico" />
<link
rel="apple-touch-icon"
sizes="180x180"
href="/static/touch-icon.png"
/>
<link
rel="icon"
type="image/png"
sizes="32x32"
href="/static/favicon-32x32.png"
/>
<link
rel="icon"
type="image/png"
sizes="16x16"
href="/static/favicon-16x16.png"
/>
<link rel="manifest" href="/static/site.webmanifest" />
<link rel="mask-icon" href="/static/safari-tab.svg" color="#67ea94" />
<link rel="shortcut icon" href="/favicon.ico" />
<link rel="apple-touch-icon" sizes="180x180" href="/touch-icon.png" />
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png" />
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png" />
<link rel="manifest" href="/site.webmanifest" />
<link rel="mask-icon" href="/safari-tab.svg" color="#67ea94" />
<link href="https://rsms.me/inter/inter.css" rel="stylesheet" />
<link href="https://fonts.gstatic.com" rel="preconnect" />
@ -47,6 +33,6 @@
<body>
<div id="root"></div>
<noscript>You need to enable JavaScript to run this app.</noscript>
<script type="module" src="/static/index.js"></script>
<script type="module" src="/index.js"></script>
</body>
</html>

4
public/site.webmanifest

@ -5,12 +5,12 @@
"description": "Meshtastic web app",
"icons": [
{
"src": "/static/android-192.png",
"src": "/android-192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "/static/android-512.png",
"src": "/android-512.png",
"sizes": "512x512",
"type": "image/png"
}

4
snowpack.config.mjs

@ -1,8 +1,8 @@
/** @type {import("snowpack").SnowpackUserConfig } */
export default {
mount: {
public: { url: '/static' },
src: { url: '/static' },
public: { url: '/' },
src: { url: '/' },
},
plugins: [
'@snowpack/plugin-react-refresh',

4
src/App.tsx

@ -27,6 +27,8 @@ import { Messages } from '@pages/Messages';
import { Nodes } from '@pages/Nodes/Index';
import { Settings } from '@pages/settings/Index';
import { NotFound } from './pages/NotFound';
const App = (): JSX.Element => {
const dispatch = useAppDispatch();
const route = useRoute();
@ -159,7 +161,7 @@ const App = (): JSX.Element => {
{route.name === 'nodes' && <Nodes />}
{route.name === 'settings' && <Settings />}
{route.name === 'about' && <About />}
{route.name === false && 'Not Found'}
{route.name === false && <NotFound />}
</div>
</div>
</div>

2
src/components/generic/Button.tsx

@ -21,7 +21,7 @@ export const Button = ({
}: ButtonProps): JSX.Element => {
return (
<button
className={`items-center select-none flex dark:text-white ${
className={`items-center select-none flex dark:text-white active:scale-95 ${
active && !disabled ? 'bg-gray-100 dark:bg-gray-700' : ''
} ${
circle ? 'rounded-full h-10 w-10' : 'rounded-md p-3 space-x-3 text-sm'

8
src/components/menu/Logo.tsx

@ -3,15 +3,11 @@ import React from 'react';
export const Logo = (): JSX.Element => {
return (
<>
<img
title="Logo"
className="w-16 dark:hidden"
src="/static/Logo_Black.svg"
/>
<img title="Logo" className="w-16 dark:hidden" src="/Logo_Black.svg" />
<img
title="Logo"
className="hidden w-16 dark:flex"
src="/static/Logo_White.svg"
src="/Logo_White.svg"
/>
</>
);

5
src/pages/About.tsx

@ -1,11 +1,14 @@
import React from 'react';
import { Card } from '@app/components/generic/Card';
import { PrimaryTemplate } from '@components/templates/PrimaryTemplate';
export const About = (): JSX.Element => {
return (
<PrimaryTemplate title="meshtastic-web" tagline="About">
<p>Content</p>
<Card title="Project desc" description="...">
<p className="p-10">Content</p>
</Card>
</PrimaryTemplate>
);
};

18
src/pages/NotFound.tsx

@ -0,0 +1,18 @@
import React from 'react';
import { Card } from '@app/components/generic/Card';
import { PrimaryTemplate } from '@components/templates/PrimaryTemplate';
export const NotFound = (): JSX.Element => {
return (
<PrimaryTemplate title="Page not found" tagline="404">
<Card
title="The requested file or directory could not be found"
description="Better luck next time"
>
<br />
<br />
</Card>
</PrimaryTemplate>
);
};

138
src/pages/settings/Connection.tsx

@ -3,6 +3,7 @@ import React from 'react';
import { useForm } from 'react-hook-form';
import { useTranslation } from 'react-i18next';
import { Card } from '@app/components/generic/Card';
import { Input } from '@app/components/generic/Input';
import { Tabs } from '@app/components/generic/Tabs';
import { Toggle } from '@app/components/generic/Toggle';
@ -58,76 +59,81 @@ export const Connection = ({
</Button>
}
>
<div className="w-full max-w-3xl md:max-w-xl">
<div className="flex w-full p-2 mb-2 border dark:border-gray-600 rounded-3xl">
Current connection method:
<div className="px-1 my-auto ml-2 text-sm bg-gray-400 rounded-full dark:bg-primaryDark">
BLE
<Card
title="Basic settings"
description="Device name and user parameters"
>
<div className="w-full max-w-3xl p-10 md:max-w-xl">
<div className="flex w-full p-2 mb-2 border dark:border-gray-600 rounded-3xl">
Current connection method:
<div className="px-1 my-auto ml-2 text-sm bg-gray-400 rounded-full dark:bg-primaryDark">
BLE
</div>
</div>
</div>
<form className="space-y-2" onSubmit={onSubmit}>
<Tabs
className="h-60"
tabs={[
{
name: 'HTTP',
body: (
<div className="space-y-2">
<Input label={'Device URL'} />
<Toggle label="Use TLS?" />
</div>
),
},
{
name: 'Bluetooth',
body: (
<div className="space-y-2">
Devices:
<Button
onClick={async (): Promise<void> => {
console.log(await bleConnection.getDevices());
}}
>
Get Devices
</Button>
<div className="flex justify-between p-2 border rounded-3xl dark:border-600">
Device Name
<LinkIcon className="w-5 h-5 my-auto mr-2 text-gray-300" />
</div>
<div className="flex justify-between p-2 border rounded-3xl dark:border-600">
Device Name
<LinkIcon className="w-5 h-5 my-auto mr-2 text-gray-600" />
<form className="space-y-2" onSubmit={onSubmit}>
<Tabs
className="mb-10 h-60"
tabs={[
{
name: 'HTTP',
body: (
<div className="space-y-2">
<Input label={'Device URL'} />
<Toggle label="Use TLS?" />
</div>
</div>
),
},
{
name: 'Serial',
body: (
<div className="space-y-2">
Devices:
<Button
onClick={async (): Promise<void> => {
console.log(await serialConnection.getPorts());
}}
>
Get Devices
</Button>
<div className="flex justify-between p-2 border rounded-3xl dark:border-600">
Device Name
<LinkIcon className="w-5 h-5 my-auto mr-2 text-gray-300" />
),
},
{
name: 'Bluetooth',
body: (
<div className="space-y-2">
Devices:
<Button
onClick={async (): Promise<void> => {
console.log(await bleConnection.getDevices());
}}
>
Get Devices
</Button>
<div className="flex justify-between p-2 border rounded-3xl dark:border-600">
Device Name
<LinkIcon className="w-5 h-5 my-auto mr-2 text-gray-300" />
</div>
<div className="flex justify-between p-2 border rounded-3xl dark:border-600">
Device Name
<LinkIcon className="w-5 h-5 my-auto mr-2 text-gray-600" />
</div>
</div>
<div className="flex justify-between p-2 border rounded-3xl dark:border-600">
Device Name
<LinkIcon className="w-5 h-5 my-auto mr-2 text-gray-600" />
),
},
{
name: 'Serial',
body: (
<div className="space-y-2">
Devices:
<Button
onClick={async (): Promise<void> => {
console.log(await serialConnection.getPorts());
}}
>
Get Devices
</Button>
<div className="flex justify-between p-2 border rounded-3xl dark:border-600">
Device Name
<LinkIcon className="w-5 h-5 my-auto mr-2 text-gray-300" />
</div>
<div className="flex justify-between p-2 border rounded-3xl dark:border-600">
Device Name
<LinkIcon className="w-5 h-5 my-auto mr-2 text-gray-600" />
</div>
</div>
</div>
),
},
]}
/>
</form>
</div>
),
},
]}
/>
</form>
</div>
</Card>
</PrimaryTemplate>
);
};

2
src/pages/settings/Device.tsx

@ -67,7 +67,7 @@ export const Device = ({ navOpen, setNavOpen }: DeviceProps): JSX.Element => {
title="Basic settings"
description="Device name and user parameters"
>
<div className="p-10">
<div className="w-full max-w-3xl p-10 md:max-w-xl">
<form className="space-y-2" onSubmit={onSubmit}>
<Input label={'Device Name'} {...register('longName')} />
<Input

84
src/pages/settings/Interface.tsx

@ -3,6 +3,7 @@ import React from 'react';
import { Jp, Pt, Us } from 'react-flags-select';
import { useTranslation } from 'react-i18next';
import { Card } from '@app/components/generic/Card';
import { Select } from '@app/components/generic/Select';
import i18n from '@app/core/translation';
import { Button } from '@components/generic/Button';
@ -44,45 +45,50 @@ export const Interface = ({
</Button>
}
>
<div className="w-full max-w-3xl space-y-2 md:max-w-xl">
<Select
label="Language"
active={
i18n.language === 'en'
? {
name: 'English',
value: 'en',
icon: <Us />,
}
: i18n.language === 'pt'
? { name: 'Português', value: 'pt', icon: <Pt /> }
: i18n.language === 'jp'
? { name: '日本', value: 'jp', icon: <Jp /> }
: { name: 'English', value: 'en', icon: <Us /> }
}
onChange={(value): void => {
void i18n.changeLanguage(value);
}}
id="aaa"
options={[
{
name: 'English',
value: 'en',
icon: <Us className="w-6" />,
},
{
name: 'Português',
value: 'pt',
icon: <Pt className="w-6" />,
},
{
name: '日本',
value: 'jp',
icon: <Jp className="w-6" />,
},
]}
/>
</div>
<Card
title="Basic settings"
description="Device name and user parameters"
>
<div className="w-full max-w-3xl space-y-2 md:max-w-xl p-10">
<Select
label="Language"
active={
i18n.language === 'en'
? {
name: 'English',
value: 'en',
icon: <Us />,
}
: i18n.language === 'pt'
? { name: 'Português', value: 'pt', icon: <Pt /> }
: i18n.language === 'jp'
? { name: '日本', value: 'jp', icon: <Jp /> }
: { name: 'English', value: 'en', icon: <Us /> }
}
onChange={(value): void => {
void i18n.changeLanguage(value);
}}
id="aaa"
options={[
{
name: 'English',
value: 'en',
icon: <Us className="w-6" />,
},
{
name: 'Português',
value: 'pt',
icon: <Pt className="w-6" />,
},
{
name: '日本',
value: 'jp',
icon: <Jp className="w-6" />,
},
]}
/>
</div>
</Card>
</PrimaryTemplate>
);
};

46
src/pages/settings/Radio.tsx

@ -3,6 +3,7 @@ import React from 'react';
import { useForm } from 'react-hook-form';
import { useTranslation } from 'react-i18next';
import { Card } from '@app/components/generic/Card';
import { connection } from '@app/core/connection';
import { useAppSelector } from '@app/hooks/redux';
import { Button } from '@components/generic/Button';
@ -53,26 +54,31 @@ export const Radio = ({ navOpen, setNavOpen }: RadioProps): JSX.Element => {
</Button>
}
>
<div className="w-full max-w-3xl md:max-w-xl">
<form className="space-y-2" onSubmit={onSubmit}>
<Input label={t('strings.wifi_ssid')} {...register('wifiSsid')} />
<Input
type="password"
label={t('strings.wifi_psk')}
{...register('wifiPassword')}
/>
<Input
label={'Charge current'}
disabled
{...register('chargeCurrent')}
/>
<Input
label={'Last GPS Attempt'}
disabled
{...register('gpsAttemptTime')}
/>
</form>
</div>
<Card
title="Basic settings"
description="Device name and user parameters"
>
<div className="w-full max-w-3xl p-10 md:max-w-xl">
<form className="space-y-2" onSubmit={onSubmit}>
<Input label={t('strings.wifi_ssid')} {...register('wifiSsid')} />
<Input
type="password"
label={t('strings.wifi_psk')}
{...register('wifiPassword')}
/>
<Input
label={'Charge current'}
disabled
{...register('chargeCurrent')}
/>
<Input
label={'Last GPS Attempt'}
disabled
{...register('gpsAttemptTime')}
/>
</form>
</div>
</Card>
</PrimaryTemplate>
);
};

Loading…
Cancel
Save